UNPKG

nexshop-web-contents

Version:

Nexshop Web Contents Project

632 lines (532 loc) 26 kB
import React from 'react'; import {expect} from 'chai'; import {shallow} from "enzyme"; import configureStore from 'redux-mock-store'; import sinon from 'sinon'; import * as Redux from 'redux'; import {actions as dialogActions} from "nexshop-web-dialog"; import {contentsActions, playlistActions, previewActions, sceneActions} from 'nexshop-web-store'; import {actions as popupActions} from "nexshop-web-popup"; import Contents from '../../../src/component/contents/contents'; import {closeFloatingView, openFloatingView} from '../../../src/action/floating-view'; import ContentsView from '../../../src/component/contents/contents-view'; import FloatingView from '../../../src/component/contents/floating-view/floating-view'; const { fetchContentsAsync, willBeDeletedContentsItem, willBeOverwroteContentItem, selectContentsItemForPreview, selectUploadFiles, uploadFilesAsync, removeSelectedContentsItemIndex, setSelectedContentsItemIndex, updateFolderAsync, updateFolderData, pushFolderBreadcrumb, popFolderBreadcrumb, setSelectedContentsItemIds, updateContentsItemData, updateContentsItemAsync, copyContents, } = contentsActions; const {playlistDetailAsync} = playlistActions; const {playlistPreviewAsync} = previewActions; const {moveSceneDetailAsync, selectScenePreview} = sceneActions; const {closePopup, openPopup, closeAllPopup} = popupActions; describe('Contents Spec', () => { let wrapper, instance, mockHistory; let spyOpenFloatingView, spyCloseFloatingView, spyFetchContentsAsync, spyWillBeDeletedContentsItem, spyWillBeOverwroteContentItem, spySelectContentsItemForPreview, spyOpenDialog, spyClosePopup, spyOpenPopup, spyUpdateFolderData, spyPushFolderBreadcrumb, spyPopFolderBreadcrumb, spyCloseAllPopup; let spySelectUploadFiles; let spyUploadFilesAsync; let spySetSelectedContentsItemIndex; let spyRemoveSelectedContentsItemIndex; let spyUpdateFolderAsync; let spyPlaylistPreviewAsync; let spyPlaylistDetailAsync; let spyMoveSceneDetailAsync; let spySelectScenePreview; let spySetSelectedContentsItemIds; let spyUpdateContentsItemData; let spyUpdateContentsItemAsync; let storeState, mockStore; let spyCopyContents; let spyHistoryPush; let spyUploadFileExist; const {openDialog} = dialogActions; function getWrapperAndInstance(mockStore, mockHistory) { wrapper = shallow(<Contents store={mockStore} history={mockHistory}/>).dive(); instance = wrapper.instance(); return {wrapper, instance}; } beforeEach(() => { spyOpenFloatingView = sinon.spy(); spyCloseFloatingView = sinon.spy(); spyFetchContentsAsync = sinon.spy(); spyWillBeDeletedContentsItem = sinon.spy(); spyWillBeOverwroteContentItem = sinon.spy(); spySelectContentsItemForPreview = sinon.spy(); spyOpenDialog = sinon.spy(); spySelectUploadFiles = sinon.spy(); spyUploadFilesAsync = sinon.spy(); spySetSelectedContentsItemIndex = sinon.spy(); spyRemoveSelectedContentsItemIndex = sinon.spy(); spyUpdateFolderAsync = sinon.spy(); spyPlaylistPreviewAsync = sinon.spy(); spyMoveSceneDetailAsync = sinon.spy(); spyClosePopup = sinon.spy(); spyOpenPopup = sinon.spy(); spyUpdateFolderData = sinon.spy(); spyPushFolderBreadcrumb = sinon.spy(); spyPopFolderBreadcrumb = sinon.spy(); spyCloseAllPopup = sinon.spy(); spySetSelectedContentsItemIds = sinon.spy(); spyUpdateContentsItemData = sinon.spy(); spyUpdateContentsItemAsync = sinon.spy(); spyPlaylistDetailAsync = sinon.spy(); spyCopyContents = sinon.spy(); spyHistoryPush = sinon.spy(); spySelectScenePreview = sinon.spy(); spyUploadFileExist = sinon.spy(); sinon.stub(Redux, "bindActionCreators").withArgs({ openFloatingView, closeFloatingView, fetchContentsAsync, willBeDeletedContentsItem, willBeOverwroteContentItem, selectContentsItemForPreview, selectUploadFiles, uploadFilesAsync, openDialog, setSelectedContentsItemIndex, removeSelectedContentsItemIndex, updateFolderAsync, playlistPreviewAsync, playlistDetailAsync, moveSceneDetailAsync, selectScenePreview, updateFolderData, pushFolderBreadcrumb, popFolderBreadcrumb, openPopup, closePopup, closeAllPopup, setSelectedContentsItemIds, updateContentsItemData, updateContentsItemAsync, copyContents, }, sinon.match.func).returns({ openFloatingView: spyOpenFloatingView, closeFloatingView: spyCloseFloatingView, fetchContentsAsync: spyFetchContentsAsync, willBeDeletedContentsItem: spyWillBeDeletedContentsItem, willBeOverwroteContentItem: spyWillBeOverwroteContentItem, selectContentsItemForPreview: spySelectContentsItemForPreview, selectUploadFiles: spySelectUploadFiles, uploadFilesAsync: spyUploadFilesAsync, openDialog: spyOpenDialog, setSelectedContentsItemIndex: spySetSelectedContentsItemIndex, removeSelectedContentsItemIndex: spyRemoveSelectedContentsItemIndex, playlistPreviewAsync: spyPlaylistPreviewAsync, playlistDetailAsync: spyPlaylistDetailAsync, updateFolderAsync: spyUpdateFolderAsync, moveSceneDetailAsync: spyMoveSceneDetailAsync, selectScenePreview: spySelectScenePreview, closePopup: spyClosePopup, closeAllPopup: spyCloseAllPopup, openPopup: spyOpenPopup, updateFolderData: spyUpdateFolderData, pushFolderBreadcrumb: spyPushFolderBreadcrumb, popFolderBreadcrumb: spyPopFolderBreadcrumb, setSelectedContentsItemIds: spySetSelectedContentsItemIds, updateContentsItemData: spyUpdateContentsItemData, updateContentsItemAsync: spyUpdateContentsItemAsync, copyContents: spyCopyContents, }); storeState = { floatingView: {visibility: true}, contents: { selectedUploadFiles: [{name: '1', type: 'mock/one'}, {name: '2', type: 'mock/two'}], contents: [{ id: 'some id', name: 'media1', status: 'selected', type: 'playlist', thumbnailUrls: { thumbnail: 'some url', medium: null, large: null } }, { id: 'other id', name: 'media2', type: 'image', thumbnailUrls: { thumbnail: 'some url', medium: null, large: null } }, { id: 'scene id', name: 'scene sample', type: 'scene', thumbnailUrls: { thumbnail: 'scene some url', medium: null, large: null } }], folders: [{id: 'folder id', name: 'folder1'}, {id: '2', name: 'folder2'}], breadcrumb: [{name: 'RootFolder', id: 'rootId'}], selectedContentsItemIds: [], searchOption: { name: '', type: 'all' }, }, popup: {}, contextMenuOpenedIndex: -1, }; mockHistory = { push: spyHistoryPush }; mockStore = configureStore()(storeState); ({instance, wrapper} = getWrapperAndInstance(mockStore, mockHistory)); }); afterEach(() => { Redux.bindActionCreators.restore(); }); describe('Contents', () => { it('passes contents to ContentsView', () => { expect(wrapper.find(ContentsView).prop('contents').length).to.equal(3); }); it('passes folders to FolderView', () => { expect(wrapper.find(ContentsView).prop('folders')).to.deep.equal( [{id: 'folder id', name: 'folder1'}, {id: '2', name: 'folder2'}]); }); it('draws floating view when floatingViewVisibility is true', () => { expect(wrapper.find(FloatingView).length).to.equal(1); }); it('passes files, onClose props to FloatingView', () => { expect(wrapper.find(FloatingView).prop('files')).to.deep.equal([{name: '1', type: 'mock/one'}, { name: '2', type: 'mock/two' }]); expect(wrapper.find(FloatingView).prop('onClose')).to.equal(spyCloseFloatingView); }); it('does not draw floating view when floatingViewVisibility is false', () => { wrapper.setProps({floatingViewVisibility: false}); expect(wrapper.find(FloatingView).length).to.equal(0); }); describe('onContentsClick', () => { it('passes onContentItemClick with contentsItemSelected', () => { let {onContentsClick} = wrapper.find(ContentsView).props(); const spyContentsSelectedAndPlaylistAsync = sinon.spy(wrapper.instance(), 'contentsItemSelected'); onContentsClick(undefined, 0); expect(spyContentsSelectedAndPlaylistAsync.called).to.true; }); }); describe('onContentItemDoubleClick', () => { it('passes playlistDetailAsync with playlist type contentsItem', () => { let {onContentItemDoubleClick} = wrapper.find(ContentsView).props(); onContentItemDoubleClick((0)); expect(spyPlaylistDetailAsync.calledWith('some id', '/contents/playlist-detail')).to.true; }); it('could not call playlistDetailAsync with non-playlist type contentsItem', () => { let {onContentItemDoubleClick} = wrapper.find(ContentsView).props(); onContentItemDoubleClick(1); expect(spyPlaylistDetailAsync.called).to.false; }); it('call moveSceneDetailAsync, history push with scene type id', () => { let {onContentItemDoubleClick} = wrapper.find(ContentsView).props(); onContentItemDoubleClick(2); expect(spyMoveSceneDetailAsync.calledWith('scene id')).to.true; }); }); describe('onContextMenuClicked', () => { it('call ContextMenuClicked method', () => { let {onContextMenuClicked} = wrapper.find(ContentsView).props(); const spyContextMenuClicked = sinon.spy(wrapper.instance(), "contextMenuClicked"); onContextMenuClicked(undefined, 0); expect(spyContextMenuClicked.calledWith(undefined, 0)).to.true; }); it('call setSelectedContentsItemIds with folder', () => { wrapper.instance().contextMenuClicked('folder', 0); expect(spySetSelectedContentsItemIds.calledWith(['folder id'])).to.true; }); it('call setSelectedContentsItemIds with playlist contents item', () => { wrapper.instance().contextMenuClicked('playlist', 0); expect(spySetSelectedContentsItemIds.calledWith(['some id'])).to.true; }); }); }); describe('Mapping props', () => { it('has props.floatingViewVisibility as true when redux floatingView visibility state is true', () => { expect(instance.props.floatingViewVisibility).to.be.true; }); it('has props.selectedUploadFiles as redux contents selectedUploadFiles state', () => { expect(instance.props.selectedUploadFiles).to.deep.equal([{name: '1', type: 'mock/one'}, { name: '2', type: 'mock/two' }]); }); it('has props.contents as redux contents state', () => { expect(instance.props.contents).to.deep.equal( [{ id: 'some id', name: 'media1', status: 'selected', type: 'playlist', thumbnailUrls: { thumbnail: 'some url', medium: null, large: null } }, { id: 'other id', name: 'media2', type: 'image', thumbnailUrls: { thumbnail: 'some url', medium: null, large: null } }, { id: 'scene id', name: 'scene sample', type: 'scene', thumbnailUrls: { thumbnail: 'scene some url', medium: null, large: null } }]); }); it('has action openDialog and openPopup', () => { expect(instance.props.actions).to.deep.equal({ openFloatingView: spyOpenFloatingView, closeFloatingView: spyCloseFloatingView, fetchContentsAsync: spyFetchContentsAsync, willBeDeletedContentsItem: spyWillBeDeletedContentsItem, willBeOverwroteContentItem: spyWillBeOverwroteContentItem, selectContentsItemForPreview: spySelectContentsItemForPreview, selectUploadFiles: spySelectUploadFiles, uploadFilesAsync: spyUploadFilesAsync, openDialog: spyOpenDialog, setSelectedContentsItemIndex: spySetSelectedContentsItemIndex, removeSelectedContentsItemIndex: spyRemoveSelectedContentsItemIndex, updateFolderAsync: spyUpdateFolderAsync, playlistPreviewAsync: spyPlaylistPreviewAsync, selectScenePreview: spySelectScenePreview, playlistDetailAsync: spyPlaylistDetailAsync, moveSceneDetailAsync: spyMoveSceneDetailAsync, updateFolderData: spyUpdateFolderData, pushFolderBreadcrumb: spyPushFolderBreadcrumb, popFolderBreadcrumb: spyPopFolderBreadcrumb, openPopup: spyOpenPopup, closePopup: spyClosePopup, closeAllPopup: spyCloseAllPopup, setSelectedContentsItemIds: spySetSelectedContentsItemIds, updateContentsItemData: spyUpdateContentsItemData, updateContentsItemAsync: spyUpdateContentsItemAsync, copyContents: spyCopyContents, }); }); describe('contextMenuVisibility ', () => { it('contextMenuVisibility is not true when popup do not have "context-menu" or visibility is false', () => { expect(wrapper.instance().props.contextMenuVisibility).to.not.true; storeState.popup = {'context-menu': {visibility: false}}; mockStore = configureStore()(storeState); ({instance, wrapper} = getWrapperAndInstance(mockStore, mockHistory)); expect(wrapper.instance().props.contextMenuVisibility).to.not.true; }); it('contextMenuVisibility is true when popup do have "context-menu" and visibility is true', () => { storeState.popup = {'context-menu': {visibility: true}}; mockStore = configureStore()(storeState); ({instance, wrapper} = getWrapperAndInstance(mockStore, mockHistory)); expect(wrapper.instance().props.contextMenuVisibility).to.true; }); }); }); describe('restore selected td column', () => { const spyAddEventListener = sinon.spy(); const spyRemoveEventListener = sinon.spy(); beforeEach(() => { wrapper.setProps({ contents: [] }); sinon.stub(document, 'getElementsByTagName').returns([ { addEventListener: spyAddEventListener, removeEventListener: spyRemoveEventListener, } ]) }); afterEach(() => { spyAddEventListener.reset(); spyRemoveEventListener.reset(); document.getElementsByTagName.restore(); }); it('add event listener to click func when componentDidMount calls', () => { wrapper.instance().componentDidMount(); expect(spyAddEventListener.calledWith('click', instance.removeSelectedContentsItem)).to.be.true; expect(spyRemoveSelectedContentsItemIndex.called).to.be.true; }); it('remove event listener to click when componentWillUnmount calls', () => { wrapper.instance().componentWillUnmount(); expect(spyRemoveEventListener.calledWith('click', instance.removeSelectedContentsItem)).to.be.true; }); it('does not call removeSelectedContentsItemIndex when calls removeSelectedContentsItem func with TD target ', () => { const e = { target: { nodeName: 'TD', parentNode: { nodeName: 'TD' } } }; wrapper.instance().removeSelectedContentsItem(e); expect(spyRemoveSelectedContentsItemIndex.called).to.be.false; }); }); describe('method test', () => { it('calls setSelectedContentsItemIndex when contentsItemSelected with contentsItem', () => { const contentsItem = { type: 'playlist', id: 'some id' }; wrapper.instance().contentsItemSelected([contentsItem.id]); expect(spySetSelectedContentsItemIds.calledWith(['some id'])).to.true; }); it('calls playlistDetailAsync when contentsItemDetailAsync with playlist type contentsItem', () => { const contentsItem = { type: 'playlist', id: 'some id' }; wrapper.instance().contentsItemDetailAsync(contentsItem); expect(spyPlaylistDetailAsync.calledWith('some id', '/contents/playlist-detail')).to.true; }); describe('when ContextMenuClicked with index 1', () => { it('and folder type then call openPopup and closeAllPopup action', () => { wrapper.instance().contextMenuClicked(undefined, 1); expect(spyOpenPopup.calledWith("context-menu")).to.true; expect(spyCloseAllPopup.called).to.true; }); it('and contents item type then call openPopup and closeAllPopup action', () => { wrapper.instance().contextMenuClicked('image', 1); expect(spyOpenPopup.calledWith("context-menu")).to.true; expect(spyCloseAllPopup.called).to.true; }); it('then contextMenuOpenedIndex should be 1', () => { wrapper.instance().contextMenuClicked(undefined, 1); expect(wrapper.instance().state.contextMenuOpenedIndex).to.equal(1); }); }); describe('when ContextMenuClicked with index 1 and contextMenuOpenedIndex was 1', () => { it('then contextMenuOpenedIndex should not change and does not called contentsItemSelected', () => { const beforeContextMenuOpenedIndex = 1; wrapper.setState({ contextMenuOpenedIndex: beforeContextMenuOpenedIndex }); const spyContentsItemSelected = sinon.spy(wrapper.instance(), 'contentsItemSelected'); wrapper.instance().contextMenuClicked(undefined, 1); expect(wrapper.instance().state.contextMenuOpenedIndex).to.equal(beforeContextMenuOpenedIndex); expect(spyContentsItemSelected.called).to.false; }); }); describe('when calls closeContextMenuPopup', () => { it('then contextMenuOpenedIndex state is -1', () => { wrapper.instance().closeContextMenuPopup(); expect(wrapper.instance().state.contextMenuOpenedIndex).to.equal(-1); }); it('then call closePopup', () => { wrapper.instance().closeContextMenuPopup(); expect(spyCloseAllPopup.called).to.true; }); }); describe('when calls rename with folder', () => { it('then closeContextMenuPopup and updateFolderData method call', () => { const closeContextMenuPopup = sinon.spy(wrapper.instance(), 'closeContextMenuPopup'); wrapper.instance().setState({contextMenuOpenedIndex: 0}); wrapper.instance().rename('folder'); expect(closeContextMenuPopup.called).to.true; expect(spyUpdateFolderData.calledWith({id: 'folder id', name: 'folder1', status: 'new'})).to.true; }); }); describe('when calls rename with contentsItem', () => { it('then closeContextMenuPopup and updateContentsItemData method call', () => { const closeContextMenuPopup = sinon.spy(wrapper.instance(), 'closeContextMenuPopup'); wrapper.instance().setState({contextMenuOpenedIndex: 0}); wrapper.instance().rename('playlist'); expect(closeContextMenuPopup.called).to.true; expect(spyUpdateContentsItemData.calledWith( { id: 'some id', name: 'media1', type: 'playlist', thumbnailUrls: { thumbnail: 'some url', medium: null, large: null } , status: 'new' })).to.true; }); }); describe('when calls onFolderItemDoubleClick', () => { it('then call history push to /contents/folder/folderId', () => { wrapper.instance().onFolderItemDoubleClick({name: 'some folder name', id: 'someFolderId'}); expect(spyHistoryPush.calledWith('/contents/folder/someFolderId')).to.true; }); }); describe('when calls onBreadcrumbItemClick', () => { it('then call spyPopFolderBreadcrumb and spyFetchAllUnderFolderAsync', () => { wrapper.instance().onBreadcrumbItemClick('someFolderId', 1); expect(spyHistoryPush.calledWith('/contents/folder/someFolderId')).to.true; }); }); describe('when calls contentsItemSelected', () => { it('set contentsItem id to setSelectedContentsItemIds', () => { wrapper.instance().contentsItemSelected(['contentsId']); expect(spySetSelectedContentsItemIds.calledWith(['contentsId'])).to.true; }); }); describe('moveToPreview Spec', () => { const playlistId = 'some id'; const sceneId = 'scene id'; const notPlaylistId = 'other id'; beforeEach(() => { wrapper.setProps({ history: {push: sinon.spy()} }); sinon.stub(document, 'getElementById').returns({ getClientRects: () => { return [{width: 16, height: 9}] } }); }); afterEach(() => { document.getElementById.restore(); }); it('call selectContentsItemForPreview when moveToPreview executed', () => { wrapper.instance().moveToPreview(playlistId); expect(spySelectContentsItemForPreview.calledWith(playlistId)).to.be.true; }); it('route to "/contents/contents-preview" when contentsItem type is not playlist', () => { wrapper.instance().moveToPreview(notPlaylistId); expect(wrapper.instance().props.history.push.calledWith('/contents/contents-preview')).to.be.true; }); it('route to "contents/scene-preview" when contentItem type is scene', () => { wrapper.instance().moveToPreview(sceneId); expect(wrapper.instance().props.history.push.calledWith('/contents/scene-preview')).to.be.true; }); it('call playlistPreviewAsync when contentsItem type is playlist', () => { wrapper.instance().moveToPreview(playlistId); expect(spyPlaylistPreviewAsync.calledWith(playlistId, {width: 16, height: 9})).to.be.true; }); it('when show preview then close context popup.', () => { wrapper.instance().contextMenuClicked(undefined, 1); wrapper.instance().moveToPreview(playlistId); expect(spyCloseAllPopup.called).to.true; }); }); describe('when calls copyToClick', () => { it('then call closePopup', () => { wrapper.instance().copyToClick('playlist', 0); expect(spyCloseAllPopup.called).to.true; expect(spyCopyContents.calledWith(wrapper.instance().getIdForType('playlist', 0))).to.true; }); }); }); describe('pass props', () => { describe('ContentsView', () => { it('pass moveToPreview for onPreview', () => { expect(wrapper.find(ContentsView).prop('onPreview')).to.equal(wrapper.instance().moveToPreview); }); }); }); });