Extending Jest configuration hooks

I’ve been looking at what it takes to extend Jest setup/teardown hooks in the RedwoodJS context. Some are pretty straightforward, but some are a bit tricky – especially when looking at future proofing.

setupFiles and setupFilesAfterEnv are easy: both use arrays as parameters and luckily Jest will properly combine them; e.g., just adding setupFilesAfterEnv: [path.join(__dirname, './jest.setup.cjs')] to the api/jest.config.js (and/or web/jest.config.js) file will run first the RedwoodJS hook and then the project hook.

testEnvironment is also pretty simple because Redwood behaves the same way for both the api and web sides. This call wants a class as an argument, so all we need to do there is inherit from the Redwood class (web, api), properly chain into super where appropriate, and we are good to go.

globalSetup and globaTeardown are where the difficulties lie. These calls take a string as an argument, and any settings added into the api or web project config files will override/obliterate any RedwoodJS settings. We can use a similar trick as we did for testEnvironment to avoid this, but instead of deriving a class we have to use a function.

  • Create a file named api/jest.globalSetup.cjs:
const redwoodGlobal = require('@redwoodjs/testing/config/jest/api/globalSetup.js');

module.exports = async function () {
  // RedwoodJS already uses a globalSetup function, so we want to make sure that gets called first
  await redwoodGlobal();

  // custom Jest setup code for api side goes here...
  • Then in jest.config.js add the entry globalSetup: path.join(__dirname, './jest.globalSetup.cjs')

This will call the RedwoodJS custom code and then ours. Easy peasy.

The complication comes beecause RedwoodJS only uses globalSetup on the api side and doesn’t use globalTeardown at all. So if we want to use any of those hooks in our projects there isn’t anything to chain into. Which is fine, right up until a future version of RedwoodJS where one of these hooks is now used. If we aren’t watching the Jest config files with each release, our custom hooks will obliterate the good intentions of the future Redwood developers.

My suggestion would be to add entries that do nothing on the web and api sides for these (currently) unused configuration hooks so we can always properly chain into the RedwoodJS stack. Now, when new functionality is added that wants these, it gets added and our project code automatically does the right thing.

Maybe these hooks aren’t used often by project developers enough to merit this effort and maybe the liklihood of Redwood using these hooks is low enough to warrant inclusion, but I wanted to throw this out there for discussion.