Karma with jsdom+custom shims/polyfills should create the right environment for the tests
- Dominant language
- TypeScript
- Stars
- 27k
- Forks
- 11.8k
- Avg merge
- 14h 23m
- Merged PRs (30d)
- 162
Description
# 🐞 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?
No, the previous mayor version (8.x.x) the issue was present as well.
### Description
We are using `jsdom` as the target browser for unit testing in our Angular library. Our library uses the `crypto` API which is not implemented in `jsdom`, so we need a shim for this API. We did it as it's indicated in its docs:
```js
const dom = new JSDOM(`
Hello
`, {beforeParse(window) {
window.document.childNodes.length === 0;
window.someCoolAPI = () => { /* ... */ };
}
});
```
Luckely the `karma-json-launcher` offers the posibility to configure the `jsdom` instance throught `karma.conf.js` file:
```js
// karma.conf.js
const jsdom = require("jsdom");
module.exports = function(config) {
config.set({
browsers: ['jsdom'],
jsdomLauncher: {
jsdom: {
beforeParse(window) {
window.someCoolAPI = () => { /* ... */ };
}
}
}
});
};
```
The karma plugin creates the jsdom [instance correctly](https://github.com/badeball/karma-jsdom-launcher/blob/3c364d8988a7a1bc8d4687ec76810cb530adfffe/index.js#L28-L40) with the passed options, and it tries to parse the url where karma is running. But unfortunalety the `someCoolAPI` is not present in test context inside `window` property and test fails with a `ReferenceError: someCoolAPI is not defined`
On the other hand, when you try to manually create your own `jsdom` instance (same way `karma-json-launcher does`), with `someCoolAPI` polyfill, and parse any html document which use that API inside it works, jsdom parses the document and the scripst are executed correctly, so that makes me think is not a `jsdom` or `karma-jsdom-launcher` problem. Can be an issue with the CLI, or Karma itself?
## 🔬 Minimal Reproduction
1.
```sh
$ ng new foo
$ cd foo
$ npm install karma-jsdom-launcher jsdom
```
2. Configure `angular.json` file as @badeball indicates [here ](https://github.com/badeball/karma-jsdom-launcher#i-am-using-angular-cli-and-the-test-suite-hangs-indefinitely) due to #11561 and #13580
3. Configure `karma.config.js` file as `karma-jsdom-launcher` docs indicates:
```js
// karma.config.js
...
plugins: [
....
require('karma-jsdom-launcher'),
....
],
...
browsers: ['jsdom'],
jsdomLauncher: {
jsdom: {
beforeParse(window) {
window.someCoolAPI = () => { /* ... */ };
}
}
},
...
```
4. Create `app.component.ts` that uses that `someCoolAPI` in some way.
```
@Component({...})
export class AppComponent {
constructor() {
window.someCoolAPI(); //the test will fail here because someCoolAPI is not defined
}
}
```
5.
```sh
ng test
```
## 🔥 Exception or Error
> ng test
10% building 2/2 modules 0 active24 04 2020 23:56:59.854:WARN [karma]: No captured browser, open http://localhost:9877/
24 04 2020 23:56:59.871:INFO [karma-server]: Karma v4.4.1 server started at http://0.0.0.0:9877/
24 04 2020 23:56:59.873:INFO [launcher]: Launching browsers jsdom with concurrency unlimited
24 04 2020 23:56:59.911:INFO [launcher]: Starting browser jsdom
24 04 2020 23:57:12.239:WARN [karma]: No captured browser, open http://localhost:9877/
24 04 2020 23:57:12.552:INFO [Mozilla/5.0 (win32) AppleWebKit/537.36 (KHTML, like Gecko) jsdom/16.2.2]: Connected on socket BdQYHk1WXZIxjHKdAAAA with id 85109278
Mozilla/5.0 (win32) AppleWebKit/537.36 (KHTML, like Gecko) jsdom/16.2.2 AppComponent should create the app FAILED
ReferenceError: crypto is not defined
at
at new AppComponent (http://localhost:9877/_karma_webpack_/main.js:580:21)
at NodeInjectorFactory.AppComponent_Factory [as factory] (ng:///AppComponent/ɵfac.js:5:10)
at getNodeInjectable (http://localhost:9877/_karma_webpack_/vendor.js:41519:44)
at instantiateRootComponent (http://localhost:9877/_karma_webpack_/vendor.js:47483:23)
at createRootComponent (http://localhost:9877/_karma_webpack_/vendor.js:60827:23)
at ComponentFactory$1.create (http://localhost:9877/_karma_webpack_/vendor.js:66890:25)
at initComponent (http://localhost:9877/_karma_webpack_/vendor.js:82940:51)
at ZoneDelegate.invoke (http://localhost:9877/_karma_webpack_/polyfills.js:3836:30)
at ProxyZoneSpec.push../node_modules/zone.js/dist/zone-testing.js.ProxyZoneSpec.onInvoke (http://localhost:9877/_karma_webpack_/vendor.js:100670:43)
at ZoneDelegate.invoke (http://localhost:9877/_karma_webpack_/polyfills.js:3835:36)
Mozilla/5.0 (win32) AppleWebKit/537.36 (KHTML, like Gecko) jsdom/16.2.2: Executed 1 of 3 (1 FAILED) (0 secs / 0.294 secs)
Mozilla/5.0 (win32) AppleWebKit/537.36 (KHTML, like Gecko) jsdom/16.2.2 AppComponent should create the app FAILED
ReferenceError: crypto is not defined
at
at new AppComponent (http://localhost:9877/_karma_webpack_/main.js:580:21)
at NodeInjectorFactory.AppComponent_Factory [as factory] (ng:///AppComponent/ɵfac.js:5:10)
at getNodeInjectable (http://localhost:9877/_karma_webpack_/vendor.js:41519:44)
at instantiateRootComponent (http://localhost:9877/_karma_webpack_/vendor.js:47483:23)
at createRootComponent (http://localhost:9877/_karma_webpack_/vendor.js:60827:23)
at ComponentFactory$1.create (http://localhost:9877/_karma_webpack_/vendor.js:66890:25)
at initComponent (http://localhost:9877/_karma_webpack_/vendor.js:82940:51)
at ZoneDelegate.invoke (http://localhost:9877/_karma_webpack_/polyfills.js:3836:30)
at ProxyZoneSpec.push../node_modules/zone.js/dist/zone-testing.js.ProxyZoneSpec.onInvoke (http://localhost:9877/_karma_webpack_/vendor.js:100670:43)
## 🌍 Your Environment
Angular CLI: 9.1.3
Node: 12.10.0
OS: win32 x64
Angular: 9.1.3
... animations, cli, common, compiler, compiler-cli, core, forms
... language-service, platform-browser, platform-browser-dynamic
... router
Ivy Workspace: Yes
Package Version
-----------------------------------------------------------
@angular-devkit/architect 0.901.3
@angular-devkit/build-angular 0.901.3
@angular-devkit/build-optimizer 0.901.3
@angular-devkit/build-webpack 0.901.3
@angular-devkit/core 9.1.3
@angular-devkit/schematics 9.1.3
@ngtools/webpack 9.1.3
@schematics/angular 9.1.3
@schematics/update 0.901.3
rxjs 6.5.5
typescript 3.8.3
webpack 4.42.0
Contributor guide
Research direction
Start by reproducing the failure with the documented angular.json and karma.config.js setup, then run ng test using karma-jsdom-launcher and the beforeParse shim. Trace how the jsdom environment reaches the test context; done means custom shims such as someCoolAPI or crypto are available during tests without breaking the existing launcher setup.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript, typescript
- Domain
- cli, testing
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100