Skip to content

Commit 1892426

Browse files
committed
docs: update testEnvironment and testEnvironmentOptions doc
1 parent 7cf3b8d commit 1892426

File tree

9 files changed

+1163
-208
lines changed

9 files changed

+1163
-208
lines changed

docs/Configuration.md

Lines changed: 105 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1889,15 +1889,17 @@ More about serializers API can be found [here](https://github.com/jestjs/jest/tr
18891889

18901890
:::
18911891

1892-
### `testEnvironment` \[string]
1892+
### `testEnvironment` \[node | jsdom | string]
18931893

1894-
Default: `"node"`
1894+
Default: `node`
18951895

18961896
The test environment that will be used for testing. The default environment in Jest is a Node.js environment. If you are building a web app, you can use a browser-like environment through [`jsdom`](https://github.com/jsdom/jsdom) instead.
18971897

18981898
By adding a `@jest-environment` docblock at the top of the file, you can specify another environment to be used for all tests in that file:
18991899

1900-
```js
1900+
- With built-in environments:
1901+
1902+
```js tab title="my-test.spec.js"
19011903
/**
19021904
* @jest-environment jsdom
19031905
*/
@@ -1908,99 +1910,116 @@ test('use jsdom in this test file', () => {
19081910
});
19091911
```
19101912

1911-
You can create your own module that will be used for setting up the test environment. The module must export a class with `setup`, `teardown` and `getVmContext` methods. You can also pass variables from this module to your test suites by assigning them to `this.global` object – this will make them available in your test suites as global variables. The constructor is passed [`globalConfig`](https://github.com/jestjs/jest/blob/v29.2.1/packages/jest-types/src/Config.ts#L358-L422) and [`projectConfig`](https://github.com/jestjs/jest/blob/v29.2.1/packages/jest-types/src/Config.ts#L424-L481) as its first argument, and [`testEnvironmentContext`](https://github.com/jestjs/jest/blob/491e7cb0f2daa8263caccc72d48bdce7ba759b11/packages/jest-environment/src/index.ts#L13) as its second.
1912-
1913-
The class may optionally expose an asynchronous `handleTestEvent` method to bind to events fired by [`jest-circus`](https://github.com/jestjs/jest/tree/main/packages/jest-circus). Normally, `jest-circus` test runner would pause until a promise returned from `handleTestEvent` gets fulfilled, **except for the next events**: `start_describe_definition`, `finish_describe_definition`, `add_hook`, `add_test` or `error` (for the up-to-date list you can look at [SyncEvent type in the types definitions](https://github.com/jestjs/jest/tree/main/packages/jest-types/src/Circus.ts)). That is caused by backward compatibility reasons and `process.on('unhandledRejection', callback)` signature, but that usually should not be a problem for most of the use cases.
1913+
```ts tab title="my-test.spec.ts"
1914+
/**
1915+
* @jest-environment jsdom
1916+
*/
19141917

1915-
Any docblock pragmas in test files will be passed to the environment constructor and can be used for per-test configuration. If the pragma does not have a value, it will be present in the object with its value set to an empty string. If the pragma is not present, it will not be present in the object.
1918+
test('use jsdom in this test file', () => {
1919+
const element = document.createElement('div');
1920+
expect(element).not.toBeNull();
1921+
});
1922+
```
19161923

1917-
To use this class as your custom environment, refer to it by its full path within the project. For example, if your class is stored in `my-custom-environment.js` in some subfolder of your project, then the annotation might look like this:
1924+
- With custom environment:
19181925

1919-
```js
1926+
```js tab title="my-test.spec.js"
19201927
/**
1921-
* @jest-environment ./src/test/my-custom-environment
1928+
* @jest-environment ./my-custom-environment.js
19221929
*/
1923-
```
19241930

1925-
:::info
1926-
1927-
TestEnvironment is sandboxed. Each test suite will trigger setup/teardown in their own TestEnvironment.
1931+
test('use jsdom in this test file', () => {
1932+
const element = document.createElement('div');
1933+
expect(element).not.toBeNull();
1934+
});
1935+
```
19281936

1929-
:::
1937+
```ts tab title="my-test.spec.ts"
1938+
/**
1939+
* @jest-environment ./my-custom-environment.ts
1940+
*/
19301941

1931-
Example:
1942+
test('use jsdom in this test file', () => {
1943+
const element = document.createElement('div');
1944+
expect(element).not.toBeNull();
1945+
});
1946+
```
19321947

1933-
```js
1934-
// my-custom-environment
1935-
const NodeEnvironment = require('jest-environment-node').TestEnvironment;
1948+
You can also define custom environment. When non-builtin environment is used, Jest will try to load either the file path or the package name defined as value for `testEnvironment`. That file or the package should export an object with the shape of `JestEnvironment`:
19361949

1937-
class CustomEnvironment extends NodeEnvironment {
1950+
```js tab title="environment.js"
1951+
/**
1952+
* @implements {import('@jest/environment').JestEnvironment}
1953+
*/
1954+
class CustomEnvironment {
19381955
constructor(config, context) {
1939-
super(config, context);
1940-
console.log(config.globalConfig);
1941-
console.log(config.projectConfig);
1942-
this.testPath = context.testPath;
1943-
this.docblockPragmas = context.docblockPragmas;
1944-
}
1945-
1946-
async setup() {
1947-
await super.setup();
1948-
await someSetupTasks(this.testPath);
1949-
this.global.someGlobalObject = createGlobalObject();
1950-
1951-
// Will trigger if docblock contains @my-custom-pragma my-pragma-value
1952-
if (this.docblockPragmas['my-custom-pragma'] === 'my-pragma-value') {
1953-
// ...
1954-
}
1955-
}
1956-
1957-
async teardown() {
1958-
this.global.someGlobalObject = destroyGlobalObject();
1959-
await someTeardownTasks();
1960-
await super.teardown();
1956+
const {projectConfig} = config;
1957+
// Implement the constructor
19611958
}
19621959

1960+
// Example of a method
19631961
getVmContext() {
1964-
return super.getVmContext();
1965-
}
1966-
1967-
async handleTestEvent(event, state) {
1968-
if (event.name === 'test_start') {
1969-
// ...
1970-
}
1962+
return null;
19711963
}
1964+
// Implement the required methods here
19721965
}
19731966

19741967
module.exports = CustomEnvironment;
19751968
```
19761969

1977-
```js
1978-
// my-test-suite
1979-
/**
1980-
* @jest-environment ./my-custom-environment
1981-
*/
1982-
let someGlobalObject;
1970+
```ts tab title="environment.ts"
1971+
import type {
1972+
EnvironmentContext,
1973+
JestEnvironment,
1974+
JestEnvironmentConfig,
1975+
} from '@jest/environment';
19831976

1984-
beforeAll(() => {
1985-
someGlobalObject = globalThis.someGlobalObject;
1986-
});
1977+
export default class CustomEnvironment implements JestEnvironment {
1978+
constructor(config: JestEnvironmentConfig, context: EnvironmentContext) {
1979+
const {projectConfig} = config;
1980+
// Implement the constructor
1981+
}
1982+
1983+
// Example of a method
1984+
getVmContext() {
1985+
return null;
1986+
}
1987+
// Implement the required methods here
1988+
}
19871989
```
19881990

1991+
Jest also exposes `builtinEnvironments` through `jest-environment-node` and `jest-environment-jsdom` packages, in case you just want to extend it. You can read more about extending environments in [our guide](TestEnvironment.md).
1992+
19891993
### `testEnvironmentOptions` \[Object]
19901994

19911995
Default: `{}`
19921996

1993-
Test environment options that will be passed to the `testEnvironment`. The relevant options depend on the environment.
1997+
Test environment options that will be passed to the `testEnvironment`. The relevant options depend on the environment being used.
1998+
1999+
#### Node Environment Options
2000+
2001+
When using the `node` environment, you can configure various options that are passed to `runInContext`. These options include:
19942002

1995-
For example, you can override options passed to [`jsdom`](https://github.com/jsdom/jsdom):
2003+
- **`globalsCleanup`** (**'on'** | **'soft'** | **'off'**): Controls cleanup of global variables between tests. Default: `'soft'`.
2004+
- All the options listed in the [vm.runInContext](https://nodejs.org/api/vm.html#scriptrunincontextcontextifiedobject-options) documentation
2005+
2006+
#### JSDOM Environment Options
2007+
2008+
When using the `jsdom` environment, you can configure various options that are passed to [jsdom](https://github.com/jsdom/jsdom). These options include:
2009+
2010+
- **`url`** - The URL of the page (affects `window.location` and relative URLs). Default: `"http://localhost"`
2011+
- **`userAgent`** - The user agent string. Default: a generic user agent
2012+
- All the options listed in the [jsdom](https://github.com/jsdom/jsdom)
2013+
2014+
For example, you can override options passed to `jsdom`:
19962015

19972016
```js tab title="jest.config.js"
19982017
const {defineConfig} = require('jest');
19992018

20002019
module.exports = defineConfig({
20012020
testEnvironment: 'jsdom',
20022021
testEnvironmentOptions: {
2003-
html: '<html lang="zh-cmn-Hant"></html>',
2022+
html: '<html lang="en-US"></html>',
20042023
url: 'https://jestjs.io/',
20052024
userAgent: 'Agent/007',
20062025
},
@@ -2013,14 +2032,23 @@ import {defineConfig} from 'jest';
20132032
export default defineConfig({
20142033
testEnvironment: 'jsdom',
20152034
testEnvironmentOptions: {
2016-
html: '<html lang="zh-cmn-Hant"></html>',
2035+
html: '<html lang="en-US"></html>',
20172036
url: 'https://jestjs.io/',
20182037
userAgent: 'Agent/007',
20192038
},
20202039
});
20212040
```
20222041

2023-
Both `jest-environment-jsdom` and `jest-environment-node` allow specifying `customExportConditions`, which allow you to control which versions of a library are loaded from `exports` in `package.json`. `jest-environment-jsdom` defaults to `['browser']`. `jest-environment-node` defaults to `['node', 'node-addons']`.
2042+
#### Custom Export Conditions
2043+
2044+
The `testEnvironmentOptions` allow specifying `customExportConditions`, which control which versions of a library are loaded from `exports` in `package.json`.
2045+
2046+
The built-in environments have the following defaults:
2047+
2048+
- `jest-environment-jsdom` defaults to `['browser']`
2049+
- `jest-environment-node` defaults to `['node', 'node-addons']`
2050+
2051+
For example, you can override `customExportConditions` passed to `jsdom`:
20242052

20252053
```js tab title="jest.config.js"
20262054
const {defineConfig} = require('jest');
@@ -2057,6 +2085,20 @@ test('use jsdom and set the URL in this test file', () => {
20572085
});
20582086
```
20592087

2088+
You can combine multiple options:
2089+
2090+
```js
2091+
/**
2092+
* @jest-environment jsdom
2093+
* @jest-environment-options {"url": "https://example.com/", "userAgent": "Custom Agent"}
2094+
*/
2095+
2096+
test('use custom URL and user agent', () => {
2097+
expect(window.location.href).toBe('https://example.com/');
2098+
expect(window.navigator.userAgent).toContain('Custom Agent');
2099+
});
2100+
```
2101+
20602102
### `testFailureExitCode` \[number]
20612103

20622104
Default: `1`

0 commit comments

Comments
 (0)