UNPKG

nexshop-web-contents

Version:

Nexshop Web Contents Project

535 lines (431 loc) 22 kB
import React from 'react'; import {expect} from 'chai'; import {shallow} from "enzyme"; import sinon from "sinon"; import * as Redux from 'redux'; import configureStore from 'redux-mock-store'; import {actions as dialogActions} from "nexshop-web-dialog"; import {contentsActions, playlistActions, sceneActions} from "nexshop-web-store"; import {actions as popupActions} from "nexshop-web-popup"; import ContentsMain from '../../src/component/contents-main'; import ContentsMainView from '../../src/component/contents-main-view'; import {openFloatingView} from '../../src/action/floating-view'; const { selectUploadFiles, uploadFilesAsync, createNewFolderAsync, fetchExistContentNameAsync, replaceContentNameValidity, fetchAllUnderFolderAsync, fetchAllUnderRootFolderAsync, fetchBreadcrumbAsync, fetchContentsBySearchOptionAsync, popFolderBreadcrumb, setClearSearchOption, setSelectedContentsItemIds, uploadFileExist, updateFilesAsync } = contentsActions; const {createPlaylist} = playlistActions; const {createScene} = sceneActions; const {openPopup, closePopup, closeAllPopup} = popupActions; describe('ContentsMain Spec', () => { let wrapper; let instance; let mockStore; const spyHistoryPush = sinon.spy(); const spyOpenDialog = sinon.spy(); const spyCloseDialog = sinon.spy(); const spyOpenPopup = sinon.spy(); const spyClosePopup = sinon.spy(); const spyCloseAllPopup = sinon.spy(); const spySelectUploadFiles = sinon.spy(); const spyUploadFilesAsync = sinon.spy(); const spyUploadFileExist = sinon.spy(); const spyOpenFloatingView = sinon.spy(); const spyCreatePlaylist = sinon.spy(); const spyCreateScene = sinon.spy(); const spyCreateNewFolderAsync = sinon.spy(); const spyFetchExistContentNameAsync = sinon.spy(); const spyReplaceContentNameValidity = sinon.spy(); const spyFetchAllUnderFolderAsync = sinon.spy(); const spyFetchAllUnderRootFolderAsync = sinon.spy(); const spyFetchBreadcrumbAsync = sinon.spy(); const spyFetchContentsBySearchOptionAsync = sinon.spy(); const spyPopFolderBreadcrumb = sinon.spy(); const spySetClearSearchOption = sinon.spy(); const spySetSelectedContentsItemIds = sinon.spy(); const spyUpdateFileAsync = sinon.spy(); const mockActions = { openDialog: spyOpenDialog, closeDialog: spyCloseDialog, openPopup: spyOpenPopup, closePopup: spyClosePopup, closeAllPopup: spyCloseAllPopup, selectUploadFiles: spySelectUploadFiles, uploadFilesAsync: spyUploadFilesAsync, uploadFileExist: spyUploadFileExist, updateFilesAsync: spyUpdateFileAsync, openFloatingView: spyOpenFloatingView, createPlaylist: spyCreatePlaylist, createScene: spyCreateScene, createNewFolderAsync: spyCreateNewFolderAsync, fetchExistContentNameAsync: spyFetchExistContentNameAsync, replaceContentNameValidity: spyReplaceContentNameValidity, fetchAllUnderFolderAsync: spyFetchAllUnderFolderAsync, fetchAllUnderRootFolderAsync: spyFetchAllUnderRootFolderAsync, fetchBreadcrumbAsync: spyFetchBreadcrumbAsync, fetchContentsBySearchOptionAsync: spyFetchContentsBySearchOptionAsync, popFolderBreadcrumb: spyPopFolderBreadcrumb, setClearSearchOption: spySetClearSearchOption, setSelectedContentsItemIds: spySetSelectedContentsItemIds }; const mockHistory = { push: spyHistoryPush }; const {openDialog, closeDialog} = dialogActions; const mockStoreContents = { contentNameExisted: 'NONE', breadcrumb: [{name: 'Contents', id: 'rootId'}] }; function getWrapperAndInstance(mockStore) { wrapper = shallow(<ContentsMain store={mockStore} history={mockHistory} rootFolderId={'rootId'} match={{params: {folderId: 'someFolder'}}} location={{state: {name: 'minions', type: 'image'}}} />).dive(); instance = wrapper.instance(); return {wrapper, instance}; } beforeEach(() => { mockStore = configureStore()({ popup: {}, dialog: 'create-scene', contents: { contentNameExisted: 'NONE', breadcrumb: [{name: 'Contents', id: 'rootId'}], rootFolderId: 'rootId', willOverwriteContent: [], behaviorExistFile: 'SKIP' }, }); sinon.stub(Redux, "bindActionCreators").withArgs({ openDialog, closeDialog, openPopup, closePopup, closeAllPopup, selectUploadFiles, uploadFilesAsync, uploadFileExist, updateFilesAsync, openFloatingView, createPlaylist, createScene, createNewFolderAsync, fetchExistContentNameAsync, replaceContentNameValidity, fetchAllUnderFolderAsync, fetchAllUnderRootFolderAsync, fetchBreadcrumbAsync, fetchContentsBySearchOptionAsync, popFolderBreadcrumb, setClearSearchOption, setSelectedContentsItemIds }, sinon.match.func).returns(mockActions); ({instance, wrapper} = getWrapperAndInstance(mockStore)); }); afterEach(() => { Redux.bindActionCreators.restore(); spyHistoryPush.reset(); spyOpenDialog.reset(); spyCloseDialog.reset(); spyOpenPopup.reset(); spyClosePopup.reset(); spyCloseAllPopup.reset(); spySelectUploadFiles.reset(); spyUploadFilesAsync.reset(); spyUploadFileExist.reset(); spyOpenFloatingView.reset(); spyCreatePlaylist.reset(); spyCreateScene.reset(); spyCreateNewFolderAsync.reset(); spyFetchExistContentNameAsync.reset(); spyReplaceContentNameValidity.reset(); spyFetchAllUnderFolderAsync.reset(); spyFetchAllUnderRootFolderAsync.reset(); spyFetchBreadcrumbAsync.reset(); spyFetchContentsBySearchOptionAsync.reset(); spyPopFolderBreadcrumb.reset(); spySetClearSearchOption.reset(); spySetSelectedContentsItemIds.reset(); }); describe('Mapping props', () => { beforeEach(() => { mockStore = configureStore()({dialog: '', popup: {}, contents: mockStoreContents}); ({instance, wrapper} = getWrapperAndInstance(mockStore)); }); it('has addMenuVisibility according to "add-menu" popup state', () => { expect(instance.props.addMenuVisibility).to.be.not.true; mockStore = configureStore()({ dialog: '', popup: {'add-menu': {visibility: true}}, contents: mockStoreContents }); ({instance} = getWrapperAndInstance(mockStore)); expect(instance.props.addMenuVisibility).to.be.true; }); it('has createPlaylistDialogVisibility according to "create-playlist" dialog state', () => { expect(instance.props.createPlaylistDialogVisibility).to.be.false; mockStore = configureStore()({dialog: 'create-playlist', popup: {}, contents: mockStoreContents}); ({instance} = getWrapperAndInstance(mockStore)); expect(instance.props.createPlaylistDialogVisibility).to.be.true; }); it('has createSceneDialogVisibility according to "create-scene" dialog state', () => { expect(instance.props.createSceneDialogVisibility).to.be.false; mockStore = configureStore()({dialog: 'create-scene', popup: {}, contents: mockStoreContents}); ({instance} = getWrapperAndInstance(mockStore)); expect(instance.props.createSceneDialogVisibility).to.be.true; }); it('has maps bound actions', () => { expect(instance.props.actions).to.deep.equal(mockActions); }); describe('addMenuVisibility ', () => { it('addMenuVisibility is not true when popup do not have "add-menu" or visibility is false', () => { expect(wrapper.instance().props.addMenuVisibility).to.be.not.true; mockStore = configureStore()({ dialog: '', popup: {'add-menu': {visibility: false}}, contents: mockStoreContents }); ({instance, wrapper} = getWrapperAndInstance(mockStore)); expect(wrapper.instance().props.addMenuVisibility).to.be.not.true; }); it('addMenuVisibility is true when popup do have "add-menu" and visibility is true', () => { mockStore = configureStore()({ dialog: '', popup: {'add-menu': {visibility: true}}, contents: mockStoreContents }); ({instance, wrapper} = getWrapperAndInstance(mockStore)); expect(wrapper.instance().props.addMenuVisibility).to.be.true; }); }); }); describe('uploadFiles', () => { const files = ['fi', 'le', 's']; beforeEach(() => { ({instance} = getWrapperAndInstance(mockStore)); instance.uploadFiles(files); }); it('throws selectUploadFiles action', () => { expect(spySelectUploadFiles.calledWith(files)).to.be.true; }); it('throws uploadFileAsync after selectUploadFiles', () => { expect(spyUploadFilesAsync.calledAfter(spySelectUploadFiles)).to.be.true; }); it('throws openFloatingView after uploadFileAsync', () => { expect(spyOpenFloatingView.calledAfter(spyUploadFilesAsync)).to.be.true; }); it('throws closePopup', () => { expect(spyClosePopup.called).to.be.true; }); }); describe('openDialogAndClosePopup', () => { beforeEach(() => { instance.openDialogAndClosePopup('some dialog') }); it('calls openDialog with passed dialog name', () => { expect(spyOpenDialog.calledWith('some dialog')).to.be.true; }); it('closes AddMenu', () => { expect(spyClosePopup.called).to.be.true; }); }); describe('clicking menu item', () => { beforeEach(() => { sinon.stub(instance, 'openDialogAndClosePopup'); }); it('calls openDialogAndClosePopup with "create-playlist"', () => { instance.onCreatePlaylistMenuClicked(); expect(instance.openDialogAndClosePopup.calledWith('create-playlist')).to.be.true; }); it('calls openDialogAndClosePopup with "create-scene"', () => { instance.onCreateSceneMenuClicked(); expect(instance.openDialogAndClosePopup.calledWith('create-scene')).to.be.true; }); }); describe('onAddButtonClicked', () => { let spyStopPropagation; beforeEach(() => { spyStopPropagation = sinon.spy(); instance.onAddButtonClicked({stopPropagation: spyStopPropagation}); }); it('calls openPopup action with "add-menu"', () => { expect(spyOpenPopup.calledWith('add-menu')).to.be.true; }); it('close all popup when "add-menu" popup is already shown', () => { mockStore = configureStore()({dialog: '', popup: {name: 'add-menu'}, contents: mockStoreContents}); ({instance, wrapper} = getWrapperAndInstance(mockStore)); instance.onAddButtonClicked({stopPropagation: spyStopPropagation}); expect(spyCloseAllPopup.called).to.be.true; }); it('stops event propagation', () => { expect(spyStopPropagation.called).to.be.true; }); }); describe('onPlaylistCreated', () => { beforeEach(() => { wrapper.instance().onPlaylistCreated("title", "resolution"); }); it('calls createPlaylist action with title, resolution', () => { expect(spyCreatePlaylist.calledWith('title', 'resolution')).to.be.true; }); it('calls closeDialog action', () => { expect(spyCloseDialog.called).to.be.true; }); it('pushes new history /contents/create-playlist', () => { expect(spyHistoryPush.calledWith('/contents/create-playlist')).to.be.true; }); }); describe('onSceneCreated', () => { beforeEach(() => { wrapper.instance().onSceneCreated("title", {text: '16x9', orientation: 'vertical'}); }); it('calls spyCreateScene action with title, resolution', () => { expect(spyCreateScene.calledWith('title', {width: '16', height: '9'}, 'vertical')).to.be.true; }); it('calls closeDialog action', () => { expect(spyCloseDialog.called).to.be.true; }); it('pushes new history /contents/scene', () => { expect(spyHistoryPush.calledWith('/contents/scene')).to.be.true; }); }); describe('closeDialog', () => { it('throws closeDialog action', () => { wrapper.instance().closeDialog(); expect(spyCloseDialog.called).to.be.true; }); }); describe('onCreateNewFolderClicked', () => { it('call add new folder action', () => { wrapper.instance().onCreateNewFolderClicked(); expect(spyCreateNewFolderAsync.called).to.be.true; }); }); describe('rendering', () => { it('passes props to ContentsMainView', () => { const contentsMainViewWrapper = wrapper.find(ContentsMainView); expect(contentsMainViewWrapper.prop('onCreateSceneMenuClicked')).to.equal(instance.onCreateSceneMenuClicked); expect(contentsMainViewWrapper.prop('onSceneCreated')).to.equal(instance.onSceneCreated); expect(contentsMainViewWrapper.prop('onCreatePlaylistMenuClicked')).to.equal(instance.onCreatePlaylistMenuClicked); expect(contentsMainViewWrapper.prop('onCreateNewFolderClicked')).to.equal(instance.onCreateNewFolderClicked); expect(contentsMainViewWrapper.prop('onPlaylistCreated')).to.equal(instance.onPlaylistCreated); expect(contentsMainViewWrapper.prop('onAddButtonClicked')).to.equal(instance.onAddButtonClicked); expect(contentsMainViewWrapper.prop('addMenuVisibility')).to.equal(instance.props.addMenuVisibility); expect(contentsMainViewWrapper.prop('onSelectFiles')).to.equal(instance.uploadFiles); expect(contentsMainViewWrapper.prop('closeAddMenu')).to.equal(spyClosePopup); expect(contentsMainViewWrapper.prop('createPlaylistDialogVisibility')).to.be.false; expect(contentsMainViewWrapper.prop('createSceneDialogVisibility')).to.be.true; expect(contentsMainViewWrapper.prop('closeDialog')).to.equal(instance.closeDialog); expect(contentsMainViewWrapper.prop('fetchExistContentNameAsync')).to.equal(spyFetchExistContentNameAsync); expect(contentsMainViewWrapper.prop('breadcrumb')).to.deep.equal(mockStoreContents.breadcrumb); expect(contentsMainViewWrapper.prop('contentNameExisted')).to.equal(mockStoreContents.contentNameExisted); expect(contentsMainViewWrapper.prop('replaceContentNameValidity')).to.equal(spyReplaceContentNameValidity); }); }); describe('componentWillMount from router url', () => { it('passes fetchAllUnderRootFolderAsync, fetchBreadcrumbAsync with rootFolderId, setClearSearchOption and setSelectedContentsItemIds with empty array ' + 'when came from GMB "Contents" button from another navigation bar menu', () => { wrapper.instance().componentWillMount(); expect(spyFetchAllUnderRootFolderAsync.called).to.true; expect(spySetSelectedContentsItemIds.calledWith([])).to.true; }); }); describe('componentWillReceiveProps with nextProps', () => { let nextProps; beforeEach(() => { spyFetchAllUnderFolderAsync.reset(); spyFetchBreadcrumbAsync.reset(); spyFetchAllUnderRootFolderAsync.reset(); spyFetchContentsBySearchOptionAsync.reset(); spyPopFolderBreadcrumb.reset(); spyFetchAllUnderRootFolderAsync.reset(); spySetClearSearchOption.reset(); spySetSelectedContentsItemIds.reset(); nextProps = { rootFolderId: 'rootId', match: {params: {folderId: 'someFolder'}}, location: {state: {name: 'minions', type: 'image'}}, actions: { fetchAllUnderFolderAsync: spyFetchAllUnderFolderAsync, fetchBreadcrumbAsync: spyFetchBreadcrumbAsync, fetchAllUnderRootFolderAsync: spyFetchAllUnderRootFolderAsync, fetchContentsBySearchOptionAsync: spyFetchContentsBySearchOptionAsync, popFolderBreadcrumb: spyPopFolderBreadcrumb, setClearSearchOption: spySetClearSearchOption, setSelectedContentsItemIds: spySetSelectedContentsItemIds }, willOverwriteContent: [], behaviorExistFile: 'SKIP' }; }); describe('initDataFromRouter', () => { it('call initDataFromRouter when componentWillReceiveProps', () => { let spyInitDataFromRouter = sinon.spy(wrapper.instance(), 'initDataFromRouter'); wrapper.instance().componentWillReceiveProps(nextProps); expect(spyInitDataFromRouter.calledWith(nextProps)).to.true; }); it('passes fetchAllUnderFolderAsync with folderId, fetchBreadcrumbAsync with folderId, setClearSearchOption, setSelectedContentsItemIds with empty array ' + 'when folder moved', () => { wrapper.instance().folderId = 'otherFolder'; delete nextProps.location.state; wrapper.instance().initDataFromRouter(nextProps); expect(spyFetchAllUnderFolderAsync.calledWith('someFolder')).to.true; expect(spyFetchBreadcrumbAsync.calledWith('someFolder')).to.true; expect(spySetClearSearchOption.called).to.true; expect(spySetSelectedContentsItemIds.calledWith([])).to.true; expect(wrapper.instance().folderId).to.equal('someFolder'); }); it('passes fetchContentsBySearchOptionAsync with searchOptions, popFolderBreadcrumb with 0 ' + 'when search', () => { wrapper.instance().searchOptions = {name: 'minions', type: 'video'}; delete nextProps.match.params.folderId; wrapper.instance().initDataFromRouter(nextProps); expect(spyFetchContentsBySearchOptionAsync.calledWith({name: 'minions', type: 'image'})).to.true; expect(spyPopFolderBreadcrumb.calledWith(0)).to.true; expect(wrapper.instance().searchOptions).to.deep.equal({name: 'minions', type: 'image'}); }); it('passes fetchAllUnderRootFolderAsync, fetchBreadcrumbAsync with rootFolderId, setClearSearchOption and setSelectedContentsItemIds with empty array ' + 'when came from GMB "Contents" button after folder move or search', () => { wrapper.instance().folderId = 'otherFolder'; delete nextProps.match.params.folderId; delete nextProps.location.state; wrapper.instance().initDataFromRouter(nextProps); expect(spyFetchAllUnderRootFolderAsync.called).to.true; expect(spySetSelectedContentsItemIds.calledWith([])).to.true; }); it('passes not fetchAllUnderFolderAsync, fetchBreadcrumbAsync, fetchAllUnderRootFolderAsync, ' + 'fetchContentsBySearchOptionAsync, popFolderBreadcrumb, setClearSearchOption, setSelectedContentsItemIds ' + 'when folder moved', () => { wrapper.instance().folderId = 'someFolder'; wrapper.instance().searchOptions = nextProps.location.state; wrapper.instance().initDataFromRouter(nextProps); expect(spyFetchAllUnderFolderAsync.called).to.false; expect(spyFetchContentsBySearchOptionAsync.called).to.false; expect(spyFetchBreadcrumbAsync.called).to.false; expect(spySetClearSearchOption.called).to.false; expect(spySetSelectedContentsItemIds.called).to.false; expect(spyPopFolderBreadcrumb.called).to.false; expect(spyFetchAllUnderRootFolderAsync.called).to.false; }); }); describe('willOverwriteContent', () => { describe('willOverwriteContent is exist and changed', () => { beforeEach(() => { nextProps.willOverwriteContent = [{id: 'some contents file'}]; }); it('passes uploadFileExist for each willOverwriteContent when behaviorExistFile is "SKIP"', () => { wrapper.instance().componentWillReceiveProps(nextProps); expect(spyUploadFileExist.calledWith({id: 'some contents file'})).to.true; }); it('passes openDialog with overwrite-contents-item when behaviorExistFile is not "SKIP"', () => { nextProps.behaviorExistFile = 'NONE'; wrapper.instance().componentWillReceiveProps(nextProps); expect(spyOpenDialog.calledWith('overwrite-contents-item')).to.true; }); }); }); }); });