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