{"id":1296,"date":"2020-11-11T03:53:01","date_gmt":"2020-11-11T03:53:01","guid":{"rendered":"http:\/\/10.0.0.14\/?p=1296"},"modified":"2021-09-07T23:21:42","modified_gmt":"2021-09-07T23:21:42","slug":"tdd-with-gatsby-django-docker-part-2-chapter-10-setup-gatsby-for-tdd","status":"publish","type":"post","link":"https:\/\/tutorials.leesonresearch.com\/tutorials\/2020\/11\/11\/tdd-with-gatsby-django-docker-part-2-chapter-10-setup-gatsby-for-tdd\/","title":{"rendered":"TDD with Gatsby, Django &#038; Docker Part 2, Chapter 10 &#8212; Setup Gatsby for TDD ~"},"content":{"rendered":"\n<h1 class=\"wp-block-heading\">Setting Up Gatsby for Unit Testing<\/h1>\n\n\n\n<p>We are going to be using the Jest testing framework for react which was developed by Facebook. So first, we install all the Jest dependencies that play well with Gatsby.<\/p>\n\n\n\n<p>I&#8217;m not going to go into detail of how all these configuration files function since the <a href=\"https:\/\/www.gatsbyjs.com\/docs\/unit-testing\/\" target=\"_blank\" rel=\"noreferrer noopener\">Gatsby Unit Testing Config documentation <\/a>already walks through all the files in detail.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Install Dependencies<\/h4>\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# power down the app and cd into frontend on your local computer\nnpm install --save-dev jest@26.6.3 babel-jest@26.6.3 react-test-renderer babel-preset-gatsby identity-obj-proxy\n<\/pre><\/div>\n\n\n<p class=\"warning\">At the time of this writing babel-jest version 27.0.0 breaks with gatsby. As a work-around we installed babel-jest version 26.6.3 along with jest version 26.6.3.<\/p>\n\n\n\n<p>We need to create five configuration files for Jest:<\/p>\n\n\n\n<ol class=\"wp-block-list\"><li>jest.config.js<\/li><li>jest-preprocess.js<\/li><li>__mocks__\/file-mock.js<\/li><li>loadershim.js<\/li><li>__mocks__\/gatsby.js<\/li><\/ol>\n\n\n\n<h4 class=\"wp-block-heading\">Create Config File for Jest<\/h4>\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\/\/ frontend\/jest.config.js\n\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`],\n}\n<\/pre><\/div>\n\n\n<h4 class=\"wp-block-heading\">Create jest-preprocess.js<\/h4>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: Double click to copy; notranslate\" title=\"Double click to copy\">\nconst babelOptions = {\n  presets: &#x5B;&quot;babel-preset-gatsby&quot;],\n}\n\nmodule.exports = require(&quot;babel-jest&quot;).createTransformer(babelOptions)\n<\/pre><\/div>\n\n\n<h4 class=\"wp-block-heading\">Create __mocks__\/file-mock.js (note double underscores)<\/h4>\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\/\/ frontend\/__mocks__\/file-mock.js\n\nmodule.exports = &quot;test-file-stub&quot;\n<\/pre><\/div>\n\n\n<h4 class=\"wp-block-heading\">Create Global loadershim.js<\/h4>\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\/\/ frontend\/loadershim.js\n\nglobal.___loader = {\n  enqueue: jest.fn(),\n}\n<\/pre><\/div>\n\n\n<h4 class=\"wp-block-heading\">Mock Gatsby<\/h4>\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# frontend\/__mocks__\/gatsby.js\n\nconst React = require(&quot;react&quot;)\nconst gatsby = jest.requireActual(&quot;gatsby&quot;)\n\nmodule.exports = {\n  ...gatsby,\n  graphql: jest.fn(),\n  Link: jest.fn().mockImplementation(\n    \/\/ these props are invalid for an `a` tag\n    ({\n      activeClassName,\n      activeStyle,\n      getProps,\n      innerRef,\n      partiallyActive,\n      ref,\n      replace,\n      to,\n      ...rest\n    }) =&gt;\n      React.createElement(&quot;a&quot;, {\n        ...rest,\n        href: to,\n      })\n  ),\n  StaticQuery: jest.fn(),\n  useStaticQuery: jest.fn(),\n}\n<\/pre><\/div>\n\n\n<p>Finally we need to update our package.json file where the default test script has not been set to jest.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; highlight: [10]; title: Double click to copy; notranslate\" title=\"Double click to copy\">\n\/\/ frontend\/package.json\n\n&quot;scripts&quot;: {\n    &quot;build&quot;: &quot;gatsby build&quot;,\n    &quot;develop&quot;: &quot;gatsby develop&quot;,\n    &quot;format&quot;: &quot;prettier --write \\&quot;**\/*.{js,jsx,ts,tsx,json,md}\\&quot;&quot;,\n    &quot;start&quot;: &quot;npm run develop&quot;,\n    &quot;serve&quot;: &quot;gatsby serve&quot;,\n    &quot;clean&quot;: &quot;gatsby clean&quot;,\n    &quot;test&quot;: &quot;jest&quot;\n<\/pre><\/div>\n\n\n<h4 class=\"wp-block-heading\">Creating a Header Component<\/h4>\n\n\n\n<p>Before we begin writing tests lets build a header component to display the title of our site. The component below is based is pulled from the Gatsby.js documentation for <a rel=\"noreferrer noopener\" href=\"https:\/\/www.gatsbyjs.com\/docs\/testing-components-with-graphql\/\" target=\"_blank\">testing components with GraphQL<\/a> where they have a detailed breakdown of all the elements  in this header that will enable us to test with Jest.<\/p>\n\n\n\n<p>Start by creating a new directory and header.js file:<\/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\">\nmkdir frontend\/src\/components\ntouch frontend\/src\/components\/header.js\n<\/pre><\/div>\n\n\n<p>&#8230; and populate the header.js file 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\">\n\/\/ frontend\/src\/components\/header.js\n\n\/\/ 1)\nimport { Link } from &quot;gatsby&quot;\n\n\/\/ 2)\nimport PropTypes from &quot;prop-types&quot;\n\n\/\/ 3)\nimport React from &quot;react&quot;\n\n\/\/ 4)\nimport { useStaticQuery, graphql } from &quot;gatsby&quot;\n\n\/\/ 5)\nexport const PureHeader = ({ data }) =&gt; (\n\n  \/\/ 6)\n  &amp;lt;header\n    style={{\n      background: `rebeccapurple`,\n      marginBottom: `1.45rem`,\n    }}\n  &gt;\n    &amp;lt;div\n      style={{\n        margin: `0 auto`,\n        maxWidth: 960,\n        padding: `1.45rem 1.0875rem`,\n      }}\n    &gt;\n      &amp;lt;h1 style={{ margin: 0 }}&gt;\n\n        \/\/ 7)\n        &amp;lt;Link\n          to=&quot;\/&quot;\n          style={{\n            color: `white`,\n            textDecoration: `none`,\n          }}\n        &gt;\n\n          \/\/ 8)\n          {data.site.siteMetadata.title}\n        &amp;lt;\/Link&gt;\n      &amp;lt;\/h1&gt;\n    &amp;lt;\/div&gt;\n  &amp;lt;\/header&gt;\n)\n\n\/\/ 9)\nexport const Header = props =&gt; {\n\n  \/\/ 10)\n  const data = useStaticQuery(graphql`\n    query {\n      site {\n        siteMetadata {\n          title\n        }\n      }\n    }\n  `)\n  \/\/ 11)\n  return &amp;lt;PureHeader {...props} data={data}&gt;&amp;lt;\/PureHeader&gt;\n}\n\n\/\/ 12)\nHeader.propTypes = {\n  siteTitle: PropTypes.string,\n}\n\n\/\/ 13)\nHeader.defaultProps = {\n  siteTitle: ``,\n}\n\n\/\/ 14\nexport default Header\n<\/pre><\/div>\n\n\n<h4 class=\"wp-block-heading\">Structure of a Gatsby Component<\/h4>\n\n\n\n<p>Lets break down what we are building in this <strong>header<\/strong> component step by step.<\/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\/\/ 1)\nimport { Link } from &quot;gatsby&quot;\n<\/pre><\/div>\n\n\n<p>We start by importing the Gatsby Link component which allows us to link between internal pages in Gatsby. When we want to navigate between internal Gatsby pages we will by using the Link tag instead of traditional anchor (a) tags.<\/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\/\/ 2) \nimport PropTypes from &quot;prop-types&quot;\n<\/pre><\/div>\n\n\n<p>We will be using propTypes which help us to keep track if our component is receiving the correct type data or not.<\/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\/\/ 3)\nimport React from &quot;react&quot;\n<\/pre><\/div>\n\n\n<p>Of course we import react since Gatsby is built on top of React.<\/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\/\/ 4)\nimport { useStaticQuery, graphql } from &quot;gatsby&quot;\n<\/pre><\/div>\n\n\n<p>We will be using useStaticQuery, (a React hook), and graphql to query the siteMetadata for the title we&#8217;ve set for our site in gatsby-config.js.<\/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\/\/ 5)\nexport const PureHeader = ({ data }) =&gt; (\n<\/pre><\/div>\n\n\n<p>Its this function PureHeader we will be testing with Jest. More on this later.<\/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\/\/ 6)\n&amp;lt;header\n    style={{\n      background: `rebeccapurple`,\n      marginBottom: `1.45rem`,\n    }}\n  &gt;\n<\/pre><\/div>\n\n\n<p>We define our HTML header element with some inline styling.<\/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\/\/ 7)\n        &amp;lt;Link\n          to=&quot;\/&quot;\n          style={{\n            color: `white`,\n            textDecoration: `none`,\n          }}\n        &gt;\n<\/pre><\/div>\n\n\n<p>Using the Gatsby Link component we link the header to the index page of the site.<\/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          \/\/ 8)\n          {data.site.siteMetadata.title}\n<\/pre><\/div>\n\n\n<p>Using the data prop we passed into our function, we pull the title of our site from Gatsby-config.js. Note the curly braces. Anytime we want to embed a javascript snippet or in this case our <em>{data.site.siteMetadata.title}<\/em> variable, we wrap the javascript code in braces.<\/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\/\/ 9)\nexport const Header = props =&gt; {\n<\/pre><\/div>\n\n\n<p>This is the second function where we will use useStaticQuery and graphql to query the siteMetadata in the Gatsby-config.js file.<\/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  \/\/ 10)\n  const data = useStaticQuery(graphql`\n    query {\n      site {\n        siteMetadata {\n          title\n        }\n      }\n    }\n  `)\n<\/pre><\/div>\n\n\n<p>Here we define the query with graphql and execute the query with useStaticQuery.<\/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\/\/ 11)\n  return &amp;lt;PureHeader {...props} data={data}&gt;&amp;lt;\/PureHeader&gt;\n<\/pre><\/div>\n\n\n<p>We return the PureHeader with the <em>data<\/em> prop containing the siteMetadata.<\/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\/\/ 12)\nHeader.propTypes = {\n  siteTitle: PropTypes.string,\n}\n<\/pre><\/div>\n\n\n<p>Now we can implement  propTypes for our component which in this case is siteTitle of the PropType string. This isn&#8217;t absolutely necessary for the Gatsby component to render properly but it is a good coding practice to explicitly enforce type casting in our app.<\/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\/\/ 13)\nHeader.defaultProps = {\n  siteTitle: ``,\n}\n<\/pre><\/div>\n\n\n<p>Here we define the defaultProps which in this case is an empty string but, if we were to import this component into a page and not pass in the siteTitle argument we could define a default siteTitle.<\/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\/\/ 14)\nexport default Header\n<\/pre><\/div>\n\n\n<p>Finally we export our Header function to make available for import into a page or another component.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">What is a Pure Function and Why Use It?<\/h4>\n\n\n\n<p>We have two functions in this header.js file:<\/p>\n\n\n\n<ol class=\"wp-block-list\"><li>export const <strong>PureHeader<\/strong> = ({ data }) =&gt; ( \/\/ &#8230; code<\/li><li>export const <strong>Header<\/strong> = props =&gt; { \/\/ &#8230; code<\/li><\/ol>\n\n\n\n<p>Of the two the first is a pure function. What is a pure function?<\/p>\n\n\n\n<p>A <strong><a href=\"https:\/\/www.tutorialspoint.com\/what-is-a-pure-function-in-javascript\" target=\"_blank\" rel=\"noreferrer noopener\">pure function<\/a><\/strong> is a<strong>&nbsp;deterministic function<\/strong>. This means when a same input is passed every time, the function will return same output.<\/p>\n\n\n\n<p>A <strong>pure function<\/strong> will have the following properties:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>It depends only on its <strong>own arguments<\/strong><\/li><li>It wont try to change variables out of its scope<\/li><li>It doesn&#8217;t produce any <strong>side effects<\/strong><\/li><\/ul>\n\n\n\n<p>Its the first bullet point that concerns us. Our PureHeader only deals with the argument, ({data}), that was passed by the Header function.<\/p>\n\n\n\n<p>The second Header function is not pure because its changing variables out of its scope when it runs useStaticQuery and graphql to query siteMetadata.<\/p>\n\n\n\n<p>Why does this matter?<\/p>\n\n\n\n<p>If we were to write a jest test and run it against the second Header function the test would fail because Jest needs to mock the query itself before running the test. By testing the PureHeader we can use Jest to mock the query and pass in our mocked data into the imported PureHeader.<\/p>\n\n\n\n<p>What an elegant solution to the problem of testing GraphQL components!<\/p>\n\n\n\n<p>Before we write our Jest header.js test lets import the Header into our index.js file. <\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Import Header Component into Index File<\/h4>\n\n\n\n<p>Lets refactor our index page to import our <strong>Header<\/strong> function by adding:<\/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\/\/ frontend\/src\/pages\/index.js\n\n\/\/ code ...\n\nimport Header from &quot;..\/components\/header&quot;\n\n\/\/ code ...\n\n&amp;lt;Header \/&gt;\n<\/pre><\/div>\n\n\n<p>The complete updated index.js file is follows:<\/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\/\/ frontend\/src\/pages\/index.js\n\nimport React from &quot;react&quot;\nimport { useQuery } from '@apollo\/client';\nimport gql from 'graphql-tag';\nimport Header from &quot;..\/components\/header&quot;\n\nconst APOLLO_QUERY = gql`\n  query {\n    todo(id: 1) {\n      id\n      title\n      task\n    }\n  }\n`;\n\nexport default function Home() {\n  const { loading, error, data } = useQuery(APOLLO_QUERY)\n  if (loading) return &amp;lt;p&gt;Loading...&amp;lt;\/p&gt;;\n  if (error) return &amp;lt;p&gt;Error!&amp;lt;\/p&gt;;\n  \n  return(\n    &amp;lt;div&gt;\n      &amp;lt;Header \/&gt;\n      &amp;lt;div&gt;\n        Hello world!\n      &amp;lt;\/div&gt;\n\n      &amp;lt;div&gt;\n        Todo Title: {data.todo.title}\n      &amp;lt;\/div&gt;\n    &amp;lt;\/div&gt;\n    \n  )\n}\n<\/pre><\/div>\n\n\n<h4 class=\"wp-block-heading\">Configure Site Meta Data for Gatsby<\/h4>\n\n\n\n<p>We now can define global meta data properties in gatsby-config .js file where we will import our site&#8217;s into our index file.<\/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\/\/ frontend\/gatsby-config.js\n\n\/**\n * Configure your Gatsby site with this file.\n *\n * See: https:\/\/www.gatsbyjs.com\/docs\/gatsby-config\/\n *\/\n\nmodule.exports = {\n  siteMetadata: {\n    title: `Gatsby Todo App`,\n    description: `A fabulous description of our Todo app here...`,\n    author: `Ron Leeson`,\n  },\n  plugins: &#x5B;],\n}\n<\/pre><\/div>\n\n\n<h4 class=\"wp-block-heading\">Writing Our First Test<\/h4>\n\n\n\n<p>The first test we write will be for the Header component by creating a directory in our components directory for __tests__ and a file for the header.js test.<\/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\">\nmkdir frontend\/src\/components\/__tests__\ntouch frontend\/src\/components\/__tests__\/header.js\n<\/pre><\/div>\n\n\n<p>Populate the header.js file 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\">\n\/\/ frontend\/src\/components\/__tests__\/header.js\n\nimport React from 'react'\n\n\/\/ 1)\n\/**\nRender the React component to a pure JavaScript objec without depending on the DOM\n**\/\nimport renderer from 'react-test-renderer'\n\n\/\/ 2) Import our PureHeader we just built\nimport { PureHeader as Header } from '..\/header'\n\n\/\/ 3) \n\/**\nUsing the Jest describe method for containing our test\n**\/\ndescribe(&quot;Header&quot;, () =&gt; {\n  it(&quot;renders correctly&quot;, () =&gt; {\n    \/\/ Created using query from Header.js\n    const data = {\n      site: {\n        siteMetadata: {\n          title: &quot;Gatsby Todo App&quot;\n        },\n      },\n    }\n\n    \/\/ 4) Make a snapshot of the PureHeader\n    const tree = renderer.create(&amp;lt;Header data={data} \/&gt;).toJSON()\n\n    \/\/ 5) \n    \/**\n    On the initial test we take the snapshot, on subsequent tests \n    we compare the new snapshot against the initial snapshot for\n    a match. If they match test passes, if they don't match \n    the test fails.\n    **\/\n    expect(tree).toMatchSnapshot()\n  })\n})\n<\/pre><\/div>\n\n\n<p>With all dependencies installed, our new Header component imported into our refactored index file, we are now ready to  rebuild the frontend docker container.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Rebuild Frontend Docker Container<\/h4>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: Double click to copy; notranslate\" title=\"Double click to copy\">\ndocker-compose build frontend\n<\/pre><\/div>\n\n\n<p>If you run into some errors while building or booting up the app you can tell Docker to clear the cache before building the frontend container:<\/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\">\ndocker-compose build --no-cache frontend\n<\/pre><\/div>\n\n\n<p>Now we are ready to boot up and see if our index page renders:<\/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\">\ndocker-compose -f docker-compose.yml -f docker-compose-dev.yml up\n\n# Or using the Makefile command\nmake dev\n<\/pre><\/div>\n\n\n<p>Going to http:\/\/localhost:8000 in your browser you should see something like this:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"844\" height=\"542\" src=\"http:\/\/10.0.0.14\/wp-content\/uploads\/2020\/11\/gatsby_index_pg_1.png\" alt=\"\" class=\"wp-image-1394\" srcset=\"https:\/\/tutorials.leesonresearch.com\/tutorials\/wp-content\/uploads\/2020\/11\/gatsby_index_pg_1.png 844w, https:\/\/tutorials.leesonresearch.com\/tutorials\/wp-content\/uploads\/2020\/11\/gatsby_index_pg_1-300x193.png 300w, https:\/\/tutorials.leesonresearch.com\/tutorials\/wp-content\/uploads\/2020\/11\/gatsby_index_pg_1-768x493.png 768w, https:\/\/tutorials.leesonresearch.com\/tutorials\/wp-content\/uploads\/2020\/11\/gatsby_index_pg_1-600x385.png 600w\" sizes=\"auto, (max-width: 844px) 100vw, 844px\" \/><\/figure>\n\n\n\n<p>If you get an error because the Django backend server failed to boot, try starting the backend as follows:<\/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\">\ndocker-compose up -d database\ndocker-compose up -d server\n\n# now start the frontend in development mode\nmake dev\n<\/pre><\/div>\n\n\n<h4 class=\"wp-block-heading\">Running Jest Tests<\/h4>\n\n\n\n<p>To run tests in Jest here are a few of the available commands:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>npm test \/\/ Run all the tests once<\/li><li>npm test &#8212; &#8211;watch \/\/ Tell Jest to watch for changes in code and run tests again<\/li><li>npm test &#8212; &#8211;u \/\/ Update snapshots<\/li><\/ul>\n\n\n\n<p>Since we are running Jest in our docker frontend container the command to run a test looks like:<\/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# this will take the intial snapshot of the Header component\ndocker-compose run frontend npm test\n\n# run the test again and changes to the Header will be compared against the inital snapshot\ndocker-compose run frontend npm test\n<\/pre><\/div>\n\n\n<p>Running the commands above you should see like the following in your terminal:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"499\" src=\"http:\/\/10.0.0.14\/wp-content\/uploads\/2020\/11\/gatsby_jest_test_1-1-1024x499.png\" alt=\"\" class=\"wp-image-1445\" srcset=\"https:\/\/tutorials.leesonresearch.com\/tutorials\/wp-content\/uploads\/2020\/11\/gatsby_jest_test_1-1-1024x499.png 1024w, https:\/\/tutorials.leesonresearch.com\/tutorials\/wp-content\/uploads\/2020\/11\/gatsby_jest_test_1-1-300x146.png 300w, https:\/\/tutorials.leesonresearch.com\/tutorials\/wp-content\/uploads\/2020\/11\/gatsby_jest_test_1-1-768x374.png 768w, https:\/\/tutorials.leesonresearch.com\/tutorials\/wp-content\/uploads\/2020\/11\/gatsby_jest_test_1-1-600x292.png 600w, https:\/\/tutorials.leesonresearch.com\/tutorials\/wp-content\/uploads\/2020\/11\/gatsby_jest_test_1-1-945x460.png 945w, https:\/\/tutorials.leesonresearch.com\/tutorials\/wp-content\/uploads\/2020\/11\/gatsby_jest_test_1-1.png 1033w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<h4 class=\"wp-block-heading\">Jest Testing Apollo\/Client Queries<\/h4>\n\n\n\n<p>Its considered best practice to test the smallest component possible rather than test a full page. So, instead of testing the full index.js page, we can move the GET_TODO_QUERY out of index.js into a separate todo.js component. <\/p>\n\n\n\n<p>Start by creating a file for todo.js:<\/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\/\/ frontend\/src\/components\/todo.js\n\nimport React from &quot;react&quot;\nimport { gql, useQuery } from '@apollo\/client'\nimport PropTypes from &quot;prop-types&quot;\n\nexport const GET_TODO_QUERY = gql`\n  query GetTodo($id: Int) {\n    todo(id: $id) {\n      id\n      title\n      task\n    }\n  }\n`;\n\nexport const Todo = ({ id }) =&gt; {\n  const { loading, error, data } = useQuery(\n    GET_TODO_QUERY,\n    { variables: { id }}\n  );\n  if (loading) return &amp;lt;p&gt;Loading...&amp;lt;\/p&gt;;\n  if (error) return &amp;lt;p&gt;Error!&amp;lt;\/p&gt;;\n\n  return (\n    &amp;lt;div&gt;\n      &amp;lt;h5&gt;Todo:&amp;lt;\/h5&gt;\n      id: {data.todo.id} &amp;lt;br \/&gt;\n      title: {data.todo.title}\n    &amp;lt;\/div&gt;\n  )\n}\n\nTodo.propTypes = {\n  id: PropTypes.number.isRequired\n}\n\nTodo.defaultProps = {\n  id: ``,\n}\n\nexport default Todo\n<\/pre><\/div>\n\n\n<p>Refactor the index.js file to import our new Todo component:<\/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\/\/ frontend\/src\/pages\/index.js\n\nimport React from &quot;react&quot;\nimport Header from &quot;..\/components\/header&quot;\nimport Todo from &quot;..\/components\/todo&quot;\n\nexport default function Home() {\n  return(\n    &amp;lt;div&gt;\n\n      &amp;lt;Header \/&gt;\n\n      &amp;lt;div&gt;\n        Hello world!\n      &amp;lt;\/div&gt;\n\n      &amp;lt;Todo id = {2} \/&gt;\n      \n    &amp;lt;\/div&gt;\n    \n  )\n}\n<\/pre><\/div>\n\n\n<h4 class=\"wp-block-heading\">Testing Todo Component with GraphQL<\/h4>\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 React from &quot;react&quot;\nimport { MockedProvider } from '@apollo\/client\/testing';\nimport renderer from &quot;react-test-renderer&quot;\n\/\/ The component AND the query need to be exported\nimport { GET_TODO_QUERY, Todo } from '..\/todo';\n\nconst mocks = &#x5B;\n  {\n    request: {\n      query: GET_TODO_QUERY,\n      variables: {\n        id: 1,\n      },\n    },\n    result: {\n      data: {\n        todo: { id: '1', title: 'Test' },\n      },\n    },\n  },\n];\n\nit('renders without error', () =&gt; {\n  renderer.create(\n    &amp;lt;MockedProvider mocks={mocks} addTypename={false}&gt;\n      &amp;lt;Todo id={1} \/&gt;\n    &amp;lt;\/MockedProvider&gt;,\n  );\n});\n<\/pre><\/div>\n\n\n<h4 class=\"wp-block-heading\">Run the Jest Test Suite<\/h4>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: Double click to copy; notranslate\" title=\"Double click to copy\">\ndocker-compose run frontend npm test\n\n# or if you want Jest to run in the background watching for changes\ndocker-compose run frontend npm test -- --watchAll\n\n# if you want to update your snapshots\ndocker-compose run frontend npm test -- --u\n<\/pre><\/div>\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"399\" src=\"http:\/\/10.0.0.14\/wp-content\/uploads\/2020\/11\/gatsby_jest_test_2-1024x399.png\" alt=\"\" class=\"wp-image-1449\" srcset=\"https:\/\/tutorials.leesonresearch.com\/tutorials\/wp-content\/uploads\/2020\/11\/gatsby_jest_test_2-1024x399.png 1024w, https:\/\/tutorials.leesonresearch.com\/tutorials\/wp-content\/uploads\/2020\/11\/gatsby_jest_test_2-300x117.png 300w, https:\/\/tutorials.leesonresearch.com\/tutorials\/wp-content\/uploads\/2020\/11\/gatsby_jest_test_2-768x300.png 768w, https:\/\/tutorials.leesonresearch.com\/tutorials\/wp-content\/uploads\/2020\/11\/gatsby_jest_test_2-600x234.png 600w, https:\/\/tutorials.leesonresearch.com\/tutorials\/wp-content\/uploads\/2020\/11\/gatsby_jest_test_2-945x369.png 945w, https:\/\/tutorials.leesonresearch.com\/tutorials\/wp-content\/uploads\/2020\/11\/gatsby_jest_test_2.png 1033w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>And there we have it, testing for Gatsby page queries and Apollo graphql queries.<\/p>\n\n\n\n<p>Having to type out these long docker-compose commands to run tests can get old so, lets update our Makefile with some shortcuts for our Gatsby tests and while we are at it, lets add shortcuts for our Django backend tests as well. Remember those? I know, it was a long time ago&#8230;<\/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\">\nbuild:\n\tdocker-compose build\n\ndev:\n\tdocker-compose -f docker-compose.yml -f docker-compose-dev.yml up \n\ndev-down:\n\tdocker-compose -f docker-compose.yml -f docker-compose-dev.yml down\n\ndev-build-no--cache:\n\tdocker-compose -f docker-compose.yml -f docker-compose-dev.yml build --no-cache frontend\n\nprod:\n\tdocker-compose up -d \n\nprod-down:\n\tdocker-compose down\n\n\n# Django Backend Testing\ndj-test:\n\tdocker-compose run server .\/manage.py test\n\npytest:\n\tdocker-compose run server pytest\n\npytest-verbose:\n\tdocker-compose run server pytest -vv\n\n# Gatsby Frontend Testing\ntest:\n\tdocker-compose run frontend npm test\n\nwatch:\n\tdocker-compose run frontend npm test -- --watchAll\n\nupdate-snapshot:\n\tdocker-compose run frontend npm test -- --u\n\n\nup-non-daemon:\n\tdocker-compose up\n\nstart:\n\tdocker-compose start\n\nstop:\n\tdocker-compose stop\n\ndown:\n\tdocker-compose down\n\nrestart:\n\tdocker-compose stop &amp;amp;&amp;amp; docker-compose start\n\nrestart-dev:\n\tdocker-compose down &amp;amp;&amp;amp; docker-compose -f docker-compose.yml -f docker-compose-dev.yml up -d\n\nrestart-frontend:\n\tdocker-compose stop frontend &amp;amp;&amp;amp; docker-compose start frontend\n\nrestart-server:\n\tdocker-compose stop server &amp;amp;&amp;amp; docker-compose start server\n\nshell-server:\n\tdocker exec -ti server bash\n\nshell-frontend:\n\tdocker exec -ti frontend bash\n\nshell-db:\n\tdocker exec -ti postgres bash\n\nlog-server:\n\tdocker-compose logs server\n\nlog-frontend:\n\tdocker-compose logs frontend\n\nlog-db:\n\tdocker-compose logs postgres\n\ncollectstatic:\n\tdocker exec server \/bin\/sh -c &quot;python manage.py collectstatic --noinput&quot;\n\nmigrations:\n\tdocker exec server \/bin\/sh -c &quot;python manage.py makemigrations; python manage.py migrate&quot;\n<\/pre><\/div>\n\n\n<p>Lets run all our tests to date for both front and back ends:<\/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# Run Gatsby tests\nmake test\n\n# Run Django pytests\nmake pytest\n<\/pre><\/div>\n\n\n<p>And I am pleased as punch to see all my tests pass. Woohoo! We haven&#8217;t broken anything. If we had some fails we would know where to go to fix them. Got to love automated testing. \ud83d\ude42<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Conclusion<\/h4>\n\n\n\n<p>Now that we have&#8230;<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Our Gatsby\/Docker development environment setup<\/li><li>Gatsby configured to use the Apollo\/Client<\/li><li>Gatsby configured for using Jest to test both page and Apollo queries<\/li><\/ul>\n\n\n\n<p>&#8230; we have all of the basic infrastructure we need to build out our Gatsby Todo app frontend.<\/p>\n\n\n\n<p>Next up in chapter 11 we will restructure our Gatsby project to implement a layout component which allows us to share markup, styles, and functionality across multiple pages.<\/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-9-configure-apollo-client\">&lt; Previous:  Chapter 9<\/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-11-layout-component\">Next: Chapter 11 &gt;<\/a><\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Setting Up Gatsby for Unit Testing We are going to be using the Jest testing framework for react which was developed by Facebook. So first, we install all the Jest dependencies that play well with Gatsby. I&#8217;m not going to&#8230; <a class=\"more-link\" href=\"https:\/\/tutorials.leesonresearch.com\/tutorials\/2020\/11\/11\/tdd-with-gatsby-django-docker-part-2-chapter-10-setup-gatsby-for-tdd\/\">Continue Reading &rarr;<\/a><\/p>\n","protected":false},"author":1,"featured_media":277,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[20,12],"tags":[10,29,35],"class_list":["post-1296","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-featured-tutorial","category-gatsby","tag-gatsby","tag-tdd","tag-unit-testing"],"_links":{"self":[{"href":"https:\/\/tutorials.leesonresearch.com\/tutorials\/wp-json\/wp\/v2\/posts\/1296","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=1296"}],"version-history":[{"count":99,"href":"https:\/\/tutorials.leesonresearch.com\/tutorials\/wp-json\/wp\/v2\/posts\/1296\/revisions"}],"predecessor-version":[{"id":2501,"href":"https:\/\/tutorials.leesonresearch.com\/tutorials\/wp-json\/wp\/v2\/posts\/1296\/revisions\/2501"}],"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=1296"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/tutorials.leesonresearch.com\/tutorials\/wp-json\/wp\/v2\/categories?post=1296"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/tutorials.leesonresearch.com\/tutorials\/wp-json\/wp\/v2\/tags?post=1296"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}