{"id":2579,"date":"2021-09-16T00:39:52","date_gmt":"2021-09-16T00:39:52","guid":{"rendered":"http:\/\/10.0.0.14:5557\/?p=2579"},"modified":"2021-11-27T23:53:50","modified_gmt":"2021-11-27T23:53:50","slug":"tdd-with-gatsby-django-docker-part-2-chapter-14-frontend-testing-with-enzyme","status":"publish","type":"post","link":"https:\/\/tutorials.leesonresearch.com\/tutorials\/2021\/09\/16\/tdd-with-gatsby-django-docker-part-2-chapter-14-frontend-testing-with-enzyme\/","title":{"rendered":"TDD with Gatsby, Django &#038; Docker Part 2, Chapter 15 &#8212; Frontend Testing with Enzyme"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\">Testing with Enzyme<\/h2>\n\n\n\n<p>Up to now we have been successfully running tests against the frontend using Jest but in the previous chapter we added a new module <strong><a rel=\"noreferrer noopener\" href=\"https:\/\/www.npmjs.com\/package\/react-onclickoutside\" target=\"_blank\">react-onclickoutside<\/a><\/strong> which enables the user to close the mobile fly out menu by clicking anywhere outside the menu. Here&#8217;s the gotcha! The react-onclickoutside module is known as a HOC, (Higher-Order Component), and the Jest testing framework we&#8217;ve been using cannot test HOCs so, if we were to run our frontend tests &#8212; one of our test would fail.<\/p>\n\n\n\n<p>Despair not!<\/p>\n\n\n\n<p>We can use an additional tool called Enzyme which can successfully test HOCs.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: Double click to copy; notranslate\" title=\"Double click to copy\">\nnpm i --save-dev enzyme enzyme-adapter-react-17-updated enzyme-to-json jest raf react-addons-shallow-compare react-test-renderer\n<\/pre><\/div>\n\n\n<h3 class=\"wp-block-heading\">What are Higher-Order Components?<\/h3>\n\n\n\n<p>Drawing from React&#8217;s official docs for Higher-Order Components; a higher-order component is a function that takes a component and returns a new component.<\/p>\n\n\n\n<p>Wha&#8230; ?<br><br>In the course of this tutorial we have been writing components that transforms props into a UI, (user interface). But since the react-onclickoutside module is a HOC, the react-onclickoutside module is taking our Navbar component, (frontend\/src\/components\/navbar.js), and transforming it into a new Navbar.handleClickOutside component which listens for mouse clicks outside of the navbar menu.<\/p>\n\n\n\n<p>If we were to run our frontend tests now they would fail because we are trying to test the navbar component but the navbar component is now a child component of react-onclickoutside component. <\/p>\n\n\n\n<p>To be honest I have not dug into the inner workings of react-onclickoutside other than to know that this component is watching for a state change e.g. mouse click outside of the wrapped component. <\/p>\n\n\n\n<p>So, where does that leave us? One possible solution is to run only a shallow test which targets to the parent Header component but Jest doesn&#8217;t provide shallow testing hence the need of an additionial testing utility of <a rel=\"noreferrer noopener\" href=\"https:\/\/enzymejs.github.io\/enzyme\/\" target=\"_blank\">Enzyme<\/a> which does provide shallow testing.<\/p>\n\n\n\n<p>So, <a rel=\"noreferrer noopener\" href=\"https:\/\/enzymejs.github.io\/enzyme\/\" target=\"_blank\">Enzyme<\/a> it is &#8212; let the games commence!<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Configuring Enzyme<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">setupTests.js<\/h4>\n\n\n\n<p>Create a file for setupTests.js in the root of the frontend directory and populate the files with the following:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: Double click to copy; notranslate\" title=\"Double click to copy\">\nimport Enzyme from &quot;enzyme&quot;;\nimport Adapter from &quot;enzyme-adapter-react-17-updated&quot;;\n\nEnzyme.configure({\n  adapter: new Adapter()\n});\n\n\/\/ a global graphql is expected by gatsby\nglobal.graphql = () =&gt; ''\n<\/pre><\/div>\n\n\n<h4 class=\"wp-block-heading\">jest.config.json<\/h4>\n\n\n\n<p>Updating the jest config file add paths to the raf\/polyfill and the setupTests.js file we just created. As well setup the snapshotSerializers.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; highlight: [15,16]; title: Double click to copy; notranslate\" title=\"Double click to copy\">\nmodule.exports = {\n  transform: {\n    &quot;^.+\\\\.jsx?$&quot;: `&amp;lt;rootDir&gt;\/jest-preprocess.js`,\n  },\n  moduleNameMapper: {\n    &quot;.+\\\\.(css|styl|less|sass|scss)$&quot;: `identity-obj-proxy`,\n    &quot;.+\\\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$&quot;: `&amp;lt;rootDir&gt;\/__mocks__\/file-mock.js`,\n  },\n  testPathIgnorePatterns: &#x5B;`node_modules`, `\\\\.cache`, `&amp;lt;rootDir&gt;.*\/public`],\n  transformIgnorePatterns: &#x5B;`node_modules\/(?!(gatsby)\/)`],\n  globals: {\n    __PATH_PREFIX__: ``,\n  },\n  testURL: `http:\/\/localhost`,\n  setupFiles: &#x5B;`&amp;lt;rootDir&gt;\/loadershim.js`, `raf\/polyfill`, `&amp;lt;rootDir&gt;\/setupTests.js`],\n  snapshotSerializers: &#x5B;&quot;enzyme-to-json\/serializer&quot;],\n}\n<\/pre><\/div>\n\n\n<h3 class=\"wp-block-heading\">Refactor Test for Header<\/h3>\n\n\n\n<p>We are going to refactor our Header test as follows:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: jscript; highlight: [5,6,8,9,10,11,12,13,14,15,16,17,18,19,20,21]; title: Double click to copy; notranslate\" title=\"Double click to copy\">\n\/\/ frontend\/src\/components\/tests\/header.js\n\nimport React from 'react';\nimport { PureHeader as Header } from '..\/header';\nimport renderer from 'react-test-renderer';\nimport { shallow } from 'enzyme'\n\ndescribe(&quot;Header&quot;, () =&gt; {\n  const data = {\n    site: {\n      siteMetadata: {\n        title: &quot;Gatsby Todo App&quot;\n      },\n    },\n  }\n\n  it(&quot;renders correctly&quot;, () =&gt; {\n    const wrapper = shallow(&lt;Header data={data} \/&gt;)\n    expect(wrapper).toMatchSnapshot()\n  })\n})\n<\/pre><\/div>\n\n\n<p>We need to rebuild the frontend since we&#8217;ve updated and added new config files:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: Double click to copy; notranslate\" title=\"Double click to copy\">\ndocker-compose build --no-cache frontend\n<\/pre><\/div>\n\n\n<p>Before running tests on the frontend might be prudent to update our frontend snapshot:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: Double click to copy; notranslate\" title=\"Double click to copy\">\nmake update-snapshot\n# or\ndocker-compose run frontend npm test -- --u\n\n# run frontend tests\nmake test\n# or \ndocker-compose run frontend npm test\n<\/pre><\/div>\n\n\n<p>If all goes well, our frontend tests should pass:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: Double click to copy; notranslate\" title=\"Double click to copy\">\n&gt; jest\n\n PASS  src\/components\/__tests__\/header.js\n  Header\n    \u2713 renders correctly (17 ms)\n\nTest Suites: 1 passed, 1 total\nTests:       1 passed, 1 total\nSnapshots:   1 passed, 1 total\nTime:        4.571 s\nRan all test suites.\n<\/pre><\/div>\n\n\n<p>Voila! Our tests passed.<\/p>\n\n\n\n<p>What&#8217;s next?<\/p>\n\n\n\n<div class=\"wp-block-buttons is-layout-flex wp-block-buttons-is-layout-flex\">\n<div class=\"wp-block-button\"><a class=\"wp-block-button__link\" href=\"tdd-with-gatsby-django-docker-part-2-chapter-14-mobile-menu\">&lt; Previous:  Chapter 14<\/a><\/div>\n\n\n\n<div class=\"wp-block-button\"><a class=\"wp-block-button__link\" href=\"tdd-with-gatsby-django-docker-part-2-chapter-14-frontend-testing-with-enzyme\">Next: Chapter 16 ><\/a><\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Testing with Enzyme Up to now we have been successfully running tests against the frontend using Jest but in the previous chapter we added a new module react-onclickoutside which enables the user to close the mobile fly out menu by&#8230; <a class=\"more-link\" href=\"https:\/\/tutorials.leesonresearch.com\/tutorials\/2021\/09\/16\/tdd-with-gatsby-django-docker-part-2-chapter-14-frontend-testing-with-enzyme\/\">Continue Reading &rarr;<\/a><\/p>\n","protected":false},"author":1,"featured_media":277,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[16,13,20,12],"tags":[],"class_list":["post-2579","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-django","category-docker","category-featured-tutorial","category-gatsby"],"_links":{"self":[{"href":"https:\/\/tutorials.leesonresearch.com\/tutorials\/wp-json\/wp\/v2\/posts\/2579","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/tutorials.leesonresearch.com\/tutorials\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/tutorials.leesonresearch.com\/tutorials\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/tutorials.leesonresearch.com\/tutorials\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/tutorials.leesonresearch.com\/tutorials\/wp-json\/wp\/v2\/comments?post=2579"}],"version-history":[{"count":29,"href":"https:\/\/tutorials.leesonresearch.com\/tutorials\/wp-json\/wp\/v2\/posts\/2579\/revisions"}],"predecessor-version":[{"id":2639,"href":"https:\/\/tutorials.leesonresearch.com\/tutorials\/wp-json\/wp\/v2\/posts\/2579\/revisions\/2639"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/tutorials.leesonresearch.com\/tutorials\/wp-json\/wp\/v2\/media\/277"}],"wp:attachment":[{"href":"https:\/\/tutorials.leesonresearch.com\/tutorials\/wp-json\/wp\/v2\/media?parent=2579"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/tutorials.leesonresearch.com\/tutorials\/wp-json\/wp\/v2\/categories?post=2579"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/tutorials.leesonresearch.com\/tutorials\/wp-json\/wp\/v2\/tags?post=2579"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}