UNPKG

@bilingo/video-player

Version:
228 lines (205 loc) 6.82 kB
import React from 'react'; import { mount, shallow } from 'enzyme'; import video from './video'; import { EVENTS } from './constants'; const TestControl = ({ duration }) => { return <div>{duration}</div>; }; const TestVideo = ({ video, ...restProps }) => { // Remove `videoEl` so we do not spread an unsupported // prop onto a DOM element. delete restProps.videoEl; return ( <div> <video {...restProps}> <source src="1" /> </video> <TestControl {...video} /> </div> ); }; describe('video', () => { let Component; let component; beforeAll(() => { Component = video(TestVideo); }); describe('the wrapped component', () => { beforeEach(() => { component = mount(<Component autoPlay />); }); describe('HTMLMediaElement API as props', () => { let testControl; beforeEach(() => { component = mount(<Component autoPlay />); testControl = component.find(TestControl); expect(testControl.props()).toEqual({}); }); it('should be provided when a video event is triggered', () => { component.find('video').node.dispatchEvent(new Event('play')); }); it('should be provided when an error occurs on last source element', () => { component.find('source').node.dispatchEvent(new Event('error')); }); afterEach(() => { // Only matching a subset is sufficient. expect(testControl.props()).toMatchObject({ controller: undefined, autoPlay: undefined, controls: false, currentSrc: '', currentTime: 0, defaultMuted: false, defaultPlaybackRate: 1, duration: 0, ended: false, error: undefined, loop: false, mediaGroup: undefined, muted: false, networkState: 0, paused: true, playbackRate: 1, preload: '', readyState: 0, seeking: false, src: '', startDate: undefined, volume: 1, }); }); }); it('should remove all event listeners from the video element when unmounted', () => { const removeEventListenerSpy = jest.fn(); component = mount(<Component autoPlay />); const { updateState } = component.instance(); component.find('video').node.removeEventListener = removeEventListenerSpy; expect(removeEventListenerSpy).not.toHaveBeenCalled(); component.unmount(); EVENTS.forEach(event => { expect(removeEventListenerSpy).toHaveBeenCalledWith( event.toLowerCase(), updateState, ); }); }); it('should remove "error" event listener from the source element when unmounted', () => { const removeEventListenerSpy = jest.fn(); component = mount(<Component autoPlay />); const { updateState } = component.instance(); component.find( 'source', ).node.removeEventListener = removeEventListenerSpy; expect(removeEventListenerSpy).not.toHaveBeenCalled(); component.unmount(); expect(removeEventListenerSpy).toHaveBeenCalledWith('error', updateState); }); }); describe('mapping to props', () => { const videoEl = {}; beforeAll(() => { component = shallow(<Component autoPlay />); // Emulate videoEl being present // e.g. componentDidMount fired. component.instance().videoEl = videoEl; component.instance().forceUpdate(); }); beforeEach(() => { // Reset spy videoEl.play = jest.fn(); }); it("returns a component with it's ownProps", () => { expect(component.find(TestVideo).prop('autoPlay')).toBe(true); }); it('returns a component with a videoEl prop', () => { expect(component.find(TestVideo).prop('videoEl')).toBe(videoEl); }); it('returns a component with all of its state on the `video` prop', () => { const state = { html5: '1', dom: 2, properties() { return 3; }, }; component.setState(state); expect(component.find(TestVideo).prop('video')).toEqual(state); }); it('can customise the mapping of props using mapToProps', () => { const Component = video(TestVideo, (state, ownProps) => { return { state, ownProps, }; }); const component = shallow(<Component autoPlay />); component.setState({ paused: true, }); expect(component.find(TestVideo).prop('state').paused).toBe(true); expect(component.find(TestVideo).prop('ownProps').autoPlay).toBe(true); }); it('can map videoEl to props for creating custom API methods', () => { const Component = video(TestVideo, undefined, (el, state, ownProps) => { return { togglePlay: () => { el.play(ownProps.testProp); }, }; }); const component = shallow(<Component autoPlay testProp="testValue" />); component.instance().videoEl = videoEl; component.instance().forceUpdate(); component.find(TestVideo).prop('togglePlay')(); expect(videoEl.play).toHaveBeenCalledWith('testValue'); }); it('allows mapVideoElToProps to take precedence over mapStateToProps', () => { const Component = video( TestVideo, () => ({ duplicateKey: 'mapStateToProps', }), () => ({ duplicateKey: 'mapVideoElToProps', }), ); const component = shallow(<Component />); expect(component.find(TestVideo).prop('duplicateKey')).toBe( 'mapVideoElToProps', ); }); it('allows ownProps to take precedence over mapVideoElToProps and mapStateToProps', () => { const Component = video( TestVideo, () => ({ duplicateKey: 'mapStateToProps', }), () => ({ duplicateKey: 'mapVideoElToProps', }), ); const component = shallow(<Component duplicateKey="ownProps" />); expect(component.find(TestVideo).prop('duplicateKey')).toBe('ownProps'); }); it('allows cusomtisation of merging ownProps, mapVideoElToProps and mapStateToProps to change the merging precedence', () => { const Component = video( TestVideo, () => ({ duplicateKey: 'mapStateToProps', }), () => ({ duplicateKey: 'mapVideoElToProps', }), (stateProps, videoElProps, ownProps) => ({ ...ownProps, ...stateProps, ...videoElProps, }), ); const component = shallow(<Component duplicateKey="ownProps" />); expect(component.find(TestVideo).prop('duplicateKey')).toBe( 'mapVideoElToProps', ); }); }); });