import React from 'react'; import { mount, shallow } from 'enzyme'; import video from './video'; import { EVENTS } from './constants'; const TestControl = ({ duration }) => { return (
{ duration }
); }; const TestVideo = ({ video, ...restProps }) => { // Remove `videoEl` so we do not spread an unsupported // prop onto a DOM element. delete restProps.videoEl; return (
); }; describe('video', () => { let Component; let component; beforeAll(() => { Component = video(TestVideo); }); describe('the wrapped component', () => { beforeEach(() => { component = mount( ); }); describe('HTMLMediaElement API as props', () => { let testControl; beforeEach(() => { component = mount( ); 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( ); const updateState = component.instance().updateState; 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( ); const updateState = component.instance().updateState; component.find('source').node.removeEventListener = removeEventListenerSpy; expect(removeEventListenerSpy).not.toHaveBeenCalled(); component.unmount(); expect(removeEventListenerSpy).toHaveBeenCalledWith('error', updateState); }); }); describe('mapping to props', () => { let videoEl = {}; beforeAll(() => { component = shallow( ); // 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: function() { 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.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.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( ); 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( ); 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) => Object.assign({}, ownProps, stateProps, videoElProps)); const component = shallow( ); expect(component.find(TestVideo).prop('duplicateKey')).toBe('mapVideoElToProps'); }); }); });