UNPKG

nexshop-web-contents

Version:

Nexshop Web Contents Project

536 lines (406 loc) 20.4 kB
import React from 'react'; import {expect} from 'chai'; import {shallow} from "enzyme"; import sinon from 'sinon'; import {ContextMenu, ContextMenuItemView} from 'nexshop-web-elements'; import ContentsView from "../../../src/component/contents/contents-view"; import ContentsItemView from "../../../src/component/contents/contents-item-view"; import FolderView from "../../../src/component/contents/folder-view"; describe('Contents View Spec', () => { let wrapper; let spyDeleteContentsItem; let spyOpenDialog; let spyWillBeDeletedContentsItem; let spySelectUploadFiles; let spyUploadFilesAsync; let spyOpenFloatingView; let spyOnContentsClick; let spyUpdateFolderAsync; let spyOnContentItemDoubleClick; let spyOnContextMenuClicked; let spyCloseContextMenuPopup; let spyUpdateFolderData; let spyOnFolderItemDoubleClick; let spyOnBreadcrumbItemClick; let spyOnPreview; let spyRename; let spyUpdateContentsItemAsync; let spyUpdateContentsItemData; let spyMoveToClick; let spyCopyToClick; const SELECTED_FOLDER_ID = '3423424'; const SELECTED_CONTENTS_ITEM_ID = 1; const CONTENTS = [ { id: 1, name: 'first.file', lastModifiedTimestamp: '2017-09-07T09:15:51.283Z', type: 'image', fileSizeBytes: 213674, thumbnailUrls: { thumbnail: 'first.thumbnail.file', }, status: 'new' }, { id: 2, name: 'second.file', lastModifiedTimestamp: '2017-09-08T16:15:51.283Z', type: 'video', fileSizeBytes: 12345670, thumbnailUrls: { thumbnail: 'second.thumbnail.file' } }, ]; const FOLDERS = Object.freeze([ { createdTimestamp: "2017-10-24T07:01:36.026Z", lastModifiedTimestamp: "2017-10-24T07:01:36.027Z", id: "3423424", parentId: "334535", name: "Summer Festival", ancestors: [ "334535" ] }, { createdTimestamp: "2017-09-28T02:02:39.959Z", lastModifiedTimestamp: "2017-09-28T02:02:39.959Z", id: "59cc583fa153d66606dd6e5c", parentId: "334535", name: "Folder_170928_1", ancestors: [ "334535" ] } ]); const dummyBreadcrumb = [{name: 'folder1', id: 'folder1'}, {name: 'folder2', id: 'folder2'}, { name: 'folder3', id: 'folder3' }]; const searchOption = {name: '', type: 'all'}; beforeEach(() => { spyDeleteContentsItem = sinon.spy(); spyOpenDialog = sinon.spy(); spyWillBeDeletedContentsItem = sinon.spy(); spySelectUploadFiles = sinon.spy(); spyUploadFilesAsync = sinon.spy(); spyOpenFloatingView = sinon.spy(); spyOnContentsClick = sinon.spy(); spyUpdateFolderAsync = sinon.spy(); spyOnContentItemDoubleClick = sinon.spy(); spyOnContextMenuClicked = sinon.spy(); spyCloseContextMenuPopup = sinon.spy(); spyUpdateFolderData = sinon.spy(); spyOnFolderItemDoubleClick = sinon.spy(); spyOnBreadcrumbItemClick = sinon.spy(); spyOnPreview = sinon.spy(); spyRename = sinon.spy(); spyUpdateContentsItemAsync = sinon.spy(); spyUpdateContentsItemData = sinon.spy(); spyMoveToClick = sinon.spy(); spyCopyToClick = sinon.spy(); wrapper = shallow(<ContentsView contents={CONTENTS} folders={FOLDERS} onDeleteContentsItem={spyDeleteContentsItem} willBeDeletedContentsItem={spyWillBeDeletedContentsItem} openDialog={spyOpenDialog} selectUploadFiles={spySelectUploadFiles} uploadFilesAsync={spyUploadFilesAsync} openFloatingView={spyOpenFloatingView} onContentsClick={spyOnContentsClick} updateFolderAsync={spyUpdateFolderAsync} onContentItemDoubleClick={spyOnContentItemDoubleClick} onContextMenuClicked={spyOnContextMenuClicked} contextMenuVisibility={true} closePopup={spyCloseContextMenuPopup} updateFolderData={spyUpdateFolderData} onFolderItemDoubleClick={spyOnFolderItemDoubleClick} breadcrumb={dummyBreadcrumb} onBreadcrumbItemClick={spyOnBreadcrumbItemClick} onPreview={spyOnPreview} rename={spyRename} updateContentsItemAsync={spyUpdateContentsItemAsync} updateContentsItemData={spyUpdateContentsItemData} moveToClick={spyMoveToClick} copyToClick={spyCopyToClick} searchOption={searchOption} />); }); describe('Passing Props to ContentsItemView and FolderView', () => { let firstContentsItemProps; let secondContentsItemProps; let firstFolderProps; let secondFolderProps; beforeEach(() => { firstContentsItemProps = wrapper.find(ContentsItemView).at(0).props(); secondContentsItemProps = wrapper.find(ContentsItemView).at(1).props(); firstFolderProps = wrapper.find(FolderView).at(0).props(); secondFolderProps = wrapper.find(FolderView).at(1).props(); wrapper.setState({type: 'image', index: 0}); }); it('passes contentsItem', () => { let {contentsItem} = firstContentsItemProps; expect(contentsItem).to.deep.equal(CONTENTS[0]); }); it('passes folderItem', () => { let {folder} = firstFolderProps; expect(folder).to.deep.equal(FOLDERS[0]); }); it('passes onDelete with closure props.openDialog and willBeDeletedContentsItem with index', () => { firstContentsItemProps.onDelete(); expect(spyOpenDialog.calledWith('delete-contents-item')).to.be.true; expect(spyWillBeDeletedContentsItem.calledWith(0)).to.be.true; secondContentsItemProps.onDelete(); expect(spyOpenDialog.calledWith('delete-contents-item')).to.be.true; expect(spyWillBeDeletedContentsItem.calledWith(1)).to.be.true; }); it('passes onPreview with closure props.onSelectedPreviewItemIndex with id', () => { firstContentsItemProps.onPreview(); expect(spyOnPreview.calledWith(1)).to.be.true; secondContentsItemProps.onPreview(); expect(spyOnPreview.calledWith(2)).to.be.true; }); it('passes onClick with onContentsClick with type and index', () => { firstContentsItemProps.onClick(); expect(spyOnContentsClick.calledWith('image', 0)).to.true; secondContentsItemProps.onClick(); expect(spyOnContentsClick.calledWith('video', 1)).to.true; }); it('passes onDoubleClick with onContentItemDoubleClick with index', () => { firstContentsItemProps.onDoubleClick(); expect(spyOnContentItemDoubleClick.calledWith(0)).to.true; }); it('passes onClick with onContentsClick with folder type and index', () => { firstFolderProps.onClick(); expect(spyOnContentsClick.calledWith('folder', 0)).to.true; }); it('passes onDoubleClick with onFolderItemDoubleClick with folder item', () => { firstFolderProps.onDoubleClick(); expect(spyOnFolderItemDoubleClick.calledWith(FOLDERS[0])).to.true; }); describe('passes onContextMenu prop', () => { it('with onContextMenu on FolderView', () => { const e = {preventDefault: sinon.spy()}; sinon.stub(wrapper.instance(), 'getContentsScrollTop').returns(0); firstFolderProps.onContextMenu(e); expect(spyOnContextMenuClicked.calledWith('folder', 0)).to.true; }); it('with onContextMenu on ContentsItemView', () => { const e = {preventDefault: sinon.spy()}; sinon.stub(wrapper.instance(), 'getContentsScrollTop').returns(0); firstContentsItemProps.onContextMenu(e); expect(spyOnContextMenuClicked.calledWith('image', 0)).to.true; }); }); it('passes onBreadcrumbItemClick with id and index', () => { wrapper.find('.contents-breadcrumb-item > span').at(1).simulate('click'); expect(spyOnBreadcrumbItemClick.calledWith('folder2', 1)).to.true; }); it('passes selectedContentsItemIds when folder is selected', () => { wrapper.setProps({ selectedContentsItemIds: [SELECTED_FOLDER_ID] }); firstFolderProps = wrapper.find(FolderView).at(0).props(); expect(firstFolderProps.selectedContentsItemIds[0]).to.deep.equal(SELECTED_FOLDER_ID); }); it('passes selectedContentsItemIds when contentsItem is selected', () => { wrapper.setProps({ selectedContentsItemIds: [SELECTED_CONTENTS_ITEM_ID] }); firstContentsItemProps = wrapper.find(ContentsItemView).at(0).props(); expect(firstContentsItemProps.selectedContentsItemIds[0]).to.deep.equal(SELECTED_CONTENTS_ITEM_ID); }); it('passes onMoveToClick on contents item\'s Context menu and open move to Dialog with onClosePopup', () => { wrapper.find(ContextMenuItemView).at(0).props().onClick(); expect(spyCloseContextMenuPopup.called).to.true; expect(spyOpenDialog.calledWith('move-to')); }); it('passes onTagToClick on contents item\'s Context menu and open move to Dialog with onClosePopup', () => { wrapper.find(ContextMenuItemView).at(2).props().onClick(); expect(spyCloseContextMenuPopup.called).to.true; expect(spyOpenDialog.calledWith('add-tag')); }); it('passes onCopyToClick on contents item\'s Context menu and copied contents', () => { wrapper.find(ContextMenuItemView).at(1).props().onClick(); expect(spyCopyToClick.calledWith('image', 0)).to.true; }); it('passes onMoveToClick on folder\'s Context menu and open move to Dialog with onClosePopup', () => { wrapper.find(ContextMenuItemView).at(0).props().onClick(); expect(spyCloseContextMenuPopup.called).to.true; expect(spyOpenDialog.calledWith('move-to')); }); it('passes rename on folder\'s Context menu with onRenameClick', () => { wrapper.find(ContextMenuItemView).at(3).props().onClick(); expect(spyRename.calledWith('image')).to.true; }); it('show search bar and contents size when searchOption is exist', () => { wrapper.setProps({ searchOption: {name: 'search name', type: 'image'} }); expect(wrapper.find('.contents-search-result').exists()).to.true; expect(wrapper.find('.contents-search-result').text()).to.equal('Search result 2'); }); }); it('has rows as many as contentsItem', () => { expect(wrapper.find(ContentsItemView).length).to.equal(2); }); it('has rows as many as folders', () => { expect(wrapper.find(FolderView).length).to.equal(2); }); it('shows drop zone when dropping state is true', () => { expect(wrapper.find('.contents-drop-area').length).to.equal(0); wrapper.setState({dropping: true}); expect(wrapper.find('.contents-drop-area').length).to.equal(1); }); it('set drop zone top and height by scroll top', () => { wrapper.setState({dropping: true}); expect(wrapper.find('.contents-drop-area').html()).to.contain('style="top:0px;height:calc(100vh - 110px - 50px);"') }); it('getContentsScrollTop function return 0 when this.contentWrapper is undefined', () => { expect(wrapper.instance().getContentsScrollTop()).to.equal(0); }); it('set drop zone top and height by scroll top when contentWrapper is scrolled', () => { sinon.stub(wrapper.instance(), 'getContentsScrollTop').returns(70); wrapper.setState({dropping: true}); expect(wrapper.find('.contents-drop-area').html()).to.contain('style="top:20px;height:calc(100vh - 110px - 0px);"') }); const createDragOverEvent = (kind, names = []) => { return { preventDefault: sinon.spy(), dataTransfer: { types: [kind], files: names.map((name) => ({name})) } }; }; describe('render', () => { let firstContentsItemProps; let firstFolderProps; beforeEach(() => { firstContentsItemProps = wrapper.find(ContentsItemView).at(0).props(); firstFolderProps = wrapper.find(FolderView).at(0).props(); }); it('ContextMenu is exist when contextMenuVisibility is true', () => { wrapper.setProps({ contextMenuVisibility: true, }); expect(wrapper.find(ContextMenu).exists()).to.true; }); describe('context menu render', () => { it('show "Make To" and "Rename" item when contextmenu is opened on folder item ', () => { const e = {preventDefault: sinon.spy()}; sinon.stub(wrapper.instance(), 'getContentsScrollTop').returns(0); firstFolderProps.onContextMenu(e); expect(wrapper.find(ContextMenuItemView).nodes[0].props.text).to.equal("Move To"); expect(wrapper.find(ContextMenuItemView).nodes[1].props.text).to.equal("Rename"); }); it('show "Make To" and "Rename" item when contextmenu is opened on folder item ', () => { const e = {preventDefault: sinon.spy()}; sinon.stub(wrapper.instance(), 'getContentsScrollTop').returns(0); firstContentsItemProps.onContextMenu(e); expect(wrapper.find(ContextMenuItemView).nodes[0].props.text).to.equal("Move To"); expect(wrapper.find(ContextMenuItemView).nodes[1].props.text).to.equal("Make a copy"); expect(wrapper.find(ContextMenuItemView).nodes[2].props.text).to.equal("Manage Tag"); expect(wrapper.find(ContextMenuItemView).nodes[3].props.text).to.equal("Rename"); }); }); }); describe('drag enter', () => { it('prevents default', () => { let event = createDragOverEvent('Files'); wrapper.find('.contents-wrapper').simulate('dragenter', event); expect(event.preventDefault.called).to.be.true; }); it('increments drag counter', () => { wrapper.find('.contents-wrapper').simulate('dragenter', createDragOverEvent('Files')); expect(wrapper.instance().dragCounter).to.equal(1); wrapper.find('.contents-wrapper').simulate('dragenter', createDragOverEvent('Files')); expect(wrapper.instance().dragCounter).to.equal(2); }); it('does not change state when dropping state is already true', () => { wrapper.find('.contents-wrapper').simulate('dragenter', createDragOverEvent('Files')); sinon.spy(wrapper.instance(), 'setState'); wrapper.find('.contents-wrapper').simulate('dragenter', createDragOverEvent('Files')); expect(wrapper.instance().setState.notCalled).to.be.true; }); it('changes dropping as true when dragover event has items which is file', () => { wrapper.find('.contents-wrapper').simulate('dragenter', createDragOverEvent('Files')); expect(wrapper.state('dropping')).to.be.true; }); it('does not change if any item is not file', () => { wrapper.find('.contents-wrapper').simulate('dragenter', createDragOverEvent('Not_Files')); expect(wrapper.state('dropping')).to.be.false; }); }); describe('drag leave', () => { it('prevents default', () => { let event = createDragOverEvent(); wrapper.find('.contents-wrapper').simulate('dragleave', event); expect(event.preventDefault.called).to.be.true; }); it('decrements drag counter', () => { wrapper.instance().dragCounter = 2; wrapper.find('.contents-wrapper').simulate('dragleave', createDragOverEvent()); expect(wrapper.instance().dragCounter).to.equal(1); }); it('changes dropping state as false only when drag counter is 0', () => { wrapper.instance().dragCounter = 2; wrapper.setState({dropping: true}); wrapper.find('.contents-wrapper').simulate('dragleave', createDragOverEvent()); expect(wrapper.state('dropping')).to.be.true; wrapper.find('.contents-wrapper').simulate('dragleave', createDragOverEvent()); expect(wrapper.state('dropping')).to.be.false; }); }); describe('drag over', () => { it('prevents default', () => { let event = createDragOverEvent(); wrapper.find('.contents-wrapper').simulate('dragover', event); expect(event.preventDefault.called).to.be.true; }); }); describe('drop', () => { it('prevents default', () => { let event = createDragOverEvent('Files', []); wrapper.find('.contents-wrapper').simulate('drop', event); expect(event.preventDefault.called).to.be.true; }); it('set drag counter to 0', () => { wrapper.instance().dragCounter = 10; wrapper.find('.contents-wrapper').simulate('drop', createDragOverEvent('Files', [])); expect(wrapper.instance().dragCounter).to.equal(0); }); it('change dropping state as false', () => { wrapper.setState({ dropping: true }); wrapper.find('.contents-wrapper').simulate('drop', createDragOverEvent('Files')); expect(wrapper.state('dropping')).to.be.false; }); function assertFilesAreUploaded(files, expected) { expect(spySelectUploadFiles.calledWith(files)).to.equal(expected); expect(spyUploadFilesAsync.calledWith(files)).to.equal(expected); expect(spyOpenFloatingView.called).to.equal(expected); } it('call 3 actions after setState is called with valid file extension', () => { sinon.stub(wrapper.instance(), 'setState'); let fileNames = ['a.jpg', 'b.mp4']; let files = fileNames.map((name) => ({name})); wrapper.find('.contents-wrapper').simulate('drop', createDragOverEvent('Files', fileNames)); const stateCallback = wrapper.instance().setState.lastCall.args[1]; stateCallback(); assertFilesAreUploaded(files, true); }); it('do not call 3 actions after setState is called with invalid file extension', () => { sinon.stub(wrapper.instance(), 'setState'); let fileNames = ['a.bad', 'b.mp4']; let files = fileNames.map((name) => ({name})); wrapper.find('.contents-wrapper').simulate('drop', createDragOverEvent('Files', fileNames)); const stateCallback = wrapper.instance().setState.lastCall.args[1]; stateCallback(); assertFilesAreUploaded(files, false); }); }); });