Jest testing with ReasonML & Create-React-App

reasonreact

#1

I recently converted a create-react-app project to ReasonReact, and testing is the one part that I can’t seem to get right. CRA’s Jest configuration doesn’t play nicely with Reason, and I keep running against walls when I try to roll my own Jest config.

CRA’s Jest seems to have problems with (at least) two Reason conventions in particular: 1) keeping your __tests__ directory outside of your src directory, and 2) applying Babel transforms to Bucklescript libraries in node_modules (I’m using ES6).

There may be other issues too, but that’s as far as I’ve gotten at this point.

I’m sure I can’t be the only person who’s had to deal with this. Is this a solved problem? How have other people handled it?

I would rather not eject if I can help it. I’m very happy with the CRA Webpack setup, and I don’t want to have to maintain it myself. I wonder if using something like react-app-rewired is what I need. I’ve never had to configure Jest myself until now, so I’m not sure what I should be looking for.


#2

FWIW, I have tests colocated. Here’s my whole Jest config:

module.exports = {
  clearMocks: true,

  // If we need something more sophisticated (or simpler to understand)
  // there’s a regexp version of this option, somewhere
  testMatch: [
    "**/__tests__/**/*.[jt]s?(x)",
    "**/*_test.bs.js"
  ],
};

Don’t know if its gonna bite me yet, but at least the tests themselves don’t seem to get bundled. So that whole keeping __tests__ outside of src doesn’t seem like such a strict requirement.

But yeah, I did eject CRA.


#3

@johnridesabike I’m running reason-react@0.7.0 with un-ejected create-react-app@3.0.1, so it is possible. I’m assuming you’re using https://github.com/glennsl/bs-jest as well. What you need to do is:

  1. Point to your tests in sources in bsconfig.json:
{
  "sources": [
    // snipped...
    {
      "dir": "src/__tests__",
      "subdirs": true,
      "type": "dev"
    }
}
  1. Place your tests in src/__tests__/ with a _test.re suffix, for example: src/__tests__/components/Component_test.re

  2. Compile Reason to JS: yarn run bsb -make-world
    At this point your test should be compiled to JavaScript in src/__tests__/components/Componente_test.bs.js

  3. Run jest with --transformIgnorePatterns flag:

yarn run test --transformIgnorePatterns "node_modules/(?!(bs-platform|reason-react|@glennsl\/bs-jest)/)"

This should help with jest not being able to compile libraries with babel. See my answer to Problem with bsconfig.json when running tests for more information.


#4

Thanks for the help guys. @pewniak747, I think that was the exact advice I needed. It seems to be working fine now!

A couple of comments from having just set it up:

  • Adding __tests__ to src seemed to make the bsb compiler break at first. It said that each test module was there twice. I think it was because bsb was seeing them once as a “regular” source and once as a dev source. I changed my subdirs property for my regular source to only include the (single) subdir I used, instead of true, and that fixed it.
  • My test command ended up being much longer. I had to add the following to the regex: |bs-jest-dom|re-classnames|bs-css|bs-webapi|bs-react-testing-library|bs-dom-testing-library I guess that’s not necessarily a problem, but not elegant (I guess I could whitelist everything that starts with bs- or re-.)

I’m just glad it’s working, though! I can finally go back to checking my test terminal instead of clicking around the dev server to see if I broke anything.

I’ll post an update if I learn any new tips and tricks. Having this process more streamlined is definitely on my ReasonML wish-list :slight_smile:


#5

There is also Rely (https://reason-native.com/docs/rely/) from the Reason Native website (https://reason-native.com/) which exposes a Jest-like interface for testing in pure Reason rather than testing on the generated JS.


#6

Looks sweet, but can it be used with BuckleScript?


#7

Seems to be for native only, not for the JS side.


#8

As of CRA 3.1.0, you can now extend more Jest configuration fields without using the CLI!

I took the ignore pattern out of the test command and put it in my package.json like this:

{
  "jest": {
    "transformIgnorePatterns": [
      "node_modules/(?!(reason-[a-z\\-]+|@[a-z\\-]+/bs-[a-z\\-]+|re-classnames|bs-[a-z\\-]+)/)"
    ]
  }
}

Also: after I upgraded to CRA 3.1, I wasn’t able to test at first because my Jest version was outdated, and CRA required a higher version. I’m guessing bs-jest or something else was using an old version? I manually installed the latest and that seemed to fix it, at least for now.