/
jsdom_environment.test.ts
148 lines (125 loc) · 4.59 KB
/
jsdom_environment.test.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import {makeGlobalConfig, makeProjectConfig} from '@jest/test-utils';
import JSDomEnvironment from '../';
describe('JSDomEnvironment', () => {
it('should configure setTimeout/setInterval to use the browser api', () => {
const env = new JSDomEnvironment(
{
globalConfig: makeGlobalConfig(),
projectConfig: makeProjectConfig(),
},
{console, docblockPragmas: {}, testPath: __filename},
);
env.fakeTimers!.useFakeTimers();
const timer1 = env.global.setTimeout(() => {}, 0);
const timer2 = env.global.setInterval(() => {}, 0);
[timer1, timer2].forEach(timer => {
expect(typeof timer).toBe('number');
});
});
it('has modern fake timers implementation', () => {
const env = new JSDomEnvironment(
{
globalConfig: makeGlobalConfig(),
projectConfig: makeProjectConfig(),
},
{console, docblockPragmas: {}, testPath: __filename},
);
expect(env.fakeTimersModern).toBeDefined();
});
it('should respect userAgent option', () => {
const env = new JSDomEnvironment(
{
globalConfig: makeGlobalConfig(),
projectConfig: makeProjectConfig({
testEnvironmentOptions: {
userAgent: 'foo',
},
}),
},
{console, docblockPragmas: {}, testPath: __filename},
);
expect(env.dom.window.navigator.userAgent).toBe('foo');
});
it('should respect url option', () => {
const env = new JSDomEnvironment(
{
globalConfig: makeGlobalConfig(),
projectConfig: makeProjectConfig(),
},
{console, docblockPragmas: {}, testPath: __filename},
);
expect(env.dom.window.location.href).toBe('http://localhost/');
const envWithUrl = new JSDomEnvironment(
{
globalConfig: makeGlobalConfig(),
projectConfig: makeProjectConfig({
testEnvironmentOptions: {
url: 'https://jestjs.io',
},
}),
},
{console, docblockPragmas: {}, testPath: __filename},
);
expect(envWithUrl.dom.window.location.href).toBe('https://jestjs.io/');
});
/**
* When used in conjunction with Custom Elements (part of the WebComponents standard)
* setting the `global` and `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 call CE disconnectedCallback with valid globals on teardown', () => {
const env = new JSDomEnvironment(
{
globalConfig: makeGlobalConfig(),
projectConfig: makeProjectConfig(),
},
{console, docblockPragmas: {}, testPath: __filename},
);
let hasDisconnected = false;
let documentWhenDisconnected = null;
// define a custom element
const {HTMLElement} = env.global;
class MyCustomElement extends HTMLElement {
disconnectedCallback() {
hasDisconnected = true;
documentWhenDisconnected = env.global.document;
}
}
// append an instance of the custom element
env.global.customElements.define('my-custom-element', MyCustomElement);
const instance = env.global.document.createElement('my-custom-element');
env.global.document.body.appendChild(instance);
// teardown will disconnect the custom elements
env.teardown();
expect(hasDisconnected).toBe(true);
expect(documentWhenDisconnected).not.toBeNull();
});
it('should not fire load event after the environment was teared down', async () => {
const env = new JSDomEnvironment(
{
globalConfig: makeGlobalConfig(),
projectConfig: makeProjectConfig(),
},
{console, docblockPragmas: {}, testPath: __filename},
);
const loadHandler = jest.fn();
env.global.document.addEventListener('load', loadHandler);
env.teardown();
// The `load` event is fired in microtasks, wait until the microtask queue is reliably flushed
await new Promise(resolve => setTimeout(resolve, 0));
expect(loadHandler).not.toHaveBeenCalled();
});
});