Search code examples
angulartypescripttestingjestjsts-jest

I cannot configure jest properly to import modules (setupFilesAfterEnv)


I am using @angular-builders/jest in order to replace karma by jest when testing angular projects. There are 2 libraries that I like to get extra matchers for jest: jest-extended and @testing-library/jest-dom.

I cannot find a way to import automatically the matchers so that I don't have to import them in each spec file.

minimal example to reproduce the problem with jest-extended

First, create an angular project and install jest dependencies

ng new --defaults my-project
cd my-project
yarn add -D jest @types/jest @angular-builders/jest jest-extended

Then edit angular.json to replace builder

...
"test": {
    "builder": "@angular-builders/jest:run"
},

So far, I can run and pass the tests using jest with command

ng test

Now I add a test using one of the jest-extended matchers. In app.component.spec.ts:

...
  it('should work with jest-extended matchers', () => {
    expect([1, 1, 1]).toBeArrayOfSize(3);
  });

Attempt #1

create jest.config.js

module.exports = {
  setupFilesAfterEnv: [
    'jest-extended',
  ],
};

Does not work, I get error TS2339: Property 'toBeArrayOfSize' does not exist on type 'ArrayLikeMatchers<number>'

Attempt #2

use an intermediate setup file; create jest.config.js

module.exports = {
  setupFilesAfterEnv: [
    'my-jest-setup.ts',
  ],
};

with my-jest-setup.ts

import 'jest-extended'

Works! Test passes... BUT as soon as I change something in my spec file

...
  it('should work with jest-extended matchers', () => {
    expect([1, 1, 1]).toBeArrayOfSize(3);
    expect(true).toBeTruthy();
  });

and run the test again, I get the same error as in attempt #1. I suspect a cache issue

Workaround

Use attempt #2 and clear jest cache before each run with

ng test --clearCache && ng test

I don't like this solution because the cache is intended to speed up things and clearing the cache each time has a sensitive impact when there are many spec files. Moreover, I don't think it is possible to clear cache when using jest in watch mode

Sorry, this was a bit long, thanks if you read it to the end


Solution

  • I finally found what I believe the right solution. Starting from minimal example to reproduce the problem with jest-extended,

    1. create jest.config.js file (Attempt 1 was finally a good start)
    module.exports = {
      setupFilesAfterEnv: [
        'jest-extended',
      ],
    };
    
    1. edit tsconfig.spec.json and replace "types": ["jasmine", "node"] by "types": ["jest", "node", "jest-extended"]
    {
      "extends": "./tsconfig.json",
      "compilerOptions": {
        "outDir": "./out-tsc/spec",
        "types": ["jest", "node", "jest-extended"] // <==== what was missing
      },
      "files": ["src/test.ts", "src/polyfills.ts"],
      "include": ["src/**/*.spec.ts", "src/**/*.d.ts"]
    }
    
    

    and voilà. This will actually includes jest and jest-extended declaration files in compilation. I now get all the benefits of TypeScript type checkings and the speed improvements of the cache (except for first run, obviously).

    I hope this helps