diff --git a/jest/setup.js b/jest/setup.js index 6c6f32f..46b6c2d 100644 --- a/jest/setup.js +++ b/jest/setup.js @@ -1,8 +1,3 @@ -import Enzyme from 'enzyme'; -import Adapter from 'enzyme-adapter-react-16'; - -Enzyme.configure({ adapter: new Adapter() }); - global.___loader = { enqueue: jest.fn() }; diff --git a/package.json b/package.json index 0debeeb..94ce179 100644 --- a/package.json +++ b/package.json @@ -56,11 +56,9 @@ "node_modules" ], "setupFilesAfterEnv": [ + "react-testing-library/cleanup-after-each", "/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" } } diff --git a/src/__mocks__/component-mock.js b/src/__mocks__/component-mock.js new file mode 100644 index 0000000..96afcc9 --- /dev/null +++ b/src/__mocks__/component-mock.js @@ -0,0 +1,19 @@ +const React = require('react'); + +const buildMock = component => { + const componentName = component.displayName || component.name || 'Component'; + const Mock = ({ children, ...props }) => ( + { children } + ); + Mock.propTypes = component.propTypes; + return Mock; +}; + +module.exports = path => { + const actual = jest.requireActual(path); + return buildMock(actual.default || actual); +}; + +module.exports.buildMock = buildMock; diff --git a/src/__mocks__/react-i18next.js b/src/__mocks__/react-i18next.js new file mode 100644 index 0000000..14d998c --- /dev/null +++ b/src/__mocks__/react-i18next.js @@ -0,0 +1,6 @@ +const reactI18next = jest.requireActual('react-i18next'); + +module.exports = { + ...reactI18next, + Trans: require('__mocks__/component-mock').buildMock(reactI18next.Trans) +}; diff --git a/src/components/App/__snapshots__/test.js.snap b/src/components/App/__snapshots__/test.js.snap index cd1a630..57e33f4 100644 --- a/src/components/App/__snapshots__/test.js.snap +++ b/src/components/App/__snapshots__/test.js.snap @@ -1,293 +1,255 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`App removing rendered expression 1`] = ` - - + - - - + + - + `; exports[`App removing rendered expression 2`] = ` - - + - + `; exports[`App rendering 1`] = ` - - + - + `; exports[`App rendering an expression 1`] = ` - - + - + `; exports[`App rendering an expression 2`] = ` - - + - - + + `; exports[`App rendering an expression 3`] = ` - - + - - - - -`; - -exports[`App rendering image details 1`] = ` - - - - - - -`; - -exports[`App rendering image details 2`] = ` - - - - - + - + `; exports[`App rendering with an invalid syntax 1`] = ` - - + - + `; exports[`App rendering with an invalid syntax 2`] = ` - - + - - + + `; exports[`App rendering with an invalid syntax 3`] = ` - - + -

- + An error occurred while rendering the regular expression. - +

- + Retry - +
- -
+
+ `; diff --git a/src/components/App/test.js b/src/components/App/test.js index 982ff1c..6d66368 100644 --- a/src/components/App/test.js +++ b/src/components/App/test.js @@ -1,5 +1,14 @@ +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( ); - expect(component).toMatchSnapshot(); + expect(asFragment()).toMatchSnapshot(); }); test('rendering an expression', async () => { - const component = shallow( + const { asFragment, rerender } = render( ); - expect(component).toMatchSnapshot(); + expect(asFragment()).toMatchSnapshot(); - component.setProps({ - expr: 'test expression' - }); + rerender( + + ); - 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( ); - expect(component).toMatchSnapshot(); + expect(asFragment()).toMatchSnapshot(); - component.setProps({ - expr: 'test expression' - }); - - expect(component).toMatchSnapshot(); - - // Give a beat for module to load - await new Promise(resolve => setTimeout(resolve)); - - expect(component).toMatchSnapshot(); - }); - - test('removing rendered expression', async () => { - const component = shallow( - - ); - - // 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( - - ); - - // Give a beat for module to load - await new Promise(resolve => setTimeout(resolve)); - - expect(component).toMatchSnapshot(); - - component.instance().handleSvg({ - svg: 'test svg content' - }); - - expect(component).toMatchSnapshot(); - }); - - test('retrying expression rendering', () => { - jest.spyOn(console, 'error').mockImplementation(() => {}); - - const component = shallow( + rerender( ); - const instance = component.instance(); - const event = { preventDefault: jest.fn() }; + expect(asFragment()).toMatchSnapshot(); - jest.spyOn(instance, 'handleRender'); + // Give a beat for module to load + await new Promise(resolve => setTimeout(resolve)); - instance.handleRetry(event); - - expect(event.preventDefault).toHaveBeenCalled(); - expect(instance.handleRender).toHaveBeenCalled(); + expect(asFragment()).toMatchSnapshot(); }); - test('submitting an expression to render', () => { - const component = shallow( + test('removing rendered expression', async () => { + const { asFragment, rerender } = render( + + ); + + // Give a beat for module to load + await new Promise(resolve => setTimeout(resolve)); + + expect(asFragment()).toMatchSnapshot(); + + rerender( ); - 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(); }); }); diff --git a/src/components/Footer/__snapshots__/test.js.snap b/src/components/Footer/__snapshots__/test.js.snap index 2ede97f..26bebd6 100644 --- a/src/components/Footer/__snapshots__/test.js.snap +++ b/src/components/Footer/__snapshots__/test.js.snap @@ -1,42 +1,50 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`Footer rendering 1`] = ` - + Generated images licensed: + + TRANSLATE(Creative Commons CC-BY-3.0 License) + +
+ + +
+ abc-123 +
+ + `; diff --git a/src/components/Footer/test.js b/src/components/Footer/test.js index e681fc2..2e7bf3a 100644 --- a/src/components/Footer/test.js +++ b/src/components/Footer/test.js @@ -1,14 +1,14 @@ import React from 'react'; -import { shallow } from 'enzyme'; +import { render } from 'react-testing-library'; import { mockT } from 'i18n'; import { Footer } from 'components/Footer'; describe('Footer', () => { test('rendering', () => { - const component = shallow( + const { asFragment } = render(