<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Tom Sherman</title>
    <description>The latest articles on DEV Community by Tom Sherman (@tomsherman).</description>
    <link>https://dev.to/tomsherman</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F92527%2F9bd60d87-ebfb-45aa-bb00-d0dba294ca8e.jpg</url>
      <title>DEV Community: Tom Sherman</title>
      <link>https://dev.to/tomsherman</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/tomsherman"/>
    <language>en</language>
    <item>
      <title>Running Jest Tests in a Real Browser</title>
      <dc:creator>Tom Sherman</dc:creator>
      <pubDate>Sun, 26 Jul 2020 10:26:14 +0000</pubDate>
      <link>https://dev.to/tomsherman/running-jest-tests-in-a-real-browser-589h</link>
      <guid>https://dev.to/tomsherman/running-jest-tests-in-a-real-browser-589h</guid>
      <description>&lt;p&gt;If you didn't know, Jest is in my opinion the best testing framework for modern JavaScript and TypeScript. The developer experience is so smooth and lightning fast (lightning smooth?) which makes chasing that holy grail of 100% unit test coverage a breeze. Unfortunately, like many things, unit tests do not offer you 100% protection. To explain why I'd love for you to indulge me while I tell a very short story;&lt;/p&gt;

&lt;h2&gt;
  
  
  The unit test footgun
&lt;/h2&gt;

&lt;p&gt;So picture this; I'm writing a new feature, following the rules, obeying TDD, watching the terminal light up green as I add code for my test cases. I finish writing my feature and all of my tests pass, great! It's &lt;a href="https://twitter.com/kvlly/status/1098941288727093248?lang=en"&gt;not Friday&lt;/a&gt; so I deploy my changes to production, all of the logs look great so I go to bed after another successful day of being a &lt;a href="https://medium.com/@stevenpcurtis.sc/the-dangerous-myth-of-the-10x-developer-534d0e9159c9#:~:text=Terminology,job%20specification%20and%20limited%20benefit"&gt;10x developer&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The next day I log on to see a critical bug has been raised relating to the perfect feature I finished yesterday. How could this happen? Weren't all of my tests green? Some of you may know where this is going. After diagnosing the bug for a couple of hours I find that the code I've written uses some relatively new feature of some Web API that isn't supported in several of my user's browsers. I slap myself on the back of the wrist for not considering this before deploying and get to work on a fix. But I ask myself, why wasn't this caught by the unit tests?&lt;/p&gt;

&lt;p&gt;The answer is down to Jest not being a &lt;em&gt;real&lt;/em&gt; browser. You have access to all of the various DOM APIs when writing Jest tests but these are provided by &lt;a href="https://github.com/jsdom/jsdom"&gt;JSDOM&lt;/a&gt; and your tests are actually running in Node. Jest has no native way to run your tests in a browser environment out of the box.&lt;/p&gt;

&lt;h2&gt;
  
  
  Some alternative solutions before we get to the good stuff
&lt;/h2&gt;

&lt;p&gt;There are some ways to solve this. You could have a separate test suite using a different framework that can run in a real browser. In my experience though, this is difficult to sell to other developers. Now we have to write a load of tests twice, one for Jest to get tight feedback loops and once for the browser. What makes this worse is that usually your browser testing framework will have a completely different API and sometimes need to be written in a completely different language.&lt;/p&gt;

&lt;p&gt;Another solution could be to use &lt;a href="https://github.com/smooth-code/jest-puppeteer"&gt;jest-puppeteer&lt;/a&gt;. This is a great tool for spawning a headless version of Chrome and using the puppeteer API to write your tests inside of Jest. This technique works well as you're still in the Jest ecosystem, but now you have to choose if a test needs to be written using puppeteer or if it's ok to run in a Node and JSDOM environment. It also doesn't help if you've already got hundreds (or thousands) of tests written for your application.&lt;/p&gt;

&lt;p&gt;So in summary, we're looking for a solution that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Runs in real browsers that reflect the actual users of the application&lt;/li&gt;
&lt;li&gt;Doesn't waste our time by making us write tests twice or choose between environments&lt;/li&gt;
&lt;li&gt;Allow us to take advantage of the Jest APIs&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The good stuff
&lt;/h2&gt;

&lt;p&gt;Here's the TL;DR of how we have our cake and eat it too:&lt;/p&gt;

