Skip to content

Commit

Permalink
Merge pull request #177 from tkloht/react16
Browse files Browse the repository at this point in the history
React16
  • Loading branch information
tkloht authored Apr 2, 2018
2 parents 86a00c0 + 633f05f commit 2a29fa7
Show file tree
Hide file tree
Showing 12 changed files with 8,229 additions and 82 deletions.
6 changes: 6 additions & 0 deletions .babelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"presets": ["stage-0", "es2015", "react"],
"plugins": [
["transform-class-properties"],
],
}
1 change: 1 addition & 0 deletions __mocks__/fileMock.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = 'test-file-stub';
18 changes: 18 additions & 0 deletions __mocks__/react-intl.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import React from 'react';

const Intl = require.requireActual('react-intl');

// Here goes intl context injected into component, feel free to extend
const intl = {
formatMessage: ({defaultMessage}) => defaultMessage
};

Intl.injectIntl = (Node) => {
const renderWrapped = props => <Node {...props} intl={intl} />;
renderWrapped.displayName = Node.displayName
|| Node.name
|| 'Component';
return renderWrapped;
};

module.exports = Intl;
1 change: 1 addition & 0 deletions __mocks__/styleMock.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = {};
5 changes: 5 additions & 0 deletions lib/__tests__/.eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"rules": {
"max-len": 0,
},
}
137 changes: 137 additions & 0 deletions lib/__tests__/VideoCover.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
/* eslint-env mocha*/
import VideoCover from '../index';
import VideoCoverFallback from '../VideoCoverFallback';

import React from 'react';
import { shallow } from 'enzyme';

function setUserAgent(userAgent) {
const originalNavigator = window.navigator;
/* eslint-disable no-native-reassign, no-proto, no-underscore-dangle */
navigator = {};
navigator.__proto__ = originalNavigator;
navigator.__defineGetter__('userAgent', () => userAgent);
/* eslint-enable no-native-reassign, no-proto, no-underscore-dangle */
}

describe('VideoCover', () => {
it('should render a video tag', () => {
const wrapper = shallow(<VideoCover />);
const video = wrapper.find('video');
expect(video).toExist();
});

it('should not render Fallback component by default', () => {
const wrapper = shallow(<VideoCover />);
expect(wrapper.find(VideoCoverFallback)).not.toExist();
});

it('should set classname of <video/> according prop', () => {
const className = 'WhateverClassNameYouWant EvenMultipleClassNames';
const wrapper = shallow(<VideoCover className={className} />);
expect(wrapper).toHaveClassName('WhateverClassNameYouWant');
expect(wrapper).toHaveClassName('EvenMultipleClassNames');
});

it('should render Fallback component if forceFallback prop is set', () => {
const wrapper = shallow(<VideoCover forceFallback />);
expect(wrapper.find(VideoCoverFallback)).toExist();
});

describe('styles without fallback', () => {
it('should have width and height 100% by default', () => {
const wrapper = shallow(<VideoCover />);
expect(wrapper).toHaveStyle('height', '100%');
expect(wrapper).toHaveStyle('width', '100%');
});
it('should have any additional styles passed in via style-prop', () => {
const wrapper = shallow(<VideoCover />);
expect(wrapper).not.toHaveStyle('background-color');
expect(wrapper).not.toHaveStyle('color');
expect(wrapper).not.toHaveStyle('line-height');
const nextWrapper = wrapper.setProps({
style: {
backgroundColor: 'red',
color: 'teal',
lineHeight: 10,
},
});
expect(wrapper).toHaveStyle({
backgroundColor: 'red',
color: 'teal',
lineHeight: 10,
});
});
it('should be possible to override width and height props', () => {
const wrapper = shallow(<VideoCover style={{ width: '50%', height: '50%' }} />);
expect(wrapper).toHaveStyle('height', '50%');
expect(wrapper).toHaveStyle('width', '50%');
});
it('should have object-fit set to cover', () => {
const wrapper = shallow(<VideoCover />);
expect(wrapper).toHaveStyle('objectFit', 'cover');
});
it('should not be possible to override object-fit', () => {
const wrapper = shallow(<VideoCover style={{ objectFit: 'contain' }} />);
expect(wrapper).toHaveStyle('objectFit', 'cover');
});
});

// TODO: couldn't figure out how to mock the useragent with jest/jsdom
// re-enable these tests when fixed (see setUserAgent())
describe.skip('UserAgent', () => {
/* eslint-disable max-len */
const originalNavigator = window.navigator;
const userAgents = [
{
name: 'Trident',
needsFallback: true,
value: `Mozilla/5.0(compatible; MSIE 10.0;
WindowsNT 6.2; Win64; x64; Trident/6.0)`,
},
{
name: 'Edge',
needsFallback: true,
value: `Mozilla/5.0 (Windows NT 6.4; WOW64) AppleWebKit/537.36
(KHTML, like Gecko) Chrome/36.0.1985.143 Safari/537.36 Edge/12.0`,
},
{
name: 'Safari',
needsFallback: false,
value: `Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4)
AppleWebKit/601.5.17 (KHTML, like Gecko) Version/9.1 Safari/601.5.17`,
},
{
name: 'Chrome',
needsFallback: false,
value: `Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4)
AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.86 Safari/537.36`,
},
{
name: 'Firefox',
needsFallback: false,
value: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:44.0) Gecko/20100101 Firefox/44.0',
},
];

afterEach(() => {
// reset to original navigator after each test
window.navigator = originalNavigator;
});

/* generate tests for some known userAgents */
userAgents.forEach(({ needsFallback, name, value }) => {
it(`should ${
needsFallback ? '' : 'NOT'
} render Fallback if ${name} userAgent is used`, () => {
setUserAgent(value);
const wrapper = shallow(<VideoCover />);
if (needsFallback) {
expect(wrapper.find(VideoCoverFallback)).toExist();
} else {
expect(wrapper.find(VideoCoverFallback)).not.toExist();
}
});
});
});
});
206 changes: 206 additions & 0 deletions lib/__tests__/VideoCoverFallback.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
import VideoCoverFallback from '../VideoCoverFallback';

