diff --git a/CHANGELOG.md b/CHANGELOG.md index 762bc5c314a9..0d0a100829e0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,16 +4,27 @@ ### Fixes +- `[jest-core]` Fix typo in `scheduleAndRun` performance marker ([#14434](https://github.com/jestjs/jest/pull/14434)) +- `[jest-runner]` Handle unsafe worker_threads structureClone with function type in matchers. ([#14436](https://github.com/jestjs/jest/pull/14436)) +- `[jest-worker]` Additional error wrapper for `parentPort.postMessage` to fix unhandled `DataCloneError`. ([#14436](https://github.com/jestjs/jest/pull/14436)) + +### Chore & Maintenance + +## 29.6.3 + - `[expect, @jest/expect-utils]` `ObjectContaining` support `sumbol` as key ([#14414](https://github.com/jestjs/jest/pull/14414)) - `[expect]` Remove `@types/node` from dependencies ([#14385](https://github.com/jestjs/jest/pull/14385)) - `[jest-core]` Use workers in watch mode by default to avoid crashes ([#14059](https://github.com/facebook/jest/pull/14059) & [#14085](https://github.com/facebook/jest/pull/14085)). - `[jest-reporters]` Update `istanbul-lib-instrument` dependency to v6. ([#14401](https://github.com/jestjs/jest/pull/14401)) -- `[jest-runner]` Handle unsafe worker_threads structureClone with function type in matchers. ([#14436](https://github.com/jestjs/jest/pull/14436)) -- `[jest-worker]` Additional error wrapper for `parentPort.postMessage` to fix unhandled `DataCloneError`. ([#14436](https://github.com/jestjs/jest/pull/14436)) +- `[jest-mock]` Revert [#13692](https://github.com/jestjs/jest/pull/13692) as it was a breaking change ([#14429](https://github.com/jestjs/jest/pull/14429)) +- `[jest-mock]` Revert [#13866](https://github.com/jestjs/jest/pull/13866) as it was a breaking change ([#14429](https://github.com/jestjs/jest/pull/14429)) +- `[jest-mock]` Revert [#13867](https://github.com/jestjs/jest/pull/13867) as it was a breaking change ([#14429](https://github.com/jestjs/jest/pull/14429)) +- `[@jest/reporters]` Marks Reporter's hooks as optional ([#14433](https://github.com/jestjs/jest/pull/14433)) +- `[jest-runtime]` Fix dynamic ESM import module bug when loaded module through `jest.isolateModulesAsync` ([#14397](https://github.com/jestjs/jest/pull/14397)) ### Chore & Maintenance -### Performance +- `[jest-changed-files, jest-circus, jest-console, @jest/core, @jest/runtime, @jest/transform]` Use `invariant` and `notEmpty` from `jest-util` rather than own internal ([#14366](https://github.com/jestjs/jest/pull/14366)) ## 29.6.2 diff --git a/docs/Configuration.md b/docs/Configuration.md index 4e23e314b103..1a50070df269 100644 --- a/docs/Configuration.md +++ b/docs/Configuration.md @@ -1401,7 +1401,7 @@ Hungry for reporters? Take a look at long list of [awesome reporters](https://gi ::: -Custom reporter module must export a class that takes [`globalConfig`](https://github.com/jestjs/jest/blob/v29.2.1/packages/jest-types/src/Config.ts#L358-L422), `reporterOptions` and `reporterContext` as constructor arguments and implements at least `onRunComplete()` method (for the full list of methods and argument types see `Reporter` interface in [packages/jest-reporters/src/types.ts](https://github.com/jestjs/jest/blob/main/packages/jest-reporters/src/types.ts)): +Custom reporter module must export a class that takes [`globalConfig`](https://github.com/jestjs/jest/blob/v29.2.1/packages/jest-types/src/Config.ts#L358-L422), `reporterOptions` and `reporterContext` as constructor arguments: ```js title="custom-reporter.js" class CustomReporter { @@ -1430,6 +1430,12 @@ class CustomReporter { module.exports = CustomReporter; ``` +:::note + +For the full list of hooks and argument types see the `Reporter` interface in [packages/jest-reporters/src/types.ts](https://github.com/jestjs/jest/blob/main/packages/jest-reporters/src/types.ts). + +::: + ### `resetMocks` \[boolean] Default: `false` diff --git a/docs/ManualMocks.md b/docs/ManualMocks.md index d166114387eb..7d7e9ab8f1d1 100644 --- a/docs/ManualMocks.md +++ b/docs/ManualMocks.md @@ -29,7 +29,7 @@ Scoped modules (also known as [scoped packages](https://docs.npmjs.com/cli/v6/us :::caution -If we want to mock Node's build-in modules (e.g.: `fs` or `path`), then explicitly calling e.g. `jest.mock('path')` is **required**, because build-in modules are not mocked by default. +If we want to mock Node's built-in modules (e.g.: `fs` or `path`), then explicitly calling e.g. `jest.mock('path')` is **required**, because built-in modules are not mocked by default. ::: @@ -110,7 +110,7 @@ fs.readdirSync = readdirSync; module.exports = fs; ``` -Now we write our test. In this case `jest.mock('fs')` must be called explicitly, because `fs` is Node’s build-in module: +Now we write our test. In this case `jest.mock('fs')` must be called explicitly, because `fs` is Node’s built-in module: ```javascript title="__tests__/FileSummarizer-test.js" 'use strict'; diff --git a/docs/MockFunctionAPI.md b/docs/MockFunctionAPI.md index 5ffb11992b84..6282e1538f2d 100644 --- a/docs/MockFunctionAPI.md +++ b/docs/MockFunctionAPI.md @@ -128,9 +128,7 @@ Beware that `mockFn.mockClear()` will replace `mockFn.mock`, not just reset the ### `mockFn.mockReset()` -Does everything that [`mockFn.mockClear()`](#mockfnmockclear) does, and also removes any mocked return values or implementations. - -This is useful when you want to completely reset a _mock_ back to its initial state. +Does everything that [`mockFn.mockClear()`](#mockfnmockclear) does, and also replaces the mock implementation with an empty function, returning `undefined`. The [`resetMocks`](configuration#resetmocks-boolean) configuration option is available to reset mocks automatically before each test. diff --git a/e2e/__tests__/__snapshots__/circusDeclarationErrors.test.ts.snap b/e2e/__tests__/__snapshots__/circusDeclarationErrors.test.ts.snap index 59acd31aae2f..0e49b62527c6 100644 --- a/e2e/__tests__/__snapshots__/circusDeclarationErrors.test.ts.snap +++ b/e2e/__tests__/__snapshots__/circusDeclarationErrors.test.ts.snap @@ -16,7 +16,7 @@ exports[`defining tests and hooks asynchronously throws 1`] = ` 14 | }); 15 | }); - at eventHandler (../../packages/jest-circus/build/eventHandler.js:140:11) + at eventHandler (../../packages/jest-circus/build/eventHandler.js:141:11) at test (__tests__/asyncDefinition.test.js:12:5) ● Test suite failed to run @@ -31,7 +31,7 @@ exports[`defining tests and hooks asynchronously throws 1`] = ` 15 | }); 16 | - at eventHandler (../../packages/jest-circus/build/eventHandler.js:103:11) + at eventHandler (../../packages/jest-circus/build/eventHandler.js:104:11) at afterAll (__tests__/asyncDefinition.test.js:13:5) ● Test suite failed to run @@ -46,7 +46,7 @@ exports[`defining tests and hooks asynchronously throws 1`] = ` 20 | }); 21 | - at eventHandler (../../packages/jest-circus/build/eventHandler.js:140:11) + at eventHandler (../../packages/jest-circus/build/eventHandler.js:141:11) at test (__tests__/asyncDefinition.test.js:18:3) ● Test suite failed to run @@ -60,6 +60,6 @@ exports[`defining tests and hooks asynchronously throws 1`] = ` 20 | }); 21 | - at eventHandler (../../packages/jest-circus/build/eventHandler.js:103:11) + at eventHandler (../../packages/jest-circus/build/eventHandler.js:104:11) at afterAll (__tests__/asyncDefinition.test.js:19:3)" `; diff --git a/e2e/__tests__/__snapshots__/isolateModulesAsync.test.ts.snap b/e2e/__tests__/__snapshots__/isolateModulesAsync.test.ts.snap new file mode 100644 index 000000000000..c1577869b112 --- /dev/null +++ b/e2e/__tests__/__snapshots__/isolateModulesAsync.test.ts.snap @@ -0,0 +1,9 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`runs test with isolate modules async import 1`] = ` +"Test Suites: 1 passed, 1 total +Tests: 1 passed, 1 total +Snapshots: 0 total +Time: <> +Ran all test suites." +`; diff --git a/e2e/__tests__/isolateModulesAsync.test.ts b/e2e/__tests__/isolateModulesAsync.test.ts new file mode 100644 index 000000000000..6eb8e570225d --- /dev/null +++ b/e2e/__tests__/isolateModulesAsync.test.ts @@ -0,0 +1,20 @@ +/** + * 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 {extractSummary} from '../Utils'; +import runJest from '../runJest'; + +test('runs test with isolate modules async import', () => { + const {exitCode, stderr} = runJest('isolate-modules-async', [], { + nodeOptions: '--experimental-vm-modules --no-warnings', + }); + + const {summary} = extractSummary(stderr); + + expect(summary).toMatchSnapshot(); + expect(exitCode).toBe(0); +}); diff --git a/e2e/isolate-modules-async/__tests__/main.js b/e2e/isolate-modules-async/__tests__/main.js new file mode 100644 index 000000000000..70b9a91b908a --- /dev/null +++ b/e2e/isolate-modules-async/__tests__/main.js @@ -0,0 +1,22 @@ +/** + * 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 {jest} from '@jest/globals'; + +test('should have a fresh module state in each isolateModulesAsync context', async () => { + await jest.isolateModulesAsync(async () => { + const {getState, incState} = await import('../main.js'); + expect(getState()).toBe(0); + incState(); + expect(getState()).toBe(1); + }); + await jest.isolateModulesAsync(async () => { + const {getState, incState} = await import('../main.js'); + expect(getState()).toBe(0); + incState(); + expect(getState()).toBe(1); + }); +}); diff --git a/e2e/isolate-modules-async/main.js b/e2e/isolate-modules-async/main.js new file mode 100644 index 000000000000..fd9d95f6fab5 --- /dev/null +++ b/e2e/isolate-modules-async/main.js @@ -0,0 +1,15 @@ +/** + * 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. + */ +let myState = 0; + +export function incState() { + myState += 1; +} + +export function getState() { + return myState; +} diff --git a/e2e/isolate-modules-async/package.json b/e2e/isolate-modules-async/package.json new file mode 100644 index 000000000000..8ae42c533cda --- /dev/null +++ b/e2e/isolate-modules-async/package.json @@ -0,0 +1,8 @@ +{ + "name": "isolate-modules-async", + "type": "module", + "jest": { + "transform": {}, + "testEnvironment": "node" + } +} diff --git a/lerna.json b/lerna.json index ea81fd67af3d..9247a8fa99f6 100644 --- a/lerna.json +++ b/lerna.json @@ -8,5 +8,5 @@ "syncWorkspaceLock": true } }, - "version": "29.6.2" + "version": "29.6.3" } diff --git a/packages/babel-jest/package.json b/packages/babel-jest/package.json index 27bda5279438..4e2159511c03 100644 --- a/packages/babel-jest/package.json +++ b/packages/babel-jest/package.json @@ -1,7 +1,7 @@ { "name": "babel-jest", "description": "Jest plugin to use babel for transformation.", - "version": "29.6.2", + "version": "29.6.3", "repository": { "type": "git", "url": "https://github.com/jestjs/jest.git", diff --git a/packages/babel-plugin-jest-hoist/package.json b/packages/babel-plugin-jest-hoist/package.json index d56194756057..486107b0be41 100644 --- a/packages/babel-plugin-jest-hoist/package.json +++ b/packages/babel-plugin-jest-hoist/package.json @@ -1,6 +1,6 @@ { "name": "babel-plugin-jest-hoist", - "version": "29.5.0", + "version": "29.6.3", "repository": { "type": "git", "url": "https://github.com/jestjs/jest.git", diff --git a/packages/babel-preset-jest/package.json b/packages/babel-preset-jest/package.json index 4d664eca8cd4..e2e05eaf9129 100644 --- a/packages/babel-preset-jest/package.json +++ b/packages/babel-preset-jest/package.json @@ -1,6 +1,6 @@ { "name": "babel-preset-jest", - "version": "29.5.0", + "version": "29.6.3", "repository": { "type": "git", "url": "https://github.com/jestjs/jest.git", diff --git a/packages/diff-sequences/package.json b/packages/diff-sequences/package.json index 4ba131b9da33..9f5ac6018011 100644 --- a/packages/diff-sequences/package.json +++ b/packages/diff-sequences/package.json @@ -1,6 +1,6 @@ { "name": "diff-sequences", - "version": "29.4.3", + "version": "29.6.3", "repository": { "type": "git", "url": "https://github.com/jestjs/jest.git", diff --git a/packages/expect-utils/package.json b/packages/expect-utils/package.json index 7aa8251bb7ee..efd3dc28339b 100644 --- a/packages/expect-utils/package.json +++ b/packages/expect-utils/package.json @@ -1,6 +1,6 @@ { "name": "@jest/expect-utils", - "version": "29.6.2", + "version": "29.6.3", "repository": { "type": "git", "url": "https://github.com/jestjs/jest.git", diff --git a/packages/expect/package.json b/packages/expect/package.json index 9ec02caab9b1..55e9f07da901 100644 --- a/packages/expect/package.json +++ b/packages/expect/package.json @@ -1,6 +1,6 @@ { "name": "expect", - "version": "29.6.2", + "version": "29.6.3", "repository": { "type": "git", "url": "https://github.com/jestjs/jest.git", diff --git a/packages/jest-changed-files/package.json b/packages/jest-changed-files/package.json index a0a5c5cd1e25..e7bba017b788 100644 --- a/packages/jest-changed-files/package.json +++ b/packages/jest-changed-files/package.json @@ -1,6 +1,6 @@ { "name": "jest-changed-files", - "version": "29.5.0", + "version": "29.6.3", "repository": { "type": "git", "url": "https://github.com/jestjs/jest.git", @@ -18,6 +18,7 @@ }, "dependencies": { "execa": "^5.0.0", + "jest-util": "workspace:^", "p-limit": "^3.1.0" }, "engines": { diff --git a/packages/jest-changed-files/src/index.ts b/packages/jest-changed-files/src/index.ts index df3cb0723c34..3577d49e05ee 100644 --- a/packages/jest-changed-files/src/index.ts +++ b/packages/jest-changed-files/src/index.ts @@ -7,6 +7,7 @@ */ import pLimit = require('p-limit'); +import {isNonNullable} from 'jest-util'; import git from './git'; import hg from './hg'; import sl from './sl'; @@ -16,10 +17,6 @@ type RootPromise = ReturnType; export type {ChangedFiles, ChangedFilesPromise} from './types'; -function notEmpty(value: T | null | undefined): value is T { - return value != null; -} - // This is an arbitrary number. The main goal is to prevent projects with // many roots (50+) from spawning too many processes at once. const mutex = pLimit(5); @@ -78,8 +75,8 @@ export const findRepos = async (roots: Array): Promise => { const slRepos = await Promise.all(roots.map(findSlRoot)); return { - git: new Set(gitRepos.filter(notEmpty)), - hg: new Set(hgRepos.filter(notEmpty)), - sl: new Set(slRepos.filter(notEmpty)), + git: new Set(gitRepos.filter(isNonNullable)), + hg: new Set(hgRepos.filter(isNonNullable)), + sl: new Set(slRepos.filter(isNonNullable)), }; }; diff --git a/packages/jest-changed-files/tsconfig.json b/packages/jest-changed-files/tsconfig.json index 12688a2879d6..aad1b761e910 100644 --- a/packages/jest-changed-files/tsconfig.json +++ b/packages/jest-changed-files/tsconfig.json @@ -4,5 +4,6 @@ "rootDir": "src", "outDir": "build" }, - "include": ["./src/**/*"] + "include": ["./src/**/*"], + "references": [{"path": "../jest-util"}] } diff --git a/packages/jest-circus/package.json b/packages/jest-circus/package.json index 9e9253fe952a..701df52e3a06 100644 --- a/packages/jest-circus/package.json +++ b/packages/jest-circus/package.json @@ -1,6 +1,6 @@ { "name": "jest-circus", - "version": "29.6.2", + "version": "29.6.3", "repository": { "type": "git", "url": "https://github.com/jestjs/jest.git", diff --git a/packages/jest-circus/src/eventHandler.ts b/packages/jest-circus/src/eventHandler.ts index 0a437df1ed9a..4c401cada760 100644 --- a/packages/jest-circus/src/eventHandler.ts +++ b/packages/jest-circus/src/eventHandler.ts @@ -6,6 +6,7 @@ */ import type {Circus} from '@jest/types'; +import {invariant} from 'jest-util'; import { injectGlobalErrorHandlers, restoreGlobalErrorHandlers, @@ -15,7 +16,6 @@ import { addErrorToEachTestUnderDescribe, describeBlockHasTests, getTestDuration, - invariant, makeDescribe, makeTest, } from './utils'; diff --git a/packages/jest-circus/src/run.ts b/packages/jest-circus/src/run.ts index 02766579678f..eac6a20b06e6 100644 --- a/packages/jest-circus/src/run.ts +++ b/packages/jest-circus/src/run.ts @@ -9,6 +9,7 @@ import {AsyncLocalStorage} from 'async_hooks'; import pLimit = require('p-limit'); import {jestExpect} from '@jest/expect'; import type {Circus} from '@jest/types'; +import {invariant} from 'jest-util'; import shuffleArray, {RandomNumberGenerator, rngBuilder} from './shuffleArray'; import {dispatch, getState} from './state'; import {RETRY_TIMES} from './types'; @@ -17,7 +18,6 @@ import { getAllHooksForDescribe, getEachHooksForTest, getTestID, - invariant, makeRunResult, } from './utils'; diff --git a/packages/jest-circus/src/utils.ts b/packages/jest-circus/src/utils.ts index 9e1c8d74838b..fa45f4fbb744 100644 --- a/packages/jest-circus/src/utils.ts +++ b/packages/jest-circus/src/utils.ts @@ -17,6 +17,7 @@ import { ErrorWithStack, convertDescriptorToString, formatTime, + invariant, isPromise, } from 'jest-util'; import {format as prettyFormat} from 'pretty-format'; @@ -456,15 +457,6 @@ export const addErrorToEachTestUnderDescribe = ( } }; -export function invariant( - condition: unknown, - message?: string, -): asserts condition { - if (!condition) { - throw new Error(message); - } -} - type TestDescription = { ancestorTitles: Array; fullName: string; diff --git a/packages/jest-cli/package.json b/packages/jest-cli/package.json index 684aa0f981df..5c797662fb44 100644 --- a/packages/jest-cli/package.json +++ b/packages/jest-cli/package.json @@ -1,7 +1,7 @@ { "name": "jest-cli", "description": "Delightful JavaScript Testing.", - "version": "29.6.2", + "version": "29.6.3", "main": "./build/index.js", "types": "./build/index.d.ts", "exports": { diff --git a/packages/jest-config/package.json b/packages/jest-config/package.json index 2ac8f06dfabd..a6f459b33349 100644 --- a/packages/jest-config/package.json +++ b/packages/jest-config/package.json @@ -1,6 +1,6 @@ { "name": "jest-config", - "version": "29.6.2", + "version": "29.6.3", "repository": { "type": "git", "url": "https://github.com/jestjs/jest.git", diff --git a/packages/jest-console/package.json b/packages/jest-console/package.json index bd69334c0be5..0fd766e197e2 100644 --- a/packages/jest-console/package.json +++ b/packages/jest-console/package.json @@ -1,6 +1,6 @@ { "name": "@jest/console", - "version": "29.6.2", + "version": "29.6.3", "repository": { "type": "git", "url": "https://github.com/jestjs/jest.git", diff --git a/packages/jest-console/src/BufferedConsole.ts b/packages/jest-console/src/BufferedConsole.ts index 526d51c38fdf..2ab7d73688ed 100644 --- a/packages/jest-console/src/BufferedConsole.ts +++ b/packages/jest-console/src/BufferedConsole.ts @@ -9,7 +9,7 @@ import {AssertionError, strict as assert} from 'assert'; import {Console} from 'console'; import {InspectOptions, format, formatWithOptions, inspect} from 'util'; import chalk = require('chalk'); -import {ErrorWithStack, formatTime} from 'jest-util'; +import {ErrorWithStack, formatTime, invariant} from 'jest-util'; import type { ConsoleBuffer, LogCounters, @@ -180,9 +180,3 @@ export default class BufferedConsole extends Console { return this._buffer.length ? this._buffer : undefined; } } - -function invariant(condition: boolean, message?: string): asserts condition { - if (!condition) { - throw new Error(message); - } -} diff --git a/packages/jest-core/package.json b/packages/jest-core/package.json index 7c6989e582dc..eab191df3de6 100644 --- a/packages/jest-core/package.json +++ b/packages/jest-core/package.json @@ -1,7 +1,7 @@ { "name": "@jest/core", "description": "Delightful JavaScript Testing.", - "version": "29.6.2", + "version": "29.6.3", "main": "./build/index.js", "types": "./build/index.d.ts", "exports": { diff --git a/packages/jest-core/src/TestScheduler.ts b/packages/jest-core/src/TestScheduler.ts index 2c53db5a41fc..77caa9a95c3f 100644 --- a/packages/jest-core/src/TestScheduler.ts +++ b/packages/jest-core/src/TestScheduler.ts @@ -38,7 +38,7 @@ import { buildSnapshotResolver, cleanup as cleanupSnapshots, } from 'jest-snapshot'; -import {ErrorWithStack, requireOrImportModule} from 'jest-util'; +import {ErrorWithStack, invariant, requireOrImportModule} from 'jest-util'; import type {TestWatcher} from 'jest-watcher'; import ReporterDispatcher from './ReporterDispatcher'; import {shouldRunInBand} from './testSchedulerHelper'; @@ -425,12 +425,6 @@ class TestScheduler { } } -function invariant(condition: unknown, message?: string): asserts condition { - if (!condition) { - throw new Error(message); - } -} - const createAggregatedResults = (numTotalTestSuites: number) => { const result = makeEmptyAggregatedTestResult(); result.numTotalTestSuites = numTotalTestSuites; diff --git a/packages/jest-core/src/lib/watchPluginsHelpers.ts b/packages/jest-core/src/lib/watchPluginsHelpers.ts index 08cf4cae06ad..0479f544beb4 100644 --- a/packages/jest-core/src/lib/watchPluginsHelpers.ts +++ b/packages/jest-core/src/lib/watchPluginsHelpers.ts @@ -6,6 +6,7 @@ */ import type {Config} from '@jest/types'; +import {isNonNullable} from 'jest-util'; import type {UsageData, WatchPlugin} from 'jest-watcher'; export const filterInteractivePlugins = ( @@ -27,10 +28,6 @@ export const filterInteractivePlugins = ( }); }; -function notEmpty(value: T | null | undefined): value is T { - return value != null; -} - export const getSortedUsageRows = ( watchPlugins: Array, globalConfig: Config.GlobalConfig, @@ -56,4 +53,4 @@ export const getSortedUsageRows = ( return 0; }) .map(p => p.getUsageInfo && p.getUsageInfo(globalConfig)) - .filter(notEmpty); + .filter(isNonNullable); diff --git a/packages/jest-core/src/runJest.ts b/packages/jest-core/src/runJest.ts index b3098231c32c..45b31137d292 100644 --- a/packages/jest-core/src/runJest.ts +++ b/packages/jest-core/src/runJest.ts @@ -299,7 +299,7 @@ export default async function runJest({ detail: {numTests: allTests.length}, }); const results = await scheduler.scheduleTests(allTests, testWatcher); - performance.mark('jest/scheduleAndRun:start'); + performance.mark('jest/scheduleAndRun:end'); performance.mark('jest/cacheResults:start'); sequencer.cacheResults(allTests, results); diff --git a/packages/jest-create-cache-key-function/package.json b/packages/jest-create-cache-key-function/package.json index 4446994ec170..547c07bfffd0 100644 --- a/packages/jest-create-cache-key-function/package.json +++ b/packages/jest-create-cache-key-function/package.json @@ -1,6 +1,6 @@ { "name": "@jest/create-cache-key-function", - "version": "29.6.2", + "version": "29.6.3", "repository": { "type": "git", "url": "https://github.com/jestjs/jest.git", diff --git a/packages/jest-diff/package.json b/packages/jest-diff/package.json index 6488ec8e3df3..0722c029965f 100644 --- a/packages/jest-diff/package.json +++ b/packages/jest-diff/package.json @@ -1,6 +1,6 @@ { "name": "jest-diff", - "version": "29.6.2", + "version": "29.6.3", "repository": { "type": "git", "url": "https://github.com/jestjs/jest.git", diff --git a/packages/jest-docblock/package.json b/packages/jest-docblock/package.json index df23f9d258ef..1970c08c8d10 100644 --- a/packages/jest-docblock/package.json +++ b/packages/jest-docblock/package.json @@ -1,6 +1,6 @@ { "name": "jest-docblock", - "version": "29.4.3", + "version": "29.6.3", "repository": { "type": "git", "url": "https://github.com/jestjs/jest.git", diff --git a/packages/jest-each/package.json b/packages/jest-each/package.json index 1005558319de..739341cc553a 100644 --- a/packages/jest-each/package.json +++ b/packages/jest-each/package.json @@ -1,6 +1,6 @@ { "name": "jest-each", - "version": "29.6.2", + "version": "29.6.3", "description": "Parameterised tests for Jest", "main": "./build/index.js", "types": "./build/index.d.ts", diff --git a/packages/jest-environment-jsdom/package.json b/packages/jest-environment-jsdom/package.json index 2060256623af..d8f8cf35e84a 100644 --- a/packages/jest-environment-jsdom/package.json +++ b/packages/jest-environment-jsdom/package.json @@ -1,6 +1,6 @@ { "name": "jest-environment-jsdom", - "version": "29.6.2", + "version": "29.6.3", "repository": { "type": "git", "url": "https://github.com/jestjs/jest.git", diff --git a/packages/jest-environment-node/package.json b/packages/jest-environment-node/package.json index 304ecf582529..5e38ba41cbf9 100644 --- a/packages/jest-environment-node/package.json +++ b/packages/jest-environment-node/package.json @@ -1,6 +1,6 @@ { "name": "jest-environment-node", - "version": "29.6.2", + "version": "29.6.3", "repository": { "type": "git", "url": "https://github.com/jestjs/jest.git", diff --git a/packages/jest-environment/package.json b/packages/jest-environment/package.json index a8c104f47811..b6f25ec5f97f 100644 --- a/packages/jest-environment/package.json +++ b/packages/jest-environment/package.json @@ -1,6 +1,6 @@ { "name": "@jest/environment", - "version": "29.6.2", + "version": "29.6.3", "repository": { "type": "git", "url": "https://github.com/jestjs/jest.git", diff --git a/packages/jest-expect/package.json b/packages/jest-expect/package.json index 578f6ca43c98..5c61eb63b37d 100644 --- a/packages/jest-expect/package.json +++ b/packages/jest-expect/package.json @@ -1,6 +1,6 @@ { "name": "@jest/expect", - "version": "29.6.2", + "version": "29.6.3", "repository": { "type": "git", "url": "https://github.com/jestjs/jest.git", diff --git a/packages/jest-fake-timers/package.json b/packages/jest-fake-timers/package.json index eea6721c0826..df04e61954ed 100644 --- a/packages/jest-fake-timers/package.json +++ b/packages/jest-fake-timers/package.json @@ -1,6 +1,6 @@ { "name": "@jest/fake-timers", - "version": "29.6.2", + "version": "29.6.3", "repository": { "type": "git", "url": "https://github.com/jestjs/jest.git", diff --git a/packages/jest-get-type/package.json b/packages/jest-get-type/package.json index 5463bac7458d..356782c0248c 100644 --- a/packages/jest-get-type/package.json +++ b/packages/jest-get-type/package.json @@ -1,7 +1,7 @@ { "name": "jest-get-type", "description": "A utility function to get the type of a value", - "version": "29.4.3", + "version": "29.6.3", "repository": { "type": "git", "url": "https://github.com/jestjs/jest.git", diff --git a/packages/jest-globals/package.json b/packages/jest-globals/package.json index 39797cfa07a3..29ddf25491da 100644 --- a/packages/jest-globals/package.json +++ b/packages/jest-globals/package.json @@ -1,6 +1,6 @@ { "name": "@jest/globals", - "version": "29.6.2", + "version": "29.6.3", "repository": { "type": "git", "url": "https://github.com/jestjs/jest.git", diff --git a/packages/jest-haste-map/package.json b/packages/jest-haste-map/package.json index b6964dae1346..5fb5d70866ce 100644 --- a/packages/jest-haste-map/package.json +++ b/packages/jest-haste-map/package.json @@ -1,6 +1,6 @@ { "name": "jest-haste-map", - "version": "29.6.2", + "version": "29.6.3", "repository": { "type": "git", "url": "https://github.com/jestjs/jest.git", diff --git a/packages/jest-haste-map/src/index.ts b/packages/jest-haste-map/src/index.ts index 5012d6ef1af5..37d7c0e2b171 100644 --- a/packages/jest-haste-map/src/index.ts +++ b/packages/jest-haste-map/src/index.ts @@ -13,7 +13,7 @@ import {deserialize, serialize} from 'v8'; import {Stats, readFileSync, writeFileSync} from 'graceful-fs'; import type {Config} from '@jest/types'; import {escapePathForRegex} from 'jest-regex-util'; -import {requireOrImportModule} from 'jest-util'; +import {invariant, requireOrImportModule} from 'jest-util'; import {JestWorkerFarm, Worker} from 'jest-worker'; import HasteFS from './HasteFS'; import HasteModuleMap from './ModuleMap'; @@ -131,12 +131,6 @@ const VCS_DIRECTORIES = ['.git', '.hg', '.sl'] .map(vcs => escapePathForRegex(path.sep + vcs + path.sep)) .join('|'); -function invariant(condition: unknown, message?: string): asserts condition { - if (!condition) { - throw new Error(message); - } -} - /** * HasteMap is a JavaScript implementation of Facebook's haste module system. * diff --git a/packages/jest-jasmine2/package.json b/packages/jest-jasmine2/package.json index 0953e9a2679a..acaddf6704b8 100644 --- a/packages/jest-jasmine2/package.json +++ b/packages/jest-jasmine2/package.json @@ -1,6 +1,6 @@ { "name": "jest-jasmine2", - "version": "29.6.2", + "version": "29.6.3", "repository": { "type": "git", "url": "https://github.com/jestjs/jest.git", diff --git a/packages/jest-leak-detector/package.json b/packages/jest-leak-detector/package.json index 5cea240be6ef..aec7029e5d95 100644 --- a/packages/jest-leak-detector/package.json +++ b/packages/jest-leak-detector/package.json @@ -1,6 +1,6 @@ { "name": "jest-leak-detector", - "version": "29.6.2", + "version": "29.6.3", "repository": { "type": "git", "url": "https://github.com/jestjs/jest.git", diff --git a/packages/jest-matcher-utils/package.json b/packages/jest-matcher-utils/package.json index 0dcf8a3bd94e..6a8efd646c0c 100644 --- a/packages/jest-matcher-utils/package.json +++ b/packages/jest-matcher-utils/package.json @@ -1,7 +1,7 @@ { "name": "jest-matcher-utils", "description": "A set of utility functions for expect and related packages", - "version": "29.6.2", + "version": "29.6.3", "repository": { "type": "git", "url": "https://github.com/jestjs/jest.git", diff --git a/packages/jest-message-util/package.json b/packages/jest-message-util/package.json index 8a713cfd61ba..46be06525f29 100644 --- a/packages/jest-message-util/package.json +++ b/packages/jest-message-util/package.json @@ -1,6 +1,6 @@ { "name": "jest-message-util", - "version": "29.6.2", + "version": "29.6.3", "repository": { "type": "git", "url": "https://github.com/jestjs/jest.git", diff --git a/packages/jest-mock/package.json b/packages/jest-mock/package.json index d161044f93d5..37ce57d56f71 100644 --- a/packages/jest-mock/package.json +++ b/packages/jest-mock/package.json @@ -1,6 +1,6 @@ { "name": "jest-mock", - "version": "29.6.2", + "version": "29.6.3", "repository": { "type": "git", "url": "https://github.com/jestjs/jest.git", diff --git a/packages/jest-mock/src/__tests__/index.test.ts b/packages/jest-mock/src/__tests__/index.test.ts index 7d08d17203df..c0efe908e7d9 100644 --- a/packages/jest-mock/src/__tests__/index.test.ts +++ b/packages/jest-mock/src/__tests__/index.test.ts @@ -598,6 +598,26 @@ describe('moduleMocker', () => { expect(fn2()).not.toBe('abcd'); }); + it('is not affected by restoreAllMocks', () => { + const fn1 = moduleMocker.fn(); + fn1.mockImplementation(() => 'abcd'); + fn1(1, 2, 3); + expect(fn1.mock.calls).toEqual([[1, 2, 3]]); + moduleMocker.restoreAllMocks(); + expect(fn1(1)).toBe('abcd'); + expect(fn1.mock.calls).toEqual([[1, 2, 3], [1]]); + }); + + it('is cleared and stubbed when restored explicitly', () => { + const fn1 = moduleMocker.fn(); + fn1.mockImplementation(() => 'abcd'); + fn1(1, 2, 3); + expect(fn1.mock.calls).toEqual([[1, 2, 3]]); + fn1.mockRestore(); + expect(fn1(1)).toBeUndefined(); + expect(fn1.mock.calls).toEqual([[1]]); + }); + it('maintains function arity', () => { const mockFunctionArity1 = moduleMocker.fn(x => x); const mockFunctionArity2 = moduleMocker.fn((x, y) => y); @@ -1547,18 +1567,21 @@ describe('moduleMocker', () => { }); it('supports resetting a spy', () => { - const methodOneReturn = 0; + const methodOneReturn = 10; + let methodOneRealCalls = 0; const obj = { methodOne() { + methodOneRealCalls++; return methodOneReturn; }, }; - const spy1 = moduleMocker.spyOn(obj, 'methodOne').mockReturnValue(10); + const spy1 = moduleMocker.spyOn(obj, 'methodOne').mockReturnValue(100); // Return value is mocked. - expect(methodOneReturn).toBe(0); - expect(obj.methodOne()).toBe(10); + expect(obj.methodOne()).toBe(100); + // Real impl has not been used. + expect(methodOneRealCalls).toBe(0); expect(moduleMocker.isMockFunction(obj.methodOne)).toBe(true); @@ -1567,32 +1590,45 @@ describe('moduleMocker', () => { // After resetting the spy, the method is still mock functions. expect(moduleMocker.isMockFunction(obj.methodOne)).toBe(true); - // After resetting the spy, the method returns the original return value. - expect(methodOneReturn).toBe(0); - expect(obj.methodOne()).toBe(0); + // After resetting the spy, the method returns undefined. + expect(obj.methodOne()).toBeUndefined(); + + // Real implementation has still not been called. + expect(methodOneRealCalls).toBe(0); }); it('supports resetting all spies', () => { const methodOneReturn = 10; - const methodTwoReturn = 20; + const methodTwoReturn = {}; + let methodOneRealCalls = 0; + let methodTwoRealCalls = 0; const obj = { methodOne() { + methodOneRealCalls++; return methodOneReturn; }, methodTwo() { + methodTwoRealCalls++; return methodTwoReturn; }, }; + // methodOne is spied on and mocked. moduleMocker.spyOn(obj, 'methodOne').mockReturnValue(100); - moduleMocker.spyOn(obj, 'methodTwo').mockReturnValue(200); + // methodTwo is spied on but not mocked. + moduleMocker.spyOn(obj, 'methodTwo'); // Return values are mocked. - expect(methodOneReturn).toBe(10); - expect(methodTwoReturn).toBe(20); expect(obj.methodOne()).toBe(100); - expect(obj.methodTwo()).toBe(200); + expect(obj.methodTwo()).toBe(methodTwoReturn); + // The real implementation has not been called when mocked. + expect(methodOneRealCalls).toBe(0); + + // But has for the unmocked spy. + expect(methodTwoRealCalls).toBe(1); + + // Both are mock functions. expect(moduleMocker.isMockFunction(obj.methodOne)).toBe(true); expect(moduleMocker.isMockFunction(obj.methodTwo)).toBe(true); @@ -1602,11 +1638,16 @@ describe('moduleMocker', () => { expect(moduleMocker.isMockFunction(obj.methodOne)).toBe(true); expect(moduleMocker.isMockFunction(obj.methodTwo)).toBe(true); - // After resetting all mocks, the methods return the original return value. - expect(methodOneReturn).toBe(10); - expect(methodTwoReturn).toBe(20); - expect(obj.methodOne()).toBe(10); - expect(obj.methodTwo()).toBe(20); + // After resetting all mocks, the methods are stubs returning undefined. + expect(obj.methodOne()).toBeUndefined(); + + // NB: It may not be desirable for reset to stub a spy that was never mocked - + // consider changing in a future major. + expect(obj.methodTwo()).toBeUndefined(); + + // Real functions have not been called any more times. + expect(methodOneRealCalls).toBe(0); + expect(methodTwoRealCalls).toBe(1); }); it('supports restoring a spy', () => { @@ -1654,32 +1695,25 @@ describe('moduleMocker', () => { const spy1 = moduleMocker.spyOn(obj, 'methodOne'); const spy2 = moduleMocker.spyOn(obj, 'methodTwo'); + // First, we call with the spies: both spies and both original functions + // should be called. obj.methodOne(); obj.methodTwo(); - - // Both spies and both original functions got called. expect(methodOneCalls).toBe(1); expect(methodTwoCalls).toBe(1); expect(spy1.mock.calls).toHaveLength(1); expect(spy2.mock.calls).toHaveLength(1); - expect(moduleMocker.isMockFunction(obj.methodOne)).toBe(true); - expect(moduleMocker.isMockFunction(obj.methodTwo)).toBe(true); - moduleMocker.restoreAllMocks(); - // After restoring all mocks, the methods are not mock functions. - expect(moduleMocker.isMockFunction(obj.methodOne)).toBe(false); - expect(moduleMocker.isMockFunction(obj.methodTwo)).toBe(false); - + // Then, after resetting all mocks, we call methods again. Only the real + // methods should bump their count, not the spies. obj.methodOne(); obj.methodTwo(); - - // After restoring all mocks only the real methods bump their count, not the spies. expect(methodOneCalls).toBe(2); expect(methodTwoCalls).toBe(2); - expect(spy1.mock.calls).toHaveLength(0); - expect(spy2.mock.calls).toHaveLength(0); + expect(spy1.mock.calls).toHaveLength(1); + expect(spy2.mock.calls).toHaveLength(1); }); it('should work with getters', () => { @@ -1816,8 +1850,10 @@ describe('moduleMocker', () => { it('supports resetting a spy', () => { const methodOneReturn = 0; + let methodOneRealCalls = 0; const obj = { get methodOne() { + methodOneRealCalls++; return methodOneReturn; }, }; @@ -1827,14 +1863,13 @@ describe('moduleMocker', () => { .mockReturnValue(10); // Return value is mocked. - expect(methodOneReturn).toBe(0); expect(obj.methodOne).toBe(10); spy1.mockReset(); - // After resetting the spy, the method returns the original return value. - expect(methodOneReturn).toBe(0); - expect(obj.methodOne).toBe(0); + // After resetting the spy, the getter is a stub returning undefined + expect(obj.methodOne).toBeUndefined(); + expect(methodOneRealCalls).toBe(0); }); it('supports resetting all spies', () => { @@ -1860,11 +1895,9 @@ describe('moduleMocker', () => { moduleMocker.resetAllMocks(); - // After resetting all mocks, the methods return the original return value. - expect(methodOneReturn).toBe(10); - expect(methodTwoReturn).toBe(20); - expect(obj.methodOne).toBe(10); - expect(obj.methodTwo).toBe(20); + // After resetting all mocks, the methods are stubs + expect(obj.methodOne).toBeUndefined(); + expect(obj.methodTwo).toBeUndefined(); }); it('supports restoring a spy', () => { @@ -1913,10 +1946,10 @@ describe('moduleMocker', () => { const spy1 = moduleMocker.spyOn(obj, 'methodOne', 'get'); const spy2 = moduleMocker.spyOn(obj, 'methodTwo', 'get'); + // First, we call with the spies: both spies and both original functions + // should be called. obj.methodOne(); obj.methodTwo(); - - // Both spies and both original functions got called. expect(methodOneCalls).toBe(1); expect(methodTwoCalls).toBe(1); expect(spy1.mock.calls).toHaveLength(1); @@ -1924,14 +1957,14 @@ describe('moduleMocker', () => { moduleMocker.restoreAllMocks(); + // Then, after resetting all mocks, we call methods again. Only the real + // methods should bump their count, not the spies. obj.methodOne(); obj.methodTwo(); - - // After restoring all mocks only the real methods bump their count, not the spies. expect(methodOneCalls).toBe(2); expect(methodTwoCalls).toBe(2); - expect(spy1.mock.calls).toHaveLength(0); - expect(spy2.mock.calls).toHaveLength(0); + expect(spy1.mock.calls).toHaveLength(1); + expect(spy2.mock.calls).toHaveLength(1); }); it('should work with getters on the prototype chain', () => { @@ -2000,10 +2033,11 @@ describe('moduleMocker', () => { }); it('supports resetting a spy on the prototype chain', () => { - const methodOneReturn = 0; + let methodOneRealCalls = 0; const prototype = { get methodOne() { - return methodOneReturn; + methodOneRealCalls++; + return 1; }, }; const obj = Object.create(prototype, {}); @@ -2013,14 +2047,15 @@ describe('moduleMocker', () => { .mockReturnValue(10); // Return value is mocked. - expect(methodOneReturn).toBe(0); expect(obj.methodOne).toBe(10); spy1.mockReset(); - // After resetting the spy, the method returns the original return value. - expect(methodOneReturn).toBe(0); - expect(obj.methodOne).toBe(0); + // After resetting the spy, the method is a stub. + expect(obj.methodOne).toBeUndefined(); + + // The real implementation has not been used. + expect(methodOneRealCalls).toBe(0); }); it('supports resetting all spies on the prototype chain', () => { @@ -2040,18 +2075,14 @@ describe('moduleMocker', () => { moduleMocker.spyOn(obj, 'methodTwo', 'get').mockReturnValue(200); // Return values are mocked. - expect(methodOneReturn).toBe(10); - expect(methodTwoReturn).toBe(20); expect(obj.methodOne).toBe(100); expect(obj.methodTwo).toBe(200); moduleMocker.resetAllMocks(); - // After resetting all mocks, the methods return the original return value. - expect(methodOneReturn).toBe(10); - expect(methodTwoReturn).toBe(20); - expect(obj.methodOne).toBe(10); - expect(obj.methodTwo).toBe(20); + // After resetting all mocks, the methods are stubs + expect(obj.methodOne).toBeUndefined(); + expect(obj.methodTwo).toBeUndefined(); }); it('supports restoring a spy on the prototype chain', () => { @@ -2069,7 +2100,7 @@ describe('moduleMocker', () => { obj.methodOne(); - // The spy and the original function are called. + // The spy and the original function are called, because we have not mocked it. expect(methodOneCalls).toBe(1); expect(spy1.mock.calls).toHaveLength(1); @@ -2102,10 +2133,10 @@ describe('moduleMocker', () => { const spy1 = moduleMocker.spyOn(obj, 'methodOne', 'get'); const spy2 = moduleMocker.spyOn(obj, 'methodTwo', 'get'); + // First, we call with the spies: both spies and both original functions + // should be called. obj.methodOne(); obj.methodTwo(); - - // Both spies and both original functions got called. expect(methodOneCalls).toBe(1); expect(methodTwoCalls).toBe(1); expect(spy1.mock.calls).toHaveLength(1); @@ -2113,14 +2144,14 @@ describe('moduleMocker', () => { moduleMocker.restoreAllMocks(); + // Then, after resetting all mocks, we call methods again. Only the real + // methods should bump their count, not the spies. obj.methodOne(); obj.methodTwo(); - - // After restoring all mocks only the real methods bump their count, not the spies. expect(methodOneCalls).toBe(2); expect(methodTwoCalls).toBe(2); - expect(spy1.mock.calls).toHaveLength(0); - expect(spy2.mock.calls).toHaveLength(0); + expect(spy1.mock.calls).toHaveLength(1); + expect(spy2.mock.calls).toHaveLength(1); }); }); @@ -2159,7 +2190,7 @@ describe('moduleMocker', () => { expect(obj.property).toBe(1); }); - it('should allow mocking with value of different type', () => { + it('should allow mocking with value of different value', () => { const obj = { property: 1, }; diff --git a/packages/jest-mock/src/index.ts b/packages/jest-mock/src/index.ts index 8989c5320bf3..296934a66a85 100644 --- a/packages/jest-mock/src/index.ts +++ b/packages/jest-mock/src/index.ts @@ -254,8 +254,6 @@ type MockFunctionConfig = { specificMockImpls: Array; }; -type SpyState = {reset?: () => void; restore: () => void}; - const MOCK_CONSTRUCTOR_NAME = 'mockConstructor'; const FUNCTION_NAME_RESERVED_PATTERN = /[\s!-/:-@[-`{-~]/; @@ -504,7 +502,7 @@ export class ModuleMocker { private readonly _environmentGlobal: typeof globalThis; private _mockState: WeakMap; private _mockConfigRegistry: WeakMap; - private _spyState: Set; + private _spyState: Set<() => void>; private _invocationCallCounter: number; /** @@ -609,27 +607,27 @@ export class ModuleMocker { private _makeComponent>( metadata: MockMetadata, - spyState?: SpyState, + restore?: () => void, ): T; private _makeComponent>( metadata: MockMetadata, - spyState?: SpyState, + restore?: () => void, ): T; private _makeComponent( metadata: MockMetadata, - spyState?: SpyState, + restore?: () => void, ): T; private _makeComponent( metadata: MockMetadata, - spyState?: SpyState, + restore?: () => void, ): T; private _makeComponent( metadata: MockMetadata, - spyState?: SpyState, + restore?: () => void, ): Mock; private _makeComponent( metadata: MockMetadata, - spyState?: SpyState, + restore?: () => void, ): Record | Array | RegExp | T | Mock | undefined { if (metadata.type === 'object') { return new this._environmentGlobal.Object(); @@ -750,8 +748,8 @@ export class ModuleMocker { f._isMockFunction = true; f.getMockImplementation = () => this._ensureMockConfig(f).mockImpl as T; - if (spyState != null) { - this._spyState.add(spyState); + if (typeof restore === 'function') { + this._spyState.add(restore); } this._mockState.set(f, this._defaultMockState()); @@ -772,22 +770,12 @@ export class ModuleMocker { f.mockReset = () => { f.mockClear(); this._mockConfigRegistry.delete(f); - - if (spyState != null) { - spyState.reset?.(); - } - return f; }; f.mockRestore = () => { - f.mockClear(); - this._mockConfigRegistry.delete(f); - - if (spyState != null) { - spyState.restore(); - this._spyState.delete(spyState); - } + f.mockReset(); + return restore ? restore() : undefined; }; f.mockReturnValueOnce = (value: ReturnType) => @@ -995,14 +983,14 @@ export class ModuleMocker { object: T, propertyKey: K, ): ReplacedPropertyRestorer | undefined { - for (const {restore} of this._spyState) { + for (const spyState of this._spyState) { if ( - 'object' in restore && - 'property' in restore && - restore.object === object && - restore.property === propertyKey + 'object' in spyState && + 'property' in spyState && + spyState.object === object && + spyState.property === propertyKey ) { - return restore as ReplacedPropertyRestorer; + return spyState as ReplacedPropertyRestorer; } } @@ -1118,15 +1106,6 @@ export class ModuleMocker { return fn; } - private _attachMockImplementation( - mock: Mock, - original: T, - ) { - mock.mockImplementation(function (this: unknown) { - return original.apply(this, arguments); - }); - } - spyOn< T extends object, K extends PropertyLikeKeys, @@ -1217,41 +1196,27 @@ export class ModuleMocker { if (descriptor && descriptor.get) { const originalGet = descriptor.get; - mock = this._makeComponent( - {type: 'function'}, - { - reset: () => { - this._attachMockImplementation(mock, original); - }, - restore: () => { - descriptor!.get = originalGet; - Object.defineProperty(object, methodKey, descriptor!); - }, - }, - ); + mock = this._makeComponent({type: 'function'}, () => { + descriptor!.get = originalGet; + Object.defineProperty(object, methodKey, descriptor!); + }); descriptor.get = () => mock; Object.defineProperty(object, methodKey, descriptor); } else { - mock = this._makeComponent( - {type: 'function'}, - { - reset: () => { - this._attachMockImplementation(mock, original); - }, - restore: () => { - if (isMethodOwner) { - object[methodKey] = original; - } else { - delete object[methodKey]; - } - }, - }, - ); - // @ts-expect-error: overriding original method with a mock + mock = this._makeComponent({type: 'function'}, () => { + if (isMethodOwner) { + object[methodKey] = original; + } else { + delete object[methodKey]; + } + }); + // @ts-expect-error overriding original method with a Mock object[methodKey] = mock; } - this._attachMockImplementation(mock, original); + mock.mockImplementation(function (this: unknown) { + return original.apply(this, arguments); + }); } return object[methodKey] as Mock; @@ -1311,24 +1276,18 @@ export class ModuleMocker { ); } - descriptor[accessType] = this._makeComponent( - {type: 'function'}, - { - reset: () => { - this._attachMockImplementation( - descriptor![accessType] as Mock, - original, - ); - }, - restore: () => { - // @ts-expect-error: overriding original method with a mock - descriptor![accessType] = original; - Object.defineProperty(object, propertyKey, descriptor!); - }, - }, - ); + descriptor[accessType] = this._makeComponent({type: 'function'}, () => { + // @ts-expect-error: mock is assignable + descriptor![accessType] = original; + Object.defineProperty(object, propertyKey, descriptor!); + }); - this._attachMockImplementation(descriptor[accessType] as Mock, original); + (descriptor[accessType] as Mock).mockImplementation(function ( + this: unknown, + ) { + // @ts-expect-error - wrong context + return original.apply(this, arguments); + }); } Object.defineProperty(object, propertyKey, descriptor); @@ -1434,7 +1393,7 @@ export class ModuleMocker { restore: () => { restore(); - this._spyState.delete({restore}); + this._spyState.delete(restore); }, }; @@ -1442,7 +1401,7 @@ export class ModuleMocker { restore.property = propertyKey; restore.replaced = replaced; - this._spyState.add({restore}); + this._spyState.add(restore); return replaced.replaceValue(value); } @@ -1452,15 +1411,12 @@ export class ModuleMocker { } resetAllMocks(): void { - this.clearAllMocks(); this._mockConfigRegistry = new WeakMap(); - this._spyState.forEach(spyState => spyState.reset?.()); + this._mockState = new WeakMap(); } restoreAllMocks(): void { - this.clearAllMocks(); - this._mockConfigRegistry = new WeakMap(); - this._spyState.forEach(spyState => spyState.restore()); + this._spyState.forEach(restore => restore()); this._spyState = new Set(); } diff --git a/packages/jest-phabricator/package.json b/packages/jest-phabricator/package.json index 02ff6570875b..abae95b9bab2 100644 --- a/packages/jest-phabricator/package.json +++ b/packages/jest-phabricator/package.json @@ -1,6 +1,6 @@ { "name": "jest-phabricator", - "version": "29.6.2", + "version": "29.6.3", "repository": { "type": "git", "url": "https://github.com/jestjs/jest.git", diff --git a/packages/jest-regex-util/package.json b/packages/jest-regex-util/package.json index a947a4eb09eb..7c7efc628aed 100644 --- a/packages/jest-regex-util/package.json +++ b/packages/jest-regex-util/package.json @@ -1,6 +1,6 @@ { "name": "jest-regex-util", - "version": "29.4.3", + "version": "29.6.3", "repository": { "type": "git", "url": "https://github.com/jestjs/jest.git", diff --git a/packages/jest-repl/package.json b/packages/jest-repl/package.json index bcdb54472c2a..de915df4091f 100644 --- a/packages/jest-repl/package.json +++ b/packages/jest-repl/package.json @@ -1,6 +1,6 @@ { "name": "jest-repl", - "version": "29.6.2", + "version": "29.6.3", "repository": { "type": "git", "url": "https://github.com/jestjs/jest.git", diff --git a/packages/jest-reporters/package.json b/packages/jest-reporters/package.json index db659285d78d..4f5296ab00e1 100644 --- a/packages/jest-reporters/package.json +++ b/packages/jest-reporters/package.json @@ -1,7 +1,7 @@ { "name": "@jest/reporters", "description": "Jest's reporters", - "version": "29.6.2", + "version": "29.6.3", "main": "./build/index.js", "types": "./build/index.d.ts", "exports": { diff --git a/packages/jest-reporters/src/types.ts b/packages/jest-reporters/src/types.ts index 3f285ba9f285..a33e6ddd4f65 100644 --- a/packages/jest-reporters/src/types.ts +++ b/packages/jest-reporters/src/types.ts @@ -42,17 +42,17 @@ export interface Reporter { test: Test, testCaseResult: TestCaseResult, ) => Promise | void; - readonly onRunStart: ( + readonly onRunStart?: ( results: AggregatedResult, options: ReporterOnStartOptions, ) => Promise | void; readonly onTestStart?: (test: Test) => Promise | void; readonly onTestFileStart?: (test: Test) => Promise | void; - readonly onRunComplete: ( + readonly onRunComplete?: ( testContexts: Set, results: AggregatedResult, ) => Promise | void; - readonly getLastError: () => Error | void; + readonly getLastError?: () => Error | void; } export type ReporterContext = { diff --git a/packages/jest-resolve-dependencies/package.json b/packages/jest-resolve-dependencies/package.json index 1fa24663d173..1cbb49f93747 100644 --- a/packages/jest-resolve-dependencies/package.json +++ b/packages/jest-resolve-dependencies/package.json @@ -1,6 +1,6 @@ { "name": "jest-resolve-dependencies", - "version": "29.6.2", + "version": "29.6.3", "repository": { "type": "git", "url": "https://github.com/jestjs/jest.git", diff --git a/packages/jest-resolve/package.json b/packages/jest-resolve/package.json index c3e450021874..992a6605049b 100644 --- a/packages/jest-resolve/package.json +++ b/packages/jest-resolve/package.json @@ -1,6 +1,6 @@ { "name": "jest-resolve", - "version": "29.6.2", + "version": "29.6.3", "repository": { "type": "git", "url": "https://github.com/jestjs/jest.git", diff --git a/packages/jest-runner/package.json b/packages/jest-runner/package.json index 1c519464bd50..17fb87a44e60 100644 --- a/packages/jest-runner/package.json +++ b/packages/jest-runner/package.json @@ -1,6 +1,6 @@ { "name": "jest-runner", - "version": "29.6.2", + "version": "29.6.3", "repository": { "type": "git", "url": "https://github.com/jestjs/jest.git", diff --git a/packages/jest-runtime/package.json b/packages/jest-runtime/package.json index 48daf4f01b4c..d182a9aa405b 100644 --- a/packages/jest-runtime/package.json +++ b/packages/jest-runtime/package.json @@ -1,6 +1,6 @@ { "name": "jest-runtime", - "version": "29.6.2", + "version": "29.6.3", "repository": { "type": "git", "url": "https://github.com/jestjs/jest.git", diff --git a/packages/jest-runtime/src/index.ts b/packages/jest-runtime/src/index.ts index b34ecdfe3890..9b5647215101 100644 --- a/packages/jest-runtime/src/index.ts +++ b/packages/jest-runtime/src/index.ts @@ -53,7 +53,12 @@ import type {MockMetadata, ModuleMocker} from 'jest-mock'; import {escapePathForRegex} from 'jest-regex-util'; import Resolver, {ResolveModuleConfig} from 'jest-resolve'; import {EXTENSION as SnapshotExtension} from 'jest-snapshot'; -import {createDirectory, deepCyclicCopy} from 'jest-util'; +import { + createDirectory, + deepCyclicCopy, + invariant, + isNonNullable, +} from 'jest-util'; import { createOutsideJestVmPath, decodePossibleOutsideJestVmPath, @@ -416,12 +421,15 @@ export default class Runtime { query = '', ): Promise { const cacheKey = modulePath + query; + const registry = this._isolatedModuleRegistry + ? this._isolatedModuleRegistry + : this._esmoduleRegistry; if (this._fileTransformsMutex.has(cacheKey)) { await this._fileTransformsMutex.get(cacheKey); } - if (!this._esmoduleRegistry.has(cacheKey)) { + if (!registry.has(cacheKey)) { invariant( typeof this._environment.getVmContext === 'function', 'ES Modules are only supported if your test environment has the `getVmContext` function', @@ -454,7 +462,7 @@ export default class Runtime { context, ); - this._esmoduleRegistry.set(cacheKey, wasm); + registry.set(cacheKey, wasm); transformResolve(); return wasm; @@ -462,7 +470,7 @@ export default class Runtime { if (this._resolver.isCoreModule(modulePath)) { const core = this._importCoreModule(modulePath, context); - this._esmoduleRegistry.set(cacheKey, core); + registry.set(cacheKey, core); transformResolve(); @@ -526,11 +534,11 @@ export default class Runtime { } invariant( - !this._esmoduleRegistry.has(cacheKey), + !registry.has(cacheKey), `Module cache already has entry ${cacheKey}. This is a bug in Jest, please report it!`, ); - this._esmoduleRegistry.set(cacheKey, module); + registry.set(cacheKey, module); transformResolve(); } catch (error) { @@ -539,7 +547,7 @@ export default class Runtime { } } - const module = this._esmoduleRegistry.get(cacheKey); + const module = registry.get(cacheKey); invariant( module, @@ -563,14 +571,18 @@ export default class Runtime { return; } + const registry = this._isolatedModuleRegistry + ? this._isolatedModuleRegistry + : this._esmoduleRegistry; + if (specifier === '@jest/globals') { - const fromCache = this._esmoduleRegistry.get('@jest/globals'); + const fromCache = registry.get('@jest/globals'); if (fromCache) { return fromCache; } const globals = this.getGlobalsForEsm(referencingIdentifier, context); - this._esmoduleRegistry.set('@jest/globals', globals); + registry.set('@jest/globals', globals); return globals; } @@ -586,7 +598,7 @@ export default class Runtime { return this.importMock(referencingIdentifier, specifier, context); } - const fromCache = this._esmoduleRegistry.get(specifier); + const fromCache = registry.get(specifier); if (fromCache) { return fromCache; @@ -662,7 +674,7 @@ export default class Runtime { } } - this._esmoduleRegistry.set(specifier, module); + registry.set(specifier, module); return module; } @@ -1580,7 +1592,7 @@ export default class Runtime { module.path, // __dirname module.filename, // __filename lastArgs[0], - ...lastArgs.slice(1).filter(notEmpty), + ...lastArgs.slice(1).filter(isNonNullable), ); } catch (error: any) { this.handleExecutionError(error, module); @@ -2427,7 +2439,7 @@ export default class Runtime { '__filename', this._config.injectGlobals ? 'jest' : undefined, ...this._config.sandboxInjectedGlobals, - ].filter(notEmpty); + ].filter(isNonNullable); } private handleExecutionError(e: Error, module: Module): never { @@ -2539,16 +2551,6 @@ export default class Runtime { } } -function invariant(condition: unknown, message?: string): asserts condition { - if (!condition) { - throw new Error(message); - } -} - -function notEmpty(value: T | null | undefined): value is T { - return value !== null && value !== undefined; -} - async function evaluateSyntheticModule(module: SyntheticModule) { await module.link(() => { throw new Error('This should never happen'); diff --git a/packages/jest-schemas/package.json b/packages/jest-schemas/package.json index 75fcf613723c..977931d88965 100644 --- a/packages/jest-schemas/package.json +++ b/packages/jest-schemas/package.json @@ -1,6 +1,6 @@ { "name": "@jest/schemas", - "version": "29.6.0", + "version": "29.6.3", "repository": { "type": "git", "url": "https://github.com/jestjs/jest.git", diff --git a/packages/jest-snapshot/package.json b/packages/jest-snapshot/package.json index dfd8b9c6bb2f..f9fa7fef9102 100644 --- a/packages/jest-snapshot/package.json +++ b/packages/jest-snapshot/package.json @@ -1,6 +1,6 @@ { "name": "jest-snapshot", - "version": "29.6.2", + "version": "29.6.3", "repository": { "type": "git", "url": "https://github.com/jestjs/jest.git", diff --git a/packages/jest-source-map/package.json b/packages/jest-source-map/package.json index 3f046969c8e0..b7a2d05b9134 100644 --- a/packages/jest-source-map/package.json +++ b/packages/jest-source-map/package.json @@ -1,6 +1,6 @@ { "name": "@jest/source-map", - "version": "29.6.0", + "version": "29.6.3", "repository": { "type": "git", "url": "https://github.com/jestjs/jest.git", diff --git a/packages/jest-test-result/package.json b/packages/jest-test-result/package.json index a442b5538daf..2077d5268c75 100644 --- a/packages/jest-test-result/package.json +++ b/packages/jest-test-result/package.json @@ -1,6 +1,6 @@ { "name": "@jest/test-result", - "version": "29.6.2", + "version": "29.6.3", "repository": { "type": "git", "url": "https://github.com/jestjs/jest.git", diff --git a/packages/jest-test-sequencer/package.json b/packages/jest-test-sequencer/package.json index 5b222e3eb514..92e321fcc4d6 100644 --- a/packages/jest-test-sequencer/package.json +++ b/packages/jest-test-sequencer/package.json @@ -1,6 +1,6 @@ { "name": "@jest/test-sequencer", - "version": "29.6.2", + "version": "29.6.3", "repository": { "type": "git", "url": "https://github.com/jestjs/jest.git", diff --git a/packages/jest-transform/package.json b/packages/jest-transform/package.json index 3888bf8acfee..542de763867f 100644 --- a/packages/jest-transform/package.json +++ b/packages/jest-transform/package.json @@ -1,6 +1,6 @@ { "name": "@jest/transform", - "version": "29.6.2", + "version": "29.6.3", "repository": { "type": "git", "url": "https://github.com/jestjs/jest.git", diff --git a/packages/jest-transform/src/ScriptTransformer.ts b/packages/jest-transform/src/ScriptTransformer.ts index 6728407dfcb9..8ee6aa12d8f1 100644 --- a/packages/jest-transform/src/ScriptTransformer.ts +++ b/packages/jest-transform/src/ScriptTransformer.ts @@ -20,6 +20,7 @@ import type {Config} from '@jest/types'; import HasteMap from 'jest-haste-map'; import { createDirectory, + invariant, isPromise, requireOrImportModule, tryRealpath, @@ -1034,12 +1035,6 @@ const calcTransformRegExp = (config: Config.ProjectConfig) => { return transformRegexp; }; -function invariant(condition: unknown, message?: string): asserts condition { - if (condition == null || condition === false || condition === '') { - throw new Error(message); - } -} - function assertSyncTransformer( transformer: Transformer, name: string | undefined, diff --git a/packages/jest-types/package.json b/packages/jest-types/package.json index bb8bdf35ddbc..fa55541874b9 100644 --- a/packages/jest-types/package.json +++ b/packages/jest-types/package.json @@ -1,6 +1,6 @@ { "name": "@jest/types", - "version": "29.6.1", + "version": "29.6.3", "repository": { "type": "git", "url": "https://github.com/jestjs/jest.git", diff --git a/packages/jest-util/package.json b/packages/jest-util/package.json index e166a053e16f..4b5b1c0cd36e 100644 --- a/packages/jest-util/package.json +++ b/packages/jest-util/package.json @@ -1,6 +1,6 @@ { "name": "jest-util", - "version": "29.6.2", + "version": "29.6.3", "repository": { "type": "git", "url": "https://github.com/jestjs/jest.git", diff --git a/packages/jest-util/src/index.ts b/packages/jest-util/src/index.ts index 1e73c92e0d18..531acfe4aa3a 100644 --- a/packages/jest-util/src/index.ts +++ b/packages/jest-util/src/index.ts @@ -28,3 +28,5 @@ export {default as pluralize} from './pluralize'; export {default as formatTime} from './formatTime'; export {default as tryRealpath} from './tryRealpath'; export {default as requireOrImportModule} from './requireOrImportModule'; +export {default as invariant} from './invariant'; +export {default as isNonNullable} from './isNonNullable'; diff --git a/packages/jest-util/src/invariant.ts b/packages/jest-util/src/invariant.ts new file mode 100644 index 000000000000..2e86440ae791 --- /dev/null +++ b/packages/jest-util/src/invariant.ts @@ -0,0 +1,15 @@ +/** + * 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. + */ + +export default function invariant( + condition: unknown, + message = '', +): asserts condition { + if (!condition) { + throw new Error(message); + } +} diff --git a/packages/jest-util/src/isNonNullable.ts b/packages/jest-util/src/isNonNullable.ts new file mode 100644 index 000000000000..34eddf095ef5 --- /dev/null +++ b/packages/jest-util/src/isNonNullable.ts @@ -0,0 +1,10 @@ +/** + * 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. + */ + +export default function isNonNullable(value: T): value is NonNullable { + return value != null; +} diff --git a/packages/jest-validate/package.json b/packages/jest-validate/package.json index cdc9667feb73..98513f30df49 100644 --- a/packages/jest-validate/package.json +++ b/packages/jest-validate/package.json @@ -1,6 +1,6 @@ { "name": "jest-validate", - "version": "29.6.2", + "version": "29.6.3", "repository": { "type": "git", "url": "https://github.com/jestjs/jest.git", diff --git a/packages/jest-watcher/package.json b/packages/jest-watcher/package.json index fc98d2cc20ae..d7084927b609 100644 --- a/packages/jest-watcher/package.json +++ b/packages/jest-watcher/package.json @@ -1,7 +1,7 @@ { "name": "jest-watcher", "description": "Delightful JavaScript Testing.", - "version": "29.6.2", + "version": "29.6.3", "main": "./build/index.js", "types": "./build/index.d.ts", "exports": { diff --git a/packages/jest-worker/package.json b/packages/jest-worker/package.json index 034700d8c76c..447c0220bd05 100644 --- a/packages/jest-worker/package.json +++ b/packages/jest-worker/package.json @@ -1,6 +1,6 @@ { "name": "jest-worker", - "version": "29.6.2", + "version": "29.6.3", "repository": { "type": "git", "url": "https://github.com/jestjs/jest.git", diff --git a/packages/jest/package.json b/packages/jest/package.json index 49b28053d5b3..6d9efe8943ca 100644 --- a/packages/jest/package.json +++ b/packages/jest/package.json @@ -1,7 +1,7 @@ { "name": "jest", "description": "Delightful JavaScript Testing.", - "version": "29.6.2", + "version": "29.6.3", "main": "./build/index.js", "types": "./build/index.d.ts", "exports": { diff --git a/packages/pretty-format/package.json b/packages/pretty-format/package.json index 788d1e3b1a71..2f0481fa767c 100644 --- a/packages/pretty-format/package.json +++ b/packages/pretty-format/package.json @@ -1,6 +1,6 @@ { "name": "pretty-format", - "version": "29.6.2", + "version": "29.6.3", "repository": { "type": "git", "url": "https://github.com/jestjs/jest.git", diff --git a/packages/test-globals/package.json b/packages/test-globals/package.json index a297cbaef366..4361d5984ebd 100644 --- a/packages/test-globals/package.json +++ b/packages/test-globals/package.json @@ -1,6 +1,6 @@ { "name": "@jest/test-globals", - "version": "29.6.2", + "version": "29.6.3", "private": true, "main": "./build/index.js", "types": "./build/index.d.ts", diff --git a/packages/test-utils/package.json b/packages/test-utils/package.json index 9ef19a9b90ef..955209adab6e 100644 --- a/packages/test-utils/package.json +++ b/packages/test-utils/package.json @@ -1,6 +1,6 @@ { "name": "@jest/test-utils", - "version": "29.6.2", + "version": "29.6.3", "private": true, "main": "./build/index.js", "types": "./build/index.d.ts", diff --git a/website/versioned_docs/version-29.4/Configuration.md b/website/versioned_docs/version-29.4/Configuration.md index ed92e8e2bef9..c4676dd7bfe8 100644 --- a/website/versioned_docs/version-29.4/Configuration.md +++ b/website/versioned_docs/version-29.4/Configuration.md @@ -1330,7 +1330,7 @@ Hungry for reporters? Take a look at long list of [awesome reporters](https://gi ::: -Custom reporter module must export a class that takes [`globalConfig`](https://github.com/jestjs/jest/blob/v29.2.1/packages/jest-types/src/Config.ts#L358-L422), `reporterOptions` and `reporterContext` as constructor arguments and implements at least `onRunComplete()` method (for the full list of methods and argument types see `Reporter` interface in [packages/jest-reporters/src/types.ts](https://github.com/jestjs/jest/blob/main/packages/jest-reporters/src/types.ts)): +Custom reporter module must export a class that takes [`globalConfig`](https://github.com/jestjs/jest/blob/v29.2.1/packages/jest-types/src/Config.ts#L358-L422), `reporterOptions` and `reporterContext` as constructor arguments: ```js title="custom-reporter.js" class CustomReporter { @@ -1359,6 +1359,12 @@ class CustomReporter { module.exports = CustomReporter; ``` +:::note + +For the full list of hooks and argument types see the `Reporter` interface in [packages/jest-reporters/src/types.ts](https://github.com/jestjs/jest/blob/main/packages/jest-reporters/src/types.ts). + +::: + ### `resetMocks` \[boolean] Default: `false` diff --git a/website/versioned_docs/version-29.4/ManualMocks.md b/website/versioned_docs/version-29.4/ManualMocks.md index d166114387eb..7d7e9ab8f1d1 100644 --- a/website/versioned_docs/version-29.4/ManualMocks.md +++ b/website/versioned_docs/version-29.4/ManualMocks.md @@ -29,7 +29,7 @@ Scoped modules (also known as [scoped packages](https://docs.npmjs.com/cli/v6/us :::caution -If we want to mock Node's build-in modules (e.g.: `fs` or `path`), then explicitly calling e.g. `jest.mock('path')` is **required**, because build-in modules are not mocked by default. +If we want to mock Node's built-in modules (e.g.: `fs` or `path`), then explicitly calling e.g. `jest.mock('path')` is **required**, because built-in modules are not mocked by default. ::: @@ -110,7 +110,7 @@ fs.readdirSync = readdirSync; module.exports = fs; ``` -Now we write our test. In this case `jest.mock('fs')` must be called explicitly, because `fs` is Node’s build-in module: +Now we write our test. In this case `jest.mock('fs')` must be called explicitly, because `fs` is Node’s built-in module: ```javascript title="__tests__/FileSummarizer-test.js" 'use strict'; diff --git a/website/versioned_docs/version-29.4/MockFunctionAPI.md b/website/versioned_docs/version-29.4/MockFunctionAPI.md index 5ffb11992b84..6282e1538f2d 100644 --- a/website/versioned_docs/version-29.4/MockFunctionAPI.md +++ b/website/versioned_docs/version-29.4/MockFunctionAPI.md @@ -128,9 +128,7 @@ Beware that `mockFn.mockClear()` will replace `mockFn.mock`, not just reset the ### `mockFn.mockReset()` -Does everything that [`mockFn.mockClear()`](#mockfnmockclear) does, and also removes any mocked return values or implementations. - -This is useful when you want to completely reset a _mock_ back to its initial state. +Does everything that [`mockFn.mockClear()`](#mockfnmockclear) does, and also replaces the mock implementation with an empty function, returning `undefined`. The [`resetMocks`](configuration#resetmocks-boolean) configuration option is available to reset mocks automatically before each test. diff --git a/website/versioned_docs/version-29.5/Configuration.md b/website/versioned_docs/version-29.5/Configuration.md index 0604ca6f965a..1c638f727250 100644 --- a/website/versioned_docs/version-29.5/Configuration.md +++ b/website/versioned_docs/version-29.5/Configuration.md @@ -1365,7 +1365,7 @@ Hungry for reporters? Take a look at long list of [awesome reporters](https://gi ::: -Custom reporter module must export a class that takes [`globalConfig`](https://github.com/jestjs/jest/blob/v29.2.1/packages/jest-types/src/Config.ts#L358-L422), `reporterOptions` and `reporterContext` as constructor arguments and implements at least `onRunComplete()` method (for the full list of methods and argument types see `Reporter` interface in [packages/jest-reporters/src/types.ts](https://github.com/jestjs/jest/blob/main/packages/jest-reporters/src/types.ts)): +Custom reporter module must export a class that takes [`globalConfig`](https://github.com/jestjs/jest/blob/v29.2.1/packages/jest-types/src/Config.ts#L358-L422), `reporterOptions` and `reporterContext` as constructor arguments: ```js title="custom-reporter.js" class CustomReporter { @@ -1394,6 +1394,12 @@ class CustomReporter { module.exports = CustomReporter; ``` +:::note + +For the full list of hooks and argument types see the `Reporter` interface in [packages/jest-reporters/src/types.ts](https://github.com/jestjs/jest/blob/main/packages/jest-reporters/src/types.ts). + +::: + ### `resetMocks` \[boolean] Default: `false` diff --git a/website/versioned_docs/version-29.5/ManualMocks.md b/website/versioned_docs/version-29.5/ManualMocks.md index d166114387eb..7d7e9ab8f1d1 100644 --- a/website/versioned_docs/version-29.5/ManualMocks.md +++ b/website/versioned_docs/version-29.5/ManualMocks.md @@ -29,7 +29,7 @@ Scoped modules (also known as [scoped packages](https://docs.npmjs.com/cli/v6/us :::caution -If we want to mock Node's build-in modules (e.g.: `fs` or `path`), then explicitly calling e.g. `jest.mock('path')` is **required**, because build-in modules are not mocked by default. +If we want to mock Node's built-in modules (e.g.: `fs` or `path`), then explicitly calling e.g. `jest.mock('path')` is **required**, because built-in modules are not mocked by default. ::: @@ -110,7 +110,7 @@ fs.readdirSync = readdirSync; module.exports = fs; ``` -Now we write our test. In this case `jest.mock('fs')` must be called explicitly, because `fs` is Node’s build-in module: +Now we write our test. In this case `jest.mock('fs')` must be called explicitly, because `fs` is Node’s built-in module: ```javascript title="__tests__/FileSummarizer-test.js" 'use strict'; diff --git a/website/versioned_docs/version-29.5/MockFunctionAPI.md b/website/versioned_docs/version-29.5/MockFunctionAPI.md index 5ffb11992b84..6282e1538f2d 100644 --- a/website/versioned_docs/version-29.5/MockFunctionAPI.md +++ b/website/versioned_docs/version-29.5/MockFunctionAPI.md @@ -128,9 +128,7 @@ Beware that `mockFn.mockClear()` will replace `mockFn.mock`, not just reset the ### `mockFn.mockReset()` -Does everything that [`mockFn.mockClear()`](#mockfnmockclear) does, and also removes any mocked return values or implementations. - -This is useful when you want to completely reset a _mock_ back to its initial state. +Does everything that [`mockFn.mockClear()`](#mockfnmockclear) does, and also replaces the mock implementation with an empty function, returning `undefined`. The [`resetMocks`](configuration#resetmocks-boolean) configuration option is available to reset mocks automatically before each test. diff --git a/website/versioned_docs/version-29.6/Configuration.md b/website/versioned_docs/version-29.6/Configuration.md index 4e23e314b103..1a50070df269 100644 --- a/website/versioned_docs/version-29.6/Configuration.md +++ b/website/versioned_docs/version-29.6/Configuration.md @@ -1401,7 +1401,7 @@ Hungry for reporters? Take a look at long list of [awesome reporters](https://gi ::: -Custom reporter module must export a class that takes [`globalConfig`](https://github.com/jestjs/jest/blob/v29.2.1/packages/jest-types/src/Config.ts#L358-L422), `reporterOptions` and `reporterContext` as constructor arguments and implements at least `onRunComplete()` method (for the full list of methods and argument types see `Reporter` interface in [packages/jest-reporters/src/types.ts](https://github.com/jestjs/jest/blob/main/packages/jest-reporters/src/types.ts)): +Custom reporter module must export a class that takes [`globalConfig`](https://github.com/jestjs/jest/blob/v29.2.1/packages/jest-types/src/Config.ts#L358-L422), `reporterOptions` and `reporterContext` as constructor arguments: ```js title="custom-reporter.js" class CustomReporter { @@ -1430,6 +1430,12 @@ class CustomReporter { module.exports = CustomReporter; ``` +:::note + +For the full list of hooks and argument types see the `Reporter` interface in [packages/jest-reporters/src/types.ts](https://github.com/jestjs/jest/blob/main/packages/jest-reporters/src/types.ts). + +::: + ### `resetMocks` \[boolean] Default: `false` diff --git a/website/versioned_docs/version-29.6/ManualMocks.md b/website/versioned_docs/version-29.6/ManualMocks.md index d166114387eb..7d7e9ab8f1d1 100644 --- a/website/versioned_docs/version-29.6/ManualMocks.md +++ b/website/versioned_docs/version-29.6/ManualMocks.md @@ -29,7 +29,7 @@ Scoped modules (also known as [scoped packages](https://docs.npmjs.com/cli/v6/us :::caution -If we want to mock Node's build-in modules (e.g.: `fs` or `path`), then explicitly calling e.g. `jest.mock('path')` is **required**, because build-in modules are not mocked by default. +If we want to mock Node's built-in modules (e.g.: `fs` or `path`), then explicitly calling e.g. `jest.mock('path')` is **required**, because built-in modules are not mocked by default. ::: @@ -110,7 +110,7 @@ fs.readdirSync = readdirSync; module.exports = fs; ``` -Now we write our test. In this case `jest.mock('fs')` must be called explicitly, because `fs` is Node’s build-in module: +Now we write our test. In this case `jest.mock('fs')` must be called explicitly, because `fs` is Node’s built-in module: ```javascript title="__tests__/FileSummarizer-test.js" 'use strict'; diff --git a/website/versioned_docs/version-29.6/MockFunctionAPI.md b/website/versioned_docs/version-29.6/MockFunctionAPI.md index 5ffb11992b84..6282e1538f2d 100644 --- a/website/versioned_docs/version-29.6/MockFunctionAPI.md +++ b/website/versioned_docs/version-29.6/MockFunctionAPI.md @@ -128,9 +128,7 @@ Beware that `mockFn.mockClear()` will replace `mockFn.mock`, not just reset the ### `mockFn.mockReset()` -Does everything that [`mockFn.mockClear()`](#mockfnmockclear) does, and also removes any mocked return values or implementations. - -This is useful when you want to completely reset a _mock_ back to its initial state. +Does everything that [`mockFn.mockClear()`](#mockfnmockclear) does, and also replaces the mock implementation with an empty function, returning `undefined`. The [`resetMocks`](configuration#resetmocks-boolean) configuration option is available to reset mocks automatically before each test. diff --git a/yarn.lock b/yarn.lock index 68ff4925f6ec..a83a4736f19b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12347,6 +12347,7 @@ __metadata: resolution: "jest-changed-files@workspace:packages/jest-changed-files" dependencies: execa: ^5.0.0 + jest-util: "workspace:^" p-limit: ^3.1.0 languageName: unknown linkType: soft