&lt;p&gt;Write all of your tests once using Jest as your framework. These will run in Node and JSDOM for local development to keep feedback loops tight. Then, usually part of CI, run these exact same tests in a browser environments.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Install Karma and related packages
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://karma-runner.github.io/latest/index.html"&gt;Karma&lt;/a&gt; is an amazingly versatile test runner - here we'll be using it to compile our tests, spawn a real life browser, and report our successes and failures. We'll also need some plugins to get everything working too.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm i karma karma-jasmine webpack karma-webpack expect jest-mock -D
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We'll be using &lt;a href="https://github.com/karma-runner/karma-jasmine"&gt;karma-jasmine&lt;/a&gt; because it's top-level API is almost identical to Jest's. We'll also be using &lt;a href="https://github.com/webpack-contrib/karma-webpack"&gt;karma-webpack&lt;/a&gt; to bundle our tests together so they can be used in the browser.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Create a &lt;code&gt;karma.config.js&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;set&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;karma-webpack&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;karma-jasmine&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt;

        &lt;span class="c1"&gt;// base path that will be used to resolve all patterns (eg. files, exclude)&lt;/span&gt;
        &lt;span class="na"&gt;basePath&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

        &lt;span class="c1"&gt;// frameworks to use&lt;/span&gt;
        &lt;span class="c1"&gt;// available frameworks: https://npmjs.org/browse/keyword/karma-adapter&lt;/span&gt;
        &lt;span class="na"&gt;frameworks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;jasmine&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;

        &lt;span class="c1"&gt;// list of files / patterns to load in the browser&lt;/span&gt;
        &lt;span class="c1"&gt;// Here I'm including all of the the Jest tests which are all under the __tests__ directory.&lt;/span&gt;
        &lt;span class="c1"&gt;// You may need to tweak this patter to find your test files/&lt;/span&gt;
        &lt;span class="na"&gt;files&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;__tests__/**/*.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;

        &lt;span class="c1"&gt;// preprocess matching files before serving them to the browser&lt;/span&gt;
        &lt;span class="c1"&gt;// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor&lt;/span&gt;
        &lt;span class="na"&gt;preprocessors&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// Use webpack to bundle our tests files&lt;/span&gt;
            &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;packages/*/__tests__/**/*.ts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;webpack&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3: Add the webpack config
&lt;/h3&gt;

&lt;p&gt;You can use one that you already have for your application or configure one that is based off of your Jest babel config.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;set&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="c1"&gt;// ...&lt;/span&gt;
        &lt;span class="na"&gt;webpack&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// Your webpack config here&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Creating a Webpack config is well and truly outside the scope of this article because everyone has different setups. You can read more in the &lt;a href="https://webpack.js.org/concepts/"&gt;Webpack&lt;/a&gt; and &lt;a href="https://github.com/webpack-contrib/karma-webpack"&gt;karma-webpack docs&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4: Add a &lt;code&gt;karma-setup.js&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;This is where the magic happens. There are things that Jest provides as part of the global API that is not available in Jasmine. Examples are the &lt;code&gt;expect&lt;/code&gt; &lt;a href="https://jestjs.io/docs/en/using-matchers"&gt;matchers API&lt;/a&gt; and the &lt;code&gt;jest.fn()&lt;/code&gt; &lt;a href="https://jestjs.io/docs/en/mock-functions#using-a-mock-function"&gt;mock/stubbing API&lt;/a&gt;. So we are going to include a file in our test bundle that adds these APIs to the global scope.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// the jest.fn() API&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;jest&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;jest-mock&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// The matchers API&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;expect&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;expect&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Add missing Jest functions&lt;/span&gt;
&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;test&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;each&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;inputs&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;testName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="nx"&gt;inputs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;testName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;
&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;todo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;expect&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Note that I have defined the parts of the Jest API I need, so if you use other parts then you may need to implement or import those too. The only thing that is not possible to use is the &lt;a href="https://jestjs.io/docs/en/jest-object#mock-modules"&gt;module mock API&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Add the &lt;code&gt;karma-setup.js&lt;/code&gt; file to the "preprocessors" and "files" config arrays.
&lt;/h4&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// karma.conf.js&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;set&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="c1"&gt;// ...&lt;/span&gt;
        &lt;span class="na"&gt;files&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./scripts/karma-setup.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;packages/*/__tests__/**/*.ts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;

        &lt;span class="na"&gt;preprocessors&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./karma-setup.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;webpack&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;packages/*/__tests__/**/*.ts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;webpack&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 5: Install browsers and browser launchers
&lt;/h3&gt;

&lt;p&gt;You will of course need the browsers installed on your system in order to run the tests on them. After installing them, you'll need to install the associated browser launcher.&lt;/p&gt;

