nexshop-web-contents
Version:
Nexshop Web Contents Project
536 lines (406 loc) • 20.4 kB
JavaScript
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);
});
});
});