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');
});
});
});