angular-cli icon indicating copy to clipboard operation
angular-cli copied to clipboard

Jasmine's clock mocks can't be used in library specs

Open AmadejBukorovic opened this issue 6 years ago • 4 comments
trafficstars

🐞 Bug report

Command (mark with an x)

- [ ] new
- [ ] build
- [ ] serve
- [x] test
- [ ] e2e
- [ ] generate
- [ ] add
- [ ] update
- [ ] lint
- [ ] xi18n
- [ ] run
- [ ] config
- [ ] help
- [ ] version
- [ ] doc

Is this a regression?

Not sure to be honest, but it works if the sample spec is part of the application in the workspace.

Description

Attempting to use Jasmine's clock mocks inside tests of CLI generated libraries throws an error saying 'Jasmine Clock was unable to install over custom global timer functions.'. It seems Jasmine is imported before Zone.js and therefore detects that the global timing functions, such as setTimeout, were changed afterwoods.

The issue is similar to https://github.com/angular/angular-cli/issues/11626.

🔬 Minimal Reproduction


1. npm install --global @angular/cli.
2. ng new test-app
3. cd test-app
4. ng g library time-lib
5. ng test time-lib (passes)

6. Add the following test to a spec file inside the lib-1
 (e.g.: into "time-lib.service.spec.ts"):
 
 it('should install the clock mock', () => {
    jasmine.clock().install();
    jasmine.clock().uninstall();
  });

7. ng test time-lib (fails)

🔥 Exception or Error


Chrome 74.0.3729 (Windows 10.0.0) TimeLibService should install the clock mock FAILED
        Error: Jasmine Clock was unable to install over custom global timer functions. Is the clock already installed?
            at UserContext. (src/lib/time-lib.service.spec.ts:14:21)
            at ZoneDelegate.push.../../node_modules/zone.js/dist/zone.js.ZoneDelegate.invoke (C:/DEV/_test_projects/test-app/node_modules/zone.js/dist/zone.js:391:1)
            at ProxyZoneSpec.push.../../node_modules/zone.js/dist/zone-testing.js.ProxyZoneSpec.onInvoke (C:/DEV/_test_projects/test-app/node_modules/zone.js/dist/zone-testing.js:289:1)
            at ZoneDelegate.push.../../node_modules/zone.js/dist/zone.js.ZoneDelegate.invoke (C:/DEV/_test_projects/test-app/node_modules/zone.js/dist/zone.js:390:1)
            at Zone.push.../../node_modules/zone.js/dist/zone.js.Zone.run (C:/DEV/_test_projects/test-app/node_modules/zone.js/dist/zone.js:150:1)
            at runInTestZone (C:/DEV/_test_projects/test-app/node_modules/zone.js/dist/zone-testing.js:510:1)
            at UserContext. (C:/DEV/_test_projects/test-app/node_modules/zone.js/dist/zone-testing.js:525:1)

🌍 Your Environment


Angular CLI: 7.3.9
Node: 8.11.2
OS: win32 x64
Angular: 7.2.15
... animations, common, compiler, compiler-cli, core, forms
... language-service, platform-browser, platform-browser-dynamic
... router

Package                            Version
------------------------------------------------------------
@angular-devkit/architect          0.13.9
@angular-devkit/build-angular      0.13.9
@angular-devkit/build-ng-packagr   0.13.9
@angular-devkit/build-optimizer    0.13.9
@angular-devkit/build-webpack      0.13.9
@angular-devkit/core               7.3.9
@angular-devkit/schematics         7.3.9
@angular/cli                       7.3.9
@ngtools/json-schema               1.1.0
@ngtools/webpack                   7.3.9
@schematics/angular                7.3.9
@schematics/update                 0.13.9
ng-packagr                         4.7.1
rxjs                               6.3.3
typescript                         3.2.4
webpack                            4.29.0

Anything else relevant? Based on the fix for https://github.com/angular/angular-cli/issues/11626, adding a (e.g.) test-pollyfill.ts to the library source and moving the zone.js import from the library's test.ts file into the test-pollyfill.ts file, then configuring the test architecture of the library's project in angular.jsonto use the file as the 'pollyFills' option seems to be a possible workaround for now.

AmadejBukorovic avatar May 15 '19 09:05 AmadejBukorovic

any update for the fix?

A30001835 avatar Dec 04 '19 00:12 A30001835

I had a look at this and the problem is indeed that Jasmine is loaded prior to zone.js. To force zone.js to be loaded prior to Jasmine you can use a polyfills file.

  • creating a polyfills.ts file in the library src folder contain the zone.js import
import 'zone.js/dist/zone';
  • Remove the import from karma.confg.js
  • Finally reference the polyfills.ts in the builder configuration
"test": {
  "builder": "@angular-devkit/build-angular:karma",
  "options": {
    "polyfills": "projects/asdasd/src/polyfills.ts",
    "main": "projects/asdasd/src/test.ts",
    "tsConfig": "projects/asdasd/tsconfig.spec.json",
    "karmaConfig": "projects/asdasd/karma.conf.js"
  }
},

alan-agius4 avatar Nov 13 '20 13:11 alan-agius4

As far as I can tell, this is still an issue.

Just a couple of notes on the suggested workarounds:

  • The import you need to remove is in test.js not karma.config.js
  • You also need to add a reference to the the test pollyfills file in the files section of tsconfig.spec.json

jefflage avatar Aug 09 '21 17:08 jefflage

this is still an issue with Angular 14, and the workaround doesnt work for me :(

lazurey avatar Jun 28 '22 03:06 lazurey

This issue has been automatically locked due to inactivity. Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.