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