diff --git a/CHANGELOG.md b/CHANGELOG.md index d093394b71b5..7e3137df2d1f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ - `[expect]` Allow again `expect.Matchers` generic with single value ([#11986](https://github.com/facebook/jest/pull/11986)) - `[jest-core]` Incorrect detection of open ZLIB handles ([#12022](https://github.com/facebook/jest/pull/12022)) - `[jest-environment-jsdom]` Add `@types/jsdom` dependency ([#11999](https://github.com/facebook/jest/pull/11999)) +- `[jest-environment-jsdom]` Do not reset the global.document too early on teardown ([#11871](https://github.com/facebook/jest/pull/11871)) - `[jest-transform]` Improve error and warning messages ([#11998](https://github.com/facebook/jest/pull/11998)) ### Chore & Maintenance diff --git a/packages/jest-environment-jsdom/src/__tests__/jsdom_environment.test.ts b/packages/jest-environment-jsdom/src/__tests__/jsdom_environment.test.ts index 6253fa99eb77..f10d330a7168 100644 --- a/packages/jest-environment-jsdom/src/__tests__/jsdom_environment.test.ts +++ b/packages/jest-environment-jsdom/src/__tests__/jsdom_environment.test.ts @@ -39,4 +39,28 @@ describe('JSDomEnvironment', () => { expect(env.dom.window.navigator.userAgent).toEqual('foo'); }); + + /** + * When used in conjunction with Custom Elements (part of the WebComponents standard) + * setting the global.document to null too early is problematic because: + * + * CustomElement's disconnectedCallback method is called when a custom element + * is removed from the DOM. The disconnectedCallback could need the document + * in order to remove some listener for example. + * + * global.close calls jsdom's Window.js.close which does this._document.body.innerHTML = "". + * The custom element will be removed from the DOM at this point, therefore disconnectedCallback + * will be called, so please make sure the global.document is still available at this point. + */ + it('should not set the global.document to null too early', () => { + const env = new JSDomEnvironment(makeProjectConfig()); + + const originalCloseFn = env.global.close.bind(env.global); + env.global.close = () => { + originalCloseFn(); + expect(env.global.document).not.toBeNull(); + }; + + return env.teardown(); + }); }); diff --git a/packages/jest-environment-jsdom/src/index.ts b/packages/jest-environment-jsdom/src/index.ts index 8db58a76a36e..1aab227fdb71 100644 --- a/packages/jest-environment-jsdom/src/index.ts +++ b/packages/jest-environment-jsdom/src/index.ts @@ -132,9 +132,14 @@ class JSDOMEnvironment implements JestEnvironment { if (this.errorEventListener) { this.global.removeEventListener('error', this.errorEventListener); } + this.global.close(); + // Dispose "document" to prevent "load" event from triggering. + + // Note that this.global.close() will trigger the CustomElement::disconnectedCallback + // Do not reset the document before CustomElement disconnectedCallback function has finished running, + // document should be accessible within disconnectedCallback. Object.defineProperty(this.global, 'document', {value: null}); - this.global.close(); } this.errorEventListener = null; // @ts-expect-error