Skip to content

Commit 7751fe1

Browse files
committed
docs: update testEnvironment and testEnvironmentOptions doc
1 parent 3e87145 commit 7751fe1

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
@@ -1837,15 +1837,17 @@ More about serializers API can be found [here](https://github.com/jestjs/jest/tr
18371837

18381838
:::
18391839

1840-
### `testEnvironment` \[string]
1840+
### `testEnvironment` \[node | jsdom | string]
18411841

1842-
Default: `"node"`
1842+
Default: `node`
18431843

18441844
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.
18451845

18461846
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:
18471847

1848-
```js
1848+
- With built-in environments:
1849+
1850+
```js tab title="my-test.spec.js"
18491851
/**
18501852
* @jest-environment jsdom
18511853
*/
@@ -1856,99 +1858,116 @@ test('use jsdom in this test file', () => {
18561858
});
18571859
```
18581860

1859-
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.
1860-
1861-
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.
1861+
```ts tab title="my-test.spec.ts"
1862+
/**
1863+
* @jest-environment jsdom
1864+
*/
18621865

1863-
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.
1866+
test('use jsdom in this test file', () => {
1867+
const element = document.createElement('div');
1868+
expect(element).not.toBeNull();
1869+
});
1870+
```
18641871

1865-
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:
1872+
- With custom environment:
18661873

1867-
```js
1874+
```js tab title="my-test.spec.js"
18681875
/**
1869-
* @jest-environment ./src/test/my-custom-environment
1876+
* @jest-environment ./my-custom-environment.js
18701877
*/
1871-
```
18721878

1873-
:::info
1874-
1875-
TestEnvironment is sandboxed. Each test suite will trigger setup/teardown in their own TestEnvironment.
1879+
test('use jsdom in this test file', () => {
1880+
const element = document.createElement('div');
1881+
expect(element).not.toBeNull();
1882+
});
1883+
```
18761884

1877-
:::
1885+
```ts tab title="my-test.spec.ts"
1886+
/**
1887+
* @jest-environment ./my-custom-environment.ts
1888+
*/
18781889

1879-
Example:
1890+
test('use jsdom in this test file', () => {
1891+
const element = document.createElement('div');
1892+
expect(element).not.toBeNull();
1893+
});
1894+
```
18801895

1881-
```js
1882-
// my-custom-environment
1883-
const NodeEnvironment = require('jest-environment-node').TestEnvironment;
1896+
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`:
18841897

1885-
class CustomEnvironment extends NodeEnvironment {
1898+
```js tab title="environment.js"
1899+
/**
1900+
* @implements {import('@jest/environment').JestEnvironment}
1901+
*/
1902+
class CustomEnvironment {
18861903
constructor(config, context) {
1887-
super(config, context);
1888-
console.log(config.globalConfig);
1889-
console.log(config.projectConfig);
1890-
this.testPath = context.testPath;
1891-
this.docblockPragmas = context.docblockPragmas;
1892-
}
1893-
1894-
async setup() {
1895-
await super.setup();
1896-
await someSetupTasks(this.testPath);
1897-
this.global.someGlobalObject = createGlobalObject();
1898-
1899-
// Will trigger if docblock contains @my-custom-pragma my-pragma-value
1900-
if (this.docblockPragmas['my-custom-pragma'] === 'my-pragma-value') {
1901-
// ...
1902-
}
1903-
}
1904-
1905-
async teardown() {
1906-
this.global.someGlobalObject = destroyGlobalObject();
1907-
await someTeardownTasks();
1908-
await super.teardown();
1904+
const {projectConfig} = config;
1905+
// Implement the constructor
19091906
}
19101907

1908+
// Example of a method
19111909
getVmContext() {
1912-
return super.getVmContext();
1913-
}
1914-
1915-
async handleTestEvent(event, state) {
1916-
if (event.name === 'test_start') {
1917-
// ...
1918-
}
1910+
return null;
19191911
}
1912+
// Implement the required methods here
19201913
}
19211914

19221915
module.exports = CustomEnvironment;
19231916
```
19241917

1925-
```js
1926-
// my-test-suite
1927-
/**
1928-
* @jest-environment ./my-custom-environment
1929-
*/
1930-
let someGlobalObject;
1918+
```ts tab title="environment.ts"
1919+
import type {
1920+
EnvironmentContext,
1921+
JestEnvironment,
1922+
JestEnvironmentConfig,
1923+
} from '@jest/environment';
19311924

1932-
beforeAll(() => {
1933-
someGlobalObject = globalThis.someGlobalObject;
1934-
});
1925+
export default class CustomEnvironment implements JestEnvironment {
1926+
constructor(config: JestEnvironmentConfig, context: EnvironmentContext) {
1927+
const {projectConfig} = config;
1928+
// Implement the constructor
1929+
}
1930+
1931+
// Example of a method
1932+
getVmContext() {
1933+
return null;
1934+
}
1935+
// Implement the required methods here
1936+
}
19351937
```
19361938

1939+
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).
1940+
19371941
### `testEnvironmentOptions` \[Object]
19381942

