Commit dd8c4054 authored by Jeff Avallone's avatar Jeff Avallone

Merge branch 'feature/gatsby-no-enzyme' into 'gatsby'

Replacing Enzyme with react-testing-library

See merge request !42
parents 2f7c67c9 ead8927b
Pipeline #53393167 passed with stages
in 5 minutes and 3 seconds
import Enzyme from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
Enzyme.configure({ adapter: new Adapter() });
global.___loader = {
enqueue: jest.fn()
};
......
......@@ -56,11 +56,9 @@
"node_modules"
],
"setupFilesAfterEnv": [
"react-testing-library/cleanup-after-each",
"<rootDir>/jest/setup.js"
],
"snapshotSerializers": [
"enzyme-to-json/serializer"
],
"testPathIgnorePatterns": [
"node_modules",
".cache"
......@@ -85,9 +83,6 @@
"babel-jest": "^24.5.0",
"babel-plugin-dynamic-import-node": "^2.2.0",
"babel-preset-gatsby": "^0.1.6",
"enzyme": "^3.8.0",
"enzyme-adapter-react-16": "^1.7.1",
"enzyme-to-json": "^3.3.5",
"eslint": "^5.11.1",
"eslint-plugin-jest": "^22.1.2",
"eslint-plugin-react": "^7.12.1",
......@@ -114,6 +109,7 @@
"react-feather": "^1.1.5",
"react-helmet": "^5.2.0",
"react-i18next": "^10.5.3",
"react-modal": "^3.8.1"
"react-modal": "^3.8.1",
"react-testing-library": "^6.0.2"
}
}
const React = require('react');
const buildMock = component => {
const componentName = component.displayName || component.name || 'Component';
const Mock = ({ children, ...props }) => (
<span
data-component={ componentName }
data-props={ JSON.stringify(props, null, ' ') }>{ children }</span>
);
Mock.propTypes = component.propTypes;
return Mock;
};
module.exports = path => {
const actual = jest.requireActual(path);
return buildMock(actual.default || actual);
};
module.exports.buildMock = buildMock;
const reactI18next = jest.requireActual('react-i18next');
module.exports = {
...reactI18next,
Trans: require('__mocks__/component-mock').buildMock(reactI18next.Trans)
};
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`App removing rendered expression 1`] = `
<Fragment>
<withI18nextTranslation(Form)
expr="test expression"
onSubmit={[Function]}
syntax="js"
syntaxList={
Array [
Object {
"id": "testJS",
"label": "Testing JS",
},
Object {
"id": "other",
"label": "Other",
},
]
<DocumentFragment>
<span
data-component="withI18nextTranslation(Form)"
data-props="{
\\"syntax\\": \\"js\\",
\\"expr\\": \\"test expression\\",
\\"syntaxList\\": [
{
\\"id\\": \\"testJS\\",
\\"label\\": \\"Testing JS\\"
},
{
\\"id\\": \\"other\\",
\\"label\\": \\"Other\\"
}
]
}"
>
<withI18nextTranslation(FormActions) />
</withI18nextTranslation(Form)>
<Render
data="LAYOUT(PARSED(test expression))"
onRender={[Function]}
<span
data-component="withI18nextTranslation(FormActions)"
data-props="{}"
/>
</span>
<span
data-component="Render"
data-props="{
\\"data\\": \\"LAYOUT(PARSED(test expression))\\"
}"
/>
</Fragment>
</DocumentFragment>
`;
exports[`App removing rendered expression 2`] = `
<Fragment>
<withI18nextTranslation(Form)
expr=""
onSubmit={[Function]}
syntax="js"
syntaxList={
Array [
Object {
"id": "testJS",
"label": "Testing JS",
},
Object {
"id": "other",
"label": "Other",
},
]
<DocumentFragment>
<span
data-component="withI18nextTranslation(Form)"
data-props="{
\\"syntax\\": \\"js\\",
\\"expr\\": \\"\\",
\\"syntaxList\\": [
{
\\"id\\": \\"testJS\\",
\\"label\\": \\"Testing JS\\"
},
{
\\"id\\": \\"other\\",
\\"label\\": \\"Other\\"
}
]
}"
/>
</Fragment>
</DocumentFragment>
`;
exports[`App rendering 1`] = `
<Fragment>
<withI18nextTranslation(Form)
expr=""
onSubmit={[Function]}
syntax="js"
syntaxList={
Array [
Object {
"id": "testJS",
"label": "Testing JS",
},
Object {
"id": "other",
"label": "Other",
},
]
<DocumentFragment>
<span
data-component="withI18nextTranslation(Form)"
data-props="{
\\"syntax\\": \\"js\\",
\\"expr\\": \\"\\",
\\"syntaxList\\": [
{
\\"id\\": \\"testJS\\",
\\"label\\": \\"Testing JS\\"
},
{
\\"id\\": \\"other\\",
\\"label\\": \\"Other\\"
}
]
}"
/>
</Fragment>
</DocumentFragment>
`;
exports[`App rendering an expression 1`] = `
<Fragment>
<withI18nextTranslation(Form)
expr=""
onSubmit={[Function]}
syntax="js"
syntaxList={
Array [
Object {
"id": "testJS",
"label": "Testing JS",
},
Object {
"id": "other",
"label": "Other",
},
]
<DocumentFragment>
<span
data-component="withI18nextTranslation(Form)"
data-props="{
\\"syntax\\": \\"js\\",
\\"expr\\": \\"\\",
\\"syntaxList\\": [
{
\\"id\\": \\"testJS\\",
\\"label\\": \\"Testing JS\\"
},
{
\\"id\\": \\"other\\",
\\"label\\": \\"Other\\"
}
]
}"
/>
</Fragment>
</DocumentFragment>
`;
exports[`App rendering an expression 2`] = `
<Fragment>
<withI18nextTranslation(Form)
expr="test expression"
onSubmit={[Function]}
syntax="js"
syntaxList={
Array [
Object {
"id": "testJS",
"label": "Testing JS",
},
Object {
"id": "other",
"label": "Other",
},
]
<DocumentFragment>
<span
data-component="withI18nextTranslation(Form)"
data-props="{
\\"syntax\\": \\"js\\",
\\"expr\\": \\"test expression\\",
\\"syntaxList\\": [
{
\\"id\\": \\"testJS\\",
\\"label\\": \\"Testing JS\\"
},
{
\\"id\\": \\"other\\",
\\"label\\": \\"Other\\"
}
]
}"
/>
<withI18nextTranslation(Loader) />
</Fragment>
`;
exports[`App rendering an expression 3`] = `
<Fragment>
<withI18nextTranslation(Form)
expr="test expression"
onSubmit={[Function]}
syntax="js"
syntaxList={
Array [
Object {
"id": "testJS",
"label": "Testing JS",
},
Object {
"id": "other",
"label": "Other",
},
]
}
>
<withI18nextTranslation(FormActions) />
</withI18nextTranslation(Form)>
<Render
data="LAYOUT(PARSED(test expression))"
onRender={[Function]}
<span
data-component="withI18nextTranslation(Loader)"
data-props="{}"
/>
</Fragment>
</DocumentFragment>
`;
exports[`App rendering image details 1`] = `
<Fragment>
<withI18nextTranslation(Form)
expr="test expression"
onSubmit={[Function]}
syntax="js"
syntaxList={
Array [
Object {
"id": "testJS",
"label": "Testing JS",
},
Object {
"id": "other",
"label": "Other",
},
]
}
>
<withI18nextTranslation(FormActions) />
</withI18nextTranslation(Form)>
<Render
data="LAYOUT(PARSED(test expression))"
onRender={[Function]}
/>
</Fragment>
`;
exports[`App rendering image details 2`] = `
<Fragment>
<withI18nextTranslation(Form)
expr="test expression"
onSubmit={[Function]}
syntax="js"
syntaxList={
Array [
Object {
"id": "testJS",
"label": "Testing JS",
},
Object {
"id": "other",
"label": "Other",
},
]
exports[`App rendering an expression 3`] = `
<DocumentFragment>
<span
data-component="withI18nextTranslation(Form)"
data-props="{
\\"syntax\\": \\"js\\",
\\"expr\\": \\"test expression\\",
\\"syntaxList\\": [
{
\\"id\\": \\"testJS\\",
\\"label\\": \\"Testing JS\\"
},
{
\\"id\\": \\"other\\",
\\"label\\": \\"Other\\"
}
]
}"
>
<withI18nextTranslation(FormActions)
imageDetails={
Object {
"svg": "test svg content",
}
}
<span
data-component="withI18nextTranslation(FormActions)"
data-props="{}"
/>
</withI18nextTranslation(Form)>
<Render
data="LAYOUT(PARSED(test expression))"
onRender={[Function]}
</span>
<span
data-component="Render"
data-props="{
\\"data\\": \\"LAYOUT(PARSED(test expression))\\"
}"
/>
</Fragment>
</DocumentFragment>
`;
exports[`App rendering with an invalid syntax 1`] = `
<Fragment>
<withI18nextTranslation(Form)
expr=""
onSubmit={[Function]}
syntax="invalid"
syntaxList={
Array [
Object {
"id": "testJS",
"label": "Testing JS",
},
Object {
"id": "other",
"label": "Other",
},
]
<DocumentFragment>
<span
data-component="withI18nextTranslation(Form)"
data-props="{
\\"syntax\\": \\"invalid\\",
\\"expr\\": \\"\\",
\\"syntaxList\\": [
{
\\"id\\": \\"testJS\\",
\\"label\\": \\"Testing JS\\"
},
{
\\"id\\": \\"other\\",
\\"label\\": \\"Other\\"
}
]
}"
/>
</Fragment>
</DocumentFragment>
`;
exports[`App rendering with an invalid syntax 2`] = `
<Fragment>
<withI18nextTranslation(Form)
expr="test expression"
onSubmit={[Function]}
syntax="invalid"
syntaxList={
Array [
Object {
"id": "testJS",
"label": "Testing JS",
},
Object {
"id": "other",
"label": "Other",
},
]
<DocumentFragment>
<span
data-component="withI18nextTranslation(Form)"
data-props="{
\\"syntax\\": \\"invalid\\",
\\"expr\\": \\"test expression\\",
\\"syntaxList\\": [
{
\\"id\\": \\"testJS\\",
\\"label\\": \\"Testing JS\\"
},
{
\\"id\\": \\"other\\",
\\"label\\": \\"Other\\"
}
]
}"
/>
<span
data-component="withI18nextTranslation(Loader)"
data-props="{}"
/>
<withI18nextTranslation(Loader) />
</Fragment>
</DocumentFragment>
`;
exports[`App rendering with an invalid syntax 3`] = `
<Fragment>
<withI18nextTranslation(Form)
expr="test expression"
onSubmit={[Function]}
syntax="invalid"
syntaxList={
Array [
Object {
"id": "testJS",
"label": "Testing JS",
},
Object {
"id": "other",
"label": "Other",
},
]
<DocumentFragment>
<span
data-component="withI18nextTranslation(Form)"
data-props="{
\\"syntax\\": \\"invalid\\",
\\"expr\\": \\"test expression\\",
\\"syntaxList\\": [
{
\\"id\\": \\"testJS\\",
\\"label\\": \\"Testing JS\\"
},
{
\\"id\\": \\"other\\",
\\"label\\": \\"Other\\"
}
]
}"
/>
<Message
heading="TRANSLATE(Render Failure)"
type="error"
<span
data-component="Message"
data-props="{
\\"type\\": \\"error\\",
\\"heading\\": \\"TRANSLATE(Render Failure)\\"
}"
>
<p>
<Trans>
<span
data-component="Trans"
data-props="{}"
>
An error occurred while rendering the regular expression.
</Trans>
</span>
</p>
<a
href="#retry"
onClick={[Function]}
>
<Trans>
<span
data-component="Trans"
data-props="{}"
>
Retry
</Trans>
</span>
</a>
</Message>
</Fragment>
</span>
</DocumentFragment>
`;
jest.mock('components/Form', () =>
require('__mocks__/component-mock')('components/Form'));
jest.mock('components/FormActions', () =>
require('__mocks__/component-mock')('components/FormActions'));
jest.mock('components/Loader', () =>
require('__mocks__/component-mock')('components/Loader'));
jest.mock('components/Message', () =>
require('__mocks__/component-mock')('components/Message'));
import React from 'react';
import { shallow } from 'enzyme';
import { render } from 'react-testing-library';
import { mockT } from 'i18n';
import { App } from 'components/App';
......@@ -7,7 +16,7 @@ import { App } from 'components/App';
jest.mock('syntax/js', () => ({
parse: expr => `PARSED(${ expr })`,
layout: parsed => `LAYOUT(${ parsed })`,
Render: () => ''
Render: require('__mocks__/component-mock').buildMock(function Render() {})
}));
const syntaxList = [
......@@ -18,115 +27,64 @@ const commonProps = { syntaxList, t: mockT };
describe('App', () => {
test('rendering', () => {
const component = shallow(
const { asFragment } = render(
<App expr="" syntax="js" { ...commonProps } />
);
expect(component).toMatchSnapshot();
expect(asFragment()).toMatchSnapshot();
});
test('rendering an expression', async () => {
const component = shallow(
const { asFragment, rerender } = render(
<App expr="" syntax="js" { ...commonProps } />
);
expect(component).toMatchSnapshot();
expect(asFragment()).toMatchSnapshot();
component.setProps({
expr: 'test expression'
});
rerender(
<App expr="test expression" syntax="js" { ...commonProps } />
);
expect(component).toMatchSnapshot();
expect(asFragment()).toMatchSnapshot();
// Give a beat for module to load
await new Promise(resolve => setTimeout(resolve));
expect(component).toMatchSnapshot();
expect(asFragment()).toMatchSnapshot();
});
test('rendering with an invalid syntax', async () => {
jest.spyOn(console, 'error').mockImplementation(() => {});
const component = shallow(
const { asFragment, rerender } = render(
<App expr="" syntax="invalid" { ...commonProps } />
);
expect(component).toMatchSnapshot();
expect(asFragment()).toMatchSnapshot();
component.setProps({
expr: 'test expression'
});
rerender(
<App expr="test expression" syntax="invalid" { ...commonProps } />
);
expect(component).toMatchSnapshot();
expect(asFragment()).toMatchSnapshot();
// Give a beat for module to load
await new Promise(resolve => setTimeout(resolve));
expect(component).toMatchSnapshot();
expect(asFragment()).toMatchSnapshot();
});
test('removing rendered expression', async () => {
const component = shallow(
<App expr="test expression" syntax="js" { ...commonProps } />
);
// Give a beat for module to load
await new Promise(resolve => setTimeout(resolve));
expect(component).toMatchSnapshot();
component.setProps({
expr: ''
});
expect(component).toMatchSnapshot();
});
test('rendering image details', async () => {
const component = shallow(
const { asFragment, rerender } = render(
<App expr="test expression" syntax="js" { ...commonProps } />
);
// Give a beat for module to load
await new Promise(resolve => setTimeout(resolve));
expect(component).toMatchSnapshot();
component.instance().handleSvg({
svg: 'test svg content'
});
expect(asFragment()).toMatchSnapshot();
expect(component).toMatchSnapshot();
});
test('retrying expression rendering', () => {
jest.spyOn(console, 'error').mockImplementation(() => {});
const component = shallow(
<App expr="test expression" syntax="invalid" { ...commonProps } />
);
const instance = component.instance();
const event = { preventDefault: jest.fn() };
jest.spyOn(instance, 'handleRender');
instance.handleRetry(event);
expect(event.preventDefault).toHaveBeenCalled();
expect(instance.handleRender).toHaveBeenCalled();
});
test('submitting an expression to render', () => {
const component = shallow(
rerender(
<App expr="" syntax="js" { ...commonProps } />
);
const instance = component.instance();
instance.handleSubmit({ syntax: 'test', expr: '' });
expect(document.location.hash).toEqual('');
instance.handleSubmit({ syntax: 'test', expr: 'test expression' });
expect(document.location.hash).toEqual('#syntax=test&expr=test+expression');
expect(asFragment()).toMatchSnapshot();
});
});