nexshop-web-contents
Version:
Nexshop Web Contents Project
459 lines (355 loc) • 20.7 kB
JavaScript
import React from 'react';
import {expect} from 'chai';
import {mount, shallow} from "enzyme";
import sinon from "sinon";
import {DropDown} from 'nexshop-web-elements';
import PlaylistEditorView from "../../../../src/component/playlist/playlist-editor/playlist-editor-view";
import * as TimeHelper from '../../../../src/helpers/time-helper';
import * as StringHelper from '../../../../src/helpers/string-helper';
import * as FindDOMNodeWrapper from '../../../../src/wrapper/findDOMNodeWrapper';
import {contentItemModel} from "nexshop-web-store";
describe('Playlist Editor View Spec', () => {
let wrapper;
let resolution;
let contentItems;
let spyOnDropDragContentsItem;
let spyOnDeleteItem;
let spyOnOrderChangeStart;
let spyOnOrderChangeProcess;
let spyOnOrderChangeEnd;
let spyOnSelectPreviewItem;
let spyOnUpdateContentItemTransition;
let spyOnUpdateContentItemDuration;
let spyOnUpdateContentItemFitMode;
const imageContentItem = contentItemModel.createContentItem({
id: 1,
name: 'media1',
type: 'image',
thumbnailUrls: {
thumbnail: 'first.thumbnail.file',
}
}, undefined, undefined, 'cover');
const videoContentItem = contentItemModel.createContentItem({
id: 2,
name: 'media2',
type: 'video',
thumbnailUrls: {
thumbnail: 'second.thumbnail.file',
},
durationSeconds: 52,
}, 52);
beforeEach(() => {
resolution = {
value: 'QHD',
orientation: 'horizontal'
};
contentItems = [imageContentItem, videoContentItem];
sinon.stub(FindDOMNodeWrapper, 'findDOMNode');
sinon.stub(global, 'setTimeout');
sinon.spy(TimeHelper, 'formatSeconds');
sinon.spy(StringHelper, 'leftPadZero');
spyOnDropDragContentsItem = sinon.spy();
spyOnDeleteItem = sinon.spy();
spyOnOrderChangeStart = sinon.spy();
spyOnOrderChangeProcess = sinon.spy();
spyOnOrderChangeEnd = sinon.spy();
spyOnSelectPreviewItem = sinon.spy();
spyOnUpdateContentItemTransition = sinon.spy();
spyOnUpdateContentItemDuration = sinon.spy();
spyOnUpdateContentItemFitMode = sinon.spy();
wrapper = shallow(<PlaylistEditorView resolution={resolution}
contentItems={contentItems}
onDropDragContentsItem={spyOnDropDragContentsItem}
onDeleteItem={spyOnDeleteItem}
onOrderChangeStart={spyOnOrderChangeStart}
onOrderChangeProcess={spyOnOrderChangeProcess}
onOrderChangeEnd={spyOnOrderChangeEnd}
blankIndex={-1}
onSelectPreviewItem={spyOnSelectPreviewItem}
onUpdateContentItemTransition={spyOnUpdateContentItemTransition}
onUpdateContentItemDuration={spyOnUpdateContentItemDuration}
onUpdateContentItemFitMode={spyOnUpdateContentItemFitMode}
/>);
});
afterEach(() => {
TimeHelper.formatSeconds.restore();
StringHelper.leftPadZero.restore();
FindDOMNodeWrapper.findDOMNode.restore();
global.setTimeout.restore();
});
describe('rendering', () => {
describe('top area', () => {
it('has value of resolution with given by "createPlaylist"', () => {
expect(wrapper.find('.playlist-resolution__value').text()).to.equal('QHD');
});
it('has "playlist-resolution__horizontal" className when resolution.orientation of props is horizontal', () => {
expect(wrapper.find('.playlist-resolution__horizontal').length).to.equal(1);
});
it('has "playlist-resolution__vertical" className when resolution.orientation of props is vertical', () => {
wrapper.setProps({resolution: {orientation: 'vertical'}});
expect(wrapper.find('.playlist-resolution__vertical').length).to.equal(1);
});
it('has total count', () => {
expect(StringHelper.leftPadZero.calledWith(2)).to.be.true;
expect(wrapper.find('.playlist-summary__value').at(0).text()).to.equal('02');
});
it('has total duration', () => {
expect(TimeHelper.formatSeconds.calledWith(82, 'hh:mm:ss')).to.be.true;
expect(wrapper.find('.playlist-summary__value').at(1).text()).to.equal('00:01:22');
});
});
describe('playlist item is empty', () => {
it('has playlist-item__delete', () => {
wrapper.setProps({contentItems: []});
expect(wrapper.find('.playlist-item-drag-placeholder').length).to.equal(1);
});
});
describe('playlist items', () => {
it('has "playlist-items"', () => {
expect(wrapper.find('.playlist-items').length).to.equals(1);
});
it('has "playlist-list" className', () => {
expect(wrapper.find('.playlist-items').find('.playlist-item').length).to.equal(2);
});
it('first column has thumbnail url', () => {
expect(wrapper.find('.playlist-item__thumbnail').at(0).getNode().props.style.backgroundImage)
.to.equal('url(first.thumbnail.file)');
expect(wrapper.find('.playlist-item__thumbnail').at(1).getNode().props.style.backgroundImage)
.to.equal('url(second.thumbnail.file)');
});
it('second column has contents type', () => {
expect(wrapper.find('.playlist-item').at(0).find('.playlist-item__type--image').length).to.equal(1);
expect(wrapper.find('.playlist-item').at(1).find('.playlist-item__type--video').length).to.equal(1);
});
it('third column has name', () => {
expect(wrapper.find('.playlist-item__name').at(0).text()).to.equal('media1');
expect(wrapper.find('.playlist-item__name').at(1).text()).to.equal('media2');
});
it('4th column has drop down for duration', () => {
const imageItemDuration = wrapper.find('.playlist-item__duration');
const videoItemDuration = wrapper.find('.playlist-item__duration__video');
expect(TimeHelper.formatSeconds.calledWith(52, 'mm:ss')).to.be.true;
expect(imageItemDuration.find(DropDown).prop('selected')).to.deep.equal({value: 30, text: '00:30'});
expect(videoItemDuration.text()).to.equal("00:52");
});
it('4th column formats hh:mm:ss when duration is more than 1 hour', () => {
wrapper.setProps({contentItems: [imageContentItem, Object.assign({}, videoContentItem, {durationSeconds: 3601})]});
expect(TimeHelper.formatSeconds.calledWith(3601, 'hh:mm:ss')).to.be.true;
});
it('5th column has drop down for effect', () => {
expect(wrapper.find('.playlist-item__effect').length).to.equal(contentItems.length);
const effectItems = wrapper.find('.playlist-item__effect');
expect(effectItems.at(0).find(DropDown).prop('selected')).to.deep.equal({
value: 'none',
text: 'No Effect'
});
expect(effectItems.at(1).text()).to.equal("No Effect");
});
it('6th column has fitMode drop down', () => {
expect(wrapper.find('.playlist-item__fitMode').exists()).to.true;
expect(wrapper.find('.playlist-item__fitMode').find(DropDown).at(0).prop('selected'))
.to.deep.equal({value: 'cover', text: 'Crop to fit', icon: 'crop-to-fit'});
expect(wrapper.find('.playlist-item__fitMode').find(DropDown).at(1).prop('selected'))
.to.deep.equal({value: 'contain', text: 'Fit to screen', icon: 'fit-to-screen'});
});
it('draws placeholder at blank index', () => {
wrapper.setProps({blankIndex: 1});
expect(wrapper.find('.playlist-items').childAt(1)).to.deep.equal(wrapper.find('.playlist-placeholder'));
});
it('passes transition change listener with uuid', () => {
expect(wrapper.find('.playlist-item__effect').at(0).find(DropDown).prop('onSelect').toString())
.to.equal(wrapper.instance().onTransitionEffectChange(imageContentItem.uuid).toString());
});
describe('Dragging Content', () => {
let draggingContentItem;
beforeEach(() => {
expect(wrapper.find('.playlist-item-shadow').length).to.equal(0);
wrapper.setState({draggingContentItem: imageContentItem});
draggingContentItem = wrapper.find('DraggingContentItem').dive();
});
it('draws dragging content item', () => {
expect(draggingContentItem.length).to.equal(1);
});
it('has background as thumbnail image', () => {
const thumbnailNode = draggingContentItem.find('.playlist-item__thumbnail').getNode();
expect(thumbnailNode.props.style.backgroundImage).to.equal(`url(${imageContentItem.contents.thumbnailUrls.thumbnail})`);
});
it('has class according to contentsItem type', () => {
expect(draggingContentItem.find(`.playlist-item__type--${imageContentItem.contents.type}`)).to.exist;
});
it('has contentsItem name', () => {
expect(draggingContentItem.find('.playlist-item__name').text()).to.equal(imageContentItem.contents.name);
});
it('has duration seconds', () => {
expect(draggingContentItem.find('.playlist-item__duration').text()).to.equal('00:30');
});
it('has effect name', () => {
expect(draggingContentItem.find('.playlist-item__effect').text()).to.equal('No Effect');
});
});
describe('Mouse Over & Click', () => {
const firstItemIndex = 0;
beforeEach(() => {
wrapper.find('.playlist-item').at(firstItemIndex).simulate('mouseover');
});
it('sets mouseOverUUID state', () => {
expect(wrapper.state('mouseOverUUID')).to.equal(imageContentItem.uuid);
});
it('does not change mouseOverUUID when something is dragging', () => {
wrapper.setState({isDragging: true, mouseOverUUID: ''});
wrapper.find('.playlist-item').at(firstItemIndex).simulate('mouseover');
expect(wrapper.state('mouseOverUUID')).to.equal('');
});
it('shows X button and hide when mouse leaves', () => {
expect(wrapper.find('.playlist-item--hovered').find('.playlist-item__delete').length).to.equal(1);
wrapper.find('.playlist-item-item--hovered').at(firstItemIndex).simulate('mouseleave');
expect(wrapper.find('.playlist-item').at(firstItemIndex).find('.playlist-item__delete').length).to.equal(0);
});
it('calls props.onDelete with mouse entered item index', () => {
wrapper.find('.playlist-item__delete').simulate('click');
expect(wrapper.instance().props.onDeleteItem.calledWith(firstItemIndex)).to.be.true;
});
it('appears play icon on thumbnail', () => {
expect(wrapper.find('.playlist-item-preview__play').length).to.equal(1);
});
it('disappears play icon from thumbnail', () => {
wrapper.find('.playlist-item').at(firstItemIndex).simulate('mouseleave');
expect(wrapper.find('.playlist-item__play').length).to.equal(0);
});
it('has link div to move preview', () => {
expect(wrapper.find('.playlist-item-preview-link').length).to.equal(1);
});
it('calls onSelectPreviewItem when click play icon', () => {
wrapper.find('.playlist-item-preview').simulate('click');
expect(spyOnSelectPreviewItem.calledWith(firstItemIndex)).to.be.true;
});
});
describe('Delete Item', () => {
const mouseOverIndex = 0;
let timeout;
beforeEach(() => {
wrapper.find('.playlist-item').at(mouseOverIndex).simulate('mouseover');
wrapper.find('.playlist-item__delete').simulate('click');
timeout = global.setTimeout.lastCall.args[0];
});
it('calls onDeleteItem with index', () => {
expect(spyOnDeleteItem.calledWith(mouseOverIndex)).to.be.true;
});
it('sets timeout for async process', () => {
expect(global.setTimeout.calledWith(sinon.match.func, 0)).to.be.true;
});
it('replaces mouseOverUUID with playlist[index] after render is done', () => {
wrapper.setProps({contentItems: [videoContentItem]});
timeout();
expect(wrapper.state('mouseOverUUID')).to.equal(videoContentItem.uuid);
});
it('replaces mouseOverUUID with empty string when index >= playlist.length', () => {
wrapper.setProps({contentItems: []});
timeout();
expect(wrapper.state('mouseOverUUID')).to.equal('');
});
});
describe('Mouse Drag Start & End', () => {
let spySetDragImage;
beforeEach(() => {
wrapper = mount(<PlaylistEditorView resolution={resolution}
contentItems={contentItems}
onDropDragContentsItem={spyOnDropDragContentsItem}
onDeleteItem={spyOnDeleteItem}
onOrderChangeStart={spyOnOrderChangeStart}
onOrderChangeProcess={spyOnOrderChangeProcess}
onOrderChangeEnd={spyOnOrderChangeEnd}
onSelectPreviewItem={spyOnSelectPreviewItem}
onUpdateContentItemTransition={spyOnUpdateContentItemTransition}
onUpdateContentItemDuration={spyOnUpdateContentItemDuration}
onUpdateContentItemFitMode={spyOnUpdateContentItemFitMode}
/>);
spySetDragImage = sinon.spy();
});
describe('Start', () => {
beforeEach(() => {
wrapper.find('.playlist-item').at(0).simulate('dragstart', {dataTransfer: {setDragImage: spySetDragImage}});
});
it('sets isDragging state as true', () => {
expect(wrapper.state('isDragging')).to.be.true;
});
it('sets draggingContentItem state with content at the index', () => {
expect(wrapper.state('draggingContentItem')).to.deep.equal(imageContentItem);
});
it('sets drag image with dragging element', () => {
expect(spySetDragImage.calledWith(wrapper.find('.dragging').getNode())).to.be.true;
});
it('calls props.onOrderChangeStart with selected index', () => {
expect(spyOnOrderChangeStart.calledWith(0)).to.be.true;
wrapper.find('.playlist-item').at(1).simulate('dragstart', {dataTransfer: {setDragImage: spySetDragImage}});
expect(spyOnOrderChangeStart.calledWith(1)).to.be.true;
});
});
describe('End', () => {
it('sets isDragging state as false', () => {
wrapper.setState({isDragging: true});
wrapper.find('.playlist-item').at(0).simulate('dragend', {dataTransfer: {setDragImage: spySetDragImage}});
expect(wrapper.state('isDragging')).to.be.false;
});
it('sets undefined for draggingContentItem state', () => {
expect(wrapper.state('draggingContentItem')).to.be.null;
});
it('calls props.onOrderChangeEnd', () => {
wrapper.find('.playlist-item').at(0).simulate('dragend', {dataTransfer: {setDragImage: spySetDragImage}});
expect(spyOnOrderChangeEnd.called).to.be.true;
});
});
});
describe('Mouse Drag Over', () => {
let spyPreventDefault;
let mockDragOver;
beforeEach(() => {
spyPreventDefault = sinon.spy();
mockDragOver = {preventDefault: spyPreventDefault};
wrapper.find('.playlist-item').at(0).simulate('dragover', mockDragOver);
});
it('calls props.onOrderChangeProcess with selected index', () => {
expect(spyOnOrderChangeProcess.calledWith(0)).to.be.true;
wrapper.find('.playlist-item').at(1).simulate('dragover', mockDragOver);
expect(spyOnOrderChangeProcess.calledWith(1)).to.be.true;
});
it('prevents default event', () => {
expect(spyPreventDefault.called).to.be.true;
});
});
describe('Mouse Drag Drop', () => {
it('calls props.onOrderChangeProcess with selected index', () => {
wrapper.setProps({blankIndex: 1});
wrapper.find('.playlist-placeholder').simulate('drop', {});
expect(spyOnOrderChangeEnd.called).to.be.true;
});
});
});
});
describe('drag event', () => {
it('calls props.onDropDragContentsItem when onDragDrop is called', () => {
wrapper.find('.playlist-editor-wrapper').simulate('drop');
expect(spyOnDropDragContentsItem.called).to.be.true;
});
it('calls event.preventDefault when preventDefault is called', () => {
let spyPreventDefault = sinon.spy();
let mockEvent = {
preventDefault: spyPreventDefault
};
wrapper.find('.playlist-editor-wrapper').simulate('dragover', mockEvent);
expect(spyPreventDefault.called).to.be.true;
});
});
it('onTransitionEffectChange calls onUpdateContentItemTransition with uuid, value', () => {
wrapper.instance().onTransitionEffectChange('some uuid')({value: 'i am valuable'});
expect(spyOnUpdateContentItemTransition.calledWith('some uuid', 'i am valuable')).to.be.true;
});
it('onDurationChange calls onUpdateContentItemDuration with uuid, value', () => {
wrapper.instance().onDurationChange('some uuid')({value: 'i am valuable'});
expect(spyOnUpdateContentItemDuration.calledWith('some uuid', 'i am valuable')).to.be.true;
});
it('onFitModeChange calls onUpdateContentItemFitMode with uuid, value', () => {
wrapper.instance().onFitModeChange('some uuid')({value: 'i am valuable'});
expect(spyOnUpdateContentItemFitMode.calledWith('some uuid', 'i am valuable')).to.be.true;
});
});