/
jsdom.ts
80 lines (75 loc) · 2.45 KB
/
jsdom.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
import { importModule } from 'local-pkg'
import type { Environment } from '../../types'
import { populateGlobal } from './utils'
function catchWindowErrors(window: Window) {
let userErrorListenerCount = 0
function throwUnhandlerError(e: ErrorEvent) {
if (userErrorListenerCount === 0 && e.error != null)
process.emit('uncaughtException', e.error)
}
const addEventListener = window.addEventListener.bind(window)
const removeEventListener = window.removeEventListener.bind(window)
window.addEventListener('error', throwUnhandlerError)
window.addEventListener = function (...args: Parameters<typeof addEventListener>) {
if (args[0] === 'error')
userErrorListenerCount++
return addEventListener.apply(this, args)
}
window.removeEventListener = function (...args: Parameters<typeof removeEventListener>) {
if (args[0] === 'error' && userErrorListenerCount)
userErrorListenerCount--
return removeEventListener.apply(this, args)
}
return function clearErrorHandlers() {
window.removeEventListener('error', throwUnhandlerError)
}
}
export default <Environment>({
name: 'jsdom',
async setup(global, { jsdom = {} }) {
const {
CookieJar,
JSDOM,
ResourceLoader,
VirtualConsole,
} = await importModule('jsdom') as typeof import('jsdom')
const {
html = '<!DOCTYPE html>',
userAgent,
url = 'http://localhost:3000',
contentType = 'text/html',
pretendToBeVisual = true,
includeNodeLocations = false,
runScripts = 'dangerously',
resources,
console = false,
cookieJar = false,
...restOptions
} = jsdom as any
const dom = new JSDOM(
html,
{
pretendToBeVisual,
resources: resources ?? (userAgent ? new ResourceLoader({ userAgent }) : undefined),
runScripts,
url,
virtualConsole: console && global.console ? new VirtualConsole().sendTo(global.console) : undefined,
cookieJar: cookieJar ? new CookieJar() : undefined,
includeNodeLocations,
contentType,
userAgent,
...restOptions,
},
)
const { keys, originals } = populateGlobal(global, dom.window, { bindFunctions: true })
const clearWindowErrors = catchWindowErrors(global)
return {
teardown(global) {
clearWindowErrors()
dom.window.close()
keys.forEach(key => delete global[key])
originals.forEach((v, k) => global[k] = v)
},
}
},
})