{
    "componentChunkName": "component---src-templates-blog-post-tsx",
    "path": "/blog/2018-06-13-big-testing-in-react/",
    "result": {"data":{"blogPost":{"title":"Big Testing in React","slug":"/blog/2018-06-13-big-testing-in-react/","authorNodes":[{"name":"Wil Wilsman","slug":"/people/wil-wilsman/"}],"markdown":{"html":"<h2 id=\"does-my-application-work-in-real-life\" style=\"position:relative;\"><a href=\"#does-my-application-work-in-real-life\" aria-label=\"does my application work in real life permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Does my application work in real life?</h2>\n<p>This is a big question, and big questions need big answers. How <em>do</em>\nwe answer that question, though? With <strong>big tests</strong>. When we write and\ndevelop our applications, it's with the intent that somebody will use\nit. We write tests so we can be assured that everything in our app\nworks as expected and is bug free. But how confident are you in your\ntests?</p>\n<p>A real person using your app is going to use a real browser; do your\ntests test your app in a real browser? And not everybody uses the same\nbrowser; do your tests test your app across multiple, different\nbrowsers and devices? What about the network? Chances are your app\ntalks to the network, and your tests should account for this too,\nright? Not to mention a person isn't going to interact with your app\non a component level. They're consuming <em>the entire app</em> , using all\nof it together. All of your components working with each other to\ncreate an <em>experience</em>.</p>\n<p>If your tests don't test the app in the same way a person would use\nit, how confident can you really be in them?</p>\n<p>Where do we even begin to test our apps like this? There are tools\nlike <a href=\"https://facebook.github.io/jest/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Jest</a>, but those tests don't\nrun in a real browser. There's also <a href=\"https://cypress.io\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Cypress</a>, but\nas of this writing, you currently <a href=\"https://github.com/cypress-io/cypress/issues/310\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">can't use it outside of\nChrome</a>. There's\nalso a looming thought that \"user tests are slow.\" Do they have to be?</p>\n<h2 id=\"anatomy-of-a-big-test\" style=\"position:relative;\"><a href=\"#anatomy-of-a-big-test\" aria-label=\"anatomy of a big test permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Anatomy of a Big Test</h2>\n<p>When we talk about testing the entire app in a way that a person would\ninteract with it, we're of course talking about <em>acceptance tests</em>, or\n<em>user tests</em>, or <em>end-to-end tests</em>. These types of tests have many\nnames, but it all refers to the same process of testing your app as if\nyou were an actual user.</p>\n<p>The life of an acceptance test is pretty simple. First, our app is\nmounted and we wait for it to load. Then, some interaction is\nperformed, such as filling out a form, or clicking a button; something\na person would actually do in our app. Finally, we make some\nexpectations about the state of our app after the interaction is\nperformed. Maybe this is a success message, or some other\nconfirmation. If a user does something in our app, they probably\nreceived some feedback. We want to test this interaction and ensure\nthat it works as <em>they</em> would expect it too.</p>\n<p>When a person is interacting with your app, they're using their mouse\nand keyboard which is translating to browser events that your app\nresponds to. They're not calling methods and expecting them to return\ncertain values, they're actually clicking things and expecting to\nachieve results. This is what our app's tests should do too: <em>send\nbrowser events and assert that there was feedback</em>.</p>\n<p>But how do we actually <strong>do</strong> all of this?</p>\n<h2 id=\"the-big-setup\" style=\"position:relative;\"><a href=\"#the-big-setup\" aria-label=\"the big setup permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>The Big Setup</h2>\n<p>Luckily, it's not nearly as hard as it sounds. How we interact with\nour app should be so identical to how our tests interact with our app\nthat the only difference is the entry point.</p>\n<p>In development, our entry point imports our app, mounts it, and that's\nit! The app is ready for us to start interacting with. If we're\nworking on a certain feature, we navigate directly to the part of our\napp containing it.</p>\n<p>In testing, our entry point imports all of our tests and runs\nthem. It's each test that mounts and interacts with our app. But from\nour app's point of view, nothing is any different than if it were\nbeing interacted with by a person. Only, in our tests, we can reset\nour app when necessary to make sure we're working with a clean state.</p>\n<p>Let's get to some actual code! For example's sake, let's say our app\nis built using <a href=\"https://reactjs.org\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">React</a> and\n<a href=\"https://webpack.js.org\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Webpack</a> with <a href=\"https://\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">babel-loader</a>,\n<a href=\"https://github.com/webpack-contrib/style-loader\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">style-loader</a>, and\n<a href=\"https://github.com/jantimon/html-webpack-plugin\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">html-webpack-plugin</a>. We'll\nalso be using <a href=\"https://mochajs.org/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Mocha</a> and\n<a href=\"http://www.chaijs.com/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Chai</a> to write our tests. The app in our\nexample is a simple countdown app that accepts a date input through\nsome custom spinner inputs and displays the time until or elapsed\nsince the specified date.</p>\n<p>Here's a quick look at our example app in action (<a href=\"https://bigtestjs-countdown.surge.sh/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">direct\nlink</a>):</p>\n<div class=\"website-embed\">\n  <iframe src=\"https://bigtestjs-countdown.surge.sh/\"></iframe>\n</div>\n<p>Our application's entry point looks like this:</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token comment\">// src/index.js</span>\n<span class=\"token keyword\">import</span> React <span class=\"token keyword\">from</span> <span class=\"token string\">'react'</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> render <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'react-dom'</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> App <span class=\"token keyword\">from</span> <span class=\"token string\">'./app'</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token function\">render</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&lt;</span>App <span class=\"token operator\">/</span><span class=\"token operator\">></span><span class=\"token punctuation\">,</span> document<span class=\"token punctuation\">.</span><span class=\"token function\">getElementById</span><span class=\"token punctuation\">(</span><span class=\"token string\">'root'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>If you have other necessary app code in your entry point, consider\nmoving it into a reusable module. You could even have a <code class=\"language-text\">Root</code>\ncomponent with the logic written in lifecycle hooks. The point is:\nduring development, or in production, our app is only mounted once;\nfor our tests, we need to be able to remount our app before each\nscenario.</p>\n<p>Our testing entry point will look something like this:</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token comment\">// tests/index.js</span>\n\n<span class=\"token comment\">// mocha doesn't support es modules, so we import the pre-compiled assets</span>\n<span class=\"token keyword\">import</span> <span class=\"token string\">'mocha/mocha.js'</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> <span class=\"token string\">'mocha/mocha.css'</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">// other setup could be done here too, such as registering chai helpers</span>\nmocha<span class=\"token punctuation\">.</span><span class=\"token function\">setup</span><span class=\"token punctuation\">(</span><span class=\"token string\">'bdd'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">// we import our tests using webpack's require.context</span>\n<span class=\"token comment\">// if we just use `import`, it will be hoisted above mocha's bdd setup</span>\n<span class=\"token keyword\">const</span> requireTest <span class=\"token operator\">=</span> require<span class=\"token punctuation\">.</span><span class=\"token function\">context</span><span class=\"token punctuation\">(</span><span class=\"token string\">'.'</span><span class=\"token punctuation\">,</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">,</span> <span class=\"token regex\"><span class=\"token regex-delimiter\">/</span><span class=\"token regex-source language-regex\">-test</span><span class=\"token regex-delimiter\">/</span></span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\nrequireTest<span class=\"token punctuation\">.</span><span class=\"token function\">keys</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">forEach</span><span class=\"token punctuation\">(</span>requireTest<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">// run mocha</span>\nmocha<span class=\"token punctuation\">.</span><span class=\"token function\">run</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>It's each test's job to mount and interact with the app, so all we\nneed to do here is import all of our tests and run them. We'll go over\nwhat our tests will actually look like in just a minute. For now,\nlet's pretend that our tests just do their aforementioned jobs. You\nmight be able to figure out where I'm going since I've been mentioning\n<em>entry points</em>. We're going to use our existing Webpack config to\nbundle our tests.</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token comment\">// webpack.config.js</span>\nmodule<span class=\"token punctuation\">.</span><span class=\"token function-variable function\">exports</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">env</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n  <span class=\"token literal-property property\">entry</span><span class=\"token operator\">:</span> env<span class=\"token punctuation\">.</span>testing <span class=\"token operator\">?</span> <span class=\"token string\">'./tests/index.js'</span> <span class=\"token operator\">:</span> <span class=\"token string\">'./src/index.js'</span><span class=\"token punctuation\">,</span>\n  <span class=\"token comment\">// ... other webpack config</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>We're using Webpack v4, which allows us to [export our config as a\nfunction]([Configuration\n<a href=\"https://webpack.js.org/configuration/configuration-types/#exporting-a-function\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">https://webpack.js.org/configuration/configuration-types/#exporting-a-function</a>). The\nfirst argument of this function, <code class=\"language-text\">env</code>, is populated by the <a href=\"https://webpack.js.org/api/cli/#environment-options\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">CLI\nargument</a> of the\nsame name. This way, when we start our app, we can just call <code class=\"language-text\">yarn\nstart --env.testing</code> to switch to our testing index. This new bundle\nwill run all of our tests for us, and we can open this bundle in any\nbrowser on any device to run our tests there as well!</p>\n<p><em>Note</em>: in our specific case, Mocha's HTML reported requires a\n<code class=\"language-text\">#mocha</code> container in the DOM to output it's report. We're using\n<a href=\"https://github.com/jantimon/html-webpack-plugin\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">html-webpack-plugin</a>\nalong with\n<a href=\"https://github.com/jaketrent/html-webpack-template\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">html-webpack-template</a>,\nso we can just change the <code class=\"language-text\">appMountId</code> of the template when we're in a\ntesting environment.</p>\n<p>Okay, so we know how to <em>bundle</em> our tests, but how do we actually\n<em>write</em> them?</p>\n<h2 id=\"writing-big-tests\" style=\"position:relative;\"><a href=\"#writing-big-tests\" aria-label=\"writing big tests permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Writing Big Tests</h2>\n<p>If we reflect back on our anatomy lesson, our tests do three important\nthings:</p>\n<ol>\n<li>Mount/Remount our app</li>\n<li>Interact with our app in a meaningful way</li>\n<li>Assert that something happened</li>\n</ol>\n<p>To successfully do all of these things, we'll be using a set of\nlibraries developed specifically for testing big. The\n<a href=\"https://bigtestjs.io\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">BigTest</a> suite of libraries and framework\nextensions help to answer the big question: <em>does my application work\nin real life?</em> We'll touch on a few of those libraries in the rest of\nthis article, but there are some we won't get to, and more planned for\ndevelopment.</p>\n<h3 id=\"mounting-our-app\" style=\"position:relative;\"><a href=\"#mounting-our-app\" aria-label=\"mounting our app permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Mounting Our App</h3>\n<p>First, to mount our app we can just use <code class=\"language-text\">render</code> from <code class=\"language-text\">react-dom</code>. But\naccording to the docs: \"If the React element was previously rendered\ninto the container, this will perform an update on it and only mutate\nthe DOM as necessary to reflect the latest React element.\" However,\nthis is not <em>exactly</em> what we want. While this does mount our app, we\nactually want to mount a <em>fresh instance</em> of our app every time. To do\nthis we can combine <code class=\"language-text\">render</code> and <code class=\"language-text\">unmountComponentAtNode</code>, which will\ncompletely remove a component from the DOM after calling the\nappropriate lifecycle hooks.</p>\n<p>This is pretty simple to do ourselves in our own <code class=\"language-text\">mount</code> helper, but\nto spare us from even more DIY architecture, we can just utilize the\nhelpers from <a href=\"https://github.com/bigtestjs/react\" target=\"_blank\" rel=\"nofollow noopener noreferrer\"><code class=\"language-text\">@bigtest/react</code></a>\nwhich already do this. It also provides some other useful things, such\nas setting up an in-memory <code class=\"language-text\">history</code> object for our app to provide to\n<a href=\"https://github.com/ReactTraining/react-router\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">React Router</a>, and\nbinding this history object to other helpers that allow us to navigate\nour app from within our tests.</p>\n<p>This is how we would use <code class=\"language-text\">@bigtest/react</code> to mount our app and visit a\nroute:</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> setupAppForTesting<span class=\"token punctuation\">,</span> visit <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'@bigtest/react'</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> expect <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'chai'</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">import</span> App <span class=\"token keyword\">from</span> <span class=\"token string\">'../src/app'</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token function\">describe</span><span class=\"token punctuation\">(</span><span class=\"token string\">'mounting our app and visiting a route'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token function\">beforeEach</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">await</span> <span class=\"token function\">setupAppForTesting</span><span class=\"token punctuation\">(</span>App<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token function\">visit</span><span class=\"token punctuation\">(</span><span class=\"token string\">'/2019/01/01'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token function\">it</span><span class=\"token punctuation\">(</span><span class=\"token string\">'shows the date'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">let</span> $date <span class=\"token operator\">=</span> document<span class=\"token punctuation\">.</span><span class=\"token function\">querySelector</span><span class=\"token punctuation\">(</span><span class=\"token string\">'[data-test-countdown-target]'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token function\">expect</span><span class=\"token punctuation\">(</span>$date<span class=\"token punctuation\">.</span>textContent<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>to<span class=\"token punctuation\">.</span><span class=\"token function\">equal</span><span class=\"token punctuation\">(</span><span class=\"token string\">'January 1st, 2019'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>We can reduce some boilerplate for all of our tests by creating a\nhelper file and combining the React helpers with Mocha hooks. This way\nwe also won't have to import our app into every test file.</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token comment\">// tests/helpers.js</span>\n<span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> setupAppForTesting <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'@bigtest/react'</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> App <span class=\"token keyword\">from</span> <span class=\"token string\">'../src/app'</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">export</span> <span class=\"token punctuation\">{</span> visit<span class=\"token punctuation\">,</span> location <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'@bigtest/react'</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">function</span> <span class=\"token function\">setupApplicationForTesting</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token function\">beforeEach</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">async</span> <span class=\"token keyword\">function</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>app <span class=\"token operator\">=</span> <span class=\"token keyword\">await</span> <span class=\"token function\">setupAppForTesting</span><span class=\"token punctuation\">(</span>App<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>We could have other helpers in this file, or do further setup such as\ncreating a mock server. Once we have an easy way for our tests to\nmount our app on demand, we can interact with it.</p>\n<h3 id=\"interacting-with-our-app\" style=\"position:relative;\"><a href=\"#interacting-with-our-app\" aria-label=\"interacting with our app permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Interacting With Our App</h3>\n<p>Again, we're not testing that some function returns some value or\ncalls some other function. <strong>We want to interact with our app like a\nreal person would.</strong></p>\n<p>To do this, we're going to use\n<a href=\"https://github.com/bigtestjs/interactor\" target=\"_blank\" rel=\"nofollow noopener noreferrer\"><code class=\"language-text\">@bigtest/interactor</code></a> to\nsend real browser events to our app. I won't go into too much detail\nhere, but interactors are a very powerful, composable, way to interact\nwith the DOM. Interactors will wait for elements to exist before\ninteracting with them, so we don't have to worry about timing our\ntests correctly to sync up with any run loops.</p>\n<p>If you're familiar with the <a href=\"https://martinfowler.com/bliki/PageObject.html\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">page object\npattern</a>, you'll know\nthat they can abstract the internal structure of a page away from the\nuser-facing functionality. They also reduce a lot of boilerplate\naround the UI in our tests, so that if changes are necessary, only the\npage objects need to be updated. You can think of interactors as\ncomposable page objects for modern components.</p>\n<p>Let's create an interactor for the custom spinner input in our app:</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token comment\">// tests/interactors/spinner.js</span>\n<span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> interactor<span class=\"token punctuation\">,</span> clickable<span class=\"token punctuation\">,</span> value <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'@bigtest/interactor'</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">default</span> @interactor <span class=\"token keyword\">class</span> <span class=\"token class-name\">SpinnerInteractor</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token comment\">// common helpers provide easy to define interactions</span>\n  prev <span class=\"token operator\">=</span> <span class=\"token function\">clickable</span><span class=\"token punctuation\">(</span><span class=\"token string\">'[data-test-spinner-prev]'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  next <span class=\"token operator\">=</span> <span class=\"token function\">clickable</span><span class=\"token punctuation\">(</span><span class=\"token string\">'[data-test-spinner-next]'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  value <span class=\"token operator\">=</span> <span class=\"token function\">value</span><span class=\"token punctuation\">(</span><span class=\"token string\">'input'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token comment\">// complex interactions can be expressed as methods</span>\n  <span class=\"token function\">select</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">option</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">let</span> self <span class=\"token operator\">=</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token comment\">// for each letter in `option`, send a keypress event</span>\n    <span class=\"token comment\">// that will trigger the spinner's typeahead feature</span>\n    <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">let</span> key <span class=\"token keyword\">of</span> option<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n      self <span class=\"token operator\">=</span> self<span class=\"token punctuation\">.</span><span class=\"token function\">trigger</span><span class=\"token punctuation\">(</span><span class=\"token string\">'keypress'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token literal-property property\">charCode</span><span class=\"token operator\">:</span> key<span class=\"token punctuation\">.</span><span class=\"token function\">charCodeAt</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n      <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n\n    <span class=\"token comment\">// methods that return a new instance of itself are chainable</span>\n    <span class=\"token keyword\">return</span> self<span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>And we can use this interactor like so:</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token comment\">// interactors are lazy, so we can initialize them without anything</span>\n<span class=\"token comment\">// actually existing in the DOM yet</span>\n<span class=\"token keyword\">const</span> year <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">SpinnerInteractor</span><span class=\"token punctuation\">(</span><span class=\"token string\">'[data-test-year-field]'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">// when accessing properties, an error might be thrown if the element does</span>\n<span class=\"token comment\">// not exist; this can be more useful than typical expectation failures</span>\n<span class=\"token function\">expect</span><span class=\"token punctuation\">(</span>year<span class=\"token punctuation\">.</span>value<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>to<span class=\"token punctuation\">.</span><span class=\"token function\">equal</span><span class=\"token punctuation\">(</span><span class=\"token string\">'2019'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token comment\">//=> Error: unable to find \"[data-test-year-field]\"</span>\n\n<span class=\"token comment\">// methods return new interactors that can then be chained from one another</span>\n<span class=\"token keyword\">let</span> selectYear <span class=\"token operator\">=</span> year<span class=\"token punctuation\">.</span><span class=\"token function\">select</span><span class=\"token punctuation\">(</span><span class=\"token string\">'2019'</span><span class=\"token punctuation\">)</span>\n<span class=\"token keyword\">let</span> selectYearThenPrev <span class=\"token operator\">=</span> selectYear<span class=\"token punctuation\">.</span><span class=\"token function\">prev</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">// interactions do not start until `interactor.run()` is called, or when</span>\n<span class=\"token comment\">// used with the async/await syntax; they will resolve once the element</span>\n<span class=\"token comment\">// exists and has been interacted with, or when the timeout ellapses</span>\n<span class=\"token keyword\">await</span> selectYearThenPrev<span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">await</span> year<span class=\"token punctuation\">.</span><span class=\"token function\">next</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>We can then take these smaller interactors and compose them to create\nmore complex interactions.</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token comment\">// tests/interactors/form.js</span>\n<span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> interactor<span class=\"token punctuation\">,</span> scoped <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'@bigtest/interactor'</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> SpinnerInteractor <span class=\"token keyword\">from</span> <span class=\"token string\">'./spinner'</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">default</span> @interactor <span class=\"token keyword\">class</span> <span class=\"token class-name\">DateFormInteractor</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token comment\">// the default scope allows us to omit the selector when calling `new`</span>\n  <span class=\"token keyword\">static</span> defaultScope <span class=\"token operator\">=</span> <span class=\"token string\">'[data-test-date-form]'</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token comment\">// interactors are composable and nested methods return an instance</span>\n  <span class=\"token comment\">// of the top-most interactor for chaining</span>\n  year <span class=\"token operator\">=</span> <span class=\"token function\">scoped</span><span class=\"token punctuation\">(</span><span class=\"token string\">'[data-test-year-field]'</span><span class=\"token punctuation\">,</span> SpinnerInteractor<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  month <span class=\"token operator\">=</span> <span class=\"token function\">scoped</span><span class=\"token punctuation\">(</span><span class=\"token string\">'[data-test-month-field]'</span><span class=\"token punctuation\">,</span> SpinnerInteractor<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  day <span class=\"token operator\">=</span> <span class=\"token function\">scoped</span><span class=\"token punctuation\">(</span><span class=\"token string\">'[data-test-day-field]'</span><span class=\"token punctuation\">,</span> SpinnerInteractor<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  hour <span class=\"token operator\">=</span> <span class=\"token function\">scoped</span><span class=\"token punctuation\">(</span><span class=\"token string\">'[data-test-hour-field]'</span><span class=\"token punctuation\">,</span> SpinnerInteractor<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  minute <span class=\"token operator\">=</span> <span class=\"token function\">scoped</span><span class=\"token punctuation\">(</span><span class=\"token string\">'[data-test-minute-field]'</span><span class=\"token punctuation\">,</span> SpinnerInteractor<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  submit <span class=\"token operator\">=</span> <span class=\"token function\">scoped</span><span class=\"token punctuation\">(</span><span class=\"token string\">'button[type=\"submit\"]'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token comment\">// getters can also be used for computed properties</span>\n  <span class=\"token keyword\">get</span> <span class=\"token function\">value</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">let</span> date <span class=\"token operator\">=</span> <span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>year<span class=\"token punctuation\">.</span>value<span class=\"token interpolation-punctuation punctuation\">}</span></span><span class=\"token string\">/</span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>month<span class=\"token punctuation\">.</span>value<span class=\"token interpolation-punctuation punctuation\">}</span></span><span class=\"token string\">/</span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>day<span class=\"token punctuation\">.</span>value<span class=\"token interpolation-punctuation punctuation\">}</span></span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">let</span> time <span class=\"token operator\">=</span> <span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>hour<span class=\"token punctuation\">.</span>value<span class=\"token interpolation-punctuation punctuation\">}</span></span><span class=\"token string\">:</span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>minute<span class=\"token punctuation\">.</span>value<span class=\"token interpolation-punctuation punctuation\">}</span></span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">return</span> <span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${</span>date<span class=\"token interpolation-punctuation punctuation\">}</span></span><span class=\"token string\">@</span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${</span>time<span class=\"token interpolation-punctuation punctuation\">}</span></span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>You'll notice our use of <code class=\"language-text\">data-test-*</code> attributes. This is because, if\nusing element IDs or CSS selectors, updates to the app's design or\nmarkup mean your tests will most likely break. By using data\nattributes, we can make our tests and interactors resilient to future\nchanges. We can also use a babel transform like\n<a href=\"https://github.com/wireapp/babel-plugin-remove-jsx-attributes\" target=\"_blank\" rel=\"nofollow noopener noreferrer\"><code class=\"language-text\">babel-plugin-remove-jsx-attributes</code></a>\nto remove our testing attributes in production.</p>\n<p>Now that we've successfully set up some interactors, we can use them\nto start interacting with our app in our tests.</p>\n<h3 id=\"making-assertions-about-our-app\" style=\"position:relative;\"><a href=\"#making-assertions-about-our-app\" aria-label=\"making assertions about our app permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Making Assertions About Our App</h3>\n<p>Making assertions sounds pretty straightforward, but since real apps\ntypically have some async operations associated with them, making\nassertions at the correct time can be cumbersome and\nheadache-inducing.</p>\n<p>For example, let's say we need to test that when a user clicks a\nbutton they are shown a random message. When does the message appear\nin the DOM so that we can make an assertion about it? After the user\nclicks, sure, but how long after the user clicks? In React, it's\nwhenever the render loop gets around to rendering that specific\nmessage. What if the app makes a network request for this message\nfirst? Well, now we need to also wait for a response before making our\nassertion.</p>\n<p>Interactors wait for elements to exist in the DOM before interacting\nwith them, but can we do the same thing with our assertions? Well, yes\nwe can! Interactors use\n<a href=\"https://github.com/bigtestjs/convergence\" target=\"_blank\" rel=\"nofollow noopener noreferrer\"><code class=\"language-text\">@bigtest/convergence</code></a>\nunder the hood, and we can utilize convergences for assertions too.</p>\n<p>What's a convergence? To put it simply, it's a pure assertion that can\nrun repeatedly until either it passes, or a timeout has been\nexceeded. And pure assertions are expectations that do not cause side\neffects.</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> when <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'@bigtest/convergence'</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">// will only continue once the expectation is true</span>\n<span class=\"token keyword\">await</span> <span class=\"token function\">when</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token operator\">!</span>app<span class=\"token punctuation\">.</span>state<span class=\"token punctuation\">.</span>isLoading<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">// works when throwing errors as well</span>\n<span class=\"token keyword\">await</span> <span class=\"token function\">when</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token function\">expect</span><span class=\"token punctuation\">(</span>foo<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>to<span class=\"token punctuation\">.</span><span class=\"token function\">equal</span><span class=\"token punctuation\">(</span><span class=\"token string\">'bar'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token function\">expect</span><span class=\"token punctuation\">(</span>baz<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>to<span class=\"token punctuation\">.</span>be<span class=\"token punctuation\">.</span>undefined<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>Convergent assertions will be called several, maybe even hundreds of\ntimes, depending on the timeout and if the assertion ever passes. So\nhaving side effects in our assertions could cause unintended behavior\nthat may also result in some serious slowdown.</p>\n<p>In regard to our tests, if we make sure all of our assertions are all\npure by keeping our interactions inside of hooks, we can use\n<a href=\"https://github.com/bigtestjs/mocha\" target=\"_blank\" rel=\"nofollow noopener noreferrer\"><code class=\"language-text\">@bigtest/mocha</code></a> to\nautomatically turn all of our <code class=\"language-text\">it</code> statements into convergences for\nus.</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> describe<span class=\"token punctuation\">,</span> beforeEach<span class=\"token punctuation\">,</span> it <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'@bigtest/mocha'</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> expect <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'chai'</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> setupApplicationForTesting<span class=\"token punctuation\">,</span> location <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'./helpers'</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> DateFormInteractor <span class=\"token keyword\">from</span> <span class=\"token string\">'./interactors/form'</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token function\">describe</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Date Picker'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">const</span> form <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">DateFormInteractor</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token comment\">// for our example app, this function also stubs the date to a constant value</span>\n  <span class=\"token function\">setupApplicationForTesting</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token function\">it</span><span class=\"token punctuation\">(</span><span class=\"token string\">'defaults to the current date'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token function\">expect</span><span class=\"token punctuation\">(</span>form<span class=\"token punctuation\">.</span>value<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>to<span class=\"token punctuation\">.</span><span class=\"token function\">equal</span><span class=\"token punctuation\">(</span><span class=\"token string\">'2018/1/1@0:0'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token function\">describe</span><span class=\"token punctuation\">(</span><span class=\"token string\">'submitting a date and time'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token function\">beforeEach</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n      <span class=\"token keyword\">await</span> form\n        <span class=\"token punctuation\">.</span>year<span class=\"token punctuation\">.</span><span class=\"token function\">select</span><span class=\"token punctuation\">(</span><span class=\"token string\">'2019'</span><span class=\"token punctuation\">)</span>\n        <span class=\"token punctuation\">.</span>hour<span class=\"token punctuation\">.</span><span class=\"token function\">select</span><span class=\"token punctuation\">(</span><span class=\"token string\">'12'</span><span class=\"token punctuation\">)</span>\n        <span class=\"token punctuation\">.</span>minute<span class=\"token punctuation\">.</span><span class=\"token function\">select</span><span class=\"token punctuation\">(</span><span class=\"token string\">'30'</span><span class=\"token punctuation\">)</span>\n        <span class=\"token punctuation\">.</span>submit<span class=\"token punctuation\">.</span><span class=\"token function\">click</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token comment\">// if this fails, @bigtest/mocha's `it` will keep rerunning until it</span>\n    <span class=\"token comment\">// passes or a timeout has been exceeded</span>\n    <span class=\"token function\">it</span><span class=\"token punctuation\">(</span><span class=\"token string\">'goes to the date countdown'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n      <span class=\"token function\">expect</span><span class=\"token punctuation\">(</span><span class=\"token function\">location</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>pathname<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>to<span class=\"token punctuation\">.</span><span class=\"token function\">equal</span><span class=\"token punctuation\">(</span><span class=\"token string\">'/2019/01/01/12:30'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>And there we go! We've officially written some big tests that properly\ninteract with our app how a user would.</p>\n<h2 id=\"the-big-finale\" style=\"position:relative;\"><a href=\"#the-big-finale\" aria-label=\"the big finale permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>The Big Finale</h2>\n<p>Alright, so we've written our tests and we can run them just by\nrunning our app in a testing environment. Our tests interact with our\napp just how a user would, and all of our tests pass with flying\ncolors. But we have real projects with CI/CD pipelines and these tests\nneed to be automatically run, reported, and tracked for us.</p>\n<p>Thankfully again, we don't have to do this\nourselves. <a href=\"https://github.com/karma-runner/karma\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Karma</a> is a\nframework agnostic test runner that can automatically launch browsers\nand generate reports for us. It has plenty of plugins to work with the\nbrowsers and frameworks we're already using. For our test suite, we're\ngoing to be using\n<a href=\"https://github.com/webpack-contrib/karma-webpack\" target=\"_blank\" rel=\"nofollow noopener noreferrer\"><code class=\"language-text\">karma-webpack</code></a>,\n<a href=\"https://github.com/karma-runner/karma-mocha\" target=\"_blank\" rel=\"nofollow noopener noreferrer\"><code class=\"language-text\">karma-mocha</code></a>, and\n<a href=\"https://github.com/litixsoft/karma-mocha-reporter\" target=\"_blank\" rel=\"nofollow noopener noreferrer\"><code class=\"language-text\">karma-mocha-reporter</code></a>. To\nlaunch our browser, we'll use\n<a href=\"https://github.com/karma-runner/karma-chrome-launcher\" target=\"_blank\" rel=\"nofollow noopener noreferrer\"><code class=\"language-text\">karma-chrome-launcher</code></a>.</p>\n<p>There are a couple things we need to change first to get our Karma\nplugins working smoothly:</p>\n<ol>\n<li><code class=\"language-text\">karma-webpack</code> takes a Webpack config, but will disregard our\n<code class=\"language-text\">entry</code> and use the file defined in our Karma config instead. This\nmeans some of the testing setup we did in our Webpack config won't\nbe necessary anymore.</li>\n<li><code class=\"language-text\">karma-mocha</code> will automatically set up Mocha and run our tests for\nus, so we'll need to remove the Mocha imports and initialization we\nmanually did in our testing index.</li>\n</ol>\n<p>Our new testing index will now look something like this:</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token comment\">// tests/index.js</span>\n<span class=\"token comment\">// other setup could be done here too, such as registering chai helpers</span>\n<span class=\"token keyword\">const</span> requireTest <span class=\"token operator\">=</span> require<span class=\"token punctuation\">.</span><span class=\"token function\">context</span><span class=\"token punctuation\">(</span><span class=\"token string\">'.'</span><span class=\"token punctuation\">,</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">,</span> <span class=\"token regex\"><span class=\"token regex-delimiter\">/</span><span class=\"token regex-source language-regex\">-test</span><span class=\"token regex-delimiter\">/</span></span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\nrequireTest<span class=\"token punctuation\">.</span><span class=\"token function\">keys</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">forEach</span><span class=\"token punctuation\">(</span>requireTest<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>And our Karma config will look like this:</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\">module<span class=\"token punctuation\">.</span><span class=\"token function-variable function\">exports</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">config</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  config<span class=\"token punctuation\">.</span><span class=\"token function\">set</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n    <span class=\"token literal-property property\">frameworks</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span><span class=\"token string\">'mocha'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> <span class=\"token comment\">// sets up the Mocha framework automatically</span>\n    <span class=\"token literal-property property\">reporters</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span><span class=\"token string\">'mocha'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> <span class=\"token comment\">// reports back to the CLI formatted like Mocha</span>\n    <span class=\"token literal-property property\">browsers</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span><span class=\"token string\">'Chrome'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> <span class=\"token comment\">// automatically launches chrome to run our tests</span>\n\n    <span class=\"token literal-property property\">files</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span>\n      <span class=\"token comment\">// karma-webpack will watch our files</span>\n      <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">pattern</span><span class=\"token operator\">:</span> <span class=\"token string\">'tests/index.js'</span><span class=\"token punctuation\">,</span> <span class=\"token literal-property property\">watched</span><span class=\"token operator\">:</span> <span class=\"token boolean\">false</span> <span class=\"token punctuation\">}</span>\n    <span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n\n    <span class=\"token literal-property property\">preprocessors</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n      <span class=\"token comment\">// tells Karma that we'll be using Webpack to process this file</span>\n      <span class=\"token string-property property\">'tests/index.js'</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span><span class=\"token string\">'webpack'</span><span class=\"token punctuation\">]</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n\n    <span class=\"token comment\">// Mocha reporter options</span>\n    <span class=\"token literal-property property\">mochaReporter</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n      <span class=\"token literal-property property\">showDiff</span><span class=\"token operator\">:</span> <span class=\"token boolean\">true</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n\n    <span class=\"token comment\">// our webpack config exports a function</span>\n    <span class=\"token literal-property property\">webpack</span><span class=\"token operator\">:</span> <span class=\"token function\">require</span><span class=\"token punctuation\">(</span><span class=\"token string\">'./webpack.config'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n\n    <span class=\"token comment\">// webpack dev middleware options</span>\n    <span class=\"token literal-property property\">webpackMiddleware</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n      <span class=\"token literal-property property\">stats</span><span class=\"token operator\">:</span> <span class=\"token string\">'minimal'</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n\n    <span class=\"token comment\">// for more Karma config options, check out the documentation</span>\n    <span class=\"token comment\">// http://karma-runner.github.io/2.0/config/configuration-file.html</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>With all of that set up, we can run <code class=\"language-text\">karma start</code> to launch our\nbrowser and automatically start our tests! For our CI/CD integration,\nwe can add the flag <code class=\"language-text\">--single-run</code> to exit after running our tests in\nthe specified browsers. To add other browsers, we simple just have to\ninstall other launchers like\n<a href=\"https://github.com/karma-runner/karma-firefox-launcher\" target=\"_blank\" rel=\"nofollow noopener noreferrer\"><code class=\"language-text\">karma-firefox-launcher</code></a>\nor\n<a href=\"https://github.com/karma-runner/karma-safari-launcher\" target=\"_blank\" rel=\"nofollow noopener noreferrer\"><code class=\"language-text\">karma-safari-launcher</code></a>. We\ncould even use any of the browsers and devices available on\nBrowserStack via\n<a href=\"https://github.com/karma-runner/karma-browserstack-launcher\" target=\"_blank\" rel=\"nofollow noopener noreferrer\"><code class=\"language-text\">karma-browserstack-launcher</code></a>!</p>\n<hr>\n<p>With a little bit of manual setup, and through testing big, we've\nanswered the question: <em>Does my application work in real life?</em>\nHowever, we've only scratched the surface in this article. We glossed\nover some things like convergences and interactors, and we didn't even\nget to touch on server mocking with\n<a href=\"https://github.com/bigtestjs/mirage\" target=\"_blank\" rel=\"nofollow noopener noreferrer\"><code class=\"language-text\">@bigtest/mirage</code></a>.</p>\n<p>Our countdown app lives in the <a href=\"https://github.com/bigtestjs/examples/tree/master/react/countdown\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">BigTest examples\nrepository</a>\nwhere you can check out the rest of our tests and the entirety of our\nconfiguration files. There will be more examples to come, including\nother frameworks and more complicated test setups. Keep an eye out in\nthe future for more BigTest blog posts and guides, and feel free to\nfollow and contribute to all of the projects over at the <a href=\"https://github.com/bigtestjs\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">BigTest\nGitHub organization</a>.</p>","frontmatter":{"date":"June 13, 2018","description":"When we write and develop our applications, it's with the intent that somebody will use it. We write tests so we can be assured that everything in our app works as expected and is bug free. But how confident are you in your tests?","tags":["react","open source","bigtest","testing"],"img":{"childImageSharp":{"fixed":{"src":"/static/6b456f27c574350fa94dd270fff6d243/a7715/2018-06-13-big-testing-in-react_bigtest.jpg"}}}}}}},"pageContext":{"id":"9c6207cb-9568-536a-9d26-5e5f5f9a310b"}},
    "staticQueryHashes": ["1241260443"]}