jest-preset-angular: Yarn Workspace Monorepo + Library Built with Angular 12 + Jest Throws an Error

🐛 Bug Report

So, this is an interesting situation. I’m responsible for a component library within our company, and we recently updated for Angular 12. Part of Angular’s guidance for library authors, is to compile with Partial Ivy starting in Angular 12. An app that’s using our library in an Angular project that’s nested within a monorepo, using Yarn Workspaces, is failing to run tests on components that use stuff from our library, with the following error:

Error: thrown: "Failed to load header.component.html"

That html is a file nested (and built) within our library code. It isn’t even a template that’s in the app project. Just to test this out, I rebuilt the library with Ivy completely disabled, published it, installed it in the app and re-tested, and the tests run fine. So it seems the Jest config is having trouble working with Partial Ivy libraries, when node_modules is hoisted to the top of the repo. I found this issue in another library’s repo, seeming to indicate the same problem after they build with Partial Ivy: https://github.com/tiberiuzuld/angular-gridster2/issues/740

Another, possibly related issue, was resolved in the angular repo a year and a half ago. Could point towards a possible solution https://github.com/angular/angular/issues/35747

To Reproduce

Steps to reproduce the behavior: Setup monorepo with Yarn workspaces. Create new Angular app as a project within the monorepo with Jest configured Install that angular-gridster2 library Add one of their components to the app.component.html, and import the module into the spec Run the test

Expected behavior

Should run without error

Link to repo (highly encouraged)

My repo is internal, but if you’re unable to reproduce with the steps above, I can try and set something up.

Error log:

Error: thrown: "Failed to load header.component.html"

    at context.<computed> (C:\Users\<user>\src\Atom\node_modules\zone.js\bundles\zone-testing-bundle.umd.js:4309:39)
    at C:\Users\<user>\src\Atom\packages\GuideApp\src\app\app.component.spec.ts:55:3
    at ZoneDelegate.Object.<anonymous>.ZoneDelegate.invoke (C:\Users\<user>\src\Atom\node_modules\zone.js\bundles\zone-testing-bundle.umd.js:407:30)
    at Zone.Object.<anonymous>.Zone.run (C:\Users\<user>\src\Atom\node_modules\zone.js\bundles\zone-testing-bundle.umd.js:167:47)
    at C:\Users\<user>\src\Atom\node_modules\zone.js\bundles\zone-testing-bundle.umd.js:4227:33
    at _dispatchDescribe (C:\Users\<user>\src\Atom\node_modules\jest-circus\build\index.js:97:26)
    at describe (C:\Users\<user>\src\Atom\node_modules\jest-circus\build\index.js:60:5)
    at context.<computed> (C:\Users\<user>\src\Atom\node_modules\zone.js\bundles\zone-testing-bundle.umd.js:4270:39)
    at Object.<anonymous> (C:\Users\<user>\src\Atom\packages\GuideApp\src\app\app.component.spec.ts:26:1)
    at Runtime._execModule (C:\Users\<user>\src\Atom\node_modules\jest-runtime\build\index.js:1394:24)
    at Runtime._loadModule (C:\Users\<user>\src\Atom\node_modules\jest-runtime\build\index.js:996:12)
    at Runtime.requireModule (C:\Users\<user>\src\Atom\node_modules\jest-runtime\build\index.js:828:12)
    at jestAdapter (C:\Users\<user>\src\Atom\node_modules\jest-circus\build\legacy-code-todo-rewrite\jestAdapter.js:79:13)
    at processTicksAndRejections (internal/process/task_queues.js:95:5)
    at runTestInternal (C:\Users\<user>\src\Atom\packages\GuideApp\node_modules\jest-runner\build\runTest.js:389:16)
    at runTest (C:\Users\<user>\src\Atom\packages\GuideApp\node_modules\jest-runner\build\runTest.js:481:34)
    at TestRunner.runTests (C:\Users\<user>\src\Atom\packages\GuideApp\node_modules\jest-runner\build\index.js:111:12)
    at TestScheduler.scheduleTests (C:\Users\<user>\src\Atom\packages\GuideApp\node_modules\@jest\core\build\TestScheduler.js:333:13)
    at runJest (C:\Users\<user>\src\Atom\packages\GuideApp\node_modules\@jest\core\build\runJest.js:387:19)
    at _run10000 (C:\Users\<user>\src\Atom\packages\GuideApp\node_modules\@jest\core\build\cli\index.js:408:7)
    at runCLI (C:\Users\<user>\src\Atom\packages\GuideApp\node_modules\@jest\core\build\cli\index.js:261:3)
    at Object.run (C:\Users\<user>\src\Atom\packages\GuideApp\node_modules\jest-cli\build\cli\index.js:163:37)