import React from 'react';
import { shallow, mount } from 'enzyme';

describe('VideoCoverFallback', () => {
it('should update container ratio when mounted', () => {
const spy = jest.fn();
class WithSpy extends VideoCoverFallback {
updateContainerRatio = spy;
}
mount(<WithSpy />);
expect(spy).toBeCalled();
});

it('should call onFallbackDidMount prop when mounted', () => {
const spy = jest.fn();
mount(<VideoCoverFallback onFallbackDidMount={spy} />);
expect(spy).toBeCalled();
});

it('should pass this.updateContainerRatio as parameter in onFallbackWillUnmount', () => {
let resizeNotifier;
const wrapper = mount(<VideoCoverFallback
onFallbackDidMount={result => {
resizeNotifier = result;
}}
/>);
expect(resizeNotifier).toEqual(wrapper.instance().updateContainerRatio);
});

it('should initialize window-resize eventlisteners if props.remeasureOnWindowResize is set', () => {
const spy = jest.fn();
class WithSpy extends VideoCoverFallback {
initEventListeners = spy;
}
mount(<WithSpy remeasureOnWindowResize />);
expect(spy).toBeCalled();
});

it('should NOT initialize window-resize eventlisteners if props.remeasureOnWindowResize is not set', () => {
const spy = jest.fn();
class WithSpy extends VideoCoverFallback {
initEventListeners = spy;
}
mount(<WithSpy />);
expect(spy).not.toBeCalled();
});

it('should remove eventlisteners before unmount', () => {
const spy = jest.fn();
class WithSpy extends VideoCoverFallback {
removeEventListeners = spy;
}
const wrapper = mount(<WithSpy />);
wrapper.unmount();
expect(spy).toBeCalled();
});

it('should add/remove eventlisteners if props.remeasureOnWindowResize changes', () => {
const addSpy = jest.fn();
const removeSpy = jest.fn();
class WithSpy extends VideoCoverFallback {
initEventListeners = addSpy;
removeEventListeners = removeSpy;
}
const wrapper = mount(<WithSpy />);
expect(addSpy).not.toBeCalled();
expect(removeSpy).not.toBeCalled();
wrapper.setProps({ remeasureOnWindowResize: true });
expect(addSpy).toBeCalled();
expect(removeSpy).not.toBeCalled();
wrapper.setProps({ remeasureOnWindowResize: false });
expect(addSpy).toBeCalled();
expect(removeSpy).toBeCalled();
});

it('should render a video tag inside a container-div', () => {
const wrapper = shallow(<VideoCoverFallback />);
expect(wrapper.find('div')).toExist();
expect(wrapper.find('div video')).toExist();
});

it('should pass props.className to the container-div', () => {
const wrapper = shallow(<VideoCoverFallback className="some-classname" />);
expect(wrapper).toHaveClassName('some-classname');
});

it('should invoke updateVideoRatio on loadedData media event', () => {
const spy = jest.fn();
class WithSpy extends VideoCoverFallback {
updateVideoRatio = spy;
}
const wrapper = shallow(<WithSpy />);
const video = wrapper.find('video');
video.simulate('loadedData', {
target: {
videoWidth: 50,
videoHeight: 50,
},
});
expect(spy).toBeCalledWith(50, 50);
});

it('should apply all props.videoOptions to the video tag', () => {
const wrapper = shallow(<VideoCoverFallback
videoOptions={{
src: 'http://some-video-url.mp4',
}}
/>);
expect(wrapper.find('video')).toHaveProp('src', 'http://some-video-url.mp4');
});

describe('container-styles', () => {
it('should apply props.style to the container-div', () => {
const wrapper = shallow(<VideoCoverFallback
style={{
backgroundColor: 'teal',
lineHeight: '100px',
}}
/>);
expect(wrapper).toHaveStyle('backgroundColor', 'teal');
expect(wrapper).toHaveStyle('lineHeight', '100px');
});

it('should set width and height to 100% by default', () => {
const wrapper = shallow(<VideoCoverFallback />);
expect(wrapper).toHaveStyle('height', '100%');
expect(wrapper).toHaveStyle('width', '100%');
});

it('should be possible to override width and height via props.style', () => {
const wrapper = shallow(<VideoCoverFallback style={{ width: '50%', height: '50%' }} />);
expect(wrapper).toHaveStyle('height', '50%');
expect(wrapper).toHaveStyle('width', '50%');
});

it('should set position relative and overflow: hidden', () => {
const wrapper = shallow(<VideoCoverFallback />);
expect(wrapper).toHaveStyle('position', 'relative');
expect(wrapper).toHaveStyle('overflow', 'hidden');
});

it('should not be possible to override position and overflow', () => {
const wrapper = shallow(<VideoCoverFallback
style={{
position: 'fixed',
overflow: 'scroll',
}}
/>);
expect(wrapper).toHaveStyle('position', 'relative');
expect(wrapper).toHaveStyle('overflow', 'hidden');
});
});

// todo: maybe use generated test-data for this?
describe('video-styles', () => {
it('should have width auto, height 100% if innerRatio > outerRatio', () => {
const wrapper = shallow(<VideoCoverFallback />);
wrapper.setState({
innerRatio: 5,
outerRatio: 3,
});
expect(wrapper.find('video')).toHaveStyle('width', 'auto');
expect(wrapper.find('video')).toHaveStyle('height', '100%');
});
it('should have width 100%, height auto if innerRatio <= outerRatio', () => {
const wrapper = shallow(<VideoCoverFallback />);
wrapper.setState({
innerRatio: 3,
outerRatio: 5,
});
expect(wrapper.find('video')).toHaveStyle('width', '100%');
expect(wrapper.find('video')).toHaveStyle('height', 'auto');
});
});

describe('updateContainerRatio()', () => {
it('should set state.outerRatio to ratio of container width/height', () => {
const mockRef = {
getBoundingClientRect: () => {
const result = {
width: 4,
height: 5,
};
return result;
},
};
class WithRef extends VideoCoverFallback {
containerRef = mockRef;
}
const wrapper = shallow(<WithRef />);
wrapper.instance().updateContainerRatio();
expect(wrapper).toHaveState('outerRatio', 4 / 5);
});
});

describe('updateVideoRatio()', () => {
it('should set state.innerRatio to ratio of video width/height', () => {
const wrapper = shallow(<VideoCoverFallback />);
expect(wrapper).toHaveState('innerRatio', undefined);
wrapper.instance().updateVideoRatio(4, 5);
expect(wrapper).toHaveState('innerRatio', 4 / 5);
});
});
});
Loading

0 comments on commit 2a29fa7

Please sign in to comment.