Upgrading tests, replacing Enzyme with TestRenderer
This commit is contained in:
28
.babelrc
28
.babelrc
@ -1,28 +0,0 @@
|
||||
{
|
||||
"presets": [
|
||||
"@babel/preset-env",
|
||||
"@babel/preset-react",
|
||||
"@babel/preset-typescript"
|
||||
],
|
||||
"plugins": [
|
||||
"@babel/plugin-proposal-class-properties"
|
||||
],
|
||||
"env": {
|
||||
"development": {
|
||||
"plugins": [
|
||||
"react-element-info"
|
||||
]
|
||||
},
|
||||
"test": {
|
||||
"plugins": [
|
||||
"react-element-info",
|
||||
"@babel/plugin-transform-runtime",
|
||||
["polyfill-corejs3", { "method": "usage-global" }]
|
||||
],
|
||||
"presets": [
|
||||
"@babel/preset-env",
|
||||
"@babel/preset-react"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import ShallowRenderer from 'react-test-renderer/shallow'
|
||||
import { render } from './test-wrapper';
|
||||
import App from '../src/js/App';
|
||||
|
||||
jest.mock('react-redux', () => ({
|
||||
@ -21,9 +21,7 @@ jest.mock('react-router-dom', () => ({
|
||||
|
||||
describe('<App />', () => {
|
||||
it('should render', () => {
|
||||
const renderer = new ShallowRenderer();
|
||||
renderer.render(<App />);
|
||||
const result = renderer.getRenderOutput();
|
||||
expect(result.type).toEqual('div');
|
||||
const result = render(<App />).toJSON();
|
||||
expect(result).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
@ -1,70 +1,68 @@
|
||||
import React from 'react';
|
||||
import { BrowserRouter } from "react-router-dom";
|
||||
|
||||
// Testing-specific
|
||||
import { shallow, mount, render } from 'enzyme';
|
||||
|
||||
// Test subjects
|
||||
import { render } from '../test-wrapper';
|
||||
import Dater from '../../src/js/components/Dater';
|
||||
|
||||
describe('<Dater />', () => {
|
||||
jest.mock('react-redux', () => ({
|
||||
useSelector: jest.fn(),
|
||||
}));
|
||||
|
||||
describe('<Dater />', () => {
|
||||
it('should render null when given invalid props', () => {
|
||||
|
||||
// Invalid type
|
||||
const dom_1 = shallow(<Dater type="invalid-type" data={100000} />);
|
||||
expect(dom_1.type()).toEqual(null);
|
||||
const dom_1 = render(<Dater type="invalid-type" data={100000} />);
|
||||
expect(dom_1.toJSON()).toEqual(null);
|
||||
|
||||
// Missing type
|
||||
const dom_2 = shallow(<Dater data={100000} />);
|
||||
expect(dom_2.type()).toEqual(null);
|
||||
const dom_2 = render(<Dater data={100000} />);
|
||||
expect(dom_2.toJSON()).toEqual(null);
|
||||
|
||||
// Missing data
|
||||
const dom_4 = shallow(<Dater type="ago" />);
|
||||
expect(dom_4.type()).toEqual(null);
|
||||
const dom_4 = render(<Dater type="ago" />);
|
||||
expect(dom_4.toJSON()).toEqual(null);
|
||||
});
|
||||
|
||||
it('should handle milliseconds', () => {
|
||||
const dom = shallow(<Dater type="length" data={30000} />);
|
||||
expect(dom.text()).toEqual('0:30');
|
||||
const dom = render(<Dater type="length" data={30000} />);
|
||||
expect(dom.toJSON()).toEqual('0:30');
|
||||
});
|
||||
|
||||
it('should handle date (yyyy-mm-dd)', () => {
|
||||
const dom = shallow(<Dater type="date" data="2015-10-23" />);
|
||||
expect(dom.text()).toEqual("23/10/2015");
|
||||
const dom = render(<Dater type="date" data="2015-10-23" />);
|
||||
expect(dom.toJSON()).toEqual("23/10/2015");
|
||||
});
|
||||
|
||||
it('should handle date (mm/dd/yyyy)', () => {
|
||||
const dom = shallow(<Dater type="date" data="10/23/2015" />);
|
||||
expect(dom.text()).toEqual("23/10/2015");
|
||||
const dom = render(<Dater type="date" data="10/23/2015" />);
|
||||
expect(dom.toJSON()).toEqual("23/10/2015");
|
||||
});
|
||||
|
||||
it('should handle ago (days)', () => {
|
||||
var date = new Date();
|
||||
date.setDate( date.getDate() - 3 );
|
||||
|
||||
const dom = shallow(<Dater type="ago" data={date} />);
|
||||
expect(dom.text()).toEqual('3 days');
|
||||
const dom = render(<Dater type="ago" data={date} />);
|
||||
expect(dom.toJSON().join('')).toEqual('3 days');
|
||||
});
|
||||
|
||||
it('should handle ago (hours)', () => {
|
||||
var date = new Date();
|
||||
date.setTime( date.getTime() - 3 * 3600000 );
|
||||
|
||||
const dom = shallow(<Dater type="ago" data={date} />);
|
||||
expect(dom.text()).toEqual('3 hours');
|
||||
const dom = render(<Dater type="ago" data={date} />);
|
||||
expect(dom.toJSON().join('')).toEqual('3 hours');
|
||||
});
|
||||
|
||||
it('should handle ago (minutes)', () => {
|
||||
var date = new Date();
|
||||
date.setTime( date.getTime() - 3 * 60000 );
|
||||
|
||||
const dom = shallow(<Dater type="ago" data={date} />);
|
||||
expect(dom.text()).toEqual('3 minutes');
|
||||
const dom = render(<Dater type="ago" data={date} />);
|
||||
expect(dom.toJSON().join('')).toEqual('3 minutes');
|
||||
});
|
||||
|
||||
it('should handle total time', () => {
|
||||
var data = [
|
||||
const data = [
|
||||
{
|
||||
duration: 5 * 60000
|
||||
},
|
||||
@ -75,7 +73,7 @@ describe('<Dater />', () => {
|
||||
duration: 5 * 60000
|
||||
}
|
||||
];
|
||||
const dom = shallow(<Dater type="total-time" data={data} />);
|
||||
expect(dom.text()).toEqual('15 mins');
|
||||
const dom = render(<Dater type="total-time" data={data} />);
|
||||
expect(dom.toJSON().join('')).toEqual('15 mins');
|
||||
});
|
||||
});
|
||||
@ -1,15 +1,11 @@
|
||||
import React from 'react';
|
||||
import { BrowserRouter } from 'react-router-dom';
|
||||
import TestRenderer from 'react-test-renderer';
|
||||
import { DndProvider } from 'react-dnd';
|
||||
import { HTML5Backend } from 'react-dnd-html5-backend';
|
||||
import { GridItem } from '../../src/js/components/GridItem';
|
||||
import { render } from '../test-wrapper';
|
||||
import state from '../state';
|
||||
|
||||
jest.mock('react-redux', () => ({
|
||||
useSelector: jest.fn(),
|
||||
useDispatch: () => jest.fn(),
|
||||
useDrag: jest.fn(),
|
||||
useDispatch: jest.fn(),
|
||||
}));
|
||||
jest.mock('react-router-dom', () => ({
|
||||
...jest.requireActual('react-router-dom'),
|
||||
@ -27,32 +23,22 @@ describe('<GridItem />', () => {
|
||||
const { core: { items } } = state;
|
||||
|
||||
it('should handle album', () => {
|
||||
const result = TestRenderer.create(
|
||||
<BrowserRouter>
|
||||
<DndProvider backend={HTML5Backend}>
|
||||
const result = render(
|
||||
<GridItem item={items['local:album:md5:66fbea3593ba96a15a9d4188bebab50b']} />
|
||||
</DndProvider>
|
||||
</BrowserRouter>
|
||||
).toJSON();
|
||||
expect(result).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should handle artist', () => {
|
||||
const result = TestRenderer.create(
|
||||
<BrowserRouter>
|
||||
<DndProvider backend={HTML5Backend}>
|
||||
const result = render(
|
||||
<GridItem item={items['local:artist:md5:4f6e4f979e2c40c5e6ad1735804c29bc']} />
|
||||
</DndProvider>
|
||||
</BrowserRouter>
|
||||
).toJSON();
|
||||
expect(result).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should handle playlist', () => {
|
||||
const result = TestRenderer.create(
|
||||
<BrowserRouter>
|
||||
<DndProvider backend={HTML5Backend}>
|
||||
const result = render(
|
||||
<GridItem item={items['m3u:Local%20tester.m3u8']} />
|
||||
</DndProvider>
|
||||
</BrowserRouter>
|
||||
).toJSON();
|
||||
expect(result).toMatchSnapshot();
|
||||
});
|
||||
|
||||
@ -1,28 +1,17 @@
|
||||
import React from 'react';
|
||||
import { BrowserRouter } from "react-router-dom";
|
||||
|
||||
// Testing-specific
|
||||
import { shallow, mount, render } from 'enzyme';
|
||||
|
||||
// Test subjects
|
||||
import { render } from '../test-wrapper';
|
||||
import Link from '../../src/js/components/Link';
|
||||
|
||||
describe('<Link />', () => {
|
||||
|
||||
const dom = mount(
|
||||
<BrowserRouter>
|
||||
const result = render(
|
||||
<Link to="test" className="test-classname">Link contents</Link>
|
||||
</BrowserRouter>
|
||||
);
|
||||
).toJSON();
|
||||
|
||||
it('should render a valid <a> tag', () => {
|
||||
const a = dom.find('a');
|
||||
expect(a.length).toBe(1);
|
||||
expect(a.find('[href]').length).toBe(1);
|
||||
expect(a.text()).toEqual('Link contents');
|
||||
});
|
||||
|
||||
it('should handle className prop', () => {
|
||||
expect(dom.find('a').hasClass('test-classname')).toBe(true);
|
||||
expect(result.type).toEqual('a');
|
||||
expect(result.props.href).toEqual('/test');
|
||||
expect(result.children.join('')).toEqual('Link contents');
|
||||
expect(result.props.className).toContain('test-classname');
|
||||
});
|
||||
});
|
||||
@ -10,7 +10,7 @@ exports[`<GridItem /> should handle album 1`] = `
|
||||
className=" "
|
||||
data-qa-file="Link"
|
||||
data-qa-node="RouterLink"
|
||||
href="/album/bG9jYWw6YWxidW06bWQ1OjY2ZmJlYTM1OTNiYTk2YTE1YTlkNDE4OGJlYmFiNTBi/Sirens of the Sea"
|
||||
href="/album/bG9jYWw6YWxidW06bWQ1OjY2ZmJlYTM1OTNiYTk2YTE1YTlkNDE4OGJlYmFiNTBi/Sirens%20of%20the%20Sea"
|
||||
onClick={[Function]}
|
||||
onContextMenu={[Function]}
|
||||
>
|
||||
@ -31,8 +31,8 @@ exports[`<GridItem /> should handle album 1`] = `
|
||||
data-qa-file="Thumbnail"
|
||||
data-qa-node="div"
|
||||
style={
|
||||
Object {
|
||||
"backgroundImage": "url(\\"/local/17338e740316f18dbb5e3331ac6be6c1-500x500.jpeg\\")",
|
||||
{
|
||||
"backgroundImage": "url("/local/17338e740316f18dbb5e3331ac6be6c1-500x500.jpeg")",
|
||||
}
|
||||
}
|
||||
/>
|
||||
@ -46,8 +46,14 @@ exports[`<GridItem /> should handle album 1`] = `
|
||||
className="grid__item__name"
|
||||
data-qa-file="GridItem"
|
||||
data-qa-node="div"
|
||||
>
|
||||
<span
|
||||
data-qa-file="GridItem"
|
||||
data-qa-node="span"
|
||||
title="Sirens of the Sea"
|
||||
>
|
||||
Sirens of the Sea
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
className="grid__item__secondary"
|
||||
@ -125,8 +131,8 @@ exports[`<GridItem /> should handle artist 1`] = `
|
||||
data-qa-file="Thumbnail"
|
||||
data-qa-node="div"
|
||||
style={
|
||||
Object {
|
||||
"backgroundImage": "url(\\"https://i.scdn.co/image/4dc7080ef509c36203a131a0eab8dd5e4800d7c2\\")",
|
||||
{
|
||||
"backgroundImage": "url("https://i.scdn.co/image/4dc7080ef509c36203a131a0eab8dd5e4800d7c2")",
|
||||
}
|
||||
}
|
||||
/>
|
||||
@ -140,8 +146,14 @@ exports[`<GridItem /> should handle artist 1`] = `
|
||||
className="grid__item__name"
|
||||
data-qa-file="GridItem"
|
||||
data-qa-node="div"
|
||||
>
|
||||
<span
|
||||
data-qa-file="GridItem"
|
||||
data-qa-node="span"
|
||||
title="Above & Beyond"
|
||||
>
|
||||
Above & Beyond
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
className="grid__item__secondary"
|
||||
@ -182,7 +194,7 @@ exports[`<GridItem /> should handle playlist 1`] = `
|
||||
className=" "
|
||||
data-qa-file="Link"
|
||||
data-qa-node="RouterLink"
|
||||
href="/playlist/bTN1OkxvY2FsJTIwdGVzdGVyLm0zdTg=/Local tester"
|
||||
href="/playlist/bTN1OkxvY2FsJTIwdGVzdGVyLm0zdTg=/Local%20tester"
|
||||
onClick={[Function]}
|
||||
onContextMenu={[Function]}
|
||||
>
|
||||
@ -203,8 +215,8 @@ exports[`<GridItem /> should handle playlist 1`] = `
|
||||
data-qa-file="Thumbnail"
|
||||
data-qa-node="div"
|
||||
style={
|
||||
Object {
|
||||
"backgroundImage": "url(\\"null\\")",
|
||||
{
|
||||
"backgroundImage": "url("null")",
|
||||
}
|
||||
}
|
||||
/>
|
||||
@ -218,8 +230,14 @@ exports[`<GridItem /> should handle playlist 1`] = `
|
||||
className="grid__item__name"
|
||||
data-qa-file="GridItem"
|
||||
data-qa-node="div"
|
||||
>
|
||||
<span
|
||||
data-qa-file="GridItem"
|
||||
data-qa-node="span"
|
||||
title="Local tester"
|
||||
>
|
||||
Local tester
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
className="grid__item__secondary"
|
||||
|
||||
13
__tests__/jest-yaml-transformer.js
Normal file
13
__tests__/jest-yaml-transformer.js
Normal file
@ -0,0 +1,13 @@
|
||||
const transformer = require("jest-transform-yaml").default
|
||||
|
||||
const newTransformer = {
|
||||
...transformer,
|
||||
process: function (...params) {
|
||||
return {
|
||||
code: transformer?.process(...params),
|
||||
map: null,
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
module.exports = newTransformer;
|
||||
@ -1,4 +0,0 @@
|
||||
import Enzyme from 'enzyme';
|
||||
import Adapter from 'enzyme-adapter-react-16';
|
||||
|
||||
Enzyme.configure({ adapter: new Adapter() });
|
||||
@ -260,3 +260,4 @@ state.core.items['jest:track:three'] = {
|
||||
};
|
||||
|
||||
export default state;
|
||||
export { state }
|
||||
|
||||
35
__tests__/test-wrapper.js
Normal file
35
__tests__/test-wrapper.js
Normal file
@ -0,0 +1,35 @@
|
||||
import React from 'react';
|
||||
import TestRenderer from 'react-test-renderer';
|
||||
import { Provider as ReduxProvider } from 'react-redux/src';
|
||||
import { BrowserRouter, Route, Routes } from 'react-router-dom';
|
||||
import { DndProvider } from 'react-dnd';
|
||||
import { HTML5Backend } from 'react-dnd-html5-backend';
|
||||
import { store } from '../src/js/store';
|
||||
|
||||
const customRender = (
|
||||
element,
|
||||
{
|
||||
initialState,
|
||||
mocks,
|
||||
...options
|
||||
} = {},
|
||||
) => {
|
||||
return TestRenderer.create(
|
||||
(
|
||||
<ReduxProvider store={store}>
|
||||
<DndProvider backend={HTML5Backend}>
|
||||
<BrowserRouter basename="/">
|
||||
<Routes>
|
||||
<Route path="*" element={element} />
|
||||
</Routes>
|
||||
</BrowserRouter>
|
||||
</DndProvider>
|
||||
</ReduxProvider>
|
||||
),
|
||||
{
|
||||
...options,
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
export { customRender as render };
|
||||
@ -1,15 +1,21 @@
|
||||
import React from 'react';
|
||||
import TestRenderer from 'react-test-renderer';
|
||||
|
||||
import { Album } from '../../src/js/views/Album';
|
||||
import * as uiActions from '../../src/js/services/ui/actions';
|
||||
import * as coreActions from '../../src/js/services/core/actions';
|
||||
import state from '../state';
|
||||
import { render } from '../test-wrapper';
|
||||
import Album from '../../src/js/views/Album';
|
||||
import { state as mockState } from '../state';
|
||||
|
||||
jest.mock('react-dnd', () => ({
|
||||
...jest.requireActual('react-dnd'),
|
||||
useDrag: jest.fn(),
|
||||
useDrop: jest.fn(),
|
||||
}));
|
||||
jest.mock('redux-persist', () => ({
|
||||
...jest.requireActual('redux-persist'),
|
||||
persistReducer: jest.fn().mockImplementation((config, reducers) => reducers),
|
||||
}));
|
||||
jest.mock('react-redux', () => ({
|
||||
useSelector: jest.fn(),
|
||||
useDispatch: () => jest.fn(),
|
||||
connect: () => jest.fn(),
|
||||
useSelector: jest.fn(() => mockState),
|
||||
useDispatch: jest.fn(fn => fn()),
|
||||
connect: jest.fn(fn => fn()),
|
||||
}));
|
||||
jest.mock('react-router-dom', () => ({
|
||||
...jest.requireActual('react-router-dom'),
|
||||
@ -28,14 +34,8 @@ describe('<Album />', () => {
|
||||
|
||||
// Need to rebuild Album to functional component, at which point I'll copy previous
|
||||
// snapshot testing approach from other project
|
||||
it.skip('should render accurately', () => {
|
||||
const result = TestRenderer.create(
|
||||
<Album
|
||||
album={album}
|
||||
uiActions={uiActions}
|
||||
coreActions={coreActions}
|
||||
/>
|
||||
).toJSON();
|
||||
it('should render accurately', () => {
|
||||
const result = render(<Album album={album} />).toJSON();
|
||||
expect(result).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
@ -1,36 +1,43 @@
|
||||
module.exports = {
|
||||
verbose: true,
|
||||
collectCoverage: true,
|
||||
testEnvironment: 'jsdom',
|
||||
testMatch: [
|
||||
"<rootDir>/__tests__/**/*.test.js?(x)",
|
||||
],
|
||||
moduleDirectories: [
|
||||
"node_modules",
|
||||
"src",
|
||||
],
|
||||
moduleFileExtensions: [
|
||||
"js",
|
||||
"jsx",
|
||||
"yaml",
|
||||
],
|
||||
// moduleDirectories: [
|
||||
// "node_modules",
|
||||
// "src",
|
||||
// ],
|
||||
// moduleFileExtensions: [
|
||||
// "js",
|
||||
// "jsx",
|
||||
// "yaml",
|
||||
// ],
|
||||
moduleNameMapper: {
|
||||
/*"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga|yml|yaml)$": "<rootDir>/__mocks__/fileMock.js",*/
|
||||
"^.+\\.(css|scss|sass|less)$": "identity-obj-proxy",
|
||||
},
|
||||
transform: {
|
||||
"\\.yaml$": "yaml-jest",
|
||||
"^.+\\.jsx$": "babel-jest",
|
||||
"^.+\\.js$": "babel-jest",
|
||||
"^.+\\.ts$": "babel-jest",
|
||||
"^.+\\.tsx$": "babel-jest",
|
||||
"^.+\\.(j|t)sx?$": "babel-jest",
|
||||
"^.+\\.ya?ml$": "<rootDir>/__tests__/jest-yaml-transformer.js",
|
||||
},
|
||||
transformIgnorePatterns: [
|
||||
"node_modules/(?!react-dnd|core-dnd|@react-dnd|dnd-core|react-dnd-html5-backend|react-redux)"
|
||||
],
|
||||
coverageReporters: [
|
||||
"lcov",
|
||||
],
|
||||
collectCoverageFrom: [
|
||||
"src/**/*.{js,jsx,ts,tsx}",
|
||||
],
|
||||
setupFilesAfterEnv: [
|
||||
"./__tests__/setup.js"
|
||||
],
|
||||
globals: {
|
||||
window: {
|
||||
location: {
|
||||
hostname: 'localhost',
|
||||
port: 6680,
|
||||
protocol: 'http',
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
13
package.json
13
package.json
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "mopidy-iris",
|
||||
"version": "3.64.1",
|
||||
"version": "3.65.0",
|
||||
"description": "Mopidy HTTP interface",
|
||||
"repository": "https://github.com/jaedb/iris",
|
||||
"author": "James Barnsley <james@barnsley.nz>",
|
||||
@ -41,8 +41,8 @@
|
||||
"devDependencies": {
|
||||
"@babel/cli": "7.18.6",
|
||||
"@babel/core": "7.18.6",
|
||||
"@babel/eslint-parser": "7.18.2",
|
||||
"@babel/plugin-proposal-class-properties": "7.18.6",
|
||||
"@babel/plugin-transform-modules-commonjs": "7.18.6",
|
||||
"@babel/plugin-transform-runtime": "7.18.6",
|
||||
"@babel/polyfill": "^7.12.1",
|
||||
"@babel/preset-env": "7.18.6",
|
||||
@ -50,7 +50,6 @@
|
||||
"@babel/preset-stage-2": "7.8.3",
|
||||
"@babel/preset-typescript": "7.18.6",
|
||||
"@babel/register": "7.18.6",
|
||||
"@babel/eslint-parser": "7.18.2",
|
||||
"babel-jest": "28.1.2",
|
||||
"babel-loader": "8.2.5",
|
||||
"babel-plugin-add-module-exports": "^1.0.4",
|
||||
@ -62,8 +61,6 @@
|
||||
"copy-dir": "^1.3.0",
|
||||
"core-js": "3.23.3",
|
||||
"css-loader": "6.7.1",
|
||||
"enzyme": "^3.11.0",
|
||||
"enzyme-adapter-react-16": "^1.15.5",
|
||||
"eslint": "8.19.0",
|
||||
"eslint-config-airbnb": "19.0.4",
|
||||
"eslint-plugin-import": "2.26.0",
|
||||
@ -71,9 +68,12 @@
|
||||
"eslint-plugin-react": "7.30.1",
|
||||
"eslint-webpack-plugin": "3.2.0",
|
||||
"expose-loader": "4.0.0",
|
||||
"fake-indexeddb": "^4.0.0",
|
||||
"file-loader": "6.2.0",
|
||||
"fs-copy-file": "2.1.2",
|
||||
"jest": "28.1.2",
|
||||
"jest": "29.0.3",
|
||||
"jest-environment-jsdom": "^29.1.1",
|
||||
"jest-transform-yaml": "1.0.0",
|
||||
"js-sha256": "^0.9.0",
|
||||
"mini-css-extract-plugin": "2.6.1",
|
||||
"parse5-htmlparser2-tree-adapter": "7.0.0",
|
||||
@ -89,7 +89,6 @@
|
||||
"webpack-cli": "4.10.0",
|
||||
"webpack-dev-server": "4.9.3",
|
||||
"webpack-strip": "0.1.0",
|
||||
"yaml-jest": "1.2.0",
|
||||
"yaml-loader": "0.6.0"
|
||||
},
|
||||
"scripts": {
|
||||
|
||||
Reference in New Issue
Block a user