123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491 |
- import 'web-audio-test-api';
- import React from 'react';
- import configureStore from 'redux-mock-store';
- import {mount} from 'enzyme';
- import {LoadingState} from '../../../src/reducers/project-state';
- import VM from 'scratch-vm';
- import projectSaverHOC from '../../../src/lib/project-saver-hoc.jsx';
- describe('projectSaverHOC', () => {
- const mockStore = configureStore();
- let store;
- let vm;
- beforeEach(() => {
- store = mockStore({
- scratchGui: {
- projectChanged: false,
- projectState: {},
- projectTitle: 'Scratch Project',
- timeout: {
- autoSaveTimeoutId: null
- }
- },
- locales: {
- locale: 'en'
- }
- });
- vm = new VM();
- jest.useFakeTimers();
- });
- test('if canSave becomes true when showing a project with an id, project will be saved', () => {
- const mockedUpdateProject = jest.fn();
- const Component = () => <div />;
- const WrappedComponent = projectSaverHOC(Component);
- const mounted = mount(
- <WrappedComponent
- isShowingWithId
- canSave={false}
- isCreatingNew={false}
- isShowingSaveable={false} // set explicitly because it relies on ownProps.canSave
- isShowingWithoutId={false}
- isUpdating={false}
- loadingState={LoadingState.SHOWING_WITH_ID}
- store={store}
- vm={vm}
- onAutoUpdateProject={mockedUpdateProject}
- />
- );
- mounted.setProps({
- canSave: true,
- isShowingSaveable: true
- });
- expect(mockedUpdateProject).toHaveBeenCalled();
- });
- test('if canSave is alreatdy true and we show a project with an id, project will NOT be saved', () => {
- const mockedSaveProject = jest.fn();
- const Component = () => <div />;
- const WrappedComponent = projectSaverHOC(Component);
- const mounted = mount(
- <WrappedComponent
- canSave
- isCreatingNew={false}
- isShowingWithId={false}
- isShowingWithoutId={false}
- isUpdating={false}
- loadingState={LoadingState.LOADING_VM_WITH_ID}
- store={store}
- vm={vm}
- onAutoUpdateProject={mockedSaveProject}
- />
- );
- mounted.setProps({
- canSave: true,
- isShowingWithId: true,
- loadingState: LoadingState.SHOWING_WITH_ID
- });
- expect(mockedSaveProject).not.toHaveBeenCalled();
- });
- test('if canSave is false when showing a project without an id, project will NOT be created', () => {
- const mockedCreateProject = jest.fn();
- const Component = () => <div />;
- const WrappedComponent = projectSaverHOC(Component);
- const mounted = mount(
- <WrappedComponent
- isShowingWithoutId
- canSave={false}
- isCreatingNew={false}
- isShowingWithId={false}
- isUpdating={false}
- loadingState={LoadingState.LOADING_VM_NEW_DEFAULT}
- store={store}
- vm={vm}
- onCreateProject={mockedCreateProject}
- />
- );
- mounted.setProps({
- isShowingWithoutId: true,
- loadingState: LoadingState.SHOWING_WITHOUT_ID
- });
- expect(mockedCreateProject).not.toHaveBeenCalled();
- });
- test('if canCreateNew becomes true when showing a project without an id, project will be created', () => {
- const mockedCreateProject = jest.fn();
- const Component = () => <div />;
- const WrappedComponent = projectSaverHOC(Component);
- const mounted = mount(
- <WrappedComponent
- isShowingWithoutId
- canCreateNew={false}
- isCreatingNew={false}
- isShowingWithId={false}
- isUpdating={false}
- loadingState={LoadingState.SHOWING_WITHOUT_ID}
- store={store}
- vm={vm}
- onCreateProject={mockedCreateProject}
- />
- );
- mounted.setProps({
- canCreateNew: true
- });
- expect(mockedCreateProject).toHaveBeenCalled();
- });
- test('if canCreateNew is true and we transition to showing new project, project will be created', () => {
- const mockedCreateProject = jest.fn();
- const Component = () => <div />;
- const WrappedComponent = projectSaverHOC(Component);
- const mounted = mount(
- <WrappedComponent
- canCreateNew
- isCreatingNew={false}
- isShowingWithId={false}
- isShowingWithoutId={false}
- isUpdating={false}
- loadingState={LoadingState.LOADING_VM_NEW_DEFAULT}
- store={store}
- vm={vm}
- onCreateProject={mockedCreateProject}
- />
- );
- mounted.setProps({
- isShowingWithoutId: true,
- loadingState: LoadingState.SHOWING_WITHOUT_ID
- });
- expect(mockedCreateProject).toHaveBeenCalled();
- });
- test('if we enter creating new state, vm project should be requested', () => {
- const Component = () => <div />;
- const WrappedComponent = projectSaverHOC(Component);
- const mockedStoreProject = jest.fn(() => Promise.resolve());
- // The first wrapper is redux's Connect HOC
- WrappedComponent.WrappedComponent.prototype.storeProject = mockedStoreProject;
- const mounted = mount(
- <WrappedComponent
- canSave
- isCreatingCopy={false}
- isCreatingNew={false}
- isRemixing={false}
- isShowingWithId={false}
- isShowingWithoutId={false}
- isUpdating={false}
- loadingState={LoadingState.LOADING_VM_NEW_DEFAULT}
- reduxProjectId={'100'}
- store={store}
- vm={vm}
- />
- );
- mounted.setProps({
- isCreatingNew: true,
- loadingState: LoadingState.CREATING_NEW
- });
- expect(mockedStoreProject).toHaveBeenCalled();
- });
- test('if we enter remixing state, vm project should be requested, and alert should show', () => {
- const mockedShowCreatingRemixAlert = jest.fn();
- const Component = () => <div />;
- const WrappedComponent = projectSaverHOC(Component);
- const mockedStoreProject = jest.fn(() => Promise.resolve());
- // The first wrapper is redux's Connect HOC
- WrappedComponent.WrappedComponent.prototype.storeProject = mockedStoreProject;
- const mounted = mount(
- <WrappedComponent
- canSave
- isCreatingCopy={false}
- isCreatingNew={false}
- isRemixing={false}
- isShowingWithId={false}
- isShowingWithoutId={false}
- isUpdating={false}
- loadingState={LoadingState.SHOWING_WITH_ID}
- reduxProjectId={'100'}
- store={store}
- vm={vm}
- onShowCreatingRemixAlert={mockedShowCreatingRemixAlert}
- />
- );
- mounted.setProps({
- isRemixing: true,
- loadingState: LoadingState.REMIXING
- });
- expect(mockedStoreProject).toHaveBeenCalled();
- expect(mockedShowCreatingRemixAlert).toHaveBeenCalled();
- });
- test('if we enter creating copy state, vm project should be requested, and alert should show', () => {
- const mockedShowCreatingCopyAlert = jest.fn();
- const Component = () => <div />;
- const WrappedComponent = projectSaverHOC(Component);
- const mockedStoreProject = jest.fn(() => Promise.resolve());
- // The first wrapper is redux's Connect HOC
- WrappedComponent.WrappedComponent.prototype.storeProject = mockedStoreProject;
- const mounted = mount(
- <WrappedComponent
- canSave
- isCreatingCopy={false}
- isCreatingNew={false}
- isRemixing={false}
- isShowingWithId={false}
- isShowingWithoutId={false}
- isUpdating={false}
- loadingState={LoadingState.SHOWING_WITH_ID}
- reduxProjectId={'100'}
- store={store}
- vm={vm}
- onShowCreatingCopyAlert={mockedShowCreatingCopyAlert}
- />
- );
- mounted.setProps({
- isCreatingCopy: true,
- loadingState: LoadingState.CREATING_COPY
- });
- expect(mockedStoreProject).toHaveBeenCalled();
- expect(mockedShowCreatingCopyAlert).toHaveBeenCalled();
- });
- test('if we enter updating/saving state, vm project should be requested', () => {
- const Component = () => <div />;
- const WrappedComponent = projectSaverHOC(Component);
- const mockedStoreProject = jest.fn(() => Promise.resolve());
- // The first wrapper is redux's Connect HOC
- WrappedComponent.WrappedComponent.prototype.storeProject = mockedStoreProject;
- const mounted = mount(
- <WrappedComponent
- canSave
- isCreatingNew={false}
- isShowingWithId={false}
- isShowingWithoutId={false}
- isUpdating={false}
- loadingState={LoadingState.LOADING_VM_WITH_ID}
- reduxProjectId={'100'}
- store={store}
- vm={vm}
- />
- );
- mounted.setProps({
- isUpdating: true,
- loadingState: LoadingState.MANUAL_UPDATING
- });
- expect(mockedStoreProject).toHaveBeenCalled();
- });
- test('if we are already in updating/saving state, vm project ' +
- 'should NOT requested, alert should NOT show', () => {
- const mockedShowCreatingAlert = jest.fn();
- const Component = () => <div />;
- const WrappedComponent = projectSaverHOC(Component);
- const mockedStoreProject = jest.fn(() => Promise.resolve());
- // The first wrapper is redux's Connect HOC
- WrappedComponent.WrappedComponent.prototype.storeProject = mockedStoreProject;
- const mounted = mount(
- <WrappedComponent
- canSave
- isUpdating
- isCreatingNew={false}
- isShowingWithId={false}
- isShowingWithoutId={false}
- loadingState={LoadingState.MANUAL_UPDATING}
- reduxProjectId={'100'}
- store={store}
- vm={vm}
- onShowCreatingAlert={mockedShowCreatingAlert}
- />
- );
- mounted.setProps({
- isUpdating: true,
- loadingState: LoadingState.AUTO_UPDATING,
- reduxProjectId: '99' // random change to force a re-render and componentDidUpdate
- });
- expect(mockedStoreProject).not.toHaveBeenCalled();
- expect(mockedShowCreatingAlert).not.toHaveBeenCalled();
- });
- test('if user saves, inline saving alert should show', () => {
- const mockedShowSavingAlert = jest.fn();
- const Component = () => <div />;
- const WrappedComponent = projectSaverHOC(Component);
- const mounted = mount(
- <WrappedComponent
- canSave
- isShowingWithoutId
- canCreateNew={false}
- isCreatingNew={false}
- isManualUpdating={false}
- isShowingWithId={false}
- isUpdating={false}
- loadingState={LoadingState.SHOWING_WITH_ID}
- store={store}
- vm={vm}
- onShowSavingAlert={mockedShowSavingAlert}
- />
- );
- mounted.setProps({
- isManualUpdating: true,
- isUpdating: true
- });
- expect(mockedShowSavingAlert).toHaveBeenCalled();
- });
- test('if project is changed, it should autosave after interval', () => {
- const Component = () => <div />;
- const WrappedComponent = projectSaverHOC(Component);
- const mockedAutoUpdate = jest.fn(() => Promise.resolve());
- const mounted = mount(
- <WrappedComponent
- canSave
- isShowingSaveable
- isShowingWithId
- loadingState={LoadingState.SHOWING_WITH_ID}
- store={store}
- vm={vm}
- onAutoUpdateProject={mockedAutoUpdate}
- />
- );
- mounted.setProps({
- projectChanged: true
- });
- // Fast-forward until all timers have been executed
- jest.runAllTimers();
- expect(mockedAutoUpdate).toHaveBeenCalled();
- });
- test('if project is changed several times in a row, it should only autosave once', () => {
- const Component = () => <div />;
- const WrappedComponent = projectSaverHOC(Component);
- const mockedAutoUpdate = jest.fn(() => Promise.resolve());
- const mounted = mount(
- <WrappedComponent
- canSave
- isShowingSaveable
- isShowingWithId
- loadingState={LoadingState.SHOWING_WITH_ID}
- store={store}
- vm={vm}
- onAutoUpdateProject={mockedAutoUpdate}
- />
- );
- mounted.setProps({
- projectChanged: true,
- reduxProjectTitle: 'a'
- });
- mounted.setProps({
- projectChanged: true,
- reduxProjectTitle: 'b'
- });
- mounted.setProps({
- projectChanged: true,
- reduxProjectTitle: 'c'
- });
- // Fast-forward until all timers have been executed
- jest.runAllTimers();
- expect(mockedAutoUpdate).toHaveBeenCalledTimes(1);
- });
- test('if project is not changed, it should not autosave after interval', () => {
- const Component = () => <div />;
- const WrappedComponent = projectSaverHOC(Component);
- const mockedAutoUpdate = jest.fn(() => Promise.resolve());
- const mounted = mount(
- <WrappedComponent
- canSave
- isShowingSaveable
- isShowingWithId
- loadingState={LoadingState.SHOWING_WITH_ID}
- store={store}
- vm={vm}
- onAutoUpdateProject={mockedAutoUpdate}
- />
- );
- mounted.setProps({
- projectChanged: false
- });
- // Fast-forward until all timers have been executed
- jest.runAllTimers();
- expect(mockedAutoUpdate).not.toHaveBeenCalled();
- });
- test('when starting to remix, onRemixing should be called with param true', () => {
- const mockedOnRemixing = jest.fn();
- const mockedStoreProject = jest.fn(() => Promise.resolve());
- const Component = () => <div />;
- const WrappedComponent = projectSaverHOC(Component);
- WrappedComponent.WrappedComponent.prototype.storeProject = mockedStoreProject;
- const mounted = mount(
- <WrappedComponent
- isRemixing={false}
- store={store}
- vm={vm}
- onRemixing={mockedOnRemixing}
- />
- );
- mounted.setProps({
- isRemixing: true
- });
- expect(mockedOnRemixing).toHaveBeenCalledWith(true);
- });
- test('when starting to remix, onRemixing should be called with param false', () => {
- const mockedOnRemixing = jest.fn();
- const mockedStoreProject = jest.fn(() => Promise.resolve());
- const Component = () => <div />;
- const WrappedComponent = projectSaverHOC(Component);
- WrappedComponent.WrappedComponent.prototype.storeProject = mockedStoreProject;
- const mounted = mount(
- <WrappedComponent
- isRemixing
- store={store}
- vm={vm}
- onRemixing={mockedOnRemixing}
- />
- );
- mounted.setProps({
- isRemixing: false
- });
- expect(mockedOnRemixing).toHaveBeenCalledWith(false);
- });
- test('uses onSetProjectThumbnailer on mount/unmount', () => {
- const Component = () => <div />;
- const WrappedComponent = projectSaverHOC(Component);
- const setThumb = jest.fn();
- const mounted = mount(
- <WrappedComponent
- store={store}
- vm={vm}
- onSetProjectThumbnailer={setThumb}
- />
- );
- // Set project thumbnailer should be called on mount
- expect(setThumb).toHaveBeenCalledTimes(1);
- // And it should not pass that function on to wrapped element
- expect(mounted.find(Component).props().onSetProjectThumbnailer).toBeUndefined();
- // Unmounting should call it again with null
- mounted.unmount();
- expect(setThumb).toHaveBeenCalledTimes(2);
- expect(setThumb.mock.calls[1][0]).toBe(null);
- });
- test('uses onSetProjectSaver on mount/unmount', () => {
- const Component = () => <div />;
- const WrappedComponent = projectSaverHOC(Component);
- const setSaver = jest.fn();
- const mounted = mount(
- <WrappedComponent
- store={store}
- vm={vm}
- onSetProjectSaver={setSaver}
- />
- );
- // Set project saver should be called on mount
- expect(setSaver).toHaveBeenCalledTimes(1);
- // And it should not pass that function on to wrapped element
- expect(mounted.find(Component).props().onSetProjectSaver).toBeUndefined();
- // Unmounting should call it again with null
- mounted.unmount();
- expect(setSaver).toHaveBeenCalledTimes(2);
- expect(setSaver.mock.calls[1][0]).toBe(null);
- });
- });
|