&lt;p&gt;You can find one on npm here: &lt;a href="https://www.npmjs.com/search?q=keywords:karma-launcher"&gt;https://www.npmjs.com/search?q=keywords:karma-launcher&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I'm going to setup Chrome for the tests so I'll install &lt;a href="https://github.com/karma-runner/karma-chrome-launcher"&gt;karma-chrome-launcher&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm i karma-chrome-launcher -D
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h4&gt;
  
  
  And then add it to the karma.conf.js configuration:
&lt;/h4&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// karma.conf.js&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;set&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="c1"&gt;// ...&lt;/span&gt;
        &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;karma-webpack&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;karma-jasmine&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="c1"&gt;// Adding it to the plugins array&lt;/span&gt;
            &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;karma-chrome-launcher&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt;

        &lt;span class="c1"&gt;// I'm starting a headless browser, but I can also swap this out for "Chrome" to add debug statements, inspect console logs etc.&lt;/span&gt;
        &lt;span class="na"&gt;browsers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ChromeHeadless&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 6: Run the tests!
&lt;/h3&gt;

&lt;p&gt;Add a script to your package.json scripts, maybe call it "browser-tests"&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"browser-tests"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"karma start"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And then run &lt;code&gt;npm run browser-tests&lt;/code&gt; to the start the tests. &lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Behold your beautiful browser tests in their full glory! Now you have one Jest test suite running in Node for a great DX and in the browser for true integration tests.&lt;/p&gt;

&lt;p&gt;Now, this is a lot of setup but you do get massive benefits at the end of it. I devised this technique when we had many Jest tests and we wanted to run them in a real browser without rewriting them all. I think we ended up with a real solid solution.&lt;/p&gt;

&lt;p&gt;I'd love to know if this solution worked (or didn't work) for you, and if you have any questions just let me know!&lt;/p&gt;




&lt;p&gt;This post was originally posted on &lt;a href="https://github.com/tom-sherman/blog"&gt;my blog&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Discuss this post in the &lt;a href="https://github.com/tom-sherman/blog/issues/3"&gt;GitHub issue&lt;/a&gt; or &lt;a href="https://twitter.com/tomus_sherman/status/1287153112172638209"&gt;on Twitter&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>tdd</category>
      <category>jest</category>
      <category>javascript</category>
      <category>bdd</category>
    </item>
    <item>
      <title>Is a burrito a monad?</title>
      <dc:creator>Tom Sherman</dc:creator>
      <pubDate>Sat, 25 Jul 2020 18:02:16 +0000</pubDate>
      <link>https://dev.to/tomsherman/is-a-burrito-a-monad-3f7n</link>
      <guid>https://dev.to/tomsherman/is-a-burrito-a-monad-3f7n</guid>
      <description>&lt;p&gt;This post was &lt;a href="https://github.com/tom-sherman/blog/blob/master/posts/01-is-a-burrito-a-monad.md"&gt;originally posted&lt;/a&gt; on &lt;a href="https://github.com/tom-sherman/blog"&gt;my blog&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;As we all know, a monad is just a monoid in the category of endofunctors. This is intuitive to you and I, but what if you need to explain what a monad is in more practical terms. Well that's where the three laws of monads come in.&lt;/p&gt;

&lt;p&gt;These three laws act as a test to tell if something is a monad - if that something passes the three laws, then it's a monad - simples.&lt;/p&gt;

&lt;p&gt;Now to the main event, is a burrito monad? Well let's see if it obeys the three laws...&lt;/p&gt;

&lt;h2&gt;
  
  
  Left identity
&lt;/h2&gt;

&lt;p&gt;Take your filling, put it in a burrito - toast it - take the filling back out - the filling is warm just as if you toasted the filling itself. &lt;/p&gt;

&lt;p&gt;So the burrito passes the first law.&lt;/p&gt;

&lt;h2&gt;
  
  
  Right identity
&lt;/h2&gt;

&lt;p&gt;Unwrap the burrito to get to the filling. &lt;/p&gt;

&lt;p&gt;The burrito passes the second law.&lt;/p&gt;

&lt;h2&gt;
  
  
  Associativity
&lt;/h2&gt;

&lt;p&gt;Putting hot sauce in your burrito and then toasting it is the same as toasting it and putting hot sauce in your burrito. &lt;/p&gt;

&lt;p&gt;Thus the burrito passes the third law.&lt;/p&gt;

&lt;p&gt;The burrito is a monad 🌯&lt;/p&gt;

&lt;h2&gt;
  
  
  Further reading
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://emorehouse.wescreates.wesleyan.edu/silliness/burrito_monads.pdf"&gt;Burritos for the Hungry Mathematician&lt;/a&gt; by Ed Morehouse&lt;/p&gt;

</description>
      <category>monad</category>
    </item>
  </channel>
</rss>
