Skip to content

Commit 6a0cb64

Browse files
sheremet-vaRaul de Melo
andauthored
fix(vitest): pass environmentOptions to happy-dom integration (#3972)
Co-authored-by: Raul de Melo <melo.raulf@gmail.com>
1 parent 0f8e60b commit 6a0cb64

File tree

6 files changed

+67
-6
lines changed

6 files changed

+67
-6
lines changed

packages/vitest/src/integrations/env/happy-dom.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,12 @@ import { populateGlobal } from './utils'
55
export default <Environment>({
66
name: 'happy-dom',
77
transformMode: 'web',
8-
async setupVM() {
8+
async setupVM({ happyDOM = {} }) {
99
const { Window } = await importModule('happy-dom') as typeof import('happy-dom')
10-
const win = new Window() as any
10+
const win = new Window({
11+
...happyDOM,
12+
url: happyDOM.url || 'http://localhost:3000',
13+
}) as any
1114

1215
// TODO: browser doesn't expose Buffer, but a lot of dependencies use it
1316
win.Buffer = Buffer
@@ -26,11 +29,14 @@ export default <Environment>({
2629
},
2730
}
2831
},
29-
async setup(global) {
32+
async setup(global, { happyDOM = {} }) {
3033
// happy-dom v3 introduced a breaking change to Window, but
3134
// provides GlobalWindow as a way to use previous behaviour
3235
const { Window, GlobalWindow } = await importModule('happy-dom') as typeof import('happy-dom')
33-
const win = new (GlobalWindow || Window)()
36+
const win = new (GlobalWindow || Window)({
37+
...happyDOM,
38+
url: happyDOM.url || 'http://localhost:3000',
39+
})
3440

3541
const { keys, originals } = populateGlobal(global, win, { bindFunctions: true })
3642

packages/vitest/src/types/config.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import type { TestSequencerConstructor } from '../node/sequencers/types'
88
import type { ChaiConfig } from '../integrations/chai/config'
99
import type { CoverageOptions, ResolvedCoverageOptions } from './coverage'
1010
import type { JSDOMOptions } from './jsdom-options'
11+
import type { HappyDOMOptions } from './happy-dom-options'
1112
import type { Reporter } from './reporter'
1213
import type { SnapshotStateOptions } from './snapshot'
1314
import type { Arrayable } from './general'
@@ -24,13 +25,14 @@ export type CSSModuleScopeStrategy = 'stable' | 'scoped' | 'non-scoped'
2425

2526
export type ApiConfig = Pick<CommonServerOptions, 'port' | 'strictPort' | 'host'>
2627

27-
export { JSDOMOptions }
28+
export type { JSDOMOptions, HappyDOMOptions }
2829

2930
export interface EnvironmentOptions {
3031
/**
3132
* jsdom options.
3233
*/
3334
jsdom?: JSDOMOptions
35+
happyDOM?: HappyDOMOptions
3436
[x: string]: unknown
3537
}
3638

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/**
2+
* Happy DOM options.
3+
*/
4+
export interface HappyDOMOptions {
5+
width?: number
6+
height?: number
7+
url?: string
8+
settings?: {
9+
disableJavaScriptEvaluation?: boolean
10+
disableJavaScriptFileLoading?: boolean
11+
disableCSSFileLoading?: boolean
12+
disableIframePageLoading?: boolean
13+
disableComputedStyleRendering?: boolean
14+
enableFileSystemHttpRequests?: boolean
15+
device?: {
16+
prefersColorScheme?: string
17+
mediaType?: string
18+
}
19+
}
20+
}

packages/vitest/src/utils/test-helpers.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,13 +46,14 @@ export async function groupFilesByEnv(files: (readonly [WorkspaceProject, string
4646
const transformMode = getTransformMode(project.config.testTransformMode, file)
4747

4848
const envOptions = JSON.parse(code.match(/@(?:vitest|jest)-environment-options\s+?(.+)/)?.[1] || 'null')
49+
const envKey = env === 'happy-dom' ? 'happyDOM' : env
4950
return {
5051
file,
5152
project,
5253
environment: {
5354
name: env as VitestEnvironment,
5455
transformMode,
55-
options: envOptions ? { [env]: envOptions } as EnvironmentOptions : null,
56+
options: envOptions ? { [envKey]: envOptions } as EnvironmentOptions : null,
5657
},
5758
}
5859
}))
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/**
2+
* @vitest-environment happy-dom
3+
* @vitest-environment-options { "url": "http://my-website:5435", "settings": { "disableCSSFileLoading": true } }
4+
*/
5+
6+
/* eslint-disable vars-on-top */
7+
8+
import { expect, it } from 'vitest'
9+
10+
declare global {
11+
// eslint-disable-next-line no-var
12+
var happyDOM: any
13+
}
14+
15+
it('custom URL is changed to my-website:5435', () => {
16+
expect(location.href).toBe('http://my-website:5435/')
17+
})
18+
19+
it('accepts custom environment options', () => {
20+
// default is false
21+
expect(window.happyDOM.settings.disableCSSFileLoading).toBe(true)
22+
})

test/core/test/happy-dom.test.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,18 @@ import { expect, it, vi } from 'vitest'
1111
declare global {
1212
// eslint-disable-next-line no-var
1313
var __property_dom: unknown
14+
// eslint-disable-next-line no-var
15+
var happyDOM: any
1416
}
1517

18+
it('defaults URL to localhost:3000', () => {
19+
expect(location.href).toBe('http://localhost:3000/')
20+
})
21+
22+
it('disableCSSFileLoading is false by default because we didn\'t change options', () => {
23+
expect(window.happyDOM.settings.disableCSSFileLoading).toBe(false)
24+
})
25+
1626
it('defined on self/window are defined on global', () => {
1727
expect(self).toBeDefined()
1828
expect(window).toBeDefined()

0 commit comments

Comments
 (0)