jestjs / jest

Delightful JavaScript Testing.
https://jestjs.io
MIT License
44.16k stars 6.45k forks source link

Runtime errors during Jest test. Handful of lines breaks transpilation in completely different file #11504

Closed cefn closed 3 years ago

cefn commented 3 years ago

šŸ› Bug Report

I found in a complex Next Typescript project that adding a handful of lines in one file was enough to break transpilation and create runtime errors in a completely different file.

In commit 04c4c7b, I am able to run yarn then yarn run test and get passing tests. The passing source tree is at https://github.com/cefn/jest-transpile-failure-repro/tree/04c4c7b7013e8b88c25d3ab2a7d4a33ccd3fb191

However, after adding the handful of lines which you can see in commit 25703fc the transpiler seems to effectively break and a totally unrelated file starts to get runtime errors during the test which make no sense like...

ReferenceError: Cannot access 'SCORERS' before initialization

      47 |   sortedEntries.sort((a: Immutable<Entry>, b: Immutable<Entry>) => {
      48 |     for (const scoreName of scorePriority) {
    > 49 |       const scorer = SCORERS[scoreName]
         |                      ^
      50 |       const diff = scorer(b) - scorer(a)
      51 |       if (diff !== 0) {
      52 |         return diff

      at sort (src/util.tsx:49:22)
          at Array.sort (<anonymous>)
      at sortEntries (src/util.tsx:47:17)
      at Object.<anonymous> (src/logic.ts:10:20)
      at Object.<anonymous> (src/components/controls/Buttons.tsx:6:1)
      at Object.<anonymous> (src/components/Controls.tsx:8:1)
      at Object.<anonymous> (src/components/index.ts:1:1)
      at Object.<anonymous> (src/util.tsx:6:1)
      at Object.<anonymous> (test/util.test.ts:3:1)

This error makes no sense because SCORERS is a const defined in the module closure immediately above the function definition here.

It is also a completely unrelated file to those changed in commit 25703fc, suggesting that something about the language constructs in commit 25703fc has pushed the transpiler into an errored state.

Finally it's a runtime error in a file which is already used and runs fine in the production case, so I don't believe there are actually any typescript errors in it.

Recreating the production error

Sorry I wasn't able to reduce the overall complexity of the case (I think that's maybe part of the conditions needed to create the error). To try and clarify the problem I layered in features of my app into a reference Next+Typescript configuration without changing any of the reference babel-jest config until one of the source lines recreated the failure. In that way I've narrowed it down to the handful of lines in the commit described above which are enough to trigger the case.

The repro is based on the canonical reference repo for babel-jest with next and typescript from https://github.com/vercel/next.js/tree/master/examples/with-typescript-eslint-jest

I believe the reference repo relies on babel-jest to transpile Jest tests.

To Reproduce

Check out the repro repository https://github.com/cefn/jest-transpile-failure-repro, run yarn then yarn run test. If you check out 25703fc7 it will error, and if you then checkout HEAD^1 to go back one commit it passes

Expected behavior

Given the imported and tested source code already compiles with tsc --noEmit and even runs in production, I would expect it to also run without symbol resolution errors after babel-jest transpilation and importing into a jest test.

Link to repl or repo (highly encouraged)

See links in step-by-step above.

envinfo

cefn@penguin:~/Desktop/jest-transpile-failure-repro$ npx envinfo --preset jest
npx: installed 1 in 2.072s

  System:
    OS: Linux 5.4 Debian GNU/Linux 10 (buster) 10 (buster)
    CPU: (4) x64 06/8e
  Binaries:
    Node: 12.20.2 - ~/.nodenv/versions/12.20.2/bin/node
    Yarn: 1.22.10 - ~/.nodenv/versions/12.20.2/bin/yarn
    npm: 6.14.11 - ~/.nodenv/versions/12.20.2/bin/npm
  npmPackages:
    jest: ^26.6.3 => 26.6.3 
cefn commented 3 years ago

This issue arises from a circularity which I thought I'd checked for.

It wasn't initially reported by my running of madge with the --ts-config argument omitted...

cefn@penguin:~/Documents/github/cvnext$ npx madge --circular --extensions ts,tsx ./
Processed 18 files (1.8s) (11 warnings)
āœ” No circular dependency found!

...or where the --ts-config argument pointed to the jest-specific tsconfig (which imports the top level one)

cefn@penguin:~/Documents/github/cvnext$ npx madge --circular --ts-config tsconfig.jest.json   --extensions ts,tsx ./
Processed 18 files (1.8s) (11 warnings)
āœ” No circular dependency found!

However, if I point to the top level tsconfig.json the circularity is revealed.

cefn@penguin:~/Documents/github/cvnext$ npx madge --circular --ts-config tsconfig.json   --extensions ts,tsx ./
Processed 18 files (2.2s) 
āœ– Found 1 circular dependency!
1) src/components/index.ts > src/components/Controls.tsx > src/components/controls/Buttons.tsx > src/logic.ts > src/util.tsx

I am not 100% sure why tsc can handle this circularity without errors, while babel-jest can't. However, the issue is resolved and having circularity here should be avoided anyway.

cefn commented 3 years ago

Thanks to https://stackoverflow.com/questions/67825205/is-this-transpilation-issue-correctly-filed-against-babel-jest/67825887#67825887 for manually identifying this circularity which I hadn't spotted.

github-actions[bot] commented 3 years ago

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs. Please note this issue tracker is not a help forum. We recommend using StackOverflow or our discord channel for questions.