19391943
Default: `{}`
19401944

1941-
Test environment options that will be passed to the `testEnvironment`. The relevant options depend on the environment.
1945+
Test environment options that will be passed to the `testEnvironment`. The relevant options depend on the environment being used.
1946+
1947+
#### Node Environment Options
1948+
1949+
When using the `node` environment, you can configure various options that are passed to `runInContext`. These options include:
19421950

1943-
For example, you can override options passed to [`jsdom`](https://github.com/jsdom/jsdom):
1951+
- **`globalsCleanup`** (**'on'** | **'soft'** | **'off'**): Controls cleanup of global variables between tests. Default: `'soft'`.
1952+
- All the options listed in the [vm.runInContext](https://nodejs.org/api/vm.html#scriptrunincontextcontextifiedobject-options) documentation
1953+
1954+
#### JSDOM Environment Options
1955+
1956+
When using the `jsdom` environment, you can configure various options that are passed to [jsdom](https://github.com/jsdom/jsdom). These options include:
1957+
1958+
- **`url`** - The URL of the page (affects `window.location` and relative URLs). Default: `"http://localhost"`
1959+
- **`userAgent`** - The user agent string. Default: a generic user agent
1960+
- All the options listed in the [jsdom](https://github.com/jsdom/jsdom)
1961+
1962+
For example, you can override options passed to `jsdom`:
19441963

19451964
```js tab title="jest.config.js"
19461965
const {defineConfig} = require('jest');
19471966

19481967
module.exports = defineConfig({
19491968
testEnvironment: 'jsdom',
19501969
testEnvironmentOptions: {
1951-
html: '<html lang="zh-cmn-Hant"></html>',
1970+
html: '<html lang="en-US"></html>',
19521971
url: 'https://jestjs.io/',
19531972
userAgent: 'Agent/007',
19541973
},
@@ -1961,14 +1980,23 @@ import {defineConfig} from 'jest';
19611980
export default defineConfig({
19621981
testEnvironment: 'jsdom',
19631982
testEnvironmentOptions: {
1964-
html: '<html lang="zh-cmn-Hant"></html>',
1983+
html: '<html lang="en-US"></html>',
19651984
url: 'https://jestjs.io/',
19661985
userAgent: 'Agent/007',
19671986
},
19681987
});
19691988
```
19701989

1971-
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']`.
1990+
#### Custom Export Conditions
1991+
1992+
The `testEnvironmentOptions` allow specifying `customExportConditions`, which control which versions of a library are loaded from `exports` in `package.json`.
1993+
1994+
The built-in environments have the following defaults:
1995+
1996+
- `jest-environment-jsdom` defaults to `['browser']`
1997+
- `jest-environment-node` defaults to `['node', 'node-addons']`
1998+
1999+
For example, you can override `customExportConditions` passed to `jsdom`:
19722000

19732001
```js tab title="jest.config.js"
19742002
const {defineConfig} = require('jest');
@@ -2005,6 +2033,20 @@ test('use jsdom and set the URL in this test file', () => {
20052033
});
20062034
```
20072035

2036+
You can combine multiple options:
2037+
2038+
```js
2039+
/**
2040+
* @jest-environment jsdom
2041+
* @jest-environment-options {"url": "https://example.com/", "userAgent": "Custom Agent"}
2042+
*/
2043+
2044+
test('use custom URL and user agent', () => {
2045+
expect(window.location.href).toBe('https://example.com/');
2046+
expect(window.navigator.userAgent).toContain('Custom Agent');
2047+
});
2048+
```
2049+
20082050
### `testFailureExitCode` \[number]
20092051

20102052
Default: `1`

0 commit comments

Comments
 (0)