envinfo

System:
    OS: Windows 10

Npm packages:
    jest: 27.0.6
    jest-preset-angular: 9.0.4
    typescript: 4.3.5

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Reactions: 1
  • Comments: 19 (10 by maintainers)

Commits related to this issue

Most upvoted comments

@literalpie , it is a must to run ngcc before running Jest, otherwise Jest won’t get the correct umd modules for Angular package format. In your repo, you can just put require('jest-preset-angular/ngcc-jest-processor'); in your jest.config.js and the test will pass.

@michaelfaith in your case, you would need to run ngcc at root of the project because all of node_modules packages are hoisted at the top in the Yarn workspace. The script require('jest-preset-angular/ngcc-jest-processor'); doesn’t help in this case because it doesn’t handle the case of Yarn workspace hoisting.

Normally, when you run ngcc or using the script require('jest-preset-angular/ngcc-jest-processor');, you should see

Compiling @angular/core/testing : main as umd
Compiling @angular/platform-browser-dynamic : main as umd
Compiling @angular/platform-browser-dynamic : esm2015 as esm2015
Compiling @angular/platform-browser/testing : esm2015 as esm2015
Compiling @angular/platform-browser-dynamic/testing : esm2015 as esm2015
Compiling @angular/platform-browser/testing : main as umd
Compiling @angular/platform-browser-dynamic/testing : main as umd
Compiling @angular/common/testing : esm2015 as esm2015
Compiling @angular/common/testing : main as umd
Compiling @angular/router : esm2015 as esm2015
Compiling @angular/router : main as umd
Compiling @angular/router/testing : esm2015 as esm2015
Compiling @angular/router/testing : main as umd

the 1st time you run it. If you don’t see anything like that, you need to check your node_modules to see if it contains __ngcc_entry_points__.json which is a file created after ngcc runs.

I hope this helps you guys solving the issue. Pls understand that ngcc is a must to work with Jest, the same applies to Karma + Jasmine. When Angular CLI runs Karma + Jasmine, 1st it also needs to run ngcc to produce the correct esm2015 bundle to start testing. For Jest, we need umd (in normal mode) or umd + esm2015 in ESM mode.

I can work with that. Thanks for helping to zero in on the issue. Adding “postinstall”: “ngcc” to the top level package.json (not the lower one), it all works as expected. Appreciate the help.

We need ngcc because it does also process all packages under @angular. If those packages are not processed by ngcc, Jest won’t run correctly. If I don’t run ngcc explicitly from terminal, the require('jest-preset-angular/ngcc-jest-processor'); doesn’t run at all which explains why tests failed.

When Angular executes tests, it will access the codes which are in packages under @angular. As long as Angular still has ngcc, we still have to run it.

What I did in your repo is:

  • Run yarn install
  • Run ngcc from root of the repo
  • Run yarn repro

I see the test passed after those 3 steps. I’m not sure what else I should do?

Hi! I’m glad this issue is already being tracked because I’m also running into it. However, I don’t think yarn monorepos have anything to do with the issue. I was able to reproduce it using a basic Angular project and angular-gridster2 here.

Hope this helps!

edit: you can see the debug log output here