Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jest "Cannot find module" with typescript paths in CI

On the Gitlab-CI environment 2 of our Jest tests fail with Cannot find module.
The strange thing is that it works on my local Win10 machine - even when I run the tests in a similar docker-container (node 12.12.0).

Here is the console output:

FAIL apps/server/src/domain/dashboard/permission-group.service.spec.ts
Test suite failed to run
  Cannot find module '@cm/utils-server' from 'license.service.ts'
     9 |   isLicenseFileContent,
    10 |   LicenseStatus,
  > 11 |   parseLicenseInfo
       |                   ^
    12 | } from '@cm/license-shared';
    13 | import { ExitCode } from '../../util/exit-codes';
    14 | import { readFile } from '@cm/utils-server';
    at Resolver.resolveModule (../../node_modules/jest-resolve/build/index.js:259:17)
    at Object.<anonymous> (src/domain/license/license.service.ts:11:24)

I am not sure how to correctly interpret this output:

  1. permission-group.service.spec.ts: this is the test that fails
  2. Cannot find module '@cm/utils-server' from 'license.service.ts':
    Ok, the test or some of its dependencies, use license.service.ts and in the license.service.ts file the '@cm/utils-server' module cannot be found.
  3. What is the meaning of error-indicator (> at parseLicenseInfo)?
    • This is for the import @cm/license-shared - not for @cm/utils-server as indicated by the error message in 2
    • @cm/utils-server is also imported, but 2 lines below in line 14: So is this maybe just a bug in jest?
like image 569
TmTron Avatar asked Nov 30 '19 13:11

TmTron


1 Answers

I just had this issue and searched for some solutions. Found this site which gave a clue about what could be done: to configure Jest's moduleNameMapper property.

So, reading the documentation I found this solution:

  1. Open the tsconfig.json and jest.config.js files (or equivalent)

  2. In tsconfig.json, find your absolute paths definition. My configuration looks like this:

"paths": {
    "@modules/*": ["modules/*"],
    "@config/*": ["config/*"],
    "@shared/*": ["shared/*"]
}
  1. In the jest.config.json, find and uncomment the moduleNameMapper property and start to translate your TS absolute paths into the Jest mapper syntax. Sounds complicated, but it isn't:
moduleNameMapper: {
    "@modules/(.*)": "<rootDir>/src/modules/$1",
    "@config/(.*)": "<rootDir>/src/config/$1",
    "@shared/(.*)": "<rootDir>/src/shared/$1",
}
  • The <rootDir> if defined automatically, and points to the package.json directory
  • "@modules/(.*)" is a Regex for "any string starting with '@module/' followed by anything after it
  • "<rootDir>/src/modules/$1" is the corresponding directory. $1 is a pointer to the Regex expression between the parenthesis ((.*)). Other expressions will be pointed by $2, $3 and so on

After doing this, I was able to execute my tests without any problem.

Console output before follow the above steps:

$ jest
 FAIL  src/modules/appointments/services/CreateAppointmentService.spec.ts
  ● Test suite failed to run

    Cannot find module '...'

Console output after:

$ jest
 PASS  src/modules/appointments/services/CreateAppointmentService.spec.ts

Hope this help someone, Thanks!

like image 101
Dahan Schuster Avatar answered Sep 21 '22 04:09

Dahan Schuster