add: unit and integration testing
This commit is contained in:
+22
@@ -0,0 +1,22 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
Copyright Contributors to the Jest project.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
+131
@@ -0,0 +1,131 @@
|
||||
/**
|
||||
* 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 {Console as Console_2} from 'node:console';
|
||||
import {WriteStream} from 'node:tty';
|
||||
import {InspectOptions} from 'node:util';
|
||||
import {Config} from '@jest/types';
|
||||
import {StackTraceConfig} from 'jest-message-util';
|
||||
|
||||
export declare class BufferedConsole extends Console_2 {
|
||||
private readonly _buffer;
|
||||
private _counters;
|
||||
private _timers;
|
||||
private _groupDepth;
|
||||
Console: typeof Console_2;
|
||||
constructor();
|
||||
static write(
|
||||
this: void,
|
||||
buffer: ConsoleBuffer,
|
||||
type: LogType,
|
||||
message: LogMessage,
|
||||
stackLevel?: number,
|
||||
): ConsoleBuffer;
|
||||
private _log;
|
||||
assert(value: unknown, message?: string | Error): void;
|
||||
count(label?: string): void;
|
||||
countReset(label?: string): void;
|
||||
debug(firstArg: unknown, ...rest: Array<unknown>): void;
|
||||
dir(firstArg: unknown, options?: InspectOptions): void;
|
||||
dirxml(firstArg: unknown, ...rest: Array<unknown>): void;
|
||||
error(firstArg: unknown, ...rest: Array<unknown>): void;
|
||||
group(title?: string, ...rest: Array<unknown>): void;
|
||||
groupCollapsed(title?: string, ...rest: Array<unknown>): void;
|
||||
groupEnd(): void;
|
||||
info(firstArg: unknown, ...rest: Array<unknown>): void;
|
||||
log(firstArg: unknown, ...rest: Array<unknown>): void;
|
||||
time(label?: string): void;
|
||||
timeEnd(label?: string): void;
|
||||
timeLog(label?: string, ...data: Array<unknown>): void;
|
||||
warn(firstArg: unknown, ...rest: Array<unknown>): void;
|
||||
getBuffer(): ConsoleBuffer | undefined;
|
||||
}
|
||||
|
||||
export declare type ConsoleBuffer = Array<LogEntry>;
|
||||
|
||||
export declare class CustomConsole extends Console_2 {
|
||||
private readonly _stdout;
|
||||
private readonly _stderr;
|
||||
private readonly _formatBuffer;
|
||||
private readonly _buffer;
|
||||
private _counters;
|
||||
private _timers;
|
||||
private _groupDepth;
|
||||
Console: typeof Console_2;
|
||||
constructor(
|
||||
stdout: WriteStream,
|
||||
stderr: WriteStream,
|
||||
formatBuffer?: Formatter,
|
||||
);
|
||||
private _log;
|
||||
private _logError;
|
||||
private readonly _addToBuffer;
|
||||
assert(value: unknown, message?: string | Error): asserts value;
|
||||
count(label?: string): void;
|
||||
countReset(label?: string): void;
|
||||
debug(firstArg: unknown, ...args: Array<unknown>): void;
|
||||
dir(firstArg: unknown, options?: InspectOptions): void;
|
||||
dirxml(firstArg: unknown, ...args: Array<unknown>): void;
|
||||
error(firstArg: unknown, ...args: Array<unknown>): void;
|
||||
group(title?: string, ...args: Array<unknown>): void;
|
||||
groupCollapsed(title?: string, ...args: Array<unknown>): void;
|
||||
groupEnd(): void;
|
||||
info(firstArg: unknown, ...args: Array<unknown>): void;
|
||||
log(firstArg: unknown, ...args: Array<unknown>): void;
|
||||
time(label?: string): void;
|
||||
timeEnd(label?: string): void;
|
||||
timeLog(label?: string, ...data: Array<unknown>): void;
|
||||
warn(firstArg: unknown, ...args: Array<unknown>): void;
|
||||
getBuffer(): ConsoleBuffer | undefined;
|
||||
}
|
||||
|
||||
declare type Formatter = (type: LogType, message: LogMessage) => string;
|
||||
|
||||
export declare function getConsoleOutput(
|
||||
buffer: ConsoleBuffer,
|
||||
config: StackTraceConfig,
|
||||
globalConfig: Config.GlobalConfig,
|
||||
): string;
|
||||
|
||||
export declare type LogEntry = {
|
||||
message: LogMessage;
|
||||
origin: string;
|
||||
type: LogType;
|
||||
};
|
||||
|
||||
export declare type LogMessage = string;
|
||||
|
||||
export declare type LogType =
|
||||
| 'assert'
|
||||
| 'count'
|
||||
| 'debug'
|
||||
| 'dir'
|
||||
| 'dirxml'
|
||||
| 'error'
|
||||
| 'group'
|
||||
| 'groupCollapsed'
|
||||
| 'info'
|
||||
| 'log'
|
||||
| 'time'
|
||||
| 'warn';
|
||||
|
||||
export declare class NullConsole extends CustomConsole {
|
||||
assert(): void;
|
||||
debug(): void;
|
||||
dir(): void;
|
||||
error(): void;
|
||||
info(): void;
|
||||
log(): void;
|
||||
time(): void;
|
||||
timeEnd(): void;
|
||||
timeLog(): void;
|
||||
trace(): void;
|
||||
warn(): void;
|
||||
group(): void;
|
||||
groupCollapsed(): void;
|
||||
groupEnd(): void;
|
||||
}
|
||||
+534
@@ -0,0 +1,534 @@
|
||||
/*!
|
||||
* /**
|
||||
* * 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.
|
||||
* * /
|
||||
*/
|
||||
/******/ (() => { // webpackBootstrap
|
||||
/******/ "use strict";
|
||||
/******/ var __webpack_modules__ = ({
|
||||
|
||||
/***/ "./src/BufferedConsole.ts"
|
||||
(__unused_webpack_module, exports) {
|
||||
|
||||
|
||||
|
||||
Object.defineProperty(exports, "__esModule", ({
|
||||
value: true
|
||||
}));
|
||||
exports["default"] = void 0;
|
||||
function _nodeAssert() {
|
||||
const data = require("node:assert");
|
||||
_nodeAssert = function () {
|
||||
return data;
|
||||
};
|
||||
return data;
|
||||
}
|
||||
function _nodeConsole() {
|
||||
const data = require("node:console");
|
||||
_nodeConsole = function () {
|
||||
return data;
|
||||
};
|
||||
return data;
|
||||
}
|
||||
function _nodeUtil() {
|
||||
const data = require("node:util");
|
||||
_nodeUtil = function () {
|
||||
return data;
|
||||
};
|
||||
return data;
|
||||
}
|
||||
function _chalk() {
|
||||
const data = _interopRequireDefault(require("chalk"));
|
||||
_chalk = function () {
|
||||
return data;
|
||||
};
|
||||
return data;
|
||||
}
|
||||
function _jestUtil() {
|
||||
const data = require("jest-util");
|
||||
_jestUtil = function () {
|
||||
return data;
|
||||
};
|
||||
return data;
|
||||
}
|
||||
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
class BufferedConsole extends _nodeConsole().Console {
|
||||
_buffer = [];
|
||||
_counters = {};
|
||||
_timers = {};
|
||||
_groupDepth = 0;
|
||||
Console = _nodeConsole().Console;
|
||||
constructor() {
|
||||
super({
|
||||
write: message => {
|
||||
BufferedConsole.write(this._buffer, 'log', message);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
static write(buffer, type, message, stackLevel = 2) {
|
||||
const rawStack = new (_jestUtil().ErrorWithStack)(undefined, BufferedConsole.write).stack;
|
||||
(0, _jestUtil().invariant)(rawStack != null, 'always have a stack trace');
|
||||
const origin = rawStack.split('\n').slice(stackLevel).filter(Boolean).join('\n');
|
||||
buffer.push({
|
||||
message,
|
||||
origin,
|
||||
type
|
||||
});
|
||||
return buffer;
|
||||
}
|
||||
_log(type, message) {
|
||||
BufferedConsole.write(this._buffer, type, ' '.repeat(this._groupDepth) + message, 3);
|
||||
}
|
||||
assert(value, message) {
|
||||
try {
|
||||
_nodeAssert().strict.ok(value, message);
|
||||
} catch (error) {
|
||||
if (!(error instanceof _nodeAssert().AssertionError)) {
|
||||
throw error;
|
||||
}
|
||||
// https://github.com/jestjs/jest/pull/13422#issuecomment-1273396392
|
||||
this._log('assert', error.toString().replaceAll(/:\n\n.*\n/gs, ''));
|
||||
}
|
||||
}
|
||||
count(label = 'default') {
|
||||
if (!this._counters[label]) {
|
||||
this._counters[label] = 0;
|
||||
}
|
||||
this._log('count', (0, _nodeUtil().format)(`${label}: ${++this._counters[label]}`));
|
||||
}
|
||||
countReset(label = 'default') {
|
||||
this._counters[label] = 0;
|
||||
}
|
||||
debug(firstArg, ...rest) {
|
||||
this._log('debug', (0, _nodeUtil().format)(firstArg, ...rest));
|
||||
}
|
||||
dir(firstArg, options = {}) {
|
||||
const representation = (0, _nodeUtil().inspect)(firstArg, options);
|
||||
this._log('dir', (0, _nodeUtil().formatWithOptions)(options, representation));
|
||||
}
|
||||
dirxml(firstArg, ...rest) {
|
||||
this._log('dirxml', (0, _nodeUtil().format)(firstArg, ...rest));
|
||||
}
|
||||
error(firstArg, ...rest) {
|
||||
this._log('error', (0, _nodeUtil().format)(firstArg, ...rest));
|
||||
}
|
||||
group(title, ...rest) {
|
||||
this._groupDepth++;
|
||||
if (title != null || rest.length > 0) {
|
||||
this._log('group', _chalk().default.bold((0, _nodeUtil().format)(title, ...rest)));
|
||||
}
|
||||
}
|
||||
groupCollapsed(title, ...rest) {
|
||||
this._groupDepth++;
|
||||
if (title != null || rest.length > 0) {
|
||||
this._log('groupCollapsed', _chalk().default.bold((0, _nodeUtil().format)(title, ...rest)));
|
||||
}
|
||||
}
|
||||
groupEnd() {
|
||||
if (this._groupDepth > 0) {
|
||||
this._groupDepth--;
|
||||
}
|
||||
}
|
||||
info(firstArg, ...rest) {
|
||||
this._log('info', (0, _nodeUtil().format)(firstArg, ...rest));
|
||||
}
|
||||
log(firstArg, ...rest) {
|
||||
this._log('log', (0, _nodeUtil().format)(firstArg, ...rest));
|
||||
}
|
||||
time(label = 'default') {
|
||||
if (this._timers[label] != null) {
|
||||
return;
|
||||
}
|
||||
this._timers[label] = new Date();
|
||||
}
|
||||
timeEnd(label = 'default') {
|
||||
const startTime = this._timers[label];
|
||||
if (startTime != null) {
|
||||
const endTime = new Date();
|
||||
const time = endTime.getTime() - startTime.getTime();
|
||||
this._log('time', (0, _nodeUtil().format)(`${label}: ${(0, _jestUtil().formatTime)(time)}`));
|
||||
delete this._timers[label];
|
||||
}
|
||||
}
|
||||
timeLog(label = 'default', ...data) {
|
||||
const startTime = this._timers[label];
|
||||
if (startTime != null) {
|
||||
const endTime = new Date();
|
||||
const time = endTime.getTime() - startTime.getTime();
|
||||
this._log('time', (0, _nodeUtil().format)(`${label}: ${(0, _jestUtil().formatTime)(time)}`, ...data));
|
||||
}
|
||||
}
|
||||
warn(firstArg, ...rest) {
|
||||
this._log('warn', (0, _nodeUtil().format)(firstArg, ...rest));
|
||||
}
|
||||
getBuffer() {
|
||||
return this._buffer.length > 0 ? this._buffer : undefined;
|
||||
}
|
||||
}
|
||||
exports["default"] = BufferedConsole;
|
||||
|
||||
/***/ },
|
||||
|
||||
/***/ "./src/CustomConsole.ts"
|
||||
(__unused_webpack_module, exports) {
|
||||
|
||||
|
||||
|
||||
Object.defineProperty(exports, "__esModule", ({
|
||||
value: true
|
||||
}));
|
||||
exports["default"] = void 0;
|
||||
function _nodeAssert() {
|
||||
const data = require("node:assert");
|
||||
_nodeAssert = function () {
|
||||
return data;
|
||||
};
|
||||
return data;
|
||||
}
|
||||
function _nodeConsole() {
|
||||
const data = require("node:console");
|
||||
_nodeConsole = function () {
|
||||
return data;
|
||||
};
|
||||
return data;
|
||||
}
|
||||
function _nodeUtil() {
|
||||
const data = require("node:util");
|
||||
_nodeUtil = function () {
|
||||
return data;
|
||||
};
|
||||
return data;
|
||||
}
|
||||
function _chalk() {
|
||||
const data = _interopRequireDefault(require("chalk"));
|
||||
_chalk = function () {
|
||||
return data;
|
||||
};
|
||||
return data;
|
||||
}
|
||||
function _jestUtil() {
|
||||
const data = require("jest-util");
|
||||
_jestUtil = function () {
|
||||
return data;
|
||||
};
|
||||
return data;
|
||||
}
|
||||
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
class CustomConsole extends _nodeConsole().Console {
|
||||
_stdout;
|
||||
_stderr;
|
||||
_formatBuffer;
|
||||
_buffer = [];
|
||||
_counters = {};
|
||||
_timers = {};
|
||||
_groupDepth = 0;
|
||||
Console = _nodeConsole().Console;
|
||||
constructor(stdout, stderr, formatBuffer = (_type, message) => message) {
|
||||
super(stdout, stderr);
|
||||
this._stdout = stdout;
|
||||
this._stderr = stderr;
|
||||
this._formatBuffer = formatBuffer;
|
||||
}
|
||||
_log(type, message) {
|
||||
(0, _jestUtil().clearLine)(this._stdout);
|
||||
super.log(this._formatBuffer(type, ' '.repeat(this._groupDepth) + message));
|
||||
this._addToBuffer(type, message);
|
||||
}
|
||||
_logError(type, message) {
|
||||
(0, _jestUtil().clearLine)(this._stderr);
|
||||
super.error(this._formatBuffer(type, ' '.repeat(this._groupDepth) + message));
|
||||
this._addToBuffer(type, message);
|
||||
}
|
||||
_addToBuffer = (type, message) => {
|
||||
const rawStack = new (_jestUtil().ErrorWithStack)(undefined, this._addToBuffer).stack;
|
||||
(0, _jestUtil().invariant)(rawStack != null, 'always have a stack trace');
|
||||
const origin = rawStack.split('\n').slice(3).filter(Boolean).join('\n');
|
||||
this._buffer.push({
|
||||
message: ' '.repeat(this._groupDepth) + message,
|
||||
origin,
|
||||
type
|
||||
});
|
||||
};
|
||||
assert(value, message) {
|
||||
try {
|
||||
_nodeAssert().strict.ok(value, message);
|
||||
} catch (error) {
|
||||
if (!(error instanceof _nodeAssert().AssertionError)) {
|
||||
throw error;
|
||||
}
|
||||
// https://github.com/jestjs/jest/pull/13422#issuecomment-1273396392
|
||||
this._logError('assert', error.toString().replaceAll(/:\n\n.*\n/gs, ''));
|
||||
}
|
||||
}
|
||||
count(label = 'default') {
|
||||
if (!this._counters[label]) {
|
||||
this._counters[label] = 0;
|
||||
}
|
||||
this._log('count', (0, _nodeUtil().format)(`${label}: ${++this._counters[label]}`));
|
||||
}
|
||||
countReset(label = 'default') {
|
||||
this._counters[label] = 0;
|
||||
}
|
||||
debug(firstArg, ...args) {
|
||||
this._log('debug', (0, _nodeUtil().format)(firstArg, ...args));
|
||||
}
|
||||
dir(firstArg, options = {}) {
|
||||
const representation = (0, _nodeUtil().inspect)(firstArg, options);
|
||||
this._log('dir', (0, _nodeUtil().formatWithOptions)(options, representation));
|
||||
}
|
||||
dirxml(firstArg, ...args) {
|
||||
this._log('dirxml', (0, _nodeUtil().format)(firstArg, ...args));
|
||||
}
|
||||
error(firstArg, ...args) {
|
||||
this._logError('error', (0, _nodeUtil().format)(firstArg, ...args));
|
||||
}
|
||||
group(title, ...args) {
|
||||
this._groupDepth++;
|
||||
if (title != null || args.length > 0) {
|
||||
this._log('group', _chalk().default.bold((0, _nodeUtil().format)(title, ...args)));
|
||||
}
|
||||
}
|
||||
groupCollapsed(title, ...args) {
|
||||
this._groupDepth++;
|
||||
if (title != null || args.length > 0) {
|
||||
this._log('groupCollapsed', _chalk().default.bold((0, _nodeUtil().format)(title, ...args)));
|
||||
}
|
||||
}
|
||||
groupEnd() {
|
||||
if (this._groupDepth > 0) {
|
||||
this._groupDepth--;
|
||||
}
|
||||
}
|
||||
info(firstArg, ...args) {
|
||||
this._log('info', (0, _nodeUtil().format)(firstArg, ...args));
|
||||
}
|
||||
log(firstArg, ...args) {
|
||||
this._log('log', (0, _nodeUtil().format)(firstArg, ...args));
|
||||
}
|
||||
time(label = 'default') {
|
||||
if (this._timers[label] != null) {
|
||||
return;
|
||||
}
|
||||
this._timers[label] = new Date();
|
||||
}
|
||||
timeEnd(label = 'default') {
|
||||
const startTime = this._timers[label];
|
||||
if (startTime != null) {
|
||||
const endTime = Date.now();
|
||||
const time = endTime - startTime.getTime();
|
||||
this._log('time', (0, _nodeUtil().format)(`${label}: ${(0, _jestUtil().formatTime)(time)}`));
|
||||
delete this._timers[label];
|
||||
}
|
||||
}
|
||||
timeLog(label = 'default', ...data) {
|
||||
const startTime = this._timers[label];
|
||||
if (startTime != null) {
|
||||
const endTime = new Date();
|
||||
const time = endTime.getTime() - startTime.getTime();
|
||||
this._log('time', (0, _nodeUtil().format)(`${label}: ${(0, _jestUtil().formatTime)(time)}`, ...data));
|
||||
}
|
||||
}
|
||||
warn(firstArg, ...args) {
|
||||
this._logError('warn', (0, _nodeUtil().format)(firstArg, ...args));
|
||||
}
|
||||
getBuffer() {
|
||||
return this._buffer.length > 0 ? this._buffer : undefined;
|
||||
}
|
||||
}
|
||||
exports["default"] = CustomConsole;
|
||||
|
||||
/***/ },
|
||||
|
||||
/***/ "./src/NullConsole.ts"
|
||||
(__unused_webpack_module, exports, __webpack_require__) {
|
||||
|
||||
|
||||
|
||||
Object.defineProperty(exports, "__esModule", ({
|
||||
value: true
|
||||
}));
|
||||
exports["default"] = void 0;
|
||||
var _CustomConsole = _interopRequireDefault(__webpack_require__("./src/CustomConsole.ts"));
|
||||
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
||||
/* eslint-disable @typescript-eslint/no-empty-function */
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
class NullConsole extends _CustomConsole.default {
|
||||
assert() {}
|
||||
debug() {}
|
||||
dir() {}
|
||||
error() {}
|
||||
info() {}
|
||||
log() {}
|
||||
time() {}
|
||||
timeEnd() {}
|
||||
timeLog() {}
|
||||
trace() {}
|
||||
warn() {}
|
||||
group() {}
|
||||
groupCollapsed() {}
|
||||
groupEnd() {}
|
||||
}
|
||||
exports["default"] = NullConsole;
|
||||
|
||||
/***/ },
|
||||
|
||||
/***/ "./src/getConsoleOutput.ts"
|
||||
(__unused_webpack_module, exports) {
|
||||
|
||||
|
||||
|
||||
Object.defineProperty(exports, "__esModule", ({
|
||||
value: true
|
||||
}));
|
||||
exports["default"] = getConsoleOutput;
|
||||
function _chalk() {
|
||||
const data = _interopRequireDefault(require("chalk"));
|
||||
_chalk = function () {
|
||||
return data;
|
||||
};
|
||||
return data;
|
||||
}
|
||||
function _jestMessageUtil() {
|
||||
const data = require("jest-message-util");
|
||||
_jestMessageUtil = function () {
|
||||
return data;
|
||||
};
|
||||
return data;
|
||||
}
|
||||
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
function getConsoleOutput(buffer, config, globalConfig) {
|
||||
const TITLE_INDENT = globalConfig.verbose === true ? ' '.repeat(2) : ' '.repeat(4);
|
||||
const CONSOLE_INDENT = TITLE_INDENT + ' '.repeat(2);
|
||||
const logEntries = buffer.reduce((output, {
|
||||
type,
|
||||
message,
|
||||
origin
|
||||
}) => {
|
||||
message = message.split(/\n/).map(line => CONSOLE_INDENT + line).join('\n');
|
||||
let typeMessage = `console.${type}`;
|
||||
let noStackTrace = true;
|
||||
let noCodeFrame = true;
|
||||
if (type === 'warn') {
|
||||
message = _chalk().default.yellow(message);
|
||||
typeMessage = _chalk().default.yellow(typeMessage);
|
||||
noStackTrace = globalConfig?.noStackTrace ?? false;
|
||||
noCodeFrame = false;
|
||||
} else if (type === 'error') {
|
||||
message = _chalk().default.red(message);
|
||||
typeMessage = _chalk().default.red(typeMessage);
|
||||
noStackTrace = globalConfig?.noStackTrace ?? false;
|
||||
noCodeFrame = false;
|
||||
}
|
||||
const options = {
|
||||
noCodeFrame,
|
||||
noStackTrace
|
||||
};
|
||||
const formattedStackTrace = (0, _jestMessageUtil().formatStackTrace)(origin, config, options);
|
||||
return `${output + TITLE_INDENT + _chalk().default.dim(typeMessage)}\n${message.trimEnd()}\n${_chalk().default.dim(formattedStackTrace.trimEnd())}\n\n`;
|
||||
}, '');
|
||||
return `${logEntries.trimEnd()}\n`;
|
||||
}
|
||||
|
||||
/***/ }
|
||||
|
||||
/******/ });
|
||||
/************************************************************************/
|
||||
/******/ // The module cache
|
||||
/******/ const __webpack_module_cache__ = {};
|
||||
/******/
|
||||
/******/ // The require function
|
||||
/******/ function __webpack_require__(moduleId) {
|
||||
/******/ // Check if module is in cache
|
||||
/******/ const cachedModule = __webpack_module_cache__[moduleId];
|
||||
/******/ if (cachedModule !== undefined) {
|
||||
/******/ return cachedModule.exports;
|
||||
/******/ }
|
||||
/******/ // Create a new module (and put it into the cache)
|
||||
/******/ const module = __webpack_module_cache__[moduleId] = {
|
||||
/******/ // no module.id needed
|
||||
/******/ // no module.loaded needed
|
||||
/******/ exports: {}
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // Execute the module function
|
||||
/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
|
||||
/******/
|
||||
/******/ // Return the exports of the module
|
||||
/******/ return module.exports;
|
||||
/******/ }
|
||||
/******/
|
||||
/************************************************************************/
|
||||
let __webpack_exports__ = {};
|
||||
// This entry needs to be wrapped in an IIFE because it uses a non-standard name for the exports (exports).
|
||||
(() => {
|
||||
let exports = __webpack_exports__;
|
||||
|
||||
|
||||
Object.defineProperty(exports, "__esModule", ({
|
||||
value: true
|
||||
}));
|
||||
Object.defineProperty(exports, "BufferedConsole", ({
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _BufferedConsole.default;
|
||||
}
|
||||
}));
|
||||
Object.defineProperty(exports, "CustomConsole", ({
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _CustomConsole.default;
|
||||
}
|
||||
}));
|
||||
Object.defineProperty(exports, "NullConsole", ({
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _NullConsole.default;
|
||||
}
|
||||
}));
|
||||
Object.defineProperty(exports, "getConsoleOutput", ({
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _getConsoleOutput.default;
|
||||
}
|
||||
}));
|
||||
var _BufferedConsole = _interopRequireDefault(__webpack_require__("./src/BufferedConsole.ts"));
|
||||
var _CustomConsole = _interopRequireDefault(__webpack_require__("./src/CustomConsole.ts"));
|
||||
var _NullConsole = _interopRequireDefault(__webpack_require__("./src/NullConsole.ts"));
|
||||
var _getConsoleOutput = _interopRequireDefault(__webpack_require__("./src/getConsoleOutput.ts"));
|
||||
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
||||
})();
|
||||
|
||||
module.exports = __webpack_exports__;
|
||||
/******/ })()
|
||||
;
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
import cjsModule from './index.js';
|
||||
|
||||
export const BufferedConsole = cjsModule.BufferedConsole;
|
||||
export const CustomConsole = cjsModule.CustomConsole;
|
||||
export const NullConsole = cjsModule.NullConsole;
|
||||
export const getConsoleOutput = cjsModule.getConsoleOutput;
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
{
|
||||
"name": "@jest/console",
|
||||
"version": "30.5.1",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/jestjs/jest.git",
|
||||
"directory": "packages/jest-console"
|
||||
},
|
||||
"license": "MIT",
|
||||
"main": "./build/index.js",
|
||||
"types": "./build/index.d.ts",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./build/index.d.ts",
|
||||
"require": "./build/index.js",
|
||||
"import": "./build/index.mjs",
|
||||
"default": "./build/index.js"
|
||||
},
|
||||
"./package.json": "./package.json"
|
||||
},
|
||||
"dependencies": {
|
||||
"@jest/types": "30.5.1",
|
||||
"@types/node": "*",
|
||||
"chalk": "^4.1.2",
|
||||
"jest-message-util": "30.5.1",
|
||||
"jest-util": "30.5.1",
|
||||
"slash": "^3.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@jest/test-utils": "30.5.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"gitHead": "9ab14feccd6c15fec1334dbcb03a53a079d153d3"
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
Copyright Contributors to the Jest project.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
# @jest/core
|
||||
|
||||
Jest is currently working on providing a programmatic API. This is under development, and usage of this package directly is currently not supported.
|
||||
+112
@@ -0,0 +1,112 @@
|
||||
/**
|
||||
* 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 {TestPathPatternsExecutor} from '@jest/pattern';
|
||||
import {BaseReporter, Reporter, ReporterContext} from '@jest/reporters';
|
||||
import {AggregatedResult, Test, TestContext} from '@jest/test-result';
|
||||
import {Config} from '@jest/types';
|
||||
import {ChangedFiles} from 'jest-changed-files';
|
||||
import {TestRunnerContext} from 'jest-runner';
|
||||
import {TestWatcher} from 'jest-watcher';
|
||||
|
||||
export declare function createTestScheduler(
|
||||
globalConfig: Config.GlobalConfig,
|
||||
context: TestSchedulerContext,
|
||||
): Promise<TestScheduler>;
|
||||
|
||||
declare type Filter = (testPaths: Array<string>) => Promise<{
|
||||
filtered: Array<string>;
|
||||
}>;
|
||||
|
||||
export declare function getVersion(): string;
|
||||
|
||||
declare type ReporterConstructor = new (
|
||||
globalConfig: Config.GlobalConfig,
|
||||
reporterConfig: Record<string, unknown>,
|
||||
reporterContext: ReporterContext,
|
||||
) => BaseReporter;
|
||||
|
||||
export declare function runCLI(
|
||||
argv: Config.Argv,
|
||||
projects: Array<string>,
|
||||
): Promise<{
|
||||
results: AggregatedResult;
|
||||
globalConfig: Config.GlobalConfig;
|
||||
}>;
|
||||
|
||||
declare type SearchResult = {
|
||||
noSCM?: boolean;
|
||||
stats?: Stats;
|
||||
collectCoverageFrom?: Set<string>;
|
||||
tests: Array<Test>;
|
||||
total?: number;
|
||||
};
|
||||
|
||||
export declare class SearchSource {
|
||||
private readonly _context;
|
||||
private _dependencyResolver;
|
||||
private readonly _testPathCases;
|
||||
constructor(context: TestContext);
|
||||
private _getOrBuildDependencyResolver;
|
||||
private _filterTestPathsWithStats;
|
||||
private _getAllTestPaths;
|
||||
isTestFilePath(path: string): boolean;
|
||||
findMatchingTests(
|
||||
testPathPatternsExecutor: TestPathPatternsExecutor,
|
||||
): SearchResult;
|
||||
findRelatedTests(
|
||||
allPaths: Set<string>,
|
||||
collectCoverage: boolean,
|
||||
): Promise<SearchResult>;
|
||||
findTestsByPaths(paths: Array<string>): SearchResult;
|
||||
findRelatedTestsFromPattern(
|
||||
paths: Array<string>,
|
||||
collectCoverage: boolean,
|
||||
): Promise<SearchResult>;
|
||||
findTestRelatedToChangedFiles(
|
||||
changedFilesInfo: ChangedFiles,
|
||||
collectCoverage: boolean,
|
||||
): Promise<SearchResult>;
|
||||
private _getTestPaths;
|
||||
filterPathsWin32(paths: Array<string>): Array<string>;
|
||||
getTestPaths(
|
||||
globalConfig: Config.GlobalConfig,
|
||||
projectConfig: Config.ProjectConfig,
|
||||
changedFiles?: ChangedFiles,
|
||||
filter?: Filter,
|
||||
): Promise<SearchResult>;
|
||||
findRelatedSourcesFromTestsInChangedFiles(
|
||||
changedFilesInfo: ChangedFiles,
|
||||
): Promise<Array<string>>;
|
||||
}
|
||||
|
||||
declare type Stats = {
|
||||
roots: number;
|
||||
testMatch: number;
|
||||
testPathIgnorePatterns: number;
|
||||
testRegex: number;
|
||||
testPathPatterns?: number;
|
||||
};
|
||||
|
||||
declare class TestScheduler {
|
||||
private readonly _context;
|
||||
private readonly _dispatcher;
|
||||
private readonly _globalConfig;
|
||||
constructor(globalConfig: Config.GlobalConfig, context: TestSchedulerContext);
|
||||
addReporter(reporter: Reporter): void;
|
||||
removeReporter(reporterConstructor: ReporterConstructor): void;
|
||||
scheduleTests(
|
||||
tests: Array<Test>,
|
||||
watcher: TestWatcher,
|
||||
): Promise<AggregatedResult>;
|
||||
private _partitionTests;
|
||||
_setupReporters(tests: Array<Test>): Promise<void>;
|
||||
private _addCustomReporter;
|
||||
private _bailIfNeeded;
|
||||
}
|
||||
|
||||
declare type TestSchedulerContext = ReporterContext & TestRunnerContext;
|
||||
+4272
File diff suppressed because it is too large
Load Diff
+6
@@ -0,0 +1,6 @@
|
||||
import cjsModule from './index.js';
|
||||
|
||||
export const SearchSource = cjsModule.SearchSource;
|
||||
export const createTestScheduler = cjsModule.createTestScheduler;
|
||||
export const getVersion = cjsModule.getVersion;
|
||||
export const runCLI = cjsModule.runCLI;
|
||||
+102
@@ -0,0 +1,102 @@
|
||||
{
|
||||
"name": "@jest/core",
|
||||
"description": "Delightful JavaScript Testing.",
|
||||
"version": "30.5.1",
|
||||
"main": "./build/index.js",
|
||||
"types": "./build/index.d.ts",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./build/index.d.ts",
|
||||
"require": "./build/index.js",
|
||||
"import": "./build/index.mjs",
|
||||
"default": "./build/index.js"
|
||||
},
|
||||
"./package.json": "./package.json"
|
||||
},
|
||||
"dependencies": {
|
||||
"@jest/console": "30.5.1",
|
||||
"@jest/pattern": "30.5.0",
|
||||
"@jest/reporters": "30.5.1",
|
||||
"@jest/test-result": "30.5.1",
|
||||
"@jest/transform": "30.5.1",
|
||||
"@jest/types": "30.5.1",
|
||||
"@types/node": "*",
|
||||
"ansi-escapes": "^4.3.2",
|
||||
"chalk": "^4.1.2",
|
||||
"ci-info": "^4.2.0",
|
||||
"exit-x": "^0.2.2",
|
||||
"fast-json-stable-stringify": "^2.1.0",
|
||||
"graceful-fs": "^4.2.11",
|
||||
"jest-changed-files": "30.5.1",
|
||||
"jest-config": "30.5.1",
|
||||
"jest-haste-map": "30.5.1",
|
||||
"jest-message-util": "30.5.1",
|
||||
"jest-regex-util": "30.5.0",
|
||||
"jest-resolve": "30.5.1",
|
||||
"jest-resolve-dependencies": "30.5.1",
|
||||
"jest-runner": "30.5.1",
|
||||
"jest-runtime": "30.5.1",
|
||||
"jest-snapshot": "30.5.1",
|
||||
"jest-util": "30.5.1",
|
||||
"jest-validate": "30.5.1",
|
||||
"jest-watcher": "30.5.1",
|
||||
"pretty-format": "30.5.1",
|
||||
"slash": "^3.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@jest/test-sequencer": "30.5.1",
|
||||
"@jest/test-utils": "30.5.1",
|
||||
"@types/graceful-fs": "^4.1.9"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"node-notifier": {
|
||||
"optional": true
|
||||
}
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/jestjs/jest.git",
|
||||
"directory": "packages/jest-core"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/jestjs/jest/issues"
|
||||
},
|
||||
"homepage": "https://jestjs.io/",
|
||||
"license": "MIT",
|
||||
"keywords": [
|
||||
"ava",
|
||||
"babel",
|
||||
"coverage",
|
||||
"easy",
|
||||
"expect",
|
||||
"facebook",
|
||||
"immersive",
|
||||
"instant",
|
||||
"jasmine",
|
||||
"jest",
|
||||
"jsdom",
|
||||
"mocha",
|
||||
"mocking",
|
||||
"painless",
|
||||
"qunit",
|
||||
"runner",
|
||||
"sandboxed",
|
||||
"snapshot",
|
||||
"tap",
|
||||
"tape",
|
||||
"test",
|
||||
"testing",
|
||||
"typescript",
|
||||
"watch"
|
||||
],
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"gitHead": "9ab14feccd6c15fec1334dbcb03a53a079d153d3"
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
Copyright Contributors to the Jest project.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
+404
@@ -0,0 +1,404 @@
|
||||
# diff-sequences
|
||||
|
||||
Compare items in two sequences to find a **longest common subsequence**.
|
||||
|
||||
The items not in common are the items to delete or insert in a **shortest edit script**.
|
||||
|
||||
To maximize flexibility and minimize memory, you write **callback** functions as configuration:
|
||||
|
||||
**Input** function `isCommon(aIndex, bIndex)` compares items at indexes in the sequences and returns a truthy/falsey value. This package might call your function more than once for some pairs of indexes.
|
||||
|
||||
- Because your function encapsulates **comparison**, this package can compare items according to `===` operator, `Object.is` method, or other criterion.
|
||||
- Because your function encapsulates **sequences**, this package can find differences in arrays, strings, or other data.
|
||||
|
||||
**Output** function `foundSubsequence(nCommon, aCommon, bCommon)` receives the number of adjacent items and starting indexes of each common subsequence. If sequences do not have common items, then this package does not call your function.
|
||||
|
||||
If N is the sum of lengths of sequences and L is length of a longest common subsequence, then D = N – 2L is the number of **differences** in the corresponding shortest edit script.
|
||||
|
||||
[_An O(ND) Difference Algorithm and Its Variations_](http://xmailserver.org/diff2.pdf) by Eugene W. Myers is fast when sequences have **few** differences.
|
||||
|
||||
This package implements the **linear space** variation with optimizations so it is fast even when sequences have **many** differences.
|
||||
|
||||
## Usage
|
||||
|
||||
To add this package as a dependency of a project, do either of the following:
|
||||
|
||||
- `npm install diff-sequences`
|
||||
- `yarn add diff-sequences`
|
||||
|
||||
To use `diff` as the name of the default export from this package, do either of the following:
|
||||
|
||||
- `var diff = require('@jest/diff-sequences').default; // CommonJS modules`
|
||||
- `import diff from '@jest/diff-sequences'; // ECMAScript modules`
|
||||
|
||||
Call `diff` with the **lengths** of sequences and your **callback** functions:
|
||||
|
||||
```js
|
||||
const a = ['a', 'b', 'c', 'a', 'b', 'b', 'a'];
|
||||
const b = ['c', 'b', 'a', 'b', 'a', 'c'];
|
||||
|
||||
function isCommon(aIndex, bIndex) {
|
||||
return a[aIndex] === b[bIndex];
|
||||
}
|
||||
function foundSubsequence(nCommon, aCommon, bCommon) {
|
||||
// see examples
|
||||
}
|
||||
|
||||
diff(a.length, b.length, isCommon, foundSubsequence);
|
||||
```
|
||||
|
||||
## Example of longest common subsequence
|
||||
|
||||
Some sequences (for example, `a` and `b` in the example of usage) have more than one longest common subsequence.
|
||||
|
||||
This package finds the following common items:
|
||||
|
||||
| comparisons of common items | values | output arguments |
|
||||
| :------------------------------- | :--------- | --------------------------: |
|
||||
| `a[2] === b[0]` | `'c'` | `foundSubsequence(1, 2, 0)` |
|
||||
| `a[4] === b[1]` | `'b'` | `foundSubsequence(1, 4, 1)` |
|
||||
| `a[5] === b[3] && a[6] === b[4]` | `'b', 'a'` | `foundSubsequence(2, 5, 3)` |
|
||||
|
||||
The “edit graph” analogy in the Myers paper shows the following common items:
|
||||
|
||||
| comparisons of common items | values |
|
||||
| :------------------------------- | :--------- |
|
||||
| `a[2] === b[0]` | `'c'` |
|
||||
| `a[3] === b[2] && a[4] === b[3]` | `'a', 'b'` |
|
||||
| `a[6] === b[4]` | `'a'` |
|
||||
|
||||
Various packages which implement the Myers algorithm will **always agree** on the **length** of a longest common subsequence, but might **sometimes disagree** on which **items** are in it.
|
||||
|
||||
## Example of callback functions to count common items
|
||||
|
||||
```js
|
||||
// Return length of longest common subsequence according to === operator.
|
||||
function countCommonItems(a, b) {
|
||||
let n = 0;
|
||||
function isCommon(aIndex, bIndex) {
|
||||
return a[aIndex] === b[bIndex];
|
||||
}
|
||||
function foundSubsequence(nCommon) {
|
||||
n += nCommon;
|
||||
}
|
||||
|
||||
diff(a.length, b.length, isCommon, foundSubsequence);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
const commonLength = countCommonItems(
|
||||
['a', 'b', 'c', 'a', 'b', 'b', 'a'],
|
||||
['c', 'b', 'a', 'b', 'a', 'c'],
|
||||
);
|
||||
```
|
||||
|
||||
| category of items | expression | value |
|
||||
| :----------------- | ------------------------: | ----: |
|
||||
| in common | `commonLength` | `4` |
|
||||
| to delete from `a` | `a.length - commonLength` | `3` |
|
||||
| to insert from `b` | `b.length - commonLength` | `2` |
|
||||
|
||||
If the length difference `b.length - a.length` is:
|
||||
|
||||
- negative: its absolute value is the minimum number of items to **delete** from `a`
|
||||
- positive: it is the minimum number of items to **insert** from `b`
|
||||
- zero: there is an **equal** number of items to delete from `a` and insert from `b`
|
||||
- non-zero: there is an equal number of **additional** items to delete from `a` and insert from `b`
|
||||
|
||||
In this example, `6 - 7` is:
|
||||
|
||||
- negative: `1` is the minimum number of items to **delete** from `a`
|
||||
- non-zero: `2` is the number of **additional** items to delete from `a` and insert from `b`
|
||||
|
||||
## Example of callback functions to find common items
|
||||
|
||||
```js
|
||||
// Return array of items in longest common subsequence according to Object.is method.
|
||||
const findCommonItems = (a, b) => {
|
||||
const array = [];
|
||||
diff(
|
||||
a.length,
|
||||
b.length,
|
||||
(aIndex, bIndex) => Object.is(a[aIndex], b[bIndex]),
|
||||
(nCommon, aCommon) => {
|
||||
for (; nCommon !== 0; nCommon -= 1, aCommon += 1) {
|
||||
array.push(a[aCommon]);
|
||||
}
|
||||
},
|
||||
);
|
||||
return array;
|
||||
};
|
||||
|
||||
const commonItems = findCommonItems(
|
||||
['a', 'b', 'c', 'a', 'b', 'b', 'a'],
|
||||
['c', 'b', 'a', 'b', 'a', 'c'],
|
||||
);
|
||||
```
|
||||
|
||||
| `i` | `commonItems[i]` | `aIndex` |
|
||||
| --: | :--------------- | -------: |
|
||||
| `0` | `'c'` | `2` |
|
||||
| `1` | `'b'` | `4` |
|
||||
| `2` | `'b'` | `5` |
|
||||
| `3` | `'a'` | `6` |
|
||||
|
||||
## Example of callback functions to diff index intervals
|
||||
|
||||
Instead of slicing array-like objects, you can adjust indexes in your callback functions.
|
||||
|
||||
```js
|
||||
// Diff index intervals that are half open [start, end) like array slice method.
|
||||
const diffIndexIntervals = (a, aStart, aEnd, b, bStart, bEnd) => {
|
||||
// Validate: 0 <= aStart and aStart <= aEnd and aEnd <= a.length
|
||||
// Validate: 0 <= bStart and bStart <= bEnd and bEnd <= b.length
|
||||
|
||||
diff(
|
||||
aEnd - aStart,
|
||||
bEnd - bStart,
|
||||
(aIndex, bIndex) => Object.is(a[aStart + aIndex], b[bStart + bIndex]),
|
||||
(nCommon, aCommon, bCommon) => {
|
||||
// aStart + aCommon, bStart + bCommon
|
||||
},
|
||||
);
|
||||
|
||||
// After the last common subsequence, do any remaining work.
|
||||
};
|
||||
```
|
||||
|
||||
## Example of callback functions to emulate diff command
|
||||
|
||||
Linux or Unix has a `diff` command to compare files line by line. Its output is a **shortest edit script**:
|
||||
|
||||
- **c**hange adjacent lines from the first file to lines from the second file
|
||||
- **d**elete lines from the first file
|
||||
- **a**ppend or insert lines from the second file
|
||||
|
||||
```js
|
||||
// Given zero-based half-open range [start, end) of array indexes,
|
||||
// return one-based closed range [start + 1, end] as string.
|
||||
const getRange = (start, end) =>
|
||||
start + 1 === end ? `${start + 1}` : `${start + 1},${end}`;
|
||||
|
||||
// Given index intervals of lines to delete or insert, or both, or neither,
|
||||
// push formatted diff lines onto array.
|
||||
const pushDelIns = (aLines, aIndex, aEnd, bLines, bIndex, bEnd, array) => {
|
||||
const deleteLines = aIndex !== aEnd;
|
||||
const insertLines = bIndex !== bEnd;
|
||||
const changeLines = deleteLines && insertLines;
|
||||
if (changeLines) {
|
||||
array.push(`${getRange(aIndex, aEnd)}c${getRange(bIndex, bEnd)}`);
|
||||
} else if (deleteLines) {
|
||||
array.push(`${getRange(aIndex, aEnd)}d${String(bIndex)}`);
|
||||
} else if (insertLines) {
|
||||
array.push(`${String(aIndex)}a${getRange(bIndex, bEnd)}`);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
for (; aIndex !== aEnd; aIndex += 1) {
|
||||
array.push(`< ${aLines[aIndex]}`); // delete is less than
|
||||
}
|
||||
|
||||
if (changeLines) {
|
||||
array.push('---');
|
||||
}
|
||||
|
||||
for (; bIndex !== bEnd; bIndex += 1) {
|
||||
array.push(`> ${bLines[bIndex]}`); // insert is greater than
|
||||
}
|
||||
};
|
||||
|
||||
// Given content of two files, return emulated output of diff utility.
|
||||
const findShortestEditScript = (a, b) => {
|
||||
const aLines = a.split('\n');
|
||||
const bLines = b.split('\n');
|
||||
const aLength = aLines.length;
|
||||
const bLength = bLines.length;
|
||||
|
||||
const isCommon = (aIndex, bIndex) => aLines[aIndex] === bLines[bIndex];
|
||||
|
||||
let aIndex = 0;
|
||||
let bIndex = 0;
|
||||
const array = [];
|
||||
const foundSubsequence = (nCommon, aCommon, bCommon) => {
|
||||
pushDelIns(aLines, aIndex, aCommon, bLines, bIndex, bCommon, array);
|
||||
aIndex = aCommon + nCommon; // number of lines compared in a
|
||||
bIndex = bCommon + nCommon; // number of lines compared in b
|
||||
};
|
||||
|
||||
diff(aLength, bLength, isCommon, foundSubsequence);
|
||||
|
||||
// After the last common subsequence, push remaining change lines.
|
||||
pushDelIns(aLines, aIndex, aLength, bLines, bIndex, bLength, array);
|
||||
|
||||
return array.length === 0 ? '' : `${array.join('\n')}\n`;
|
||||
};
|
||||
```
|
||||
|
||||
## Example of callback functions to format diff lines
|
||||
|
||||
Here is simplified code to format **changed and unchanged lines** in expected and received values after a test fails in Jest:
|
||||
|
||||
```js
|
||||
// Format diff with minus or plus for change lines and space for common lines.
|
||||
const formatDiffLines = (a, b) => {
|
||||
// Jest depends on pretty-format package to serialize objects as strings.
|
||||
// Unindented for comparison to avoid distracting differences:
|
||||
const aLinesUn = format(a, {indent: 0 /*, other options*/}).split('\n');
|
||||
const bLinesUn = format(b, {indent: 0 /*, other options*/}).split('\n');
|
||||
// Indented to display changed and unchanged lines:
|
||||
const aLinesIn = format(a, {indent: 2 /*, other options*/}).split('\n');
|
||||
const bLinesIn = format(b, {indent: 2 /*, other options*/}).split('\n');
|
||||
|
||||
const aLength = aLinesIn.length; // Validate: aLinesUn.length === aLength
|
||||
const bLength = bLinesIn.length; // Validate: bLinesUn.length === bLength
|
||||
|
||||
const isCommon = (aIndex, bIndex) => aLinesUn[aIndex] === bLinesUn[bIndex];
|
||||
|
||||
// Only because the GitHub Flavored Markdown doc collapses adjacent spaces,
|
||||
// this example code and the following table represent spaces as middle dots.
|
||||
let aIndex = 0;
|
||||
let bIndex = 0;
|
||||
const array = [];
|
||||
const foundSubsequence = (nCommon, aCommon, bCommon) => {
|
||||
for (; aIndex !== aCommon; aIndex += 1) {
|
||||
array.push(`-·${aLinesIn[aIndex]}`); // delete is minus
|
||||
}
|
||||
for (; bIndex !== bCommon; bIndex += 1) {
|
||||
array.push(`+·${bLinesIn[bIndex]}`); // insert is plus
|
||||
}
|
||||
for (; nCommon !== 0; nCommon -= 1, aIndex += 1, bIndex += 1) {
|
||||
// For common lines, received indentation seems more intuitive.
|
||||
array.push(`··${bLinesIn[bIndex]}`); // common is space
|
||||
}
|
||||
};
|
||||
|
||||
diff(aLength, bLength, isCommon, foundSubsequence);
|
||||
|
||||
// After the last common subsequence, push remaining change lines.
|
||||
for (; aIndex !== aLength; aIndex += 1) {
|
||||
array.push(`-·${aLinesIn[aIndex]}`);
|
||||
}
|
||||
for (; bIndex !== bLength; bIndex += 1) {
|
||||
array.push(`+·${bLinesIn[bIndex]}`);
|
||||
}
|
||||
|
||||
return array;
|
||||
};
|
||||
|
||||
const expected = {
|
||||
searching: '',
|
||||
sorting: {
|
||||
ascending: true,
|
||||
fieldKey: 'what',
|
||||
},
|
||||
};
|
||||
const received = {
|
||||
searching: '',
|
||||
sorting: [
|
||||
{
|
||||
descending: false,
|
||||
fieldKey: 'what',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const diffLines = formatDiffLines(expected, received);
|
||||
```
|
||||
|
||||
If N is the sum of lengths of sequences and L is length of a longest common subsequence, then N – L is length of an array of diff lines. In this example, N is 7 + 9, L is 5, and N – L is 11.
|
||||
|
||||
| `i` | `diffLines[i]` | `aIndex` | `bIndex` |
|
||||
| ---: | :--------------------------------- | -------: | -------: |
|
||||
| `0` | `'··Object {'` | `0` | `0` |
|
||||
| `1` | `'····"searching": "",'` | `1` | `1` |
|
||||
| `2` | `'-···"sorting": Object {'` | `2` | |
|
||||
| `3` | `'-·····"ascending": true,'` | `3` | |
|
||||
| `4` | `'+·····"sorting": Array ['` | | `2` |
|
||||
| `5` | `'+·······Object {'` | | `3` |
|
||||
| `6` | `'+·········"descending": false,'` | | `4` |
|
||||
| `7` | `'··········"fieldKey": "what",'` | `4` | `5` |
|
||||
| `8` | `'········},'` | `5` | `6` |
|
||||
| `9` | `'+·····],'` | | `7` |
|
||||
| `10` | `'··}'` | `6` | `8` |
|
||||
|
||||
## Example of callback functions to find diff items
|
||||
|
||||
Here is simplified code to find changed and unchanged substrings **within adjacent changed lines** in expected and received values after a test fails in Jest:
|
||||
|
||||
```js
|
||||
// Return diff items for strings (compatible with diff-match-patch package).
|
||||
const findDiffItems = (a, b) => {
|
||||
const isCommon = (aIndex, bIndex) => a[aIndex] === b[bIndex];
|
||||
|
||||
let aIndex = 0;
|
||||
let bIndex = 0;
|
||||
const array = [];
|
||||
const foundSubsequence = (nCommon, aCommon, bCommon) => {
|
||||
if (aIndex !== aCommon) {
|
||||
array.push([-1, a.slice(aIndex, aCommon)]); // delete is -1
|
||||
}
|
||||
if (bIndex !== bCommon) {
|
||||
array.push([1, b.slice(bIndex, bCommon)]); // insert is 1
|
||||
}
|
||||
|
||||
aIndex = aCommon + nCommon; // number of characters compared in a
|
||||
bIndex = bCommon + nCommon; // number of characters compared in b
|
||||
array.push([0, a.slice(aCommon, aIndex)]); // common is 0
|
||||
};
|
||||
|
||||
diff(a.length, b.length, isCommon, foundSubsequence);
|
||||
|
||||
// After the last common subsequence, push remaining change items.
|
||||
if (aIndex !== a.length) {
|
||||
array.push([-1, a.slice(aIndex)]);
|
||||
}
|
||||
if (bIndex !== b.length) {
|
||||
array.push([1, b.slice(bIndex)]);
|
||||
}
|
||||
|
||||
return array;
|
||||
};
|
||||
|
||||
const expectedDeleted = ['"sorting": Object {', '"ascending": true,'].join(
|
||||
'\n',
|
||||
);
|
||||
const receivedInserted = [
|
||||
'"sorting": Array [',
|
||||
'Object {',
|
||||
'"descending": false,',
|
||||
].join('\n');
|
||||
|
||||
const diffItems = findDiffItems(expectedDeleted, receivedInserted);
|
||||
```
|
||||
|
||||
| `i` | `diffItems[i][0]` | `diffItems[i][1]` |
|
||||
| --: | ----------------: | :---------------- |
|
||||
| `0` | `0` | `'"sorting": '` |
|
||||
| `1` | `1` | `'Array [\n'` |
|
||||
| `2` | `0` | `'Object {\n"'` |
|
||||
| `3` | `-1` | `'a'` |
|
||||
| `4` | `1` | `'de'` |
|
||||
| `5` | `0` | `'scending": '` |
|
||||
| `6` | `-1` | `'tru'` |
|
||||
| `7` | `1` | `'fals'` |
|
||||
| `8` | `0` | `'e,'` |
|
||||
|
||||
The length difference `b.length - a.length` is equal to the sum of `diffItems[i][0]` values times `diffItems[i][1]` lengths. In this example, the difference `48 - 38` is equal to the sum `10`.
|
||||
|
||||
| category of diff item | `[0]` | `[1]` lengths | subtotal |
|
||||
| :-------------------- | ----: | -----------------: | -------: |
|
||||
| in common | `0` | `11 + 10 + 11 + 2` | `0` |
|
||||
| to delete from `a` | `–1` | `1 + 3` | `-4` |
|
||||
| to insert from `b` | `1` | `8 + 2 + 4` | `14` |
|
||||
|
||||
Instead of formatting the changed substrings with escape codes for colors in the `foundSubsequence` function to save memory, this example spends memory to **gain flexibility** before formatting, so a separate heuristic algorithm might modify the generic array of diff items to show changes more clearly:
|
||||
|
||||
| `i` | `diffItems[i][0]` | `diffItems[i][1]` |
|
||||
| --: | ----------------: | :---------------- |
|
||||
| `6` | `-1` | `'true'` |
|
||||
| `7` | `1` | `'false'` |
|
||||
| `8` | `0` | `','` |
|
||||
|
||||
For expected and received strings of serialized data, the result of finding changed **lines**, and then finding changed **substrings** within adjacent changed lines (as in the preceding two examples) sometimes displays the changes in a more intuitive way than the result of finding changed substrings, and then splitting them into changed and unchanged lines.
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* 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 declare type Callbacks = {
|
||||
foundSubsequence: FoundSubsequence;
|
||||
isCommon: IsCommon;
|
||||
};
|
||||
|
||||
declare function diffSequence(
|
||||
aLength: number,
|
||||
bLength: number,
|
||||
isCommon: IsCommon,
|
||||
foundSubsequence: FoundSubsequence,
|
||||
): void;
|
||||
export default diffSequence;
|
||||
|
||||
declare type FoundSubsequence = (
|
||||
nCommon: number, // caller can assume: 0 < nCommon
|
||||
aCommon: number, // caller can assume: 0 <= aCommon && aCommon < aLength
|
||||
bCommon: number,
|
||||
) => void;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
declare type IsCommon = (
|
||||
aIndex: number, // caller can assume: 0 <= aIndex && aIndex < aLength
|
||||
bIndex: number,
|
||||
) => boolean;
|
||||
+637
@@ -0,0 +1,637 @@
|
||||
/*!
|
||||
* /**
|
||||
* * 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.
|
||||
* * /
|
||||
*/
|
||||
/******/ (() => { // webpackBootstrap
|
||||
/******/ "use strict";
|
||||
let __webpack_exports__ = {};
|
||||
// This entry needs to be wrapped in an IIFE because it uses a non-standard name for the exports (exports).
|
||||
(() => {
|
||||
let exports = __webpack_exports__;
|
||||
|
||||
|
||||
Object.defineProperty(exports, "__esModule", ({
|
||||
value: true
|
||||
}));
|
||||
exports["default"] = diffSequence;
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
// This diff-sequences package implements the linear space variation in
|
||||
// An O(ND) Difference Algorithm and Its Variations by Eugene W. Myers
|
||||
|
||||
// Relationship in notation between Myers paper and this package:
|
||||
// A is a
|
||||
// N is aLength, aEnd - aStart, and so on
|
||||
// x is aIndex, aFirst, aLast, and so on
|
||||
// B is b
|
||||
// M is bLength, bEnd - bStart, and so on
|
||||
// y is bIndex, bFirst, bLast, and so on
|
||||
// Δ = N - M is negative of baDeltaLength = bLength - aLength
|
||||
// D is d
|
||||
// k is kF
|
||||
// k + Δ is kF = kR - baDeltaLength
|
||||
// V is aIndexesF or aIndexesR (see comment below about Indexes type)
|
||||
// index intervals [1, N] and [1, M] are [0, aLength) and [0, bLength)
|
||||
// starting point in forward direction (0, 0) is (-1, -1)
|
||||
// starting point in reverse direction (N + 1, M + 1) is (aLength, bLength)
|
||||
|
||||
// The “edit graph” for sequences a and b corresponds to items:
|
||||
// in a on the horizontal axis
|
||||
// in b on the vertical axis
|
||||
//
|
||||
// Given a-coordinate of a point in a diagonal, you can compute b-coordinate.
|
||||
//
|
||||
// Forward diagonals kF:
|
||||
// zero diagonal intersects top left corner
|
||||
// positive diagonals intersect top edge
|
||||
// negative diagonals intersect left edge
|
||||
//
|
||||
// Reverse diagonals kR:
|
||||
// zero diagonal intersects bottom right corner
|
||||
// positive diagonals intersect right edge
|
||||
// negative diagonals intersect bottom edge
|
||||
|
||||
// The graph contains a directed acyclic graph of edges:
|
||||
// horizontal: delete an item from a
|
||||
// vertical: insert an item from b
|
||||
// diagonal: common item in a and b
|
||||
//
|
||||
// The algorithm solves dual problems in the graph analogy:
|
||||
// Find longest common subsequence: path with maximum number of diagonal edges
|
||||
// Find shortest edit script: path with minimum number of non-diagonal edges
|
||||
|
||||
// Input callback function compares items at indexes in the sequences.
|
||||
|
||||
// Output callback function receives the number of adjacent items
|
||||
// and starting indexes of each common subsequence.
|
||||
|
||||
// Either original functions or wrapped to swap indexes if graph is transposed.
|
||||
|
||||
// Indexes in sequence a of last point of forward or reverse paths in graph.
|
||||
// Myers algorithm indexes by diagonal k which for negative is bad deopt in V8.
|
||||
// This package indexes by iF and iR which are greater than or equal to zero.
|
||||
// and also updates the index arrays in place to cut memory in half.
|
||||
// kF = 2 * iF - d
|
||||
// kR = d - 2 * iR
|
||||
|
||||
// Division of index intervals in sequences a and b at the middle change.
|
||||
// Invariant: intervals do not have common items at the start or end.
|
||||
|
||||
const pkg = '@jest/diff-sequences'; // for error messages
|
||||
const NOT_YET_SET = 0; // small int instead of undefined to avoid deopt in V8
|
||||
|
||||
// Return the number of common items that follow in forward direction.
|
||||
// The length of what Myers paper calls a “snake” in a forward path.
|
||||
const countCommonItemsF = (aIndex, aEnd, bIndex, bEnd, isCommon) => {
|
||||
let nCommon = 0;
|
||||
while (aIndex < aEnd && bIndex < bEnd && isCommon(aIndex, bIndex)) {
|
||||
aIndex += 1;
|
||||
bIndex += 1;
|
||||
nCommon += 1;
|
||||
}
|
||||
return nCommon;
|
||||
};
|
||||
|
||||
// Return the number of common items that precede in reverse direction.
|
||||
// The length of what Myers paper calls a “snake” in a reverse path.
|
||||
const countCommonItemsR = (aStart, aIndex, bStart, bIndex, isCommon) => {
|
||||
let nCommon = 0;
|
||||
while (aStart <= aIndex && bStart <= bIndex && isCommon(aIndex, bIndex)) {
|
||||
aIndex -= 1;
|
||||
bIndex -= 1;
|
||||
nCommon += 1;
|
||||
}
|
||||
return nCommon;
|
||||
};
|
||||
|
||||
// A simple function to extend forward paths from (d - 1) to d changes
|
||||
// when forward and reverse paths cannot yet overlap.
|
||||
const extendPathsF = (d, aEnd, bEnd, bF, isCommon, aIndexesF, iMaxF // return the value because optimization might decrease it
|
||||
) => {
|
||||
// Unroll the first iteration.
|
||||
let iF = 0;
|
||||
let kF = -d; // kF = 2 * iF - d
|
||||
let aFirst = aIndexesF[iF]; // in first iteration always insert
|
||||
let aIndexPrev1 = aFirst; // prev value of [iF - 1] in next iteration
|
||||
aIndexesF[iF] += countCommonItemsF(aFirst + 1, aEnd, bF + aFirst - kF + 1, bEnd, isCommon);
|
||||
|
||||
// Optimization: skip diagonals in which paths cannot ever overlap.
|
||||
const nF = Math.min(d, iMaxF);
|
||||
|
||||
// The diagonals kF are odd when d is odd and even when d is even.
|
||||
for (iF += 1, kF += 2; iF <= nF; iF += 1, kF += 2) {
|
||||
// To get first point of path segment, move one change in forward direction
|
||||
// from last point of previous path segment in an adjacent diagonal.
|
||||
// In last possible iteration when iF === d and kF === d always delete.
|
||||
if (iF !== d && aIndexPrev1 < aIndexesF[iF]) {
|
||||
aFirst = aIndexesF[iF]; // vertical to insert from b
|
||||
} else {
|
||||
aFirst = aIndexPrev1 + 1; // horizontal to delete from a
|
||||
|
||||
if (aEnd <= aFirst) {
|
||||
// Optimization: delete moved past right of graph.
|
||||
return iF - 1;
|
||||
}
|
||||
}
|
||||
|
||||
// To get last point of path segment, move along diagonal of common items.
|
||||
aIndexPrev1 = aIndexesF[iF];
|
||||
aIndexesF[iF] = aFirst + countCommonItemsF(aFirst + 1, aEnd, bF + aFirst - kF + 1, bEnd, isCommon);
|
||||
}
|
||||
return iMaxF;
|
||||
};
|
||||
|
||||
// A simple function to extend reverse paths from (d - 1) to d changes
|
||||
// when reverse and forward paths cannot yet overlap.
|
||||
const extendPathsR = (d, aStart, bStart, bR, isCommon, aIndexesR, iMaxR // return the value because optimization might decrease it
|
||||
) => {
|
||||
// Unroll the first iteration.
|
||||
let iR = 0;
|
||||
let kR = d; // kR = d - 2 * iR
|
||||
let aFirst = aIndexesR[iR]; // in first iteration always insert
|
||||
let aIndexPrev1 = aFirst; // prev value of [iR - 1] in next iteration
|
||||
aIndexesR[iR] -= countCommonItemsR(aStart, aFirst - 1, bStart, bR + aFirst - kR - 1, isCommon);
|
||||
|
||||
// Optimization: skip diagonals in which paths cannot ever overlap.
|
||||
const nR = Math.min(d, iMaxR);
|
||||
|
||||
// The diagonals kR are odd when d is odd and even when d is even.
|
||||
for (iR += 1, kR -= 2; iR <= nR; iR += 1, kR -= 2) {
|
||||
// To get first point of path segment, move one change in reverse direction
|
||||
// from last point of previous path segment in an adjacent diagonal.
|
||||
// In last possible iteration when iR === d and kR === -d always delete.
|
||||
if (iR !== d && aIndexesR[iR] < aIndexPrev1) {
|
||||
aFirst = aIndexesR[iR]; // vertical to insert from b
|
||||
} else {
|
||||
aFirst = aIndexPrev1 - 1; // horizontal to delete from a
|
||||
|
||||
if (aFirst < aStart) {
|
||||
// Optimization: delete moved past left of graph.
|
||||
return iR - 1;
|
||||
}
|
||||
}
|
||||
|
||||
// To get last point of path segment, move along diagonal of common items.
|
||||
aIndexPrev1 = aIndexesR[iR];
|
||||
aIndexesR[iR] = aFirst - countCommonItemsR(aStart, aFirst - 1, bStart, bR + aFirst - kR - 1, isCommon);
|
||||
}
|
||||
return iMaxR;
|
||||
};
|
||||
|
||||
// A complete function to extend forward paths from (d - 1) to d changes.
|
||||
// Return true if a path overlaps reverse path of (d - 1) changes in its diagonal.
|
||||
const extendOverlappablePathsF = (d, aStart, aEnd, bStart, bEnd, isCommon, aIndexesF, iMaxF, aIndexesR, iMaxR, division // update prop values if return true
|
||||
) => {
|
||||
const bF = bStart - aStart; // bIndex = bF + aIndex - kF
|
||||
const aLength = aEnd - aStart;
|
||||
const bLength = bEnd - bStart;
|
||||
const baDeltaLength = bLength - aLength; // kF = kR - baDeltaLength
|
||||
|
||||
// Range of diagonals in which forward and reverse paths might overlap.
|
||||
const kMinOverlapF = -baDeltaLength - (d - 1); // -(d - 1) <= kR
|
||||
const kMaxOverlapF = -baDeltaLength + (d - 1); // kR <= (d - 1)
|
||||
|
||||
let aIndexPrev1 = NOT_YET_SET; // prev value of [iF - 1] in next iteration
|
||||
|
||||
// Optimization: skip diagonals in which paths cannot ever overlap.
|
||||
const nF = Math.min(d, iMaxF);
|
||||
|
||||
// The diagonals kF = 2 * iF - d are odd when d is odd and even when d is even.
|
||||
for (let iF = 0, kF = -d; iF <= nF; iF += 1, kF += 2) {
|
||||
// To get first point of path segment, move one change in forward direction
|
||||
// from last point of previous path segment in an adjacent diagonal.
|
||||
// In first iteration when iF === 0 and kF === -d always insert.
|
||||
// In last possible iteration when iF === d and kF === d always delete.
|
||||
const insert = iF === 0 || iF !== d && aIndexPrev1 < aIndexesF[iF];
|
||||
const aLastPrev = insert ? aIndexesF[iF] : aIndexPrev1;
|
||||
const aFirst = insert ? aLastPrev // vertical to insert from b
|
||||
: aLastPrev + 1; // horizontal to delete from a
|
||||
|
||||
// To get last point of path segment, move along diagonal of common items.
|
||||
const bFirst = bF + aFirst - kF;
|
||||
const nCommonF = countCommonItemsF(aFirst + 1, aEnd, bFirst + 1, bEnd, isCommon);
|
||||
const aLast = aFirst + nCommonF;
|
||||
aIndexPrev1 = aIndexesF[iF];
|
||||
aIndexesF[iF] = aLast;
|
||||
if (kMinOverlapF <= kF && kF <= kMaxOverlapF) {
|
||||
// Solve for iR of reverse path with (d - 1) changes in diagonal kF:
|
||||
// kR = kF + baDeltaLength
|
||||
// kR = (d - 1) - 2 * iR
|
||||
const iR = (d - 1 - (kF + baDeltaLength)) / 2;
|
||||
|
||||
// If this forward path overlaps the reverse path in this diagonal,
|
||||
// then this is the middle change of the index intervals.
|
||||
if (iR <= iMaxR && aIndexesR[iR] - 1 <= aLast) {
|
||||
// Unlike the Myers algorithm which finds only the middle “snake”
|
||||
// this package can find two common subsequences per division.
|
||||
// Last point of previous path segment is on an adjacent diagonal.
|
||||
const bLastPrev = bF + aLastPrev - (insert ? kF + 1 : kF - 1);
|
||||
|
||||
// Because of invariant that intervals preceding the middle change
|
||||
// cannot have common items at the end,
|
||||
// move in reverse direction along a diagonal of common items.
|
||||
const nCommonR = countCommonItemsR(aStart, aLastPrev, bStart, bLastPrev, isCommon);
|
||||
const aIndexPrevFirst = aLastPrev - nCommonR;
|
||||
const bIndexPrevFirst = bLastPrev - nCommonR;
|
||||
const aEndPreceding = aIndexPrevFirst + 1;
|
||||
const bEndPreceding = bIndexPrevFirst + 1;
|
||||
division.nChangePreceding = d - 1;
|
||||
if (d - 1 === aEndPreceding + bEndPreceding - aStart - bStart) {
|
||||
// Optimization: number of preceding changes in forward direction
|
||||
// is equal to number of items in preceding interval,
|
||||
// therefore it cannot contain any common items.
|
||||
division.aEndPreceding = aStart;
|
||||
division.bEndPreceding = bStart;
|
||||
} else {
|
||||
division.aEndPreceding = aEndPreceding;
|
||||
division.bEndPreceding = bEndPreceding;
|
||||
}
|
||||
division.nCommonPreceding = nCommonR;
|
||||
if (nCommonR !== 0) {
|
||||
division.aCommonPreceding = aEndPreceding;
|
||||
division.bCommonPreceding = bEndPreceding;
|
||||
}
|
||||
division.nCommonFollowing = nCommonF;
|
||||
if (nCommonF !== 0) {
|
||||
division.aCommonFollowing = aFirst + 1;
|
||||
division.bCommonFollowing = bFirst + 1;
|
||||
}
|
||||
const aStartFollowing = aLast + 1;
|
||||
const bStartFollowing = bFirst + nCommonF + 1;
|
||||
division.nChangeFollowing = d - 1;
|
||||
if (d - 1 === aEnd + bEnd - aStartFollowing - bStartFollowing) {
|
||||
// Optimization: number of changes in reverse direction
|
||||
// is equal to number of items in following interval,
|
||||
// therefore it cannot contain any common items.
|
||||
division.aStartFollowing = aEnd;
|
||||
division.bStartFollowing = bEnd;
|
||||
} else {
|
||||
division.aStartFollowing = aStartFollowing;
|
||||
division.bStartFollowing = bStartFollowing;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
// A complete function to extend reverse paths from (d - 1) to d changes.
|
||||
// Return true if a path overlaps forward path of d changes in its diagonal.
|
||||
const extendOverlappablePathsR = (d, aStart, aEnd, bStart, bEnd, isCommon, aIndexesF, iMaxF, aIndexesR, iMaxR, division // update prop values if return true
|
||||
) => {
|
||||
const bR = bEnd - aEnd; // bIndex = bR + aIndex - kR
|
||||
const aLength = aEnd - aStart;
|
||||
const bLength = bEnd - bStart;
|
||||
const baDeltaLength = bLength - aLength; // kR = kF + baDeltaLength
|
||||
|
||||
// Range of diagonals in which forward and reverse paths might overlap.
|
||||
const kMinOverlapR = baDeltaLength - d; // -d <= kF
|
||||
const kMaxOverlapR = baDeltaLength + d; // kF <= d
|
||||
|
||||
let aIndexPrev1 = NOT_YET_SET; // prev value of [iR - 1] in next iteration
|
||||
|
||||
// Optimization: skip diagonals in which paths cannot ever overlap.
|
||||
const nR = Math.min(d, iMaxR);
|
||||
|
||||
// The diagonals kR = d - 2 * iR are odd when d is odd and even when d is even.
|
||||
for (let iR = 0, kR = d; iR <= nR; iR += 1, kR -= 2) {
|
||||
// To get first point of path segment, move one change in reverse direction
|
||||
// from last point of previous path segment in an adjacent diagonal.
|
||||
// In first iteration when iR === 0 and kR === d always insert.
|
||||
// In last possible iteration when iR === d and kR === -d always delete.
|
||||
const insert = iR === 0 || iR !== d && aIndexesR[iR] < aIndexPrev1;
|
||||
const aLastPrev = insert ? aIndexesR[iR] : aIndexPrev1;
|
||||
const aFirst = insert ? aLastPrev // vertical to insert from b
|
||||
: aLastPrev - 1; // horizontal to delete from a
|
||||
|
||||
// To get last point of path segment, move along diagonal of common items.
|
||||
const bFirst = bR + aFirst - kR;
|
||||
const nCommonR = countCommonItemsR(aStart, aFirst - 1, bStart, bFirst - 1, isCommon);
|
||||
const aLast = aFirst - nCommonR;
|
||||
aIndexPrev1 = aIndexesR[iR];
|
||||
aIndexesR[iR] = aLast;
|
||||
if (kMinOverlapR <= kR && kR <= kMaxOverlapR) {
|
||||
// Solve for iF of forward path with d changes in diagonal kR:
|
||||
// kF = kR - baDeltaLength
|
||||
// kF = 2 * iF - d
|
||||
const iF = (d + (kR - baDeltaLength)) / 2;
|
||||
|
||||
// If this reverse path overlaps the forward path in this diagonal,
|
||||
// then this is a middle change of the index intervals.
|
||||
if (iF <= iMaxF && aLast - 1 <= aIndexesF[iF]) {
|
||||
const bLast = bFirst - nCommonR;
|
||||
division.nChangePreceding = d;
|
||||
if (d === aLast + bLast - aStart - bStart) {
|
||||
// Optimization: number of changes in reverse direction
|
||||
// is equal to number of items in preceding interval,
|
||||
// therefore it cannot contain any common items.
|
||||
division.aEndPreceding = aStart;
|
||||
division.bEndPreceding = bStart;
|
||||
} else {
|
||||
division.aEndPreceding = aLast;
|
||||
division.bEndPreceding = bLast;
|
||||
}
|
||||
division.nCommonPreceding = nCommonR;
|
||||
if (nCommonR !== 0) {
|
||||
// The last point of reverse path segment is start of common subsequence.
|
||||
division.aCommonPreceding = aLast;
|
||||
division.bCommonPreceding = bLast;
|
||||
}
|
||||
division.nChangeFollowing = d - 1;
|
||||
if (d === 1) {
|
||||
// There is no previous path segment.
|
||||
division.nCommonFollowing = 0;
|
||||
division.aStartFollowing = aEnd;
|
||||
division.bStartFollowing = bEnd;
|
||||
} else {
|
||||
// Unlike the Myers algorithm which finds only the middle “snake”
|
||||
// this package can find two common subsequences per division.
|
||||
// Last point of previous path segment is on an adjacent diagonal.
|
||||
const bLastPrev = bR + aLastPrev - (insert ? kR - 1 : kR + 1);
|
||||
|
||||
// Because of invariant that intervals following the middle change
|
||||
// cannot have common items at the start,
|
||||
// move in forward direction along a diagonal of common items.
|
||||
const nCommonF = countCommonItemsF(aLastPrev, aEnd, bLastPrev, bEnd, isCommon);
|
||||
division.nCommonFollowing = nCommonF;
|
||||
if (nCommonF !== 0) {
|
||||
// The last point of reverse path segment is start of common subsequence.
|
||||
division.aCommonFollowing = aLastPrev;
|
||||
division.bCommonFollowing = bLastPrev;
|
||||
}
|
||||
const aStartFollowing = aLastPrev + nCommonF; // aFirstPrev
|
||||
const bStartFollowing = bLastPrev + nCommonF; // bFirstPrev
|
||||
|
||||
if (d - 1 === aEnd + bEnd - aStartFollowing - bStartFollowing) {
|
||||
// Optimization: number of changes in forward direction
|
||||
// is equal to number of items in following interval,
|
||||
// therefore it cannot contain any common items.
|
||||
division.aStartFollowing = aEnd;
|
||||
division.bStartFollowing = bEnd;
|
||||
} else {
|
||||
division.aStartFollowing = aStartFollowing;
|
||||
division.bStartFollowing = bStartFollowing;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
// Given index intervals and input function to compare items at indexes,
|
||||
// divide at the middle change.
|
||||
//
|
||||
// DO NOT CALL if start === end, because interval cannot contain common items
|
||||
// and because this function will throw the “no overlap” error.
|
||||
const divide = (nChange, aStart, aEnd, bStart, bEnd, isCommon, aIndexesF, aIndexesR, division // output
|
||||
) => {
|
||||
const bF = bStart - aStart; // bIndex = bF + aIndex - kF
|
||||
const bR = bEnd - aEnd; // bIndex = bR + aIndex - kR
|
||||
const aLength = aEnd - aStart;
|
||||
const bLength = bEnd - bStart;
|
||||
|
||||
// Because graph has square or portrait orientation,
|
||||
// length difference is minimum number of items to insert from b.
|
||||
// Corresponding forward and reverse diagonals in graph
|
||||
// depend on length difference of the sequences:
|
||||
// kF = kR - baDeltaLength
|
||||
// kR = kF + baDeltaLength
|
||||
const baDeltaLength = bLength - aLength;
|
||||
|
||||
// Optimization: max diagonal in graph intersects corner of shorter side.
|
||||
let iMaxF = aLength;
|
||||
let iMaxR = aLength;
|
||||
|
||||
// Initialize no changes yet in forward or reverse direction:
|
||||
aIndexesF[0] = aStart - 1; // at open start of interval, outside closed start
|
||||
aIndexesR[0] = aEnd; // at open end of interval
|
||||
|
||||
if (baDeltaLength % 2 === 0) {
|
||||
// The number of changes in paths is 2 * d if length difference is even.
|
||||
const dMin = (nChange || baDeltaLength) / 2;
|
||||
const dMax = (aLength + bLength) / 2;
|
||||
for (let d = 1; d <= dMax; d += 1) {
|
||||
iMaxF = extendPathsF(d, aEnd, bEnd, bF, isCommon, aIndexesF, iMaxF);
|
||||
if (d < dMin) {
|
||||
iMaxR = extendPathsR(d, aStart, bStart, bR, isCommon, aIndexesR, iMaxR);
|
||||
} else if (
|
||||
// If a reverse path overlaps a forward path in the same diagonal,
|
||||
// return a division of the index intervals at the middle change.
|
||||
extendOverlappablePathsR(d, aStart, aEnd, bStart, bEnd, isCommon, aIndexesF, iMaxF, aIndexesR, iMaxR, division)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// The number of changes in paths is 2 * d - 1 if length difference is odd.
|
||||
const dMin = ((nChange || baDeltaLength) + 1) / 2;
|
||||
const dMax = (aLength + bLength + 1) / 2;
|
||||
|
||||
// Unroll first half iteration so loop extends the relevant pairs of paths.
|
||||
// Because of invariant that intervals have no common items at start or end,
|
||||
// and limitation not to call divide with empty intervals,
|
||||
// therefore it cannot be called if a forward path with one change
|
||||
// would overlap a reverse path with no changes, even if dMin === 1.
|
||||
let d = 1;
|
||||
iMaxF = extendPathsF(d, aEnd, bEnd, bF, isCommon, aIndexesF, iMaxF);
|
||||
for (d += 1; d <= dMax; d += 1) {
|
||||
iMaxR = extendPathsR(d - 1, aStart, bStart, bR, isCommon, aIndexesR, iMaxR);
|
||||
if (d < dMin) {
|
||||
iMaxF = extendPathsF(d, aEnd, bEnd, bF, isCommon, aIndexesF, iMaxF);
|
||||
} else if (
|
||||
// If a forward path overlaps a reverse path in the same diagonal,
|
||||
// return a division of the index intervals at the middle change.
|
||||
extendOverlappablePathsF(d, aStart, aEnd, bStart, bEnd, isCommon, aIndexesF, iMaxF, aIndexesR, iMaxR, division)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* istanbul ignore next */
|
||||
throw new Error(`${pkg}: no overlap aStart=${aStart} aEnd=${aEnd} bStart=${bStart} bEnd=${bEnd}`);
|
||||
};
|
||||
|
||||
// Given index intervals and input function to compare items at indexes,
|
||||
// return by output function the number of adjacent items and starting indexes
|
||||
// of each common subsequence. Divide and conquer with only linear space.
|
||||
//
|
||||
// The index intervals are half open [start, end) like array slice method.
|
||||
// DO NOT CALL if start === end, because interval cannot contain common items
|
||||
// and because divide function will throw the “no overlap” error.
|
||||
const findSubsequences = (nChange, aStart, aEnd, bStart, bEnd, transposed, callbacks, aIndexesF, aIndexesR, division // temporary memory, not input nor output
|
||||
) => {
|
||||
if (bEnd - bStart < aEnd - aStart) {
|
||||
// Transpose graph so it has portrait instead of landscape orientation.
|
||||
// Always compare shorter to longer sequence for consistency and optimization.
|
||||
transposed = !transposed;
|
||||
if (transposed && callbacks.length === 1) {
|
||||
// Lazily wrap callback functions to swap args if graph is transposed.
|
||||
const {
|
||||
foundSubsequence,
|
||||
isCommon
|
||||
} = callbacks[0];
|
||||
callbacks[1] = {
|
||||
foundSubsequence: (nCommon, bCommon, aCommon) => {
|
||||
foundSubsequence(nCommon, aCommon, bCommon);
|
||||
},
|
||||
isCommon: (bIndex, aIndex) => isCommon(aIndex, bIndex)
|
||||
};
|
||||
}
|
||||
const tStart = aStart;
|
||||
const tEnd = aEnd;
|
||||
aStart = bStart;
|
||||
aEnd = bEnd;
|
||||
bStart = tStart;
|
||||
bEnd = tEnd;
|
||||
}
|
||||
const {
|
||||
foundSubsequence,
|
||||
isCommon
|
||||
} = callbacks[transposed ? 1 : 0];
|
||||
|
||||
// Divide the index intervals at the middle change.
|
||||
divide(nChange, aStart, aEnd, bStart, bEnd, isCommon, aIndexesF, aIndexesR, division);
|
||||
const {
|
||||
nChangePreceding,
|
||||
aEndPreceding,
|
||||
bEndPreceding,
|
||||
nCommonPreceding,
|
||||
aCommonPreceding,
|
||||
bCommonPreceding,
|
||||
nCommonFollowing,
|
||||
aCommonFollowing,
|
||||
bCommonFollowing,
|
||||
nChangeFollowing,
|
||||
aStartFollowing,
|
||||
bStartFollowing
|
||||
} = division;
|
||||
|
||||
// Unless either index interval is empty, they might contain common items.
|
||||
if (aStart < aEndPreceding && bStart < bEndPreceding) {
|
||||
// Recursely find and return common subsequences preceding the division.
|
||||
findSubsequences(nChangePreceding, aStart, aEndPreceding, bStart, bEndPreceding, transposed, callbacks, aIndexesF, aIndexesR, division);
|
||||
}
|
||||
|
||||
// Return common subsequences that are adjacent to the middle change.
|
||||
if (nCommonPreceding !== 0) {
|
||||
foundSubsequence(nCommonPreceding, aCommonPreceding, bCommonPreceding);
|
||||
}
|
||||
if (nCommonFollowing !== 0) {
|
||||
foundSubsequence(nCommonFollowing, aCommonFollowing, bCommonFollowing);
|
||||
}
|
||||
|
||||
// Unless either index interval is empty, they might contain common items.
|
||||
if (aStartFollowing < aEnd && bStartFollowing < bEnd) {
|
||||
// Recursely find and return common subsequences following the division.
|
||||
findSubsequences(nChangeFollowing, aStartFollowing, aEnd, bStartFollowing, bEnd, transposed, callbacks, aIndexesF, aIndexesR, division);
|
||||
}
|
||||
};
|
||||
const validateLength = (name, arg) => {
|
||||
if (typeof arg !== 'number') {
|
||||
throw new TypeError(`${pkg}: ${name} typeof ${typeof arg} is not a number`);
|
||||
}
|
||||
if (!Number.isSafeInteger(arg)) {
|
||||
throw new RangeError(`${pkg}: ${name} value ${arg} is not a safe integer`);
|
||||
}
|
||||
if (arg < 0) {
|
||||
throw new RangeError(`${pkg}: ${name} value ${arg} is a negative integer`);
|
||||
}
|
||||
};
|
||||
const validateCallback = (name, arg) => {
|
||||
const type = typeof arg;
|
||||
if (type !== 'function') {
|
||||
throw new TypeError(`${pkg}: ${name} typeof ${type} is not a function`);
|
||||
}
|
||||
};
|
||||
|
||||
// Compare items in two sequences to find a longest common subsequence.
|
||||
// Given lengths of sequences and input function to compare items at indexes,
|
||||
// return by output function the number of adjacent items and starting indexes
|
||||
// of each common subsequence.
|
||||
function diffSequence(aLength, bLength, isCommon, foundSubsequence) {
|
||||
validateLength('aLength', aLength);
|
||||
validateLength('bLength', bLength);
|
||||
validateCallback('isCommon', isCommon);
|
||||
validateCallback('foundSubsequence', foundSubsequence);
|
||||
|
||||
// Count common items from the start in the forward direction.
|
||||
const nCommonF = countCommonItemsF(0, aLength, 0, bLength, isCommon);
|
||||
if (nCommonF !== 0) {
|
||||
foundSubsequence(nCommonF, 0, 0);
|
||||
}
|
||||
|
||||
// Unless both sequences consist of common items only,
|
||||
// find common items in the half-trimmed index intervals.
|
||||
if (aLength !== nCommonF || bLength !== nCommonF) {
|
||||
// Invariant: intervals do not have common items at the start.
|
||||
// The start of an index interval is closed like array slice method.
|
||||
const aStart = nCommonF;
|
||||
const bStart = nCommonF;
|
||||
|
||||
// Count common items from the end in the reverse direction.
|
||||
const nCommonR = countCommonItemsR(aStart, aLength - 1, bStart, bLength - 1, isCommon);
|
||||
|
||||
// Invariant: intervals do not have common items at the end.
|
||||
// The end of an index interval is open like array slice method.
|
||||
const aEnd = aLength - nCommonR;
|
||||
const bEnd = bLength - nCommonR;
|
||||
|
||||
// Unless one sequence consists of common items only,
|
||||
// therefore the other trimmed index interval consists of changes only,
|
||||
// find common items in the trimmed index intervals.
|
||||
const nCommonFR = nCommonF + nCommonR;
|
||||
if (aLength !== nCommonFR && bLength !== nCommonFR) {
|
||||
const nChange = 0; // number of change items is not yet known
|
||||
const transposed = false; // call the original unwrapped functions
|
||||
const callbacks = [{
|
||||
foundSubsequence,
|
||||
isCommon
|
||||
}];
|
||||
|
||||
// Indexes in sequence a of last points in furthest reaching paths
|
||||
// from outside the start at top left in the forward direction:
|
||||
const aIndexesF = [NOT_YET_SET];
|
||||
// from the end at bottom right in the reverse direction:
|
||||
const aIndexesR = [NOT_YET_SET];
|
||||
|
||||
// Initialize one object as output of all calls to divide function.
|
||||
const division = {
|
||||
aCommonFollowing: NOT_YET_SET,
|
||||
aCommonPreceding: NOT_YET_SET,
|
||||
aEndPreceding: NOT_YET_SET,
|
||||
aStartFollowing: NOT_YET_SET,
|
||||
bCommonFollowing: NOT_YET_SET,
|
||||
bCommonPreceding: NOT_YET_SET,
|
||||
bEndPreceding: NOT_YET_SET,
|
||||
bStartFollowing: NOT_YET_SET,
|
||||
nChangeFollowing: NOT_YET_SET,
|
||||
nChangePreceding: NOT_YET_SET,
|
||||
nCommonFollowing: NOT_YET_SET,
|
||||
nCommonPreceding: NOT_YET_SET
|
||||
};
|
||||
|
||||
// Find and return common subsequences in the trimmed index intervals.
|
||||
findSubsequences(nChange, aStart, aEnd, bStart, bEnd, transposed, callbacks, aIndexesF, aIndexesR, division);
|
||||
}
|
||||
if (nCommonR !== 0) {
|
||||
foundSubsequence(nCommonR, aEnd, bEnd);
|
||||
}
|
||||
}
|
||||
}
|
||||
})();
|
||||
|
||||
module.exports = __webpack_exports__;
|
||||
/******/ })()
|
||||
;
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
import cjsModule from './index.js';
|
||||
|
||||
export default cjsModule.default;
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
{
|
||||
"name": "@jest/diff-sequences",
|
||||
"version": "30.5.0",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/jestjs/jest.git",
|
||||
"directory": "packages/diff-sequences"
|
||||
},
|
||||
"license": "MIT",
|
||||
"description": "Compare items in two sequences to find a longest common subsequence",
|
||||
"keywords": [
|
||||
"fast",
|
||||
"linear",
|
||||
"space",
|
||||
"callback",
|
||||
"diff"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
|
||||
},
|
||||
"main": "./build/index.js",
|
||||
"types": "./build/index.d.ts",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./build/index.d.ts",
|
||||
"require": "./build/index.js",
|
||||
"import": "./build/index.mjs",
|
||||
"default": "./build/index.js"
|
||||
},
|
||||
"./package.json": "./package.json"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@fast-check/jest": "^2.1.1",
|
||||
"benchmark": "^2.1.4",
|
||||
"diff": "^9.0.0"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"gitHead": "912baa37afaa979e8179240c238cb493f960527a"
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
Copyright Contributors to the Jest project.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
+477
@@ -0,0 +1,477 @@
|
||||
/**
|
||||
* 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 {Context} from 'node:vm';
|
||||
import {
|
||||
LegacyFakeTimers,
|
||||
ModernFakeTimers,
|
||||
TemporalDurationLike,
|
||||
TemporalEpochLike,
|
||||
} from '@jest/fake-timers';
|
||||
import {Circus, Config, Global as Global_2} from '@jest/types';
|
||||
import {Mocked, ModuleMocker} from 'jest-mock';
|
||||
|
||||
export declare type EnvironmentContext = {
|
||||
console: Console;
|
||||
docblockPragmas: Record<string, string | Array<string>>;
|
||||
testPath: string;
|
||||
};
|
||||
|
||||
export declare type InjectedModuleArguments =
|
||||
| [
|
||||
jest: Jest,
|
||||
...sandboxInjectedGlobals: Array<Global_2.Global[keyof Global_2.Global]>,
|
||||
]
|
||||
| [...sandboxInjectedGlobals: Array<Global_2.Global[keyof Global_2.Global]>];
|
||||
|
||||
export declare interface Jest {
|
||||
/**
|
||||
* Advances all timers by `msToRun` milliseconds. All pending "macro-tasks"
|
||||
* that have been queued via `setTimeout()` or `setInterval()`, and would be
|
||||
* executed within this time frame will be executed.
|
||||
*/
|
||||
advanceTimersByTime(msToRun: number | TemporalDurationLike): void;
|
||||
/**
|
||||
* Advances all timers by `msToRun` milliseconds, firing callbacks if necessary.
|
||||
*
|
||||
* @remarks
|
||||
* Not available when using legacy fake timers implementation.
|
||||
*/
|
||||
advanceTimersByTimeAsync(
|
||||
msToRun: number | TemporalDurationLike,
|
||||
): Promise<void>;
|
||||
/**
|
||||
* Advances all timers by the needed milliseconds to execute callbacks currently scheduled with `requestAnimationFrame`.
|
||||
* `advanceTimersToNextFrame()` is a helpful way to execute code that is scheduled using `requestAnimationFrame`.
|
||||
*
|
||||
* @remarks
|
||||
* Not available when using legacy fake timers implementation.
|
||||
*/
|
||||
advanceTimersToNextFrame(): void;
|
||||
/**
|
||||
* Advances all timers by the needed milliseconds so that only the next
|
||||
* timeouts/intervals will run. Optionally, you can provide steps, so it will
|
||||
* run steps amount of next timeouts/intervals.
|
||||
*/
|
||||
advanceTimersToNextTimer(steps?: number): void;
|
||||
/**
|
||||
* Advances the clock to the moment of the first scheduled timer, firing it.
|
||||
* Optionally, you can provide steps, so it will run steps amount of
|
||||
* next timeouts/intervals.
|
||||
*
|
||||
* @remarks
|
||||
* Not available when using legacy fake timers implementation.
|
||||
*/
|
||||
advanceTimersToNextTimerAsync(steps?: number): Promise<void>;
|
||||
/**
|
||||
* Disables automatic mocking in the module loader.
|
||||
*/
|
||||
autoMockOff(): Jest;
|
||||
/**
|
||||
* Enables automatic mocking in the module loader.
|
||||
*/
|
||||
autoMockOn(): Jest;
|
||||
/**
|
||||
* Clears the `mock.calls`, `mock.instances`, `mock.contexts` and `mock.results` properties of
|
||||
* all mocks. Equivalent to calling `.mockClear()` on every mocked function.
|
||||
*/
|
||||
clearAllMocks(): Jest;
|
||||
/**
|
||||
* Removes any pending timers from the timer system. If any timers have been
|
||||
* scheduled, they will be cleared and will never have the opportunity to
|
||||
* execute in the future.
|
||||
*/
|
||||
clearAllTimers(): void;
|
||||
/**
|
||||
* Given the name of a module, use the automatic mocking system to generate a
|
||||
* mocked version of the module for you.
|
||||
*
|
||||
* This is useful when you want to create a manual mock that extends the
|
||||
* automatic mock's behavior.
|
||||
*/
|
||||
createMockFromModule<T = unknown>(moduleName: string): Mocked<T>;
|
||||
/**
|
||||
* Indicates that the module system should never return a mocked version of
|
||||
* the specified module and its dependencies.
|
||||
*/
|
||||
deepUnmock(moduleName: string): Jest;
|
||||
/**
|
||||
* Disables automatic mocking in the module loader.
|
||||
*
|
||||
* After this method is called, all `require()`s will return the real
|
||||
* versions of each module (rather than a mocked version).
|
||||
*/
|
||||
disableAutomock(): Jest;
|
||||
/**
|
||||
* When using `babel-jest`, calls to `jest.mock()` will automatically be hoisted
|
||||
* to the top of the code block. Use this method if you want to explicitly
|
||||
* avoid this behavior.
|
||||
*/
|
||||
doMock<T = unknown>(
|
||||
moduleName: string,
|
||||
moduleFactory?: () => T,
|
||||
options?: {
|
||||
virtual?: boolean;
|
||||
},
|
||||
): Jest;
|
||||
/**
|
||||
* When using `babel-jest`, calls to `jest.unmock()` will automatically be hoisted
|
||||
* to the top of the code block. Use this method if you want to explicitly
|
||||
* avoid this behavior.
|
||||
*/
|
||||
dontMock(moduleName: string): Jest;
|
||||
/**
|
||||
* Enables automatic mocking in the module loader.
|
||||
*/
|
||||
enableAutomock(): Jest;
|
||||
/**
|
||||
* Creates a mock function. Optionally takes a mock implementation.
|
||||
*/
|
||||
fn: ModuleMocker['fn'];
|
||||
/**
|
||||
* When mocking time, `Date.now()` will also be mocked. If you for some reason
|
||||
* need access to the real current time, you can invoke this function.
|
||||
*
|
||||
* @remarks
|
||||
* Not available when using legacy fake timers implementation.
|
||||
*/
|
||||
getRealSystemTime(): number;
|
||||
/**
|
||||
* Retrieves the seed value. It will be randomly generated for each test run
|
||||
* or can be manually set via the `--seed` CLI argument.
|
||||
*/
|
||||
getSeed(): number;
|
||||
/**
|
||||
* Returns the number of fake timers still left to run.
|
||||
*/
|
||||
getTimerCount(): number;
|
||||
/**
|
||||
* Returns `true` if test environment has been torn down.
|
||||
*
|
||||
* @example
|
||||
* ```js
|
||||
* if (jest.isEnvironmentTornDown()) {
|
||||
* // The Jest environment has been torn down, so stop doing work
|
||||
* return;
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
isEnvironmentTornDown(): boolean;
|
||||
/**
|
||||
* Determines if the given function is a mocked function.
|
||||
*/
|
||||
isMockFunction: ModuleMocker['isMockFunction'];
|
||||
/**
|
||||
* `jest.isolateModules()` goes a step further than `jest.resetModules()` and
|
||||
* creates a sandbox registry for the modules that are loaded inside the callback
|
||||
* function. This is useful to isolate specific modules for every test so that
|
||||
* local module state doesn't conflict between tests.
|
||||
*/
|
||||
isolateModules(fn: () => void): Jest;
|
||||
/**
|
||||
* `jest.isolateModulesAsync()` is the equivalent of `jest.isolateModules()`, but for
|
||||
* async functions to be wrapped. The caller is expected to `await` the completion of
|
||||
* `isolateModulesAsync`.
|
||||
*/
|
||||
isolateModulesAsync(fn: () => Promise<void>): Promise<void>;
|
||||
/**
|
||||
* Mocks a module with an auto-mocked version when it is being required.
|
||||
*/
|
||||
mock<T = unknown>(
|
||||
moduleName: string,
|
||||
moduleFactory?: () => T,
|
||||
options?: {
|
||||
virtual?: boolean;
|
||||
},
|
||||
): Jest;
|
||||
/**
|
||||
* Mocks a module with the provided module factory when it is being imported.
|
||||
*/
|
||||
unstable_mockModule<T = unknown>(
|
||||
moduleName: string,
|
||||
moduleFactory: () => T | Promise<T>,
|
||||
options?: {
|
||||
virtual?: boolean;
|
||||
},
|
||||
): Jest;
|
||||
/**
|
||||
* Wraps types of the `source` object and its deep members with type definitions
|
||||
* of Jest mock function. Pass `{shallow: true}` option to disable the deeply
|
||||
* mocked behavior.
|
||||
*/
|
||||
mocked: ModuleMocker['mocked'];
|
||||
/**
|
||||
* Returns the current time in ms of the fake timer clock.
|
||||
*/
|
||||
now(): number;
|
||||
/**
|
||||
* Registers a callback function that is invoked whenever a mock is generated for a module.
|
||||
* This callback is passed the module path and the newly created mock object, and must return
|
||||
* the (potentially modified) mock object.
|
||||
*
|
||||
* If multiple callbacks are registered, they will be called in the order they were added.
|
||||
* Each callback receives the result of the previous callback as the `moduleMock` parameter,
|
||||
* making it possible to apply sequential transformations.
|
||||
*/
|
||||
onGenerateMock<T>(cb: (modulePath: string, moduleMock: T) => T): Jest;
|
||||
/**
|
||||
* Replaces property on an object with another value.
|
||||
*
|
||||
* @remarks
|
||||
* For mocking functions or 'get' or 'set' accessors, use `jest.spyOn()` instead.
|
||||
*/
|
||||
replaceProperty: ModuleMocker['replaceProperty'];
|
||||
/**
|
||||
* Returns the actual module instead of a mock, bypassing all checks on
|
||||
* whether the module should receive a mock implementation or not.
|
||||
*
|
||||
* @example
|
||||
* ```js
|
||||
* jest.mock('../myModule', () => {
|
||||
* // Require the original module to not be mocked...
|
||||
* const originalModule = jest.requireActual('../myModule');
|
||||
*
|
||||
* return {
|
||||
* __esModule: true, // Use it when dealing with esModules
|
||||
* ...originalModule,
|
||||
* getRandom: jest.fn().mockReturnValue(10),
|
||||
* };
|
||||
* });
|
||||
*
|
||||
* const getRandom = require('../myModule').getRandom;
|
||||
*
|
||||
* getRandom(); // Always returns 10
|
||||
* ```
|
||||
*/
|
||||
requireActual<T = unknown>(moduleName: string): T;
|
||||
/**
|
||||
* Returns a mock module instead of the actual module, bypassing all checks
|
||||
* on whether the module should be required normally or not.
|
||||
*/
|
||||
requireMock<T = unknown>(moduleName: string): T;
|
||||
/**
|
||||
* Resets the state of all mocks. Equivalent to calling `.mockReset()` on
|
||||
* every mocked function.
|
||||
*/
|
||||
resetAllMocks(): Jest;
|
||||
/**
|
||||
* Resets the module registry - the cache of all required modules. This is
|
||||
* useful to isolate modules where local state might conflict between tests.
|
||||
*/
|
||||
resetModules(): Jest;
|
||||
/**
|
||||
* Restores all mocks and replaced properties back to their original value.
|
||||
* Equivalent to calling `.mockRestore()` on every mocked function
|
||||
* and `.restore()` on every replaced property.
|
||||
*
|
||||
* Beware that `jest.restoreAllMocks()` only works when the mock was created
|
||||
* with `jest.spyOn()`; other mocks will require you to manually restore them.
|
||||
*/
|
||||
restoreAllMocks(): Jest;
|
||||
/**
|
||||
* Runs failed tests n-times until they pass or until the max number of
|
||||
* retries is exhausted.
|
||||
*
|
||||
* If `logErrorsBeforeRetry` is enabled, Jest will log the error(s) that caused
|
||||
* the test to fail to the console, providing visibility on why a retry occurred.
|
||||
* retries is exhausted.
|
||||
*
|
||||
* `waitBeforeRetry` is the number of milliseconds to wait before retrying
|
||||
*
|
||||
* `retryImmediately` is the flag to retry the failed test immediately after
|
||||
* failure.
|
||||
*
|
||||
* `entireDescribe` is the flag to retry all tests and hooks in the describe
|
||||
* block where `retryTimes` is called
|
||||
*
|
||||
* @remarks
|
||||
* Only available with `jest-circus` runner.
|
||||
*/
|
||||
retryTimes(
|
||||
numRetries: number,
|
||||
options?: {
|
||||
entireDescribe?: boolean;
|
||||
logErrorsBeforeRetry?: boolean;
|
||||
retryImmediately?: boolean;
|
||||
waitBeforeRetry?: number;
|
||||
},
|
||||
): Jest;
|
||||
/**
|
||||
* Exhausts tasks queued by `setImmediate()`.
|
||||
*
|
||||
* @remarks
|
||||
* Only available when using legacy fake timers implementation.
|
||||
*/
|
||||
runAllImmediates(): void;
|
||||
/**
|
||||
* Exhausts the micro-task queue (usually interfaced in node via
|
||||
* `process.nextTick()`).
|
||||
*/
|
||||
runAllTicks(): void;
|
||||
/**
|
||||
* Exhausts the macro-task queue (i.e., all tasks queued by `setTimeout()`
|
||||
* and `setInterval()`).
|
||||
*/
|
||||
runAllTimers(): void;
|
||||
/**
|
||||
* Exhausts the macro-task queue (i.e., all tasks queued by `setTimeout()`
|
||||
* and `setInterval()`).
|
||||
*
|
||||
* @remarks
|
||||
* If new timers are added while it is executing they will be run as well.
|
||||
* @remarks
|
||||
* Not available when using legacy fake timers implementation.
|
||||
*/
|
||||
runAllTimersAsync(): Promise<void>;
|
||||
/**
|
||||
* Executes only the macro-tasks that are currently pending (i.e., only the
|
||||
* tasks that have been queued by `setTimeout()` or `setInterval()` up to this
|
||||
* point). If any of the currently pending macro-tasks schedule new
|
||||
* macro-tasks, those new tasks will not be executed by this call.
|
||||
*/
|
||||
runOnlyPendingTimers(): void;
|
||||
/**
|
||||
* Executes only the macro-tasks that are currently pending (i.e., only the
|
||||
* tasks that have been queued by `setTimeout()` or `setInterval()` up to this
|
||||
* point). If any of the currently pending macro-tasks schedule new
|
||||
* macro-tasks, those new tasks will not be executed by this call.
|
||||
*
|
||||
* @remarks
|
||||
* Not available when using legacy fake timers implementation.
|
||||
*/
|
||||
runOnlyPendingTimersAsync(): Promise<void>;
|
||||
/**
|
||||
* Explicitly supplies the mock object that the module system should return
|
||||
* for the specified module.
|
||||
*
|
||||
* @remarks
|
||||
* It is recommended to use `jest.mock()` instead. The `jest.mock()` API's second
|
||||
* argument is a module factory instead of the expected exported module object.
|
||||
*/
|
||||
setMock(moduleName: string, moduleExports: unknown): Jest;
|
||||
/**
|
||||
* Set the current system time used by fake timers. Simulates a user changing
|
||||
* the system clock while your program is running. It affects the current time,
|
||||
* but it does not in itself cause e.g. timers to fire; they will fire exactly
|
||||
* as they would have done without the call to `jest.setSystemTime()`.
|
||||
*
|
||||
* @remarks
|
||||
* Not available when using legacy fake timers implementation.
|
||||
*/
|
||||
setSystemTime(now?: number | Date | TemporalEpochLike): void;
|
||||
/**
|
||||
* Set the default timeout interval for tests and before/after hooks in
|
||||
* milliseconds.
|
||||
*
|
||||
* @remarks
|
||||
* The default timeout interval is 5 seconds if this method is not called.
|
||||
*/
|
||||
setTimeout(timeout: number): Jest;
|
||||
/**
|
||||
* Creates a mock function similar to `jest.fn()` but also tracks calls to
|
||||
* `object[methodName]`.
|
||||
*
|
||||
* Optional third argument of `accessType` can be either 'get' or 'set', which
|
||||
* proves to be useful when you want to spy on a getter or a setter, respectively.
|
||||
*
|
||||
* @remarks
|
||||
* By default, `jest.spyOn()` also calls the spied method. This is different
|
||||
* behavior from most other test libraries.
|
||||
*/
|
||||
spyOn: ModuleMocker['spyOn'];
|
||||
/**
|
||||
* Indicates that the module system should never return a mocked version of
|
||||
* the specified module from `require()` (e.g. that it should always return the
|
||||
* real module).
|
||||
*/
|
||||
unmock(moduleName: string): Jest;
|
||||
/**
|
||||
* Indicates that the module system should never return a mocked version of
|
||||
* the specified module when it is being imported (e.g. that it should always
|
||||
* return the real module).
|
||||
*/
|
||||
unstable_unmockModule(moduleName: string): Jest;
|
||||
/**
|
||||
* Instructs Jest to use fake versions of the global date, performance,
|
||||
* time and timer APIs. Fake timers implementation is backed by
|
||||
* [`@sinonjs/fake-timers`](https://github.com/sinonjs/fake-timers).
|
||||
*
|
||||
* @remarks
|
||||
* Calling `jest.useFakeTimers()` once again in the same test file would reinstall
|
||||
* fake timers using the provided options.
|
||||
*/
|
||||
useFakeTimers(
|
||||
fakeTimersConfig?: Config.FakeTimersConfig | Config.LegacyFakeTimersConfig,
|
||||
): Jest;
|
||||
/**
|
||||
* Instructs Jest to restore the original implementations of the global date,
|
||||
* performance, time and timer APIs.
|
||||
*/
|
||||
useRealTimers(): Jest;
|
||||
/**
|
||||
* Updates the mode of advancing timers when using fake timers.
|
||||
*
|
||||
* @param config The configuration to use for advancing timers
|
||||
*
|
||||
* When the mode is 'interval', timers will be advanced automatically by the [delta]
|
||||
* milliseconds every [delta] milliseconds of real time. The default delta is 20 milliseconds.
|
||||
*
|
||||
* When mode is 'nextAsync', configures whether timers advance automatically to the next timer in the queue after each macrotask.
|
||||
* This mode differs from 'interval' in that it advances all the way to the next timer, regardless
|
||||
* of how far in the future that timer is scheduled (e.g. advanceTimersToNextTimerAsync).
|
||||
*
|
||||
* When mode is 'manual' (the default), timers will not advance automatically. Instead,
|
||||
* timers must be advanced using APIs such as `advanceTimersToNextTimer`, `advanceTimersByTime`, etc.
|
||||
*
|
||||
* @remarks
|
||||
* Not available when using legacy fake timers implementation.
|
||||
*/
|
||||
setTimerTickMode(
|
||||
config:
|
||||
| {
|
||||
mode: 'manual' | 'nextAsync';
|
||||
}
|
||||
| {
|
||||
mode: 'interval';
|
||||
delta?: number;
|
||||
},
|
||||
): Jest;
|
||||
}
|
||||
|
||||
export declare class JestEnvironment<Timer = unknown> {
|
||||
constructor(config: JestEnvironmentConfig, context: EnvironmentContext);
|
||||
global: Global_2.Global;
|
||||
fakeTimers: LegacyFakeTimers<Timer> | null;
|
||||
fakeTimersModern: ModernFakeTimers | null;
|
||||
moduleMocker: ModuleMocker | null;
|
||||
getVmContext(): Context | null;
|
||||
setup(): Promise<void>;
|
||||
teardown(): Promise<void>;
|
||||
handleTestEvent?: Circus.EventHandler;
|
||||
exportConditions?: () => Array<string>;
|
||||
}
|
||||
|
||||
export declare interface JestEnvironmentConfig {
|
||||
projectConfig: Config.ProjectConfig;
|
||||
globalConfig: Config.GlobalConfig;
|
||||
}
|
||||
|
||||
export declare interface JestImportMeta extends ImportMeta {
|
||||
jest: Jest;
|
||||
}
|
||||
|
||||
export declare type Module = NodeModule;
|
||||
|
||||
export declare type ModuleWrapper = (
|
||||
this: Module['exports'],
|
||||
module: Module,
|
||||
exports: Module['exports'],
|
||||
require: Module['require'],
|
||||
__dirname: string,
|
||||
__filename: Module['filename'],
|
||||
...injectedGlobals: InjectedModuleArguments
|
||||
) => unknown;
|
||||
+15
@@ -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.
|
||||
* * /
|
||||
*/
|
||||
/******/ (() => { // webpackBootstrap
|
||||
/******/ "use strict";
|
||||
let __webpack_exports__ = {};
|
||||
|
||||
module.exports = __webpack_exports__;
|
||||
/******/ })()
|
||||
;
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"name": "@jest/environment",
|
||||
"version": "30.5.1",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/jestjs/jest.git",
|
||||
"directory": "packages/jest-environment"
|
||||
},
|
||||
"license": "MIT",
|
||||
"main": "./build/index.js",
|
||||
"types": "./build/index.d.ts",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./build/index.d.ts",
|
||||
"default": "./build/index.js"
|
||||
},
|
||||
"./package.json": "./package.json"
|
||||
},
|
||||
"dependencies": {
|
||||
"@jest/fake-timers": "30.5.1",
|
||||
"@jest/types": "30.5.1",
|
||||
"@types/node": "*",
|
||||
"jest-mock": "30.5.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"gitHead": "9ab14feccd6c15fec1334dbcb03a53a079d153d3"
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
Copyright Contributors to the Jest project.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
# `@jest/expect-utils`
|
||||
|
||||
This module exports some utils for the `expect` function used in [Jest](https://jestjs.io/).
|
||||
|
||||
You probably don't want to use this package directly. E.g. if you're writing [custom matcher](https://jestjs.io/docs/expect#expectextendmatchers), you should use the injected [`this.equals`](https://jestjs.io/docs/expect#thisequalsa-b).
|
||||
+186
@@ -0,0 +1,186 @@
|
||||
/**
|
||||
* 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 declare const arrayBufferEquality: (
|
||||
a: unknown,
|
||||
b: unknown,
|
||||
) => boolean | undefined;
|
||||
|
||||
/**
|
||||
* Structural type for any object honoring Jest's asymmetric matcher protocol
|
||||
* (e.g. `expect.any(...)`, `expect.objectContaining(...)`). Detected at runtime
|
||||
* by {@link equals}.
|
||||
*/
|
||||
export declare type AsymmetricMatcher = {
|
||||
asymmetricMatch(other: unknown): boolean;
|
||||
toString(): string;
|
||||
getExpectedType?(): string;
|
||||
toAsymmetricMatcher?(): string;
|
||||
};
|
||||
|
||||
/**
|
||||
* Replaces `T` with `T | AsymmetricMatcher`, recursing into nested objects and
|
||||
* arrays:
|
||||
* ```ts
|
||||
* type DeepAsymmetricMatcher<boolean>; // AsymmetricMatcher | boolean
|
||||
* type DeepAsymmetricMatcher<{ foo: number }>; // AsymmetricMatcher | { foo: AsymmetricMatcher | number }
|
||||
* type DeepAsymmetricMatcher<[string]>; // AsymmetricMatcher | [AsymmetricMatcher | string]
|
||||
* ```
|
||||
*/
|
||||
declare type DeepAsymmetricMatcher<T> = T extends object
|
||||
? | AsymmetricMatcher
|
||||
| {
|
||||
[K in keyof T]: DeepAsymmetricMatcher<T[K]>;
|
||||
}
|
||||
: AsymmetricMatcher | T;
|
||||
|
||||
export declare function emptyObject(obj: unknown): boolean;
|
||||
|
||||
export declare const equals: EqualsFunction;
|
||||
|
||||
export declare type EqualsFunction = (
|
||||
a: unknown,
|
||||
b: unknown,
|
||||
customTesters?: Array<Tester>,
|
||||
strictCheck?: boolean,
|
||||
) => boolean;
|
||||
|
||||
/**
|
||||
* Like the built-in `Parameters<F>` utility type, but each parameter accepts an
|
||||
* asymmetric matcher (recursively for nested objects), and overloaded functions
|
||||
* yield a union of all overload parameter tuples.
|
||||
*/
|
||||
export declare type FunctionParameters<F> =
|
||||
FunctionParametersInternal<F> extends never
|
||||
? Array<unknown>
|
||||
: FunctionParametersInternal<F>;
|
||||
|
||||
/**
|
||||
* 1. If the function is overloaded or has no parameters → overloaded form
|
||||
* (union of tuples, up to 15 overloads).
|
||||
* 2. If the function has parameters → simple form.
|
||||
* 3. else → `never`.
|
||||
*/
|
||||
declare type FunctionParametersInternal<F> = F extends {
|
||||
(...args: infer P1): any;
|
||||
(...args: infer P2): any;
|
||||
(...args: infer P3): any;
|
||||
(...args: infer P4): any;
|
||||
(...args: infer P5): any;
|
||||
(...args: infer P6): any;
|
||||
(...args: infer P7): any;
|
||||
(...args: infer P8): any;
|
||||
(...args: infer P9): any;
|
||||
(...args: infer P10): any;
|
||||
(...args: infer P11): any;
|
||||
(...args: infer P12): any;
|
||||
(...args: infer P13): any;
|
||||
(...args: infer P14): any;
|
||||
(...args: infer P15): any;
|
||||
}
|
||||
? | WithAsymmetricMatchers<P1>
|
||||
| WithAsymmetricMatchers<P2>
|
||||
| WithAsymmetricMatchers<P3>
|
||||
| WithAsymmetricMatchers<P4>
|
||||
| WithAsymmetricMatchers<P5>
|
||||
| WithAsymmetricMatchers<P6>
|
||||
| WithAsymmetricMatchers<P7>
|
||||
| WithAsymmetricMatchers<P8>
|
||||
| WithAsymmetricMatchers<P9>
|
||||
| WithAsymmetricMatchers<P10>
|
||||
| WithAsymmetricMatchers<P11>
|
||||
| WithAsymmetricMatchers<P12>
|
||||
| WithAsymmetricMatchers<P13>
|
||||
| WithAsymmetricMatchers<P14>
|
||||
| WithAsymmetricMatchers<P15>
|
||||
: F extends (...args: infer P) => any
|
||||
? WithAsymmetricMatchers<P>
|
||||
: never;
|
||||
|
||||
export declare const getObjectKeys: (object: object) => Array<string | symbol>;
|
||||
|
||||
export declare const getObjectSubset: (
|
||||
object: any,
|
||||
subset: any,
|
||||
customTesters?: Array<Tester>,
|
||||
seenReferences?: WeakMap<object, boolean>,
|
||||
) => any;
|
||||
|
||||
declare type GetPath = {
|
||||
hasEndProp?: boolean;
|
||||
endPropIsDefined?: boolean;
|
||||
lastTraversedObject: unknown;
|
||||
traversedPath: Array<string>;
|
||||
value?: unknown;
|
||||
};
|
||||
|
||||
export declare const getPath: (
|
||||
object: Record<string, any>,
|
||||
propertyPath: string | Array<string>,
|
||||
) => GetPath;
|
||||
|
||||
export declare function isA<T>(typeName: string, value: unknown): value is T;
|
||||
|
||||
export declare const isError: (value: unknown) => value is Error;
|
||||
|
||||
export declare const isOneline: (
|
||||
expected: unknown,
|
||||
received: unknown,
|
||||
) => boolean;
|
||||
|
||||
export declare const iterableEquality: (
|
||||
a: any,
|
||||
b: any,
|
||||
customTesters?: Array<Tester>,
|
||||
aStack?: Array<any>,
|
||||
bStack?: Array<any>,
|
||||
) => boolean | undefined;
|
||||
|
||||
export declare const partition: <T>(
|
||||
items: Array<T>,
|
||||
predicate: (arg: T) => boolean,
|
||||
) => [Array<T>, Array<T>];
|
||||
|
||||
export declare const pathAsArray: (propertyPath: string) => Array<any>;
|
||||
|
||||
export declare const sparseArrayEquality: (
|
||||
a: unknown,
|
||||
b: unknown,
|
||||
customTesters?: Array<Tester>,
|
||||
) => boolean | undefined;
|
||||
|
||||
export declare const subsetEquality: (
|
||||
object: unknown,
|
||||
subset: unknown,
|
||||
customTesters?: Array<Tester>,
|
||||
) => boolean | undefined;
|
||||
|
||||
export declare type Tester = (
|
||||
this: TesterContext,
|
||||
a: any,
|
||||
b: any,
|
||||
customTesters: Array<Tester>,
|
||||
) => boolean | undefined;
|
||||
|
||||
export declare interface TesterContext {
|
||||
equals: EqualsFunction;
|
||||
}
|
||||
|
||||
export declare const typeEquality: (a: any, b: any) => boolean | undefined;
|
||||
|
||||
/**
|
||||
* Maps each parameter slot of a tuple to `T | AsymmetricMatcher` (recursively
|
||||
* via {@link DeepAsymmetricMatcher}). Falls back to `never` for the
|
||||
* `Array<unknown>` "any-shape" case so that {@link FunctionParameters} can
|
||||
* collapse it back to `Array<unknown>` for `UnknownFunction`-like mocks.
|
||||
*/
|
||||
declare type WithAsymmetricMatchers<P extends Array<any>> =
|
||||
Array<unknown> extends P
|
||||
? never
|
||||
: {
|
||||
[K in keyof P]: DeepAsymmetricMatcher<P[K]>;
|
||||
};
|
||||
+742
@@ -0,0 +1,742 @@
|
||||
/*!
|
||||
* /**
|
||||
* * 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.
|
||||
* * /
|
||||
*/
|
||||
/******/ (() => { // webpackBootstrap
|
||||
/******/ "use strict";
|
||||
/******/ var __webpack_modules__ = ({
|
||||
|
||||
/***/ "./src/immutableUtils.ts"
|
||||
(__unused_webpack_module, exports) {
|
||||
|
||||
|
||||
|
||||
Object.defineProperty(exports, "__esModule", ({
|
||||
value: true
|
||||
}));
|
||||
exports.isImmutableList = isImmutableList;
|
||||
exports.isImmutableOrderedKeyed = isImmutableOrderedKeyed;
|
||||
exports.isImmutableOrderedSet = isImmutableOrderedSet;
|
||||
exports.isImmutableRecord = isImmutableRecord;
|
||||
exports.isImmutableUnorderedKeyed = isImmutableUnorderedKeyed;
|
||||
exports.isImmutableUnorderedSet = isImmutableUnorderedSet;
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
// SENTINEL constants are from https://github.com/immutable-js/immutable-js/tree/main/src/predicates
|
||||
const IS_KEYED_SENTINEL = '@@__IMMUTABLE_KEYED__@@';
|
||||
const IS_SET_SENTINEL = '@@__IMMUTABLE_SET__@@';
|
||||
const IS_LIST_SENTINEL = '@@__IMMUTABLE_LIST__@@';
|
||||
const IS_ORDERED_SENTINEL = '@@__IMMUTABLE_ORDERED__@@';
|
||||
const IS_RECORD_SYMBOL = '@@__IMMUTABLE_RECORD__@@';
|
||||
function isObjectLiteral(source) {
|
||||
return source != null && typeof source === 'object' && !Array.isArray(source);
|
||||
}
|
||||
function isImmutableUnorderedKeyed(source) {
|
||||
return Boolean(source && isObjectLiteral(source) && source[IS_KEYED_SENTINEL] && !source[IS_ORDERED_SENTINEL]);
|
||||
}
|
||||
function isImmutableUnorderedSet(source) {
|
||||
return Boolean(source && isObjectLiteral(source) && source[IS_SET_SENTINEL] && !source[IS_ORDERED_SENTINEL]);
|
||||
}
|
||||
function isImmutableList(source) {
|
||||
return Boolean(source && isObjectLiteral(source) && source[IS_LIST_SENTINEL]);
|
||||
}
|
||||
function isImmutableOrderedKeyed(source) {
|
||||
return Boolean(source && isObjectLiteral(source) && source[IS_KEYED_SENTINEL] && source[IS_ORDERED_SENTINEL]);
|
||||
}
|
||||
function isImmutableOrderedSet(source) {
|
||||
return Boolean(source && isObjectLiteral(source) && source[IS_SET_SENTINEL] && source[IS_ORDERED_SENTINEL]);
|
||||
}
|
||||
function isImmutableRecord(source) {
|
||||
return Boolean(source && isObjectLiteral(source) && source[IS_RECORD_SYMBOL]);
|
||||
}
|
||||
|
||||
/***/ },
|
||||
|
||||
/***/ "./src/index.ts"
|
||||
(__unused_webpack_module, exports, __webpack_require__) {
|
||||
|
||||
|
||||
|
||||
Object.defineProperty(exports, "__esModule", ({
|
||||
value: true
|
||||
}));
|
||||
var _exportNames = {
|
||||
equals: true,
|
||||
isA: true
|
||||
};
|
||||
Object.defineProperty(exports, "equals", ({
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _jasmineUtils.equals;
|
||||
}
|
||||
}));
|
||||
Object.defineProperty(exports, "isA", ({
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _jasmineUtils.isA;
|
||||
}
|
||||
}));
|
||||
var _jasmineUtils = __webpack_require__("./src/jasmineUtils.ts");
|
||||
var _utils = __webpack_require__("./src/utils.ts");
|
||||
Object.keys(_utils).forEach(function (key) {
|
||||
if (key === "default" || key === "__esModule") return;
|
||||
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
|
||||
if (key in exports && exports[key] === _utils[key]) return;
|
||||
Object.defineProperty(exports, key, {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _utils[key];
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
/***/ },
|
||||
|
||||
/***/ "./src/jasmineUtils.ts"
|
||||
(__unused_webpack_module, exports) {
|
||||
|
||||
|
||||
|
||||
Object.defineProperty(exports, "__esModule", ({
|
||||
value: true
|
||||
}));
|
||||
exports.equals = void 0;
|
||||
exports.isA = isA;
|
||||
/*
|
||||
Copyright (c) 2008-2016 Pivotal Labs
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
// Extracted out of jasmine 2.5.2
|
||||
const equals = (a, b, customTesters, strictCheck) => {
|
||||
customTesters = customTesters || [];
|
||||
return eq(a, b, [], [], customTesters, strictCheck);
|
||||
};
|
||||
exports.equals = equals;
|
||||
function isAsymmetric(obj) {
|
||||
return !!obj && isA('Function', obj.asymmetricMatch);
|
||||
}
|
||||
function asymmetricMatch(a, b) {
|
||||
const asymmetricA = isAsymmetric(a);
|
||||
const asymmetricB = isAsymmetric(b);
|
||||
if (asymmetricA && asymmetricB) {
|
||||
return undefined;
|
||||
}
|
||||
if (asymmetricA) {
|
||||
return a.asymmetricMatch(b);
|
||||
}
|
||||
if (asymmetricB) {
|
||||
return b.asymmetricMatch(a);
|
||||
}
|
||||
}
|
||||
|
||||
// Equality function lovingly adapted from isEqual in
|
||||
// [Underscore](http://underscorejs.org)
|
||||
function eq(a, b, aStack, bStack, customTesters, strictCheck) {
|
||||
let result = true;
|
||||
const asymmetricResult = asymmetricMatch(a, b);
|
||||
if (asymmetricResult !== undefined) {
|
||||
return asymmetricResult;
|
||||
}
|
||||
const testerContext = {
|
||||
equals
|
||||
};
|
||||
for (const item of customTesters) {
|
||||
const customTesterResult = item.call(testerContext, a, b, customTesters);
|
||||
if (customTesterResult !== undefined) {
|
||||
return customTesterResult;
|
||||
}
|
||||
}
|
||||
if (a instanceof Error && b instanceof Error) {
|
||||
return a.message === b.message;
|
||||
}
|
||||
if (Object.is(a, b)) {
|
||||
return true;
|
||||
}
|
||||
// A strict comparison is necessary because `null == undefined`.
|
||||
if (a === null || b === null) {
|
||||
return false;
|
||||
}
|
||||
const className = Object.prototype.toString.call(a);
|
||||
if (className !== Object.prototype.toString.call(b)) {
|
||||
return false;
|
||||
}
|
||||
switch (className) {
|
||||
case '[object Boolean]':
|
||||
case '[object String]':
|
||||
case '[object Number]':
|
||||
if (typeof a !== typeof b) {
|
||||
// One is a primitive, one a `new Primitive()`
|
||||
return false;
|
||||
} else if (typeof a !== 'object' && typeof b !== 'object') {
|
||||
// both are proper primitives
|
||||
return false;
|
||||
} else {
|
||||
// both are `new Primitive()`s
|
||||
return Object.is(a.valueOf(), b.valueOf());
|
||||
}
|
||||
case '[object Date]':
|
||||
// Coerce dates to numeric primitive values. Dates are compared by their
|
||||
// millisecond representations. Note that invalid dates with millisecond representations
|
||||
// of `NaN` are not equivalent.
|
||||
return +a === +b;
|
||||
// RegExps are compared by their source patterns and flags.
|
||||
case '[object RegExp]':
|
||||
return a.source === b.source && a.flags === b.flags;
|
||||
// URLs are compared by their href property which contains the entire url string.
|
||||
case '[object URL]':
|
||||
return a.href === b.href;
|
||||
}
|
||||
if (typeof a !== 'object' || typeof b !== 'object') {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Use DOM3 method isEqualNode (IE>=9)
|
||||
if (isDomNode(a) && isDomNode(b)) {
|
||||
return a.isEqualNode(b);
|
||||
}
|
||||
|
||||
// Used to detect circular references.
|
||||
let length = aStack.length;
|
||||
while (length--) {
|
||||
// Linear search. Performance is inversely proportional to the number of
|
||||
// unique nested structures.
|
||||
// circular references at same depth are equal
|
||||
// circular reference is not equal to non-circular one
|
||||
if (aStack[length] === a) {
|
||||
return bStack[length] === b;
|
||||
} else if (bStack[length] === b) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Add the first object to the stack of traversed objects.
|
||||
aStack.push(a);
|
||||
bStack.push(b);
|
||||
// Recursively compare objects and arrays.
|
||||
// Compare array lengths to determine if a deep comparison is necessary.
|
||||
if (strictCheck && className === '[object Array]' && a.length !== b.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Deep compare objects.
|
||||
const aKeys = keys(a, hasKey);
|
||||
let key;
|
||||
const bKeys = keys(b, hasKey);
|
||||
// Add keys corresponding to asymmetric matchers if they miss in non strict check mode
|
||||
if (!strictCheck) {
|
||||
for (let index = 0; index !== bKeys.length; ++index) {
|
||||
key = bKeys[index];
|
||||
if ((isAsymmetric(b[key]) || b[key] === undefined) && !hasKey(a, key)) {
|
||||
aKeys.push(key);
|
||||
}
|
||||
}
|
||||
for (let index = 0; index !== aKeys.length; ++index) {
|
||||
key = aKeys[index];
|
||||
if ((isAsymmetric(a[key]) || a[key] === undefined) && !hasKey(b, key)) {
|
||||
bKeys.push(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that both objects contain the same number of properties before comparing deep equality.
|
||||
let size = aKeys.length;
|
||||
if (bKeys.length !== size) {
|
||||
return false;
|
||||
}
|
||||
while (size--) {
|
||||
key = aKeys[size];
|
||||
|
||||
// Deep compare each member
|
||||
if (strictCheck) result = hasKey(b, key) && eq(a[key], b[key], aStack, bStack, customTesters, strictCheck);else result = (hasKey(b, key) || isAsymmetric(a[key]) || a[key] === undefined) && eq(a[key], b[key], aStack, bStack, customTesters, strictCheck);
|
||||
if (!result) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Remove the first object from the stack of traversed objects.
|
||||
aStack.pop();
|
||||
bStack.pop();
|
||||
return result;
|
||||
}
|
||||
function keys(obj, hasKey) {
|
||||
const keys = [];
|
||||
for (const key in obj) {
|
||||
if (hasKey(obj, key)) {
|
||||
keys.push(key);
|
||||
}
|
||||
}
|
||||
return [...keys, ...Object.getOwnPropertySymbols(obj).filter(symbol => Object.getOwnPropertyDescriptor(obj, symbol).enumerable)];
|
||||
}
|
||||
function hasKey(obj, key) {
|
||||
return Object.prototype.hasOwnProperty.call(obj, key);
|
||||
}
|
||||
function isA(typeName, value) {
|
||||
return Object.prototype.toString.apply(value) === `[object ${typeName}]`;
|
||||
}
|
||||
function isDomNode(obj) {
|
||||
return obj !== null && typeof obj === 'object' && typeof obj.nodeType === 'number' && typeof obj.nodeName === 'string' && typeof obj.isEqualNode === 'function';
|
||||
}
|
||||
|
||||
/***/ },
|
||||
|
||||
/***/ "./src/utils.ts"
|
||||
(__unused_webpack_module, exports, __webpack_require__) {
|
||||
|
||||
|
||||
|
||||
Object.defineProperty(exports, "__esModule", ({
|
||||
value: true
|
||||
}));
|
||||
exports.arrayBufferEquality = void 0;
|
||||
exports.emptyObject = emptyObject;
|
||||
exports.typeEquality = exports.subsetEquality = exports.sparseArrayEquality = exports.pathAsArray = exports.partition = exports.iterableEquality = exports.isOneline = exports.isError = exports.getPath = exports.getObjectSubset = exports.getObjectKeys = void 0;
|
||||
var _getType = require("@jest/get-type");
|
||||
var _immutableUtils = __webpack_require__("./src/immutableUtils.ts");
|
||||
var _jasmineUtils = __webpack_require__("./src/jasmineUtils.ts");
|
||||
var Symbol = globalThis['jest-symbol-do-not-touch'] || globalThis.Symbol;
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
/**
|
||||
* Checks if `hasOwnProperty(object, key)` up the prototype chain, stopping at `Object.prototype`.
|
||||
*/
|
||||
const hasPropertyInObject = (object, key) => {
|
||||
const shouldTerminate = !object || typeof object !== 'object' || object === Object.prototype;
|
||||
if (shouldTerminate) {
|
||||
return false;
|
||||
}
|
||||
return Object.prototype.hasOwnProperty.call(object, key) || hasPropertyInObject(Object.getPrototypeOf(object), key);
|
||||
};
|
||||
|
||||
// Retrieves an object's keys for evaluation by getObjectSubset. This evaluates
|
||||
// the prototype chain for string keys but not for non-enumerable symbols.
|
||||
// (Otherwise, it could find values such as a Set or Map's Symbol.toStringTag,
|
||||
// with unexpected results.)
|
||||
const getObjectKeys = object => {
|
||||
return [...Object.keys(object), ...Object.getOwnPropertySymbols(object).filter(s => Object.getOwnPropertyDescriptor(object, s)?.enumerable)];
|
||||
};
|
||||
exports.getObjectKeys = getObjectKeys;
|
||||
const getPath = (object, propertyPath) => {
|
||||
if (!Array.isArray(propertyPath)) {
|
||||
propertyPath = pathAsArray(propertyPath);
|
||||
}
|
||||
if (propertyPath.length > 0) {
|
||||
const lastProp = propertyPath.length === 1;
|
||||
const prop = propertyPath[0];
|
||||
const newObject = object[prop];
|
||||
if (!lastProp && (newObject === null || newObject === undefined)) {
|
||||
// This is not the last prop in the chain. If we keep recursing it will
|
||||
// hit a `can't access property X of undefined | null`. At this point we
|
||||
// know that the chain has broken and we can return right away.
|
||||
return {
|
||||
hasEndProp: false,
|
||||
lastTraversedObject: object,
|
||||
traversedPath: []
|
||||
};
|
||||
}
|
||||
const result = getPath(newObject, propertyPath.slice(1));
|
||||
if (result.lastTraversedObject === null) {
|
||||
result.lastTraversedObject = object;
|
||||
}
|
||||
result.traversedPath.unshift(prop);
|
||||
if (lastProp) {
|
||||
// Does object have the property with an undefined value?
|
||||
// Although primitive values support bracket notation (above)
|
||||
// they would throw TypeError for in operator (below).
|
||||
result.endPropIsDefined = !(0, _getType.isPrimitive)(object) && prop in object;
|
||||
result.hasEndProp = newObject !== undefined || result.endPropIsDefined;
|
||||
if (!result.hasEndProp) {
|
||||
result.traversedPath.shift();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return {
|
||||
lastTraversedObject: null,
|
||||
traversedPath: [],
|
||||
value: object
|
||||
};
|
||||
};
|
||||
|
||||
// Strip properties from object that are not present in the subset. Useful for
|
||||
// printing the diff for toMatchObject() without adding unrelated noise.
|
||||
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
||||
exports.getPath = getPath;
|
||||
const getObjectSubset = (object, subset, customTesters = [], seenReferences = new WeakMap()) => {
|
||||
/* eslint-enable @typescript-eslint/explicit-module-boundary-types */
|
||||
if (Array.isArray(object)) {
|
||||
if (Array.isArray(subset) && subset.length === object.length) {
|
||||
// The map method returns correct subclass of subset.
|
||||
return subset.map((sub, i) => getObjectSubset(object[i], sub, customTesters));
|
||||
}
|
||||
} else if (object instanceof Date) {
|
||||
return object;
|
||||
} else if (isObject(object) && isObject(subset)) {
|
||||
if ((0, _jasmineUtils.equals)(object, subset, [...customTesters, iterableEquality, subsetEquality])) {
|
||||
// Avoid unnecessary copy which might return Object instead of subclass.
|
||||
return subset;
|
||||
}
|
||||
const trimmed = {};
|
||||
seenReferences.set(object, trimmed);
|
||||
for (const key of getObjectKeys(object)) {
|
||||
if (!hasPropertyInObject(subset, key)) {
|
||||
continue;
|
||||
}
|
||||
trimmed[key] = seenReferences.has(object[key]) ? seenReferences.get(object[key]) : getObjectSubset(object[key], subset[key], customTesters, seenReferences);
|
||||
}
|
||||
if (getObjectKeys(trimmed).length > 0) {
|
||||
return trimmed;
|
||||
}
|
||||
}
|
||||
return object;
|
||||
};
|
||||
exports.getObjectSubset = getObjectSubset;
|
||||
const IteratorSymbol = Symbol.iterator;
|
||||
const hasIterator = object => !!(object != null && object[IteratorSymbol]);
|
||||
|
||||
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
||||
const iterableEquality = (a, b, customTesters = [], /* eslint-enable @typescript-eslint/explicit-module-boundary-types */
|
||||
aStack = [], bStack = []) => {
|
||||
if (typeof a !== 'object' || typeof b !== 'object' || Array.isArray(a) || Array.isArray(b) || ArrayBuffer.isView(a) || ArrayBuffer.isView(b) || !hasIterator(a) || !hasIterator(b)) {
|
||||
return undefined;
|
||||
}
|
||||
if (a.constructor !== b.constructor) {
|
||||
// Same cross-realm constructor check as typeEquality — see #14011.
|
||||
// https://github.com/jestjs/jest/issues/14011
|
||||
if (a.constructor == null || b.constructor == null || a.constructor.name !== b.constructor.name || !isNativeFunction(a.constructor) || !isNativeFunction(b.constructor)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
let length = aStack.length;
|
||||
while (length--) {
|
||||
// Linear search. Performance is inversely proportional to the number of
|
||||
// unique nested structures.
|
||||
// circular references at same depth are equal
|
||||
// circular reference is not equal to non-circular one
|
||||
if (aStack[length] === a) {
|
||||
return bStack[length] === b;
|
||||
}
|
||||
}
|
||||
aStack.push(a);
|
||||
bStack.push(b);
|
||||
const iterableEqualityWithStack = (a, b) => iterableEquality(a, b, [...filteredCustomTesters], [...aStack], [...bStack]);
|
||||
|
||||
// Replace any instance of iterableEquality with the new
|
||||
// iterableEqualityWithStack so we can do circular detection
|
||||
const filteredCustomTesters = [...customTesters.filter(t => t !== iterableEquality), iterableEqualityWithStack];
|
||||
if (a.size !== undefined) {
|
||||
if (a.size !== b.size) {
|
||||
return false;
|
||||
} else if ((0, _jasmineUtils.isA)('Set', a) || (0, _immutableUtils.isImmutableUnorderedSet)(a)) {
|
||||
let allFound = true;
|
||||
for (const aValue of a) {
|
||||
if (!b.has(aValue)) {
|
||||
let has = false;
|
||||
for (const bValue of b) {
|
||||
const isEqual = (0, _jasmineUtils.equals)(aValue, bValue, filteredCustomTesters);
|
||||
if (isEqual === true) {
|
||||
has = true;
|
||||
}
|
||||
}
|
||||
if (has === false) {
|
||||
allFound = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Remove the first value from the stack of traversed values.
|
||||
aStack.pop();
|
||||
bStack.pop();
|
||||
return allFound;
|
||||
} else if ((0, _jasmineUtils.isA)('Map', a) || (0, _immutableUtils.isImmutableUnorderedKeyed)(a)) {
|
||||
let allFound = true;
|
||||
for (const aEntry of a) {
|
||||
if (!b.has(aEntry[0]) || !(0, _jasmineUtils.equals)(aEntry[1], b.get(aEntry[0]), filteredCustomTesters)) {
|
||||
let has = false;
|
||||
for (const bEntry of b) {
|
||||
const matchedKey = (0, _jasmineUtils.equals)(aEntry[0], bEntry[0], filteredCustomTesters);
|
||||
let matchedValue = false;
|
||||
if (matchedKey === true) {
|
||||
matchedValue = (0, _jasmineUtils.equals)(aEntry[1], bEntry[1], filteredCustomTesters);
|
||||
}
|
||||
if (matchedValue === true) {
|
||||
has = true;
|
||||
}
|
||||
}
|
||||
if (has === false) {
|
||||
allFound = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Remove the first value from the stack of traversed values.
|
||||
aStack.pop();
|
||||
bStack.pop();
|
||||
return allFound;
|
||||
}
|
||||
}
|
||||
let aIterator;
|
||||
let bIterator;
|
||||
try {
|
||||
aIterator = a[IteratorSymbol]();
|
||||
bIterator = b[IteratorSymbol]();
|
||||
} catch {
|
||||
// If the iterator factory itself throws (e.g. a TypedArray method used as
|
||||
// [Symbol.iterator] on a plain object), we cannot compare as iterables.
|
||||
// Return undefined so equals() falls through to Object.is / property checks.
|
||||
aStack.pop();
|
||||
bStack.pop();
|
||||
return undefined;
|
||||
}
|
||||
let aStep = aIterator.next();
|
||||
while (!aStep.done) {
|
||||
const bStep = bIterator.next();
|
||||
if (bStep.done || !(0, _jasmineUtils.equals)(aStep.value, bStep.value, filteredCustomTesters)) {
|
||||
return false;
|
||||
}
|
||||
aStep = aIterator.next();
|
||||
}
|
||||
if (!bIterator.next().done) {
|
||||
return false;
|
||||
}
|
||||
if (!(0, _immutableUtils.isImmutableList)(a) && !(0, _immutableUtils.isImmutableOrderedKeyed)(a) && !(0, _immutableUtils.isImmutableOrderedSet)(a) && !(0, _immutableUtils.isImmutableRecord)(a)) {
|
||||
const aEntries = entries(a);
|
||||
const bEntries = entries(b);
|
||||
if (!(0, _jasmineUtils.equals)(aEntries, bEntries)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Remove the first value from the stack of traversed values.
|
||||
aStack.pop();
|
||||
bStack.pop();
|
||||
return true;
|
||||
};
|
||||
exports.iterableEquality = iterableEquality;
|
||||
const entries = obj => {
|
||||
if (!isObject(obj)) return [];
|
||||
const symbolProperties = Object.getOwnPropertySymbols(obj).filter(key => key !== Symbol.iterator).map(key => [key, obj[key]]);
|
||||
return [...symbolProperties, ...Object.entries(obj)];
|
||||
};
|
||||
const isObject = a => a !== null && typeof a === 'object';
|
||||
const isObjectWithKeys = a => isObject(a) && !(a instanceof Error) && !Array.isArray(a) && !(a instanceof Date) && !(a instanceof Set) && !(a instanceof Map);
|
||||
const subsetEquality = (object, subset, customTesters = []) => {
|
||||
const filteredCustomTesters = customTesters.filter(t => t !== subsetEquality);
|
||||
|
||||
// subsetEquality needs to keep track of the references
|
||||
// it has already visited to avoid infinite loops in case
|
||||
// there are circular references in the subset passed to it.
|
||||
const subsetEqualityWithContext = (seenReferences = new WeakMap()) => (object, subset) => {
|
||||
if (!isObjectWithKeys(subset)) {
|
||||
return undefined;
|
||||
}
|
||||
if (seenReferences.has(subset)) return undefined;
|
||||
seenReferences.set(subset, true);
|
||||
const matchResult = getObjectKeys(subset).every(key => {
|
||||
if (isObjectWithKeys(subset[key])) {
|
||||
if (seenReferences.has(subset[key])) {
|
||||
return (0, _jasmineUtils.equals)(object[key], subset[key], filteredCustomTesters);
|
||||
}
|
||||
}
|
||||
const result = object != null && hasPropertyInObject(object, key) && (0, _jasmineUtils.equals)(object[key], subset[key], [...filteredCustomTesters, subsetEqualityWithContext(seenReferences)]);
|
||||
// The main goal of using seenReference is to avoid circular node on tree.
|
||||
// It will only happen within a parent and its child, not a node and nodes next to it (same level)
|
||||
// We should keep the reference for a parent and its child only
|
||||
// Thus we should delete the reference immediately so that it doesn't interfere
|
||||
// other nodes within the same level on tree.
|
||||
seenReferences.delete(subset[key]);
|
||||
return result;
|
||||
});
|
||||
seenReferences.delete(subset);
|
||||
return matchResult;
|
||||
};
|
||||
return subsetEqualityWithContext()(object, subset);
|
||||
};
|
||||
|
||||
// Returns true if `fn` is a native function (its toString contains "[native code]").
|
||||
exports.subsetEquality = subsetEquality;
|
||||
function isNativeFunction(fn) {
|
||||
return typeof fn === 'function' && Function.prototype.toString.call(fn).includes('[native code]');
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||
const typeEquality = (a, b) => {
|
||||
if (a == null || b == null || a.constructor === b.constructor ||
|
||||
// Since Jest globals are different from Node globals,
|
||||
// constructors are different even between arrays when comparing properties of mock objects.
|
||||
// Both of them should be able to compare correctly when they are array-to-array.
|
||||
// https://github.com/jestjs/jest/issues/2549
|
||||
Array.isArray(a) && Array.isArray(b)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// structuredClone (and other cross-realm calls) return objects whose
|
||||
// constructors come from a different VM context, so identity checks fail.
|
||||
// Fall back to comparing constructor names for native built-ins only —
|
||||
// user-defined classes still need identity equality.
|
||||
// https://github.com/jestjs/jest/issues/14011
|
||||
if (a.constructor != null && b.constructor != null && a.constructor.name === b.constructor.name && isNativeFunction(a.constructor) && isNativeFunction(b.constructor)) {
|
||||
return undefined;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
exports.typeEquality = typeEquality;
|
||||
const arrayBufferEquality = (a, b) => {
|
||||
let dataViewA = a;
|
||||
let dataViewB = b;
|
||||
if (isArrayBuffer(a) && isArrayBuffer(b)) {
|
||||
dataViewA = new DataView(a);
|
||||
dataViewB = new DataView(b);
|
||||
} else if (ArrayBuffer.isView(a) && ArrayBuffer.isView(b)) {
|
||||
dataViewA = new DataView(a.buffer, a.byteOffset, a.byteLength);
|
||||
dataViewB = new DataView(b.buffer, b.byteOffset, b.byteLength);
|
||||
}
|
||||
if (!(dataViewA instanceof DataView && dataViewB instanceof DataView)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// Buffers are not equal when they do not have the same byte length
|
||||
if (dataViewA.byteLength !== dataViewB.byteLength) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if every byte value is equal to each other
|
||||
for (let i = 0; i < dataViewA.byteLength; i++) {
|
||||
if (dataViewA.getUint8(i) !== dataViewB.getUint8(i)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
exports.arrayBufferEquality = arrayBufferEquality;
|
||||
function isArrayBuffer(obj) {
|
||||
return Object.prototype.toString.call(obj) === '[object ArrayBuffer]';
|
||||
}
|
||||
const sparseArrayEquality = (a, b, customTesters = []) => {
|
||||
if (!Array.isArray(a) || !Array.isArray(b)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// A sparse array [, , 1] will have keys ["2"] whereas [undefined, undefined, 1] will have keys ["0", "1", "2"]
|
||||
const aKeys = Object.keys(a);
|
||||
const bKeys = Object.keys(b);
|
||||
return (0, _jasmineUtils.equals)(a, b, customTesters.filter(t => t !== sparseArrayEquality), true) && (0, _jasmineUtils.equals)(aKeys, bKeys);
|
||||
};
|
||||
exports.sparseArrayEquality = sparseArrayEquality;
|
||||
const partition = (items, predicate) => {
|
||||
const result = [[], []];
|
||||
for (const item of items) result[predicate(item) ? 0 : 1].push(item);
|
||||
return result;
|
||||
};
|
||||
exports.partition = partition;
|
||||
const pathAsArray = propertyPath => {
|
||||
const properties = [];
|
||||
if (propertyPath === '') {
|
||||
properties.push('');
|
||||
return properties;
|
||||
}
|
||||
|
||||
// will match everything that's not a dot or a bracket, and "" for consecutive dots.
|
||||
const pattern = new RegExp('[^.[\\]]+|(?=(?:\\.)(?:\\.|$))', 'g');
|
||||
|
||||
// Because the regex won't match a dot in the beginning of the path, if present.
|
||||
if (propertyPath[0] === '.') {
|
||||
properties.push('');
|
||||
}
|
||||
propertyPath.replaceAll(pattern, match => {
|
||||
properties.push(match);
|
||||
return match;
|
||||
});
|
||||
return properties;
|
||||
};
|
||||
|
||||
// Copied from https://github.com/graingert/angular.js/blob/a43574052e9775cbc1d7dd8a086752c979b0f020/src/Angular.js#L685-L693
|
||||
exports.pathAsArray = pathAsArray;
|
||||
const isError = value => {
|
||||
switch (Object.prototype.toString.call(value)) {
|
||||
case '[object Error]':
|
||||
case '[object Exception]':
|
||||
case '[object DOMException]':
|
||||
return true;
|
||||
default:
|
||||
return value instanceof Error;
|
||||
}
|
||||
};
|
||||
exports.isError = isError;
|
||||
function emptyObject(obj) {
|
||||
return obj && typeof obj === 'object' ? Object.keys(obj).length === 0 : false;
|
||||
}
|
||||
const MULTILINE_REGEXP = /[\n\r]/;
|
||||
const isOneline = (expected, received) => typeof expected === 'string' && typeof received === 'string' && (!MULTILINE_REGEXP.test(expected) || !MULTILINE_REGEXP.test(received));
|
||||
exports.isOneline = isOneline;
|
||||
|
||||
/***/ }
|
||||
|
||||
/******/ });
|
||||
/************************************************************************/
|
||||
/******/ // The module cache
|
||||
/******/ const __webpack_module_cache__ = {};
|
||||
/******/
|
||||
/******/ // The require function
|
||||
/******/ function __webpack_require__(moduleId) {
|
||||
/******/ // Check if module is in cache
|
||||
/******/ const cachedModule = __webpack_module_cache__[moduleId];
|
||||
/******/ if (cachedModule !== undefined) {
|
||||
/******/ return cachedModule.exports;
|
||||
/******/ }
|
||||
/******/ // Create a new module (and put it into the cache)
|
||||
/******/ const module = __webpack_module_cache__[moduleId] = {
|
||||
/******/ // no module.id needed
|
||||
/******/ // no module.loaded needed
|
||||
/******/ exports: {}
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // Execute the module function
|
||||
/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
|
||||
/******/
|
||||
/******/ // Return the exports of the module
|
||||
/******/ return module.exports;
|
||||
/******/ }
|
||||
/******/
|
||||
/************************************************************************/
|
||||
/******/
|
||||
/******/ // startup
|
||||
/******/ // Load entry module and return exports
|
||||
/******/ // This entry module is referenced by other modules so it can't be inlined
|
||||
/******/ let __webpack_exports__ = __webpack_require__("./src/index.ts");
|
||||
/******/ module.exports = __webpack_exports__;
|
||||
/******/
|
||||
/******/ })()
|
||||
;
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
import cjsModule from './index.js';
|
||||
|
||||
export const equals = cjsModule.equals;
|
||||
export const isA = cjsModule.isA;
|
||||
export const arrayBufferEquality = cjsModule.arrayBufferEquality;
|
||||
export const emptyObject = cjsModule.emptyObject;
|
||||
export const getObjectKeys = cjsModule.getObjectKeys;
|
||||
export const getObjectSubset = cjsModule.getObjectSubset;
|
||||
export const getPath = cjsModule.getPath;
|
||||
export const isError = cjsModule.isError;
|
||||
export const isOneline = cjsModule.isOneline;
|
||||
export const iterableEquality = cjsModule.iterableEquality;
|
||||
export const partition = cjsModule.partition;
|
||||
export const pathAsArray = cjsModule.pathAsArray;
|
||||
export const sparseArrayEquality = cjsModule.sparseArrayEquality;
|
||||
export const subsetEquality = cjsModule.subsetEquality;
|
||||
export const typeEquality = cjsModule.typeEquality;
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"name": "@jest/expect-utils",
|
||||
"version": "30.5.1",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/jestjs/jest.git",
|
||||
"directory": "packages/expect-utils"
|
||||
},
|
||||
"license": "MIT",
|
||||
"main": "./build/index.js",
|
||||
"types": "./build/index.d.ts",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./build/index.d.ts",
|
||||
"require": "./build/index.js",
|
||||
"import": "./build/index.mjs",
|
||||
"default": "./build/index.js"
|
||||
},
|
||||
"./package.json": "./package.json"
|
||||
},
|
||||
"dependencies": {
|
||||
"@jest/get-type": "30.5.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"immutable": "^5.1.2",
|
||||
"jest-matcher-utils": "30.5.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"gitHead": "9ab14feccd6c15fec1334dbcb03a53a079d153d3"
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
Copyright Contributors to the Jest project.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
# @jest/expect
|
||||
|
||||
This package extends `expect` library with `jest-snapshot` matchers. It exports `jestExpect` object, which can be used as standalone replacement of `expect`.
|
||||
|
||||
The `jestExpect` function used in [Jest](https://jestjs.io/). You can find its documentation [on Jest's website](https://jestjs.io/docs/expect).
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
/**
|
||||
* 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 {
|
||||
AsymmetricMatchers,
|
||||
BaseExpect,
|
||||
Inverse,
|
||||
MatcherContext,
|
||||
MatcherFunction,
|
||||
MatcherFunctionWithContext,
|
||||
MatcherState,
|
||||
MatcherUtils,
|
||||
Matchers,
|
||||
} from 'expect';
|
||||
import {SnapshotMatchers, addSerializer} from 'jest-snapshot';
|
||||
|
||||
export {AsymmetricMatchers};
|
||||
|
||||
export declare type JestExpect = {
|
||||
<T = unknown>(
|
||||
actual: T,
|
||||
): JestMatchers<void, T> &
|
||||
Inverse<JestMatchers<void, T>> &
|
||||
PromiseMatchers<T>;
|
||||
addSnapshotSerializer: typeof addSerializer;
|
||||
} & BaseExpect &
|
||||
AsymmetricMatchers &
|
||||
Inverse<Omit<AsymmetricMatchers, 'any' | 'anything'>>;
|
||||
|
||||
export declare const jestExpect: JestExpect;
|
||||
|
||||
declare type JestMatchers<R extends void | Promise<void>, T> = Matchers<R, T> &
|
||||
SnapshotMatchers<R, T>;
|
||||
|
||||
export {MatcherContext};
|
||||
|
||||
export {MatcherFunction};
|
||||
|
||||
export {MatcherFunctionWithContext};
|
||||
|
||||
export {Matchers};
|
||||
|
||||
export {MatcherState};
|
||||
|
||||
export {MatcherUtils};
|
||||
|
||||
declare type PromiseMatchers<T = unknown> = {
|
||||
/**
|
||||
* Unwraps the reason of a rejected promise so any other matcher can be chained.
|
||||
* If the promise is fulfilled the assertion fails.
|
||||
*/
|
||||
rejects: JestMatchers<Promise<void>, T> &
|
||||
Inverse<JestMatchers<Promise<void>, T>>;
|
||||
/**
|
||||
* Unwraps the value of a fulfilled promise so any other matcher can be chained.
|
||||
* If the promise is rejected the assertion fails.
|
||||
*/
|
||||
resolves: JestMatchers<Promise<void>, T> &
|
||||
Inverse<JestMatchers<Promise<void>, T>>;
|
||||
};
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
/*!
|
||||
* /**
|
||||
* * 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.
|
||||
* * /
|
||||
*/
|
||||
/******/ (() => { // webpackBootstrap
|
||||
/******/ "use strict";
|
||||
let __webpack_exports__ = {};
|
||||
// This entry needs to be wrapped in an IIFE because it uses a non-standard name for the exports (exports).
|
||||
(() => {
|
||||
let exports = __webpack_exports__;
|
||||
|
||||
|
||||
Object.defineProperty(exports, "__esModule", ({
|
||||
value: true
|
||||
}));
|
||||
exports.jestExpect = void 0;
|
||||
function _expect() {
|
||||
const data = require("expect");
|
||||
_expect = function () {
|
||||
return data;
|
||||
};
|
||||
return data;
|
||||
}
|
||||
function _jestSnapshot() {
|
||||
const data = require("jest-snapshot");
|
||||
_jestSnapshot = function () {
|
||||
return data;
|
||||
};
|
||||
return data;
|
||||
}
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
function createJestExpect() {
|
||||
_expect().expect.extend({
|
||||
toMatchInlineSnapshot: _jestSnapshot().toMatchInlineSnapshot,
|
||||
toMatchSnapshot: _jestSnapshot().toMatchSnapshot,
|
||||
toThrowErrorMatchingInlineSnapshot: _jestSnapshot().toThrowErrorMatchingInlineSnapshot,
|
||||
toThrowErrorMatchingSnapshot: _jestSnapshot().toThrowErrorMatchingSnapshot
|
||||
});
|
||||
_expect().expect.addSnapshotSerializer = _jestSnapshot().addSerializer;
|
||||
return _expect().expect;
|
||||
}
|
||||
const jestExpect = exports.jestExpect = createJestExpect();
|
||||
})();
|
||||
|
||||
module.exports = __webpack_exports__;
|
||||
/******/ })()
|
||||
;
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
import cjsModule from './index.js';
|
||||
|
||||
export const jestExpect = cjsModule.jestExpect;
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"name": "@jest/expect",
|
||||
"version": "30.5.1",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/jestjs/jest.git",
|
||||
"directory": "packages/jest-expect"
|
||||
},
|
||||
"license": "MIT",
|
||||
"main": "./build/index.js",
|
||||
"types": "./build/index.d.ts",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./build/index.d.ts",
|
||||
"require": "./build/index.js",
|
||||
"import": "./build/index.mjs",
|
||||
"default": "./build/index.js"
|
||||
},
|
||||
"./package.json": "./package.json"
|
||||
},
|
||||
"dependencies": {
|
||||
"expect": "30.5.1",
|
||||
"jest-snapshot": "30.5.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"gitHead": "9ab14feccd6c15fec1334dbcb03a53a079d153d3"
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
Copyright Contributors to the Jest project.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
+129
@@ -0,0 +1,129 @@
|
||||
/**
|
||||
* 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 {
|
||||
TemporalDuration as TemporalDurationLike,
|
||||
TemporalTimelike as TemporalEpochLike,
|
||||
} from '@sinonjs/fake-timers';
|
||||
import {Config} from '@jest/types';
|
||||
import {StackTraceConfig} from 'jest-message-util';
|
||||
import {ModuleMocker} from 'jest-mock';
|
||||
|
||||
declare type Callback = (...args: Array<unknown>) => void;
|
||||
|
||||
export declare class LegacyFakeTimers<TimerRef = unknown> {
|
||||
#private;
|
||||
private _cancelledTicks;
|
||||
private readonly _config;
|
||||
private _disposed;
|
||||
private _fakeTimerAPIs;
|
||||
private _fakingTime;
|
||||
private readonly _global;
|
||||
private _immediates;
|
||||
private readonly _maxLoops;
|
||||
private readonly _moduleMocker;
|
||||
private _now;
|
||||
private _ticks;
|
||||
private readonly _timerAPIs;
|
||||
private _timers;
|
||||
private _uuidCounter;
|
||||
private readonly _timerConfig;
|
||||
constructor({
|
||||
global,
|
||||
moduleMocker,
|
||||
timerConfig,
|
||||
config,
|
||||
maxLoops,
|
||||
}: {
|
||||
global: typeof globalThis;
|
||||
moduleMocker: ModuleMocker;
|
||||
timerConfig: TimerConfig<TimerRef>;
|
||||
config: StackTraceConfig;
|
||||
maxLoops?: number;
|
||||
});
|
||||
clearAllTimers(): void;
|
||||
dispose(): void;
|
||||
reset(): void;
|
||||
now(): number;
|
||||
runAllTicks(): void;
|
||||
runAllImmediates(): void;
|
||||
private _runImmediate;
|
||||
runAllTimers(): void;
|
||||
runOnlyPendingTimers(): void;
|
||||
advanceTimersToNextTimer(steps?: number): void;
|
||||
advanceTimersByTime(msToRun: number | TemporalDurationLike_2): void;
|
||||
runWithRealTimers(cb: Callback): void;
|
||||
useRealTimers(): void;
|
||||
useFakeTimers(): void;
|
||||
getTimerCount(): number;
|
||||
private _checkFakeTimers;
|
||||
private _createMocks;
|
||||
private _fakeClearTimer;
|
||||
private _fakeClearImmediate;
|
||||
private _fakeNextTick;
|
||||
private _fakeRequestAnimationFrame;
|
||||
private _fakeSetImmediate;
|
||||
private _fakeSetInterval;
|
||||
private _fakeSetTimeout;
|
||||
private _getNextTimerHandleAndExpiry;
|
||||
private _runTimerHandle;
|
||||
}
|
||||
|
||||
export declare class ModernFakeTimers {
|
||||
private _clock;
|
||||
private readonly _config;
|
||||
private _fakingTime;
|
||||
private readonly _global;
|
||||
private readonly _fakeTimers;
|
||||
constructor({
|
||||
global,
|
||||
config,
|
||||
}: {
|
||||
global: typeof globalThis;
|
||||
config: Config.ProjectConfig;
|
||||
});
|
||||
clearAllTimers(): void;
|
||||
dispose(): void;
|
||||
runAllTimers(): void;
|
||||
runAllTimersAsync(): Promise<void>;
|
||||
runOnlyPendingTimers(): void;
|
||||
runOnlyPendingTimersAsync(): Promise<void>;
|
||||
advanceTimersToNextTimer(steps?: number): void;
|
||||
advanceTimersToNextTimerAsync(steps?: number): Promise<void>;
|
||||
advanceTimersByTime(msToRun: number | TemporalDurationLike): void;
|
||||
advanceTimersByTimeAsync(
|
||||
msToRun: number | TemporalDurationLike,
|
||||
): Promise<void>;
|
||||
advanceTimersToNextFrame(): void;
|
||||
runAllTicks(): void;
|
||||
useRealTimers(): void;
|
||||
useFakeTimers(fakeTimersConfig?: Config.FakeTimersConfig): void;
|
||||
reset(): void;
|
||||
setSystemTime(now?: number | Date | TemporalEpochLike): void;
|
||||
setTimerTickMode(tickModeConfig: {
|
||||
mode: 'interval' | 'manual' | 'nextAsync';
|
||||
delta?: number;
|
||||
}): void;
|
||||
getRealSystemTime(): number;
|
||||
now(): number;
|
||||
getTimerCount(): number;
|
||||
private _checkFakeTimers;
|
||||
private _toSinonFakeTimersConfig;
|
||||
}
|
||||
|
||||
export {TemporalDurationLike};
|
||||
|
||||
declare type TemporalDurationLike_2 = {
|
||||
total(options: {unit: string}): number;
|
||||
};
|
||||
|
||||
export {TemporalEpochLike};
|
||||
|
||||
declare type TimerConfig<Ref> = {
|
||||
idToRef: (id: number) => Ref;
|
||||
refToId: (ref: Ref) => number | void;
|
||||
};
|
||||
+739
@@ -0,0 +1,739 @@
|
||||
/*!
|
||||
* /**
|
||||
* * 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.
|
||||
* * /
|
||||
*/
|
||||
/******/ (() => { // webpackBootstrap
|
||||
/******/ "use strict";
|
||||
/******/ var __webpack_modules__ = ({
|
||||
|
||||
/***/ "./src/legacyFakeTimers.ts"
|
||||
(__unused_webpack_module, exports) {
|
||||
|
||||
|
||||
|
||||
Object.defineProperty(exports, "__esModule", ({
|
||||
value: true
|
||||
}));
|
||||
exports["default"] = void 0;
|
||||
function _nodeUtil() {
|
||||
const data = require("node:util");
|
||||
_nodeUtil = function () {
|
||||
return data;
|
||||
};
|
||||
return data;
|
||||
}
|
||||
function _jestMessageUtil() {
|
||||
const data = require("jest-message-util");
|
||||
_jestMessageUtil = function () {
|
||||
return data;
|
||||
};
|
||||
return data;
|
||||
}
|
||||
function _jestUtil() {
|
||||
const data = require("jest-util");
|
||||
_jestUtil = function () {
|
||||
return data;
|
||||
};
|
||||
return data;
|
||||
}
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* eslint-disable local/prefer-spread-eventually */
|
||||
|
||||
const MS_IN_A_YEAR = 31_536_000_000;
|
||||
class FakeTimers {
|
||||
_cancelledTicks;
|
||||
_config;
|
||||
_disposed;
|
||||
_fakeTimerAPIs;
|
||||
_fakingTime = false;
|
||||
_global;
|
||||
_immediates;
|
||||
_maxLoops;
|
||||
_moduleMocker;
|
||||
_now;
|
||||
_ticks;
|
||||
_timerAPIs;
|
||||
_timers;
|
||||
_uuidCounter;
|
||||
_timerConfig;
|
||||
constructor({
|
||||
global,
|
||||
moduleMocker,
|
||||
timerConfig,
|
||||
config,
|
||||
maxLoops
|
||||
}) {
|
||||
this._global = global;
|
||||
this._timerConfig = timerConfig;
|
||||
this._config = config;
|
||||
this._maxLoops = maxLoops || 100_000;
|
||||
this._uuidCounter = 1;
|
||||
this._moduleMocker = moduleMocker;
|
||||
|
||||
// Store original timer APIs for future reference
|
||||
this._timerAPIs = {
|
||||
cancelAnimationFrame: global.cancelAnimationFrame,
|
||||
clearImmediate: global.clearImmediate,
|
||||
clearInterval: global.clearInterval,
|
||||
clearTimeout: global.clearTimeout,
|
||||
nextTick: global.process && global.process.nextTick,
|
||||
requestAnimationFrame: global.requestAnimationFrame,
|
||||
setImmediate: global.setImmediate,
|
||||
setInterval: global.setInterval,
|
||||
setTimeout: global.setTimeout
|
||||
};
|
||||
this._disposed = false;
|
||||
this.reset();
|
||||
}
|
||||
clearAllTimers() {
|
||||
this._immediates = [];
|
||||
this._timers.clear();
|
||||
}
|
||||
dispose() {
|
||||
this._disposed = true;
|
||||
this.clearAllTimers();
|
||||
}
|
||||
reset() {
|
||||
this._cancelledTicks = {};
|
||||
this._now = 0;
|
||||
this._ticks = [];
|
||||
this._immediates = [];
|
||||
this._timers = new Map();
|
||||
}
|
||||
now() {
|
||||
if (this._fakingTime) {
|
||||
return this._now;
|
||||
}
|
||||
return Date.now();
|
||||
}
|
||||
runAllTicks() {
|
||||
this._checkFakeTimers();
|
||||
// Only run a generous number of ticks and then bail.
|
||||
// This is just to help avoid recursive loops
|
||||
let i;
|
||||
for (i = 0; i < this._maxLoops; i++) {
|
||||
const tick = this._ticks.shift();
|
||||
if (tick === undefined) {
|
||||
break;
|
||||
}
|
||||
if (!Object.prototype.hasOwnProperty.call(this._cancelledTicks, tick.uuid)) {
|
||||
// Callback may throw, so update the map prior calling.
|
||||
this._cancelledTicks[tick.uuid] = true;
|
||||
tick.callback();
|
||||
}
|
||||
}
|
||||
if (i === this._maxLoops) {
|
||||
throw new Error(`Ran ${this._maxLoops} ticks, and there are still more! ` + "Assuming we've hit an infinite recursion and bailing out...");
|
||||
}
|
||||
}
|
||||
runAllImmediates() {
|
||||
this._checkFakeTimers();
|
||||
// Only run a generous number of immediates and then bail.
|
||||
let i;
|
||||
for (i = 0; i < this._maxLoops; i++) {
|
||||
const immediate = this._immediates.shift();
|
||||
if (immediate === undefined) {
|
||||
break;
|
||||
}
|
||||
this._runImmediate(immediate);
|
||||
}
|
||||
if (i === this._maxLoops) {
|
||||
throw new Error(`Ran ${this._maxLoops} immediates, and there are still more! Assuming ` + "we've hit an infinite recursion and bailing out...");
|
||||
}
|
||||
}
|
||||
_runImmediate(immediate) {
|
||||
try {
|
||||
immediate.callback();
|
||||
} finally {
|
||||
this._fakeClearImmediate(immediate.uuid);
|
||||
}
|
||||
}
|
||||
runAllTimers() {
|
||||
this._checkFakeTimers();
|
||||
this.runAllTicks();
|
||||
this.runAllImmediates();
|
||||
|
||||
// Only run a generous number of timers and then bail.
|
||||
// This is just to help avoid recursive loops
|
||||
let i;
|
||||
for (i = 0; i < this._maxLoops; i++) {
|
||||
const nextTimerHandleAndExpiry = this._getNextTimerHandleAndExpiry();
|
||||
|
||||
// If there are no more timer handles, stop!
|
||||
if (nextTimerHandleAndExpiry === null) {
|
||||
break;
|
||||
}
|
||||
const [nextTimerHandle, expiry] = nextTimerHandleAndExpiry;
|
||||
this._now = expiry;
|
||||
this._runTimerHandle(nextTimerHandle);
|
||||
|
||||
// Some of the immediate calls could be enqueued
|
||||
// during the previous handling of the timers, we should
|
||||
// run them as well.
|
||||
if (this._immediates.length > 0) {
|
||||
this.runAllImmediates();
|
||||
}
|
||||
if (this._ticks.length > 0) {
|
||||
this.runAllTicks();
|
||||
}
|
||||
}
|
||||
if (i === this._maxLoops) {
|
||||
throw new Error(`Ran ${this._maxLoops} timers, and there are still more! ` + "Assuming we've hit an infinite recursion and bailing out...");
|
||||
}
|
||||
}
|
||||
runOnlyPendingTimers() {
|
||||
// We need to hold the current shape of `this._timers` because existing
|
||||
// timers can add new ones to the map and hence would run more than necessary.
|
||||
// See https://github.com/jestjs/jest/pull/4608 for details
|
||||
const timerEntries = [...this._timers.entries()];
|
||||
this._checkFakeTimers();
|
||||
for (const _immediate of this._immediates) this._runImmediate(_immediate);
|
||||
for (const [timerHandle, timer] of timerEntries.sort(([, left], [, right]) => left.expiry - right.expiry)) {
|
||||
this._now = timer.expiry;
|
||||
this._runTimerHandle(timerHandle);
|
||||
}
|
||||
}
|
||||
advanceTimersToNextTimer(steps = 1) {
|
||||
if (steps < 1) {
|
||||
return;
|
||||
}
|
||||
const nextExpiry = [...this._timers.values()].reduce((minExpiry, timer) => {
|
||||
if (minExpiry === null || timer.expiry < minExpiry) return timer.expiry;
|
||||
return minExpiry;
|
||||
}, null);
|
||||
if (nextExpiry !== null) {
|
||||
this.advanceTimersByTime(nextExpiry - this._now);
|
||||
this.advanceTimersToNextTimer(steps - 1);
|
||||
}
|
||||
}
|
||||
advanceTimersByTime(msToRun) {
|
||||
this._checkFakeTimers();
|
||||
let msRemaining = typeof msToRun === 'number' ? msToRun : msToRun.total({
|
||||
unit: 'millisecond'
|
||||
});
|
||||
// Only run a generous number of timers and then bail.
|
||||
// This is just to help avoid recursive loops
|
||||
let i;
|
||||
for (i = 0; i < this._maxLoops; i++) {
|
||||
const timerHandleAndExpiry = this._getNextTimerHandleAndExpiry();
|
||||
|
||||
// If there are no more timer handles, stop!
|
||||
if (timerHandleAndExpiry === null) {
|
||||
break;
|
||||
}
|
||||
const [timerHandle, nextTimerExpiry] = timerHandleAndExpiry;
|
||||
if (this._now + msRemaining < nextTimerExpiry) {
|
||||
// There are no timers between now and the target we're running to
|
||||
break;
|
||||
} else {
|
||||
msRemaining -= nextTimerExpiry - this._now;
|
||||
this._now = nextTimerExpiry;
|
||||
this._runTimerHandle(timerHandle);
|
||||
}
|
||||
}
|
||||
|
||||
// Advance the clock by whatever time we still have left to run
|
||||
this._now += msRemaining;
|
||||
if (i === this._maxLoops) {
|
||||
throw new Error(`Ran ${this._maxLoops} timers, and there are still more! ` + "Assuming we've hit an infinite recursion and bailing out...");
|
||||
}
|
||||
}
|
||||
runWithRealTimers(cb) {
|
||||
const prevClearImmediate = this._global.clearImmediate;
|
||||
const prevClearInterval = this._global.clearInterval;
|
||||
const prevClearTimeout = this._global.clearTimeout;
|
||||
const prevNextTick = this._global.process.nextTick;
|
||||
const prevSetImmediate = this._global.setImmediate;
|
||||
const prevSetInterval = this._global.setInterval;
|
||||
const prevSetTimeout = this._global.setTimeout;
|
||||
this.useRealTimers();
|
||||
let cbErr = null;
|
||||
let errThrown = false;
|
||||
try {
|
||||
cb();
|
||||
} catch (error) {
|
||||
errThrown = true;
|
||||
cbErr = error;
|
||||
}
|
||||
this._global.clearImmediate = prevClearImmediate;
|
||||
this._global.clearInterval = prevClearInterval;
|
||||
this._global.clearTimeout = prevClearTimeout;
|
||||
this._global.process.nextTick = prevNextTick;
|
||||
this._global.setImmediate = prevSetImmediate;
|
||||
this._global.setInterval = prevSetInterval;
|
||||
this._global.setTimeout = prevSetTimeout;
|
||||
if (errThrown) {
|
||||
throw cbErr;
|
||||
}
|
||||
}
|
||||
useRealTimers() {
|
||||
const global = this._global;
|
||||
if (typeof global.cancelAnimationFrame === 'function') {
|
||||
(0, _jestUtil().setGlobal)(global, 'cancelAnimationFrame', this._timerAPIs.cancelAnimationFrame);
|
||||
}
|
||||
if (typeof global.clearImmediate === 'function') {
|
||||
(0, _jestUtil().setGlobal)(global, 'clearImmediate', this._timerAPIs.clearImmediate);
|
||||
}
|
||||
(0, _jestUtil().setGlobal)(global, 'clearInterval', this._timerAPIs.clearInterval);
|
||||
(0, _jestUtil().setGlobal)(global, 'clearTimeout', this._timerAPIs.clearTimeout);
|
||||
if (typeof global.requestAnimationFrame === 'function') {
|
||||
(0, _jestUtil().setGlobal)(global, 'requestAnimationFrame', this._timerAPIs.requestAnimationFrame);
|
||||
}
|
||||
if (typeof global.setImmediate === 'function') {
|
||||
(0, _jestUtil().setGlobal)(global, 'setImmediate', this._timerAPIs.setImmediate);
|
||||
}
|
||||
(0, _jestUtil().setGlobal)(global, 'setInterval', this._timerAPIs.setInterval);
|
||||
(0, _jestUtil().setGlobal)(global, 'setTimeout', this._timerAPIs.setTimeout);
|
||||
global.process.nextTick = this._timerAPIs.nextTick;
|
||||
this._fakingTime = false;
|
||||
}
|
||||
useFakeTimers() {
|
||||
this._createMocks();
|
||||
const global = this._global;
|
||||
if (typeof global.cancelAnimationFrame === 'function') {
|
||||
(0, _jestUtil().setGlobal)(global, 'cancelAnimationFrame', this._fakeTimerAPIs.cancelAnimationFrame);
|
||||
}
|
||||
if (typeof global.clearImmediate === 'function') {
|
||||
(0, _jestUtil().setGlobal)(global, 'clearImmediate', this._fakeTimerAPIs.clearImmediate);
|
||||
}
|
||||
(0, _jestUtil().setGlobal)(global, 'clearInterval', this._fakeTimerAPIs.clearInterval);
|
||||
(0, _jestUtil().setGlobal)(global, 'clearTimeout', this._fakeTimerAPIs.clearTimeout);
|
||||
if (typeof global.requestAnimationFrame === 'function') {
|
||||
(0, _jestUtil().setGlobal)(global, 'requestAnimationFrame', this._fakeTimerAPIs.requestAnimationFrame);
|
||||
}
|
||||
if (typeof global.setImmediate === 'function') {
|
||||
(0, _jestUtil().setGlobal)(global, 'setImmediate', this._fakeTimerAPIs.setImmediate);
|
||||
}
|
||||
(0, _jestUtil().setGlobal)(global, 'setInterval', this._fakeTimerAPIs.setInterval);
|
||||
(0, _jestUtil().setGlobal)(global, 'setTimeout', this._fakeTimerAPIs.setTimeout);
|
||||
global.process.nextTick = this._fakeTimerAPIs.nextTick;
|
||||
this._fakingTime = true;
|
||||
}
|
||||
getTimerCount() {
|
||||
this._checkFakeTimers();
|
||||
return this._timers.size + this._immediates.length + this._ticks.length;
|
||||
}
|
||||
_checkFakeTimers() {
|
||||
if (!this._fakingTime) {
|
||||
this._global.console.warn('A function to advance timers was called but the timers APIs are not mocked ' + 'with fake timers. Call `jest.useFakeTimers({legacyFakeTimers: true})` ' + 'in this test file or enable fake timers for all tests by setting ' + "{'enableGlobally': true, 'legacyFakeTimers': true} in " + `Jest configuration file.\nStack Trace:\n${(0, _jestMessageUtil().formatStackTrace)(
|
||||
// eslint-disable-next-line unicorn/error-message
|
||||
new Error().stack, this._config, {
|
||||
noStackTrace: false
|
||||
})}`);
|
||||
}
|
||||
}
|
||||
#createMockFunction(implementation) {
|
||||
return this._moduleMocker.fn(implementation.bind(this));
|
||||
}
|
||||
_createMocks() {
|
||||
const promisifiableFakeSetTimeout = this.#createMockFunction(this._fakeSetTimeout);
|
||||
// @ts-expect-error: no index
|
||||
promisifiableFakeSetTimeout[_nodeUtil().promisify.custom] = (delay, arg) => new Promise(resolve => promisifiableFakeSetTimeout(resolve, delay, arg));
|
||||
this._fakeTimerAPIs = {
|
||||
cancelAnimationFrame: this.#createMockFunction(this._fakeClearTimer),
|
||||
clearImmediate: this.#createMockFunction(this._fakeClearImmediate),
|
||||
clearInterval: this.#createMockFunction(this._fakeClearTimer),
|
||||
clearTimeout: this.#createMockFunction(this._fakeClearTimer),
|
||||
nextTick: this.#createMockFunction(this._fakeNextTick),
|
||||
requestAnimationFrame: this.#createMockFunction(this._fakeRequestAnimationFrame),
|
||||
setImmediate: this.#createMockFunction(this._fakeSetImmediate),
|
||||
setInterval: this.#createMockFunction(this._fakeSetInterval),
|
||||
setTimeout: promisifiableFakeSetTimeout
|
||||
};
|
||||
}
|
||||
_fakeClearTimer(timerRef) {
|
||||
const uuid = this._timerConfig.refToId(timerRef);
|
||||
if (uuid) {
|
||||
this._timers.delete(String(uuid));
|
||||
}
|
||||
}
|
||||
_fakeClearImmediate(uuid) {
|
||||
this._immediates = this._immediates.filter(immediate => immediate.uuid !== uuid);
|
||||
}
|
||||
_fakeNextTick(callback, ...args) {
|
||||
if (this._disposed) {
|
||||
return;
|
||||
}
|
||||
const uuid = String(this._uuidCounter++);
|
||||
this._ticks.push({
|
||||
callback: () => callback.apply(null, args),
|
||||
uuid
|
||||
});
|
||||
const cancelledTicks = this._cancelledTicks;
|
||||
this._timerAPIs.nextTick(() => {
|
||||
if (!Object.prototype.hasOwnProperty.call(cancelledTicks, uuid)) {
|
||||
// Callback may throw, so update the map prior calling.
|
||||
cancelledTicks[uuid] = true;
|
||||
callback.apply(null, args);
|
||||
}
|
||||
});
|
||||
}
|
||||
_fakeRequestAnimationFrame(callback) {
|
||||
return this._fakeSetTimeout(() => {
|
||||
// TODO: Use performance.now() once it's mocked
|
||||
callback(this._now);
|
||||
}, 1000 / 60);
|
||||
}
|
||||
_fakeSetImmediate(callback, ...args) {
|
||||
if (this._disposed) {
|
||||
return null;
|
||||
}
|
||||
const uuid = String(this._uuidCounter++);
|
||||
this._immediates.push({
|
||||
callback: () => callback.apply(null, args),
|
||||
uuid
|
||||
});
|
||||
this._timerAPIs.setImmediate(() => {
|
||||
if (!this._disposed) {
|
||||
if (this._immediates.some(x => x.uuid === uuid)) {
|
||||
try {
|
||||
callback.apply(null, args);
|
||||
} finally {
|
||||
this._fakeClearImmediate(uuid);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
return uuid;
|
||||
}
|
||||
_fakeSetInterval(callback, intervalDelay, ...args) {
|
||||
if (this._disposed) {
|
||||
return null;
|
||||
}
|
||||
if (intervalDelay == null) {
|
||||
intervalDelay = 0;
|
||||
}
|
||||
const uuid = this._uuidCounter++;
|
||||
this._timers.set(String(uuid), {
|
||||
callback: () => callback.apply(null, args),
|
||||
expiry: this._now + intervalDelay,
|
||||
interval: intervalDelay,
|
||||
type: 'interval'
|
||||
});
|
||||
return this._timerConfig.idToRef(uuid);
|
||||
}
|
||||
_fakeSetTimeout(callback, delay, ...args) {
|
||||
if (this._disposed) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-bitwise,unicorn/prefer-math-trunc
|
||||
delay = Number(delay) | 0;
|
||||
const uuid = this._uuidCounter++;
|
||||
this._timers.set(String(uuid), {
|
||||
callback: () => callback.apply(null, args),
|
||||
expiry: this._now + delay,
|
||||
interval: undefined,
|
||||
type: 'timeout'
|
||||
});
|
||||
return this._timerConfig.idToRef(uuid);
|
||||
}
|
||||
_getNextTimerHandleAndExpiry() {
|
||||
let nextTimerHandle = null;
|
||||
let soonestTime = MS_IN_A_YEAR;
|
||||
for (const [uuid, timer] of this._timers.entries()) {
|
||||
if (timer.expiry < soonestTime) {
|
||||
soonestTime = timer.expiry;
|
||||
nextTimerHandle = uuid;
|
||||
}
|
||||
}
|
||||
if (nextTimerHandle === null) {
|
||||
return null;
|
||||
}
|
||||
return [nextTimerHandle, soonestTime];
|
||||
}
|
||||
_runTimerHandle(timerHandle) {
|
||||
const timer = this._timers.get(timerHandle);
|
||||
if (!timer) {
|
||||
// Timer has been cleared - we'll hit this when a timer is cleared within
|
||||
// another timer in runOnlyPendingTimers
|
||||
return;
|
||||
}
|
||||
switch (timer.type) {
|
||||
case 'timeout':
|
||||
this._timers.delete(timerHandle);
|
||||
timer.callback();
|
||||
break;
|
||||
case 'interval':
|
||||
timer.expiry = this._now + (timer.interval || 0);
|
||||
timer.callback();
|
||||
break;
|
||||
default:
|
||||
throw new Error(`Unexpected timer type: ${timer.type}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
exports["default"] = FakeTimers;
|
||||
|
||||
/***/ },
|
||||
|
||||
/***/ "./src/modernFakeTimers.ts"
|
||||
(__unused_webpack_module, exports) {
|
||||
|
||||
|
||||
|
||||
Object.defineProperty(exports, "__esModule", ({
|
||||
value: true
|
||||
}));
|
||||
exports["default"] = void 0;
|
||||
function _fakeTimers() {
|
||||
const data = require("@sinonjs/fake-timers");
|
||||
_fakeTimers = function () {
|
||||
return data;
|
||||
};
|
||||
return data;
|
||||
}
|
||||
function _jestMessageUtil() {
|
||||
const data = require("jest-message-util");
|
||||
_jestMessageUtil = function () {
|
||||
return data;
|
||||
};
|
||||
return data;
|
||||
}
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
class FakeTimers {
|
||||
_clock;
|
||||
_config;
|
||||
_fakingTime;
|
||||
_global;
|
||||
_fakeTimers;
|
||||
constructor({
|
||||
global,
|
||||
config
|
||||
}) {
|
||||
this._global = global;
|
||||
this._config = config;
|
||||
this._fakingTime = false;
|
||||
this._fakeTimers = (0, _fakeTimers().withGlobal)(global);
|
||||
}
|
||||
clearAllTimers() {
|
||||
if (this._fakingTime) {
|
||||
this._clock.reset();
|
||||
}
|
||||
}
|
||||
dispose() {
|
||||
this.useRealTimers();
|
||||
}
|
||||
runAllTimers() {
|
||||
if (this._checkFakeTimers()) {
|
||||
this._clock.runAll();
|
||||
}
|
||||
}
|
||||
async runAllTimersAsync() {
|
||||
if (this._checkFakeTimers()) {
|
||||
await this._clock.runAllAsync();
|
||||
}
|
||||
}
|
||||
runOnlyPendingTimers() {
|
||||
if (this._checkFakeTimers()) {
|
||||
this._clock.runToLast();
|
||||
}
|
||||
}
|
||||
async runOnlyPendingTimersAsync() {
|
||||
if (this._checkFakeTimers()) {
|
||||
await this._clock.runToLastAsync();
|
||||
}
|
||||
}
|
||||
advanceTimersToNextTimer(steps = 1) {
|
||||
if (this._checkFakeTimers()) {
|
||||
for (let i = steps; i > 0; i--) {
|
||||
this._clock.next();
|
||||
// Fire all timers at this point: https://github.com/sinonjs/fake-timers/issues/250
|
||||
this._clock.tick(0);
|
||||
if (this._clock.countTimers() === 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
async advanceTimersToNextTimerAsync(steps = 1) {
|
||||
if (this._checkFakeTimers()) {
|
||||
for (let i = steps; i > 0; i--) {
|
||||
await this._clock.nextAsync();
|
||||
// Fire all timers at this point: https://github.com/sinonjs/fake-timers/issues/250
|
||||
await this._clock.tickAsync(0);
|
||||
if (this._clock.countTimers() === 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
advanceTimersByTime(msToRun) {
|
||||
if (this._checkFakeTimers()) {
|
||||
// TODO: pass msToRun directly once https://github.com/sinonjs/fake-timers/pull/574 is published
|
||||
this._clock.tick(typeof msToRun === 'number' ? msToRun : msToRun.total({
|
||||
unit: 'millisecond'
|
||||
}));
|
||||
}
|
||||
}
|
||||
async advanceTimersByTimeAsync(msToRun) {
|
||||
if (this._checkFakeTimers()) {
|
||||
// TODO: pass msToRun directly once https://github.com/sinonjs/fake-timers/pull/574 is published
|
||||
await this._clock.tickAsync(typeof msToRun === 'number' ? msToRun : msToRun.total({
|
||||
unit: 'millisecond'
|
||||
}));
|
||||
}
|
||||
}
|
||||
advanceTimersToNextFrame() {
|
||||
if (this._checkFakeTimers()) {
|
||||
this._clock.runToFrame();
|
||||
}
|
||||
}
|
||||
runAllTicks() {
|
||||
if (this._checkFakeTimers()) {
|
||||
this._clock.runMicrotasks();
|
||||
}
|
||||
}
|
||||
useRealTimers() {
|
||||
if (this._fakingTime) {
|
||||
this._clock.uninstall();
|
||||
this._fakingTime = false;
|
||||
}
|
||||
}
|
||||
useFakeTimers(fakeTimersConfig) {
|
||||
if (this._fakingTime) {
|
||||
this._clock.uninstall();
|
||||
}
|
||||
this._clock = this._fakeTimers.install(this._toSinonFakeTimersConfig(fakeTimersConfig));
|
||||
this._fakingTime = true;
|
||||
}
|
||||
reset() {
|
||||
if (this._checkFakeTimers()) {
|
||||
const {
|
||||
now
|
||||
} = this._clock;
|
||||
this._clock.reset();
|
||||
this._clock.setSystemTime(now);
|
||||
}
|
||||
}
|
||||
setSystemTime(now) {
|
||||
if (this._checkFakeTimers()) {
|
||||
this._clock.setSystemTime(now);
|
||||
}
|
||||
}
|
||||
setTimerTickMode(tickModeConfig) {
|
||||
if (this._checkFakeTimers()) {
|
||||
this._clock.setTickMode(tickModeConfig);
|
||||
}
|
||||
}
|
||||
getRealSystemTime() {
|
||||
return Date.now();
|
||||
}
|
||||
now() {
|
||||
if (this._fakingTime) {
|
||||
return this._clock.now;
|
||||
}
|
||||
return Date.now();
|
||||
}
|
||||
getTimerCount() {
|
||||
if (this._checkFakeTimers()) {
|
||||
return this._clock.countTimers();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
_checkFakeTimers() {
|
||||
if (!this._fakingTime) {
|
||||
this._global.console.warn('A function to advance timers was called but the timers APIs are not replaced ' + 'with fake timers. Call `jest.useFakeTimers()` in this test file or enable ' + "fake timers for all tests by setting 'fakeTimers': {'enableGlobally': true} " + `in Jest configuration file.\nStack Trace:\n${(0, _jestMessageUtil().formatStackTrace)(
|
||||
// eslint-disable-next-line unicorn/error-message
|
||||
new Error().stack, this._config, {
|
||||
noStackTrace: false
|
||||
})}`);
|
||||
}
|
||||
return this._fakingTime;
|
||||
}
|
||||
_toSinonFakeTimersConfig(fakeTimersConfig = {}) {
|
||||
fakeTimersConfig = {
|
||||
...this._config.fakeTimers,
|
||||
...fakeTimersConfig
|
||||
};
|
||||
const advanceTimeDelta = typeof fakeTimersConfig.advanceTimers === 'number' ? fakeTimersConfig.advanceTimers : undefined;
|
||||
const toFake = new Set(Object.keys(this._fakeTimers.timers));
|
||||
if (fakeTimersConfig.doNotFake) for (const nameOfFakeableAPI of fakeTimersConfig.doNotFake) {
|
||||
toFake.delete(nameOfFakeableAPI);
|
||||
}
|
||||
return {
|
||||
advanceTimeDelta,
|
||||
loopLimit: fakeTimersConfig.timerLimit || 100_000,
|
||||
now: fakeTimersConfig.now ?? Date.now(),
|
||||
shouldAdvanceTime: Boolean(fakeTimersConfig.advanceTimers),
|
||||
shouldClearNativeTimers: true,
|
||||
toFake: [...toFake]
|
||||
};
|
||||
}
|
||||
}
|
||||
exports["default"] = FakeTimers;
|
||||
|
||||
/***/ }
|
||||
|
||||
/******/ });
|
||||
/************************************************************************/
|
||||
/******/ // The module cache
|
||||
/******/ const __webpack_module_cache__ = {};
|
||||
/******/
|
||||
/******/ // The require function
|
||||
/******/ function __webpack_require__(moduleId) {
|
||||
/******/ // Check if module is in cache
|
||||
/******/ const cachedModule = __webpack_module_cache__[moduleId];
|
||||
/******/ if (cachedModule !== undefined) {
|
||||
/******/ return cachedModule.exports;
|
||||
/******/ }
|
||||
/******/ // Create a new module (and put it into the cache)
|
||||
/******/ const module = __webpack_module_cache__[moduleId] = {
|
||||
/******/ // no module.id needed
|
||||
/******/ // no module.loaded needed
|
||||
/******/ exports: {}
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // Execute the module function
|
||||
/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
|
||||
/******/
|
||||
/******/ // Return the exports of the module
|
||||
/******/ return module.exports;
|
||||
/******/ }
|
||||
/******/
|
||||
/************************************************************************/
|
||||
let __webpack_exports__ = {};
|
||||
// This entry needs to be wrapped in an IIFE because it uses a non-standard name for the exports (exports).
|
||||
(() => {
|
||||
let exports = __webpack_exports__;
|
||||
|
||||
|
||||
Object.defineProperty(exports, "__esModule", ({
|
||||
value: true
|
||||
}));
|
||||
Object.defineProperty(exports, "LegacyFakeTimers", ({
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _legacyFakeTimers.default;
|
||||
}
|
||||
}));
|
||||
Object.defineProperty(exports, "ModernFakeTimers", ({
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _modernFakeTimers.default;
|
||||
}
|
||||
}));
|
||||
var _legacyFakeTimers = _interopRequireDefault(__webpack_require__("./src/legacyFakeTimers.ts"));
|
||||
var _modernFakeTimers = _interopRequireDefault(__webpack_require__("./src/modernFakeTimers.ts"));
|
||||
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
||||
})();
|
||||
|
||||
module.exports = __webpack_exports__;
|
||||
/******/ })()
|
||||
;
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
import cjsModule from './index.js';
|
||||
|
||||
export const LegacyFakeTimers = cjsModule.LegacyFakeTimers;
|
||||
export const ModernFakeTimers = cjsModule.ModernFakeTimers;
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
{
|
||||
"name": "@jest/fake-timers",
|
||||
"version": "30.5.1",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/jestjs/jest.git",
|
||||
"directory": "packages/jest-fake-timers"
|
||||
},
|
||||
"license": "MIT",
|
||||
"main": "./build/index.js",
|
||||
"types": "./build/index.d.ts",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./build/index.d.ts",
|
||||
"require": "./build/index.js",
|
||||
"import": "./build/index.mjs",
|
||||
"default": "./build/index.js"
|
||||
},
|
||||
"./package.json": "./package.json"
|
||||
},
|
||||
"dependencies": {
|
||||
"@jest/types": "30.5.1",
|
||||
"@sinonjs/fake-timers": "^15.4.0",
|
||||
"@types/node": "*",
|
||||
"jest-message-util": "30.5.1",
|
||||
"jest-mock": "30.5.1",
|
||||
"jest-util": "30.5.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@jest/test-utils": "30.5.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"gitHead": "9ab14feccd6c15fec1334dbcb03a53a079d153d3"
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
Copyright Contributors to the Jest project.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* 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 declare function getType(value: unknown): ValueType;
|
||||
|
||||
export declare const isPrimitive: (
|
||||
value: unknown,
|
||||
) => value is null | undefined | string | number | boolean | symbol | bigint;
|
||||
|
||||
declare type ValueType =
|
||||
| 'array'
|
||||
| 'bigint'
|
||||
| 'boolean'
|
||||
| 'function'
|
||||
| 'null'
|
||||
| 'number'
|
||||
| 'object'
|
||||
| 'regexp'
|
||||
| 'map'
|
||||
| 'set'
|
||||
| 'date'
|
||||
| 'string'
|
||||
| 'symbol'
|
||||
| 'undefined';
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
/*!
|
||||
* /**
|
||||
* * 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.
|
||||
* * /
|
||||
*/
|
||||
/******/ (() => { // webpackBootstrap
|
||||
/******/ "use strict";
|
||||
let __webpack_exports__ = {};
|
||||
// This entry needs to be wrapped in an IIFE because it uses a non-standard name for the exports (exports).
|
||||
(() => {
|
||||
let exports = __webpack_exports__;
|
||||
|
||||
|
||||
Object.defineProperty(exports, "__esModule", ({
|
||||
value: true
|
||||
}));
|
||||
exports.getType = getType;
|
||||
exports.isPrimitive = void 0;
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// get the type of a value with handling the edge cases like `typeof []`
|
||||
// and `typeof null`
|
||||
function getType(value) {
|
||||
if (value === undefined) {
|
||||
return 'undefined';
|
||||
} else if (value === null) {
|
||||
return 'null';
|
||||
} else if (Array.isArray(value)) {
|
||||
return 'array';
|
||||
} else if (typeof value === 'boolean') {
|
||||
return 'boolean';
|
||||
} else if (typeof value === 'function') {
|
||||
return 'function';
|
||||
} else if (typeof value === 'number') {
|
||||
return 'number';
|
||||
} else if (typeof value === 'string') {
|
||||
return 'string';
|
||||
} else if (typeof value === 'bigint') {
|
||||
return 'bigint';
|
||||
} else if (typeof value === 'object') {
|
||||
if (value.constructor === RegExp) {
|
||||
return 'regexp';
|
||||
} else if (value.constructor === Map) {
|
||||
return 'map';
|
||||
} else if (value.constructor === Set) {
|
||||
return 'set';
|
||||
} else if (value.constructor === Date) {
|
||||
return 'date';
|
||||
}
|
||||
return 'object';
|
||||
} else if (typeof value === 'symbol') {
|
||||
return 'symbol';
|
||||
}
|
||||
throw new Error(`value of unknown type: ${value}`);
|
||||
}
|
||||
const isPrimitive = value => Object(value) !== value;
|
||||
exports.isPrimitive = isPrimitive;
|
||||
})();
|
||||
|
||||
module.exports = __webpack_exports__;
|
||||
/******/ })()
|
||||
;
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
import cjsModule from './index.js';
|
||||
|
||||
export const getType = cjsModule.getType;
|
||||
export const isPrimitive = cjsModule.isPrimitive;
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"name": "@jest/get-type",
|
||||
"description": "A utility function to get the type of a value",
|
||||
"version": "30.5.0",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/jestjs/jest.git",
|
||||
"directory": "packages/jest-get-type"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
|
||||
},
|
||||
"license": "MIT",
|
||||
"main": "./build/index.js",
|
||||
"types": "./build/index.d.ts",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./build/index.d.ts",
|
||||
"require": "./build/index.js",
|
||||
"import": "./build/index.mjs",
|
||||
"default": "./build/index.js"
|
||||
},
|
||||
"./package.json": "./package.json"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"gitHead": "912baa37afaa979e8179240c238cb493f960527a"
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
Copyright Contributors to the Jest project.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
/**
|
||||
* 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 type { Jest } from '@jest/environment';
|
||||
import type { JestExpect } from '@jest/expect';
|
||||
import type { Global } from '@jest/types';
|
||||
import type { ClassLike, FunctionLike, Mock as JestMock, Mocked as JestMocked, MockedClass as JestMockedClass, MockedFunction as JestMockedFunction, MockedObject as JestMockedObject, Replaced as JestReplaced, Spied as JestSpied, SpiedClass as JestSpiedClass, SpiedFunction as JestSpiedFunction, SpiedGetter as JestSpiedGetter, SpiedSetter as JestSpiedSetter, UnknownFunction } from 'jest-mock';
|
||||
export declare const expect: JestExpect;
|
||||
export declare const it: Global.GlobalAdditions['it'];
|
||||
export declare const test: Global.GlobalAdditions['test'];
|
||||
export declare const fit: Global.GlobalAdditions['fit'];
|
||||
export declare const xit: Global.GlobalAdditions['xit'];
|
||||
export declare const xtest: Global.GlobalAdditions['xtest'];
|
||||
export declare const describe: Global.GlobalAdditions['describe'];
|
||||
export declare const xdescribe: Global.GlobalAdditions['xdescribe'];
|
||||
export declare const fdescribe: Global.GlobalAdditions['fdescribe'];
|
||||
export declare const beforeAll: Global.GlobalAdditions['beforeAll'];
|
||||
export declare const beforeEach: Global.GlobalAdditions['beforeEach'];
|
||||
export declare const afterEach: Global.GlobalAdditions['afterEach'];
|
||||
export declare const afterAll: Global.GlobalAdditions['afterAll'];
|
||||
declare const jest: Jest;
|
||||
declare namespace jest {
|
||||
/**
|
||||
* Constructs the type of a mock function, e.g. the return type of `jest.fn()`.
|
||||
*/
|
||||
type Mock<T extends FunctionLike = UnknownFunction> = JestMock<T>;
|
||||
/**
|
||||
* Wraps a class, function or object type with Jest mock type definitions.
|
||||
*/
|
||||
type Mocked<T extends object> = JestMocked<T>;
|
||||
/**
|
||||
* Wraps a class type with Jest mock type definitions.
|
||||
*/
|
||||
type MockedClass<T extends ClassLike> = JestMockedClass<T>;
|
||||
/**
|
||||
* Wraps a function type with Jest mock type definitions.
|
||||
*/
|
||||
type MockedFunction<T extends FunctionLike> = JestMockedFunction<T>;
|
||||
/**
|
||||
* Wraps an object type with Jest mock type definitions.
|
||||
*/
|
||||
type MockedObject<T extends object> = JestMockedObject<T>;
|
||||
/**
|
||||
* Constructs the type of a replaced property.
|
||||
*/
|
||||
type Replaced<T> = JestReplaced<T>;
|
||||
/**
|
||||
* Constructs the type of a spied class or function.
|
||||
*/
|
||||
type Spied<T extends ClassLike | FunctionLike> = JestSpied<T>;
|
||||
/**
|
||||
* Constructs the type of a spied class.
|
||||
*/
|
||||
type SpiedClass<T extends ClassLike> = JestSpiedClass<T>;
|
||||
/**
|
||||
* Constructs the type of a spied function.
|
||||
*/
|
||||
type SpiedFunction<T extends FunctionLike> = JestSpiedFunction<T>;
|
||||
/**
|
||||
* Constructs the type of a spied getter.
|
||||
*/
|
||||
type SpiedGetter<T> = JestSpiedGetter<T>;
|
||||
/**
|
||||
* Constructs the type of a spied setter.
|
||||
*/
|
||||
type SpiedSetter<T> = JestSpiedSetter<T>;
|
||||
}
|
||||
export { jest };
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
/*!
|
||||
* /**
|
||||
* * 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.
|
||||
* * /
|
||||
*/
|
||||
/******/ (() => { // webpackBootstrap
|
||||
/******/ "use strict";
|
||||
let __webpack_exports__ = {};
|
||||
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-namespace
|
||||
|
||||
throw new Error('Do not import `@jest/globals` outside of the Jest test environment');
|
||||
module.exports = __webpack_exports__;
|
||||
/******/ })()
|
||||
;
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"name": "@jest/globals",
|
||||
"version": "30.5.1",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/jestjs/jest.git",
|
||||
"directory": "packages/jest-globals"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
|
||||
},
|
||||
"license": "MIT",
|
||||
"main": "./build/index.js",
|
||||
"types": "./build/index.d.ts",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./build/index.d.ts",
|
||||
"default": "./build/index.js"
|
||||
},
|
||||
"./package.json": "./package.json"
|
||||
},
|
||||
"dependencies": {
|
||||
"@jest/environment": "30.5.1",
|
||||
"@jest/expect": "30.5.1",
|
||||
"@jest/types": "30.5.1",
|
||||
"jest-mock": "30.5.1"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"gitHead": "9ab14feccd6c15fec1334dbcb03a53a079d153d3"
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
Copyright Contributors to the Jest project.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
# @jest/pattern
|
||||
|
||||
`@jest/pattern` is a helper library for the jest library that implements the logic for parsing and matching patterns.
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"extends": "../../api-extractor.json",
|
||||
"mainEntryPointFilePath": "/Users/simen/repos/jest/packages/jest-pattern/build/index.d.ts",
|
||||
"projectFolder": "/Users/simen/repos/jest/packages/jest-pattern"
|
||||
}
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
/**
|
||||
* 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 declare class TestPathPatterns {
|
||||
readonly patterns: Array<string>;
|
||||
constructor(patterns: Array<string>);
|
||||
/**
|
||||
* Return true if there are any patterns.
|
||||
*/
|
||||
isSet(): boolean;
|
||||
/**
|
||||
* Return true if the patterns are valid.
|
||||
*/
|
||||
isValid(): boolean;
|
||||
/**
|
||||
* Return a human-friendly version of the pattern regex.
|
||||
*/
|
||||
toPretty(): string;
|
||||
/**
|
||||
* Return a TestPathPatternsExecutor that can execute the patterns.
|
||||
*/
|
||||
toExecutor(
|
||||
options: TestPathPatternsExecutorOptions,
|
||||
): TestPathPatternsExecutor;
|
||||
/** For jest serializers */
|
||||
toJSON(): any;
|
||||
}
|
||||
|
||||
export declare class TestPathPatternsExecutor {
|
||||
readonly patterns: TestPathPatterns;
|
||||
private readonly options;
|
||||
constructor(
|
||||
patterns: TestPathPatterns,
|
||||
options: TestPathPatternsExecutorOptions,
|
||||
);
|
||||
private toRegex;
|
||||
/**
|
||||
* Return true if there are any patterns.
|
||||
*/
|
||||
isSet(): boolean;
|
||||
/**
|
||||
* Return true if the patterns are valid.
|
||||
*/
|
||||
isValid(): boolean;
|
||||
/**
|
||||
* Return true if the given ABSOLUTE path matches the patterns.
|
||||
*
|
||||
* Throws an error if the patterns form an invalid regex (see `validate`).
|
||||
*/
|
||||
isMatch(absPath: string): boolean;
|
||||
/**
|
||||
* Return a human-friendly version of the pattern regex.
|
||||
*/
|
||||
toPretty(): string;
|
||||
}
|
||||
|
||||
export declare type TestPathPatternsExecutorOptions = {
|
||||
rootDir: string;
|
||||
};
|
||||
+214
@@ -0,0 +1,214 @@
|
||||
/*!
|
||||
* /**
|
||||
* * 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.
|
||||
* * /
|
||||
*/
|
||||
/******/ (() => { // webpackBootstrap
|
||||
/******/ "use strict";
|
||||
/******/ var __webpack_modules__ = ({
|
||||
|
||||
/***/ "./src/TestPathPatterns.ts"
|
||||
(__unused_webpack_module, exports) {
|
||||
|
||||
|
||||
|
||||
Object.defineProperty(exports, "__esModule", ({
|
||||
value: true
|
||||
}));
|
||||
exports.TestPathPatternsExecutor = exports.TestPathPatterns = void 0;
|
||||
function path() {
|
||||
const data = _interopRequireWildcard(require("path"));
|
||||
path = function () {
|
||||
return data;
|
||||
};
|
||||
return data;
|
||||
}
|
||||
function _jestRegexUtil() {
|
||||
const data = require("jest-regex-util");
|
||||
_jestRegexUtil = function () {
|
||||
return data;
|
||||
};
|
||||
return data;
|
||||
}
|
||||
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
class TestPathPatterns {
|
||||
constructor(patterns) {
|
||||
this.patterns = patterns;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if there are any patterns.
|
||||
*/
|
||||
isSet() {
|
||||
return this.patterns.length > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the patterns are valid.
|
||||
*/
|
||||
isValid() {
|
||||
return this.toExecutor({
|
||||
// isValid() doesn't require rootDir to be accurate, so just
|
||||
// specify a dummy rootDir here
|
||||
rootDir: '/'
|
||||
}).isValid();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a human-friendly version of the pattern regex.
|
||||
*/
|
||||
toPretty() {
|
||||
return this.patterns.join('|');
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a TestPathPatternsExecutor that can execute the patterns.
|
||||
*/
|
||||
toExecutor(options) {
|
||||
return new TestPathPatternsExecutor(this, options);
|
||||
}
|
||||
|
||||
/** For jest serializers */
|
||||
toJSON() {
|
||||
return {
|
||||
patterns: this.patterns,
|
||||
type: 'TestPathPatterns'
|
||||
};
|
||||
}
|
||||
}
|
||||
exports.TestPathPatterns = TestPathPatterns;
|
||||
class TestPathPatternsExecutor {
|
||||
constructor(patterns, options) {
|
||||
this.patterns = patterns;
|
||||
this.options = options;
|
||||
}
|
||||
toRegex(s) {
|
||||
return new RegExp(s, 'i');
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if there are any patterns.
|
||||
*/
|
||||
isSet() {
|
||||
return this.patterns.isSet();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the patterns are valid.
|
||||
*/
|
||||
isValid() {
|
||||
try {
|
||||
for (const p of this.patterns.patterns) {
|
||||
this.toRegex(p);
|
||||
}
|
||||
return true;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the given ABSOLUTE path matches the patterns.
|
||||
*
|
||||
* Throws an error if the patterns form an invalid regex (see `validate`).
|
||||
*/
|
||||
isMatch(absPath) {
|
||||
const relPath = path().relative(this.options.rootDir || '/', absPath);
|
||||
if (this.patterns.patterns.length === 0) {
|
||||
return true;
|
||||
}
|
||||
for (const p of this.patterns.patterns) {
|
||||
const pathToTest = path().isAbsolute(p) ? absPath : relPath;
|
||||
|
||||
// special case: ./foo.spec.js (and .\foo.spec.js on Windows) should
|
||||
// match /^foo.spec.js/ after stripping root dir
|
||||
let regexStr = p.replace(/^\.\//, '^');
|
||||
if (path().sep === '\\') {
|
||||
regexStr = regexStr.replace(/^\.\\/, '^');
|
||||
}
|
||||
regexStr = (0, _jestRegexUtil().replacePathSepForRegex)(regexStr);
|
||||
if (this.toRegex(regexStr).test(pathToTest)) {
|
||||
return true;
|
||||
}
|
||||
if (this.toRegex(regexStr).test(absPath)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a human-friendly version of the pattern regex.
|
||||
*/
|
||||
toPretty() {
|
||||
return this.patterns.toPretty();
|
||||
}
|
||||
}
|
||||
exports.TestPathPatternsExecutor = TestPathPatternsExecutor;
|
||||
|
||||
/***/ }
|
||||
|
||||
/******/ });
|
||||
/************************************************************************/
|
||||
/******/ // The module cache
|
||||
/******/ const __webpack_module_cache__ = {};
|
||||
/******/
|
||||
/******/ // The require function
|
||||
/******/ function __webpack_require__(moduleId) {
|
||||
/******/ // Check if module is in cache
|
||||
/******/ const cachedModule = __webpack_module_cache__[moduleId];
|
||||
/******/ if (cachedModule !== undefined) {
|
||||
/******/ return cachedModule.exports;
|
||||
/******/ }
|
||||
/******/ // Create a new module (and put it into the cache)
|
||||
/******/ const module = __webpack_module_cache__[moduleId] = {
|
||||
/******/ // no module.id needed
|
||||
/******/ // no module.loaded needed
|
||||
/******/ exports: {}
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // Execute the module function
|
||||
/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
|
||||
/******/
|
||||
/******/ // Return the exports of the module
|
||||
/******/ return module.exports;
|
||||
/******/ }
|
||||
/******/
|
||||
/************************************************************************/
|
||||
let __webpack_exports__ = {};
|
||||
// This entry needs to be wrapped in an IIFE because it uses a non-standard name for the exports (exports).
|
||||
(() => {
|
||||
let exports = __webpack_exports__;
|
||||
|
||||
|
||||
Object.defineProperty(exports, "__esModule", ({
|
||||
value: true
|
||||
}));
|
||||
Object.defineProperty(exports, "TestPathPatterns", ({
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _TestPathPatterns.TestPathPatterns;
|
||||
}
|
||||
}));
|
||||
Object.defineProperty(exports, "TestPathPatternsExecutor", ({
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _TestPathPatterns.TestPathPatternsExecutor;
|
||||
}
|
||||
}));
|
||||
var _TestPathPatterns = __webpack_require__("./src/TestPathPatterns.ts");
|
||||
})();
|
||||
|
||||
module.exports = __webpack_exports__;
|
||||
/******/ })()
|
||||
;
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
import cjsModule from './index.js';
|
||||
|
||||
export const TestPathPatterns = cjsModule.TestPathPatterns;
|
||||
export const TestPathPatternsExecutor = cjsModule.TestPathPatternsExecutor;
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"name": "@jest/pattern",
|
||||
"version": "30.5.0",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/jestjs/jest.git",
|
||||
"directory": "packages/jest-pattern"
|
||||
},
|
||||
"license": "MIT",
|
||||
"main": "./build/index.js",
|
||||
"types": "./build/index.d.ts",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./build/index.d.ts",
|
||||
"require": "./build/index.js",
|
||||
"import": "./build/index.mjs",
|
||||
"default": "./build/index.js"
|
||||
},
|
||||
"./package.json": "./package.json"
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/node": "*",
|
||||
"jest-regex-util": "30.5.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"gitHead": "912baa37afaa979e8179240c238cb493f960527a"
|
||||
}
|
||||
+132
@@ -0,0 +1,132 @@
|
||||
/**
|
||||
* 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 * as path from 'path';
|
||||
import {replacePathSepForRegex} from 'jest-regex-util';
|
||||
|
||||
export class TestPathPatterns {
|
||||
constructor(readonly patterns: Array<string>) {}
|
||||
|
||||
/**
|
||||
* Return true if there are any patterns.
|
||||
*/
|
||||
isSet(): boolean {
|
||||
return this.patterns.length > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the patterns are valid.
|
||||
*/
|
||||
isValid(): boolean {
|
||||
return this.toExecutor({
|
||||
// isValid() doesn't require rootDir to be accurate, so just
|
||||
// specify a dummy rootDir here
|
||||
rootDir: '/',
|
||||
}).isValid();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a human-friendly version of the pattern regex.
|
||||
*/
|
||||
toPretty(): string {
|
||||
return this.patterns.join('|');
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a TestPathPatternsExecutor that can execute the patterns.
|
||||
*/
|
||||
toExecutor(
|
||||
options: TestPathPatternsExecutorOptions,
|
||||
): TestPathPatternsExecutor {
|
||||
return new TestPathPatternsExecutor(this, options);
|
||||
}
|
||||
|
||||
/** For jest serializers */
|
||||
toJSON(): any {
|
||||
return {
|
||||
patterns: this.patterns,
|
||||
type: 'TestPathPatterns',
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export type TestPathPatternsExecutorOptions = {
|
||||
rootDir: string;
|
||||
};
|
||||
|
||||
export class TestPathPatternsExecutor {
|
||||
constructor(
|
||||
readonly patterns: TestPathPatterns,
|
||||
private readonly options: TestPathPatternsExecutorOptions,
|
||||
) {}
|
||||
|
||||
private toRegex(s: string): RegExp {
|
||||
return new RegExp(s, 'i');
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if there are any patterns.
|
||||
*/
|
||||
isSet(): boolean {
|
||||
return this.patterns.isSet();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the patterns are valid.
|
||||
*/
|
||||
isValid(): boolean {
|
||||
try {
|
||||
for (const p of this.patterns.patterns) {
|
||||
this.toRegex(p);
|
||||
}
|
||||
return true;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the given ABSOLUTE path matches the patterns.
|
||||
*
|
||||
* Throws an error if the patterns form an invalid regex (see `validate`).
|
||||
*/
|
||||
isMatch(absPath: string): boolean {
|
||||
const relPath = path.relative(this.options.rootDir || '/', absPath);
|
||||
|
||||
if (this.patterns.patterns.length === 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (const p of this.patterns.patterns) {
|
||||
const pathToTest = path.isAbsolute(p) ? absPath : relPath;
|
||||
|
||||
// special case: ./foo.spec.js (and .\foo.spec.js on Windows) should
|
||||
// match /^foo.spec.js/ after stripping root dir
|
||||
let regexStr = p.replace(/^\.\//, '^');
|
||||
if (path.sep === '\\') {
|
||||
regexStr = regexStr.replace(/^\.\\/, '^');
|
||||
}
|
||||
|
||||
regexStr = replacePathSepForRegex(regexStr);
|
||||
if (this.toRegex(regexStr).test(pathToTest)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (this.toRegex(regexStr).test(absPath)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a human-friendly version of the pattern regex.
|
||||
*/
|
||||
toPretty(): string {
|
||||
return this.patterns.toPretty();
|
||||
}
|
||||
}
|
||||
+259
@@ -0,0 +1,259 @@
|
||||
/**
|
||||
* 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 * as path from 'path';
|
||||
import {
|
||||
TestPathPatterns,
|
||||
TestPathPatternsExecutor,
|
||||
type TestPathPatternsExecutorOptions,
|
||||
} from '../TestPathPatterns';
|
||||
|
||||
const mockSep: jest.Mock<() => string> = jest.fn();
|
||||
const mockIsAbsolute: jest.Mock<(p: string) => boolean> = jest.fn();
|
||||
const mockRelative: jest.Mock<(from: string, to: string) => string> = jest.fn();
|
||||
jest.mock('path', () => {
|
||||
const actualPath = jest.requireActual('path');
|
||||
return {
|
||||
...actualPath,
|
||||
isAbsolute(p) {
|
||||
return mockIsAbsolute(p) || actualPath.isAbsolute(p);
|
||||
},
|
||||
relative(from, to) {
|
||||
return mockRelative(from, to) || actualPath.relative(from, to);
|
||||
},
|
||||
get sep() {
|
||||
return mockSep() || actualPath.sep;
|
||||
},
|
||||
} as typeof path;
|
||||
});
|
||||
const forcePosix = () => {
|
||||
mockSep.mockReturnValue(path.posix.sep);
|
||||
mockIsAbsolute.mockImplementation(path.posix.isAbsolute);
|
||||
mockRelative.mockImplementation(path.posix.relative);
|
||||
};
|
||||
const forceWindows = () => {
|
||||
mockSep.mockReturnValue(path.win32.sep);
|
||||
mockIsAbsolute.mockImplementation(path.win32.isAbsolute);
|
||||
mockRelative.mockImplementation(path.win32.relative);
|
||||
};
|
||||
beforeEach(() => {
|
||||
jest.resetAllMocks();
|
||||
forcePosix();
|
||||
});
|
||||
|
||||
const config = {rootDir: ''};
|
||||
|
||||
interface TestPathPatternsLike {
|
||||
isSet(): boolean;
|
||||
isValid(): boolean;
|
||||
toPretty(): string;
|
||||
}
|
||||
|
||||
const testPathPatternsLikeTests = (
|
||||
makePatterns: (
|
||||
patterns: Array<string>,
|
||||
options: TestPathPatternsExecutorOptions,
|
||||
) => TestPathPatternsLike,
|
||||
) => {
|
||||
describe('isSet', () => {
|
||||
it('returns false if no patterns specified', () => {
|
||||
const testPathPatterns = makePatterns([], config);
|
||||
expect(testPathPatterns.isSet()).toBe(false);
|
||||
});
|
||||
|
||||
it('returns true if patterns specified', () => {
|
||||
const testPathPatterns = makePatterns(['a'], config);
|
||||
expect(testPathPatterns.isSet()).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isValid', () => {
|
||||
it('succeeds for empty patterns', () => {
|
||||
const testPathPatterns = makePatterns([], config);
|
||||
expect(testPathPatterns.isValid()).toBe(true);
|
||||
});
|
||||
|
||||
it('succeeds for valid patterns', () => {
|
||||
const testPathPatterns = makePatterns(['abc+', 'z.*'], config);
|
||||
expect(testPathPatterns.isValid()).toBe(true);
|
||||
});
|
||||
|
||||
it('fails for at least one invalid pattern', () => {
|
||||
const testPathPatterns = makePatterns(['abc+', '(', 'z.*'], config);
|
||||
expect(testPathPatterns.isValid()).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('toPretty', () => {
|
||||
it('renders a human-readable string', () => {
|
||||
const testPathPatterns = makePatterns(['a/b', 'c/d'], config);
|
||||
expect(testPathPatterns.toPretty()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
describe('TestPathPatterns', () => {
|
||||
testPathPatternsLikeTests(
|
||||
(patterns: Array<string>, _: TestPathPatternsExecutorOptions) =>
|
||||
new TestPathPatterns(patterns),
|
||||
);
|
||||
});
|
||||
|
||||
describe('TestPathPatternsExecutor', () => {
|
||||
const makeExecutor = (
|
||||
patterns: Array<string>,
|
||||
options: TestPathPatternsExecutorOptions,
|
||||
) => new TestPathPatternsExecutor(new TestPathPatterns(patterns), options);
|
||||
|
||||
testPathPatternsLikeTests(makeExecutor);
|
||||
|
||||
describe('isMatch', () => {
|
||||
it('returns true with no patterns', () => {
|
||||
const testPathPatterns = makeExecutor([], config);
|
||||
expect(testPathPatterns.isMatch('/a/b')).toBe(true);
|
||||
});
|
||||
|
||||
it('returns true for same path', () => {
|
||||
const testPathPatterns = makeExecutor(['/a/b'], config);
|
||||
expect(testPathPatterns.isMatch('/a/b')).toBe(true);
|
||||
});
|
||||
|
||||
it('returns true for same path with case insensitive', () => {
|
||||
const testPathPatternsUpper = makeExecutor(['/A/B'], config);
|
||||
expect(testPathPatternsUpper.isMatch('/a/b')).toBe(true);
|
||||
expect(testPathPatternsUpper.isMatch('/A/B')).toBe(true);
|
||||
|
||||
const testPathPatternsLower = makeExecutor(['/a/b'], config);
|
||||
expect(testPathPatternsLower.isMatch('/A/B')).toBe(true);
|
||||
expect(testPathPatternsLower.isMatch('/a/b')).toBe(true);
|
||||
});
|
||||
|
||||
it('returns true for contained path', () => {
|
||||
const testPathPatterns = makeExecutor(['b/c'], config);
|
||||
expect(testPathPatterns.isMatch('/a/b/c/d')).toBe(true);
|
||||
});
|
||||
|
||||
it('returns true for explicit relative path', () => {
|
||||
const testPathPatterns = makeExecutor(['./b/c'], {
|
||||
rootDir: '/a',
|
||||
});
|
||||
expect(testPathPatterns.isMatch('/a/b/c')).toBe(true);
|
||||
});
|
||||
|
||||
it('returns true for explicit relative path for Windows with ./', () => {
|
||||
forceWindows();
|
||||
const testPathPatterns = makeExecutor(['./b/c'], {
|
||||
rootDir: 'C:\\a',
|
||||
});
|
||||
expect(testPathPatterns.isMatch('C:\\a\\b\\c')).toBe(true);
|
||||
});
|
||||
|
||||
it('returns true for explicit relative path for Windows with .\\', () => {
|
||||
forceWindows();
|
||||
const testPathPatterns = makeExecutor(['.\\b\\c'], {
|
||||
rootDir: 'C:\\a',
|
||||
});
|
||||
expect(testPathPatterns.isMatch('C:\\a\\b\\c')).toBe(true);
|
||||
});
|
||||
|
||||
it('returns true for partial file match', () => {
|
||||
const testPathPatterns = makeExecutor(['aaa'], config);
|
||||
expect(testPathPatterns.isMatch('/foo/..aaa..')).toBe(true);
|
||||
expect(testPathPatterns.isMatch('/foo/..aaa')).toBe(true);
|
||||
expect(testPathPatterns.isMatch('/foo/aaa..')).toBe(true);
|
||||
});
|
||||
|
||||
it('returns true for path suffix', () => {
|
||||
const testPathPatterns = makeExecutor(['c/d'], config);
|
||||
expect(testPathPatterns.isMatch('/a/b/c/d')).toBe(true);
|
||||
});
|
||||
|
||||
it('returns true if regex matches', () => {
|
||||
const testPathPatterns = makeExecutor(['ab*c?'], config);
|
||||
|
||||
expect(testPathPatterns.isMatch('/foo/a')).toBe(true);
|
||||
expect(testPathPatterns.isMatch('/foo/ab')).toBe(true);
|
||||
expect(testPathPatterns.isMatch('/foo/abb')).toBe(true);
|
||||
expect(testPathPatterns.isMatch('/foo/ac')).toBe(true);
|
||||
expect(testPathPatterns.isMatch('/foo/abc')).toBe(true);
|
||||
expect(testPathPatterns.isMatch('/foo/abbc')).toBe(true);
|
||||
|
||||
expect(testPathPatterns.isMatch('/foo/bc')).toBe(false);
|
||||
});
|
||||
|
||||
it('returns true only if matches relative path', () => {
|
||||
const rootDir = '/home/myuser/';
|
||||
|
||||
const testPathPatterns = makeExecutor(['home'], {
|
||||
rootDir,
|
||||
});
|
||||
expect(
|
||||
testPathPatterns.isMatch(
|
||||
path.relative(rootDir, '/home/myuser/LoginPage.js'),
|
||||
),
|
||||
).toBe(false);
|
||||
expect(
|
||||
testPathPatterns.isMatch(
|
||||
path.relative(rootDir, '/home/myuser/HomePage.js'),
|
||||
),
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it('matches absolute paths regardless of rootDir', () => {
|
||||
forcePosix();
|
||||
const testPathPatterns = makeExecutor(['/a/b'], {
|
||||
rootDir: '/foo/bar',
|
||||
});
|
||||
expect(testPathPatterns.isMatch('/a/b')).toBe(true);
|
||||
});
|
||||
|
||||
it('matches absolute paths for Windows', () => {
|
||||
forceWindows();
|
||||
const testPathPatterns = makeExecutor(['C:\\a\\b'], {
|
||||
rootDir: 'C:\\foo\\bar',
|
||||
});
|
||||
expect(testPathPatterns.isMatch('C:\\a\\b')).toBe(true);
|
||||
});
|
||||
|
||||
it('returns true if match any paths', () => {
|
||||
const testPathPatterns = makeExecutor(['a/b', 'c/d'], config);
|
||||
|
||||
expect(testPathPatterns.isMatch('/foo/a/b')).toBe(true);
|
||||
expect(testPathPatterns.isMatch('/foo/c/d')).toBe(true);
|
||||
|
||||
expect(testPathPatterns.isMatch('/foo/a')).toBe(false);
|
||||
expect(testPathPatterns.isMatch('/foo/b/c')).toBe(false);
|
||||
});
|
||||
|
||||
it('does not normalize Windows paths on POSIX', () => {
|
||||
forcePosix();
|
||||
const testPathPatterns = makeExecutor(['a\\z', 'a\\\\z'], config);
|
||||
expect(testPathPatterns.isMatch('/foo/a/z')).toBe(false);
|
||||
});
|
||||
|
||||
it('normalizes paths for Windows', () => {
|
||||
forceWindows();
|
||||
const testPathPatterns = makeExecutor(['a/b'], config);
|
||||
expect(testPathPatterns.isMatch('C:\\foo\\a\\b')).toBe(true);
|
||||
});
|
||||
|
||||
it('matches absolute path with absPath', () => {
|
||||
const pattern = '^/home/app/';
|
||||
const rootDir = '/home/app';
|
||||
const absolutePath = '/home/app/packages/';
|
||||
|
||||
const testPathPatterns = makeExecutor([pattern], {
|
||||
rootDir,
|
||||
});
|
||||
|
||||
const relativePath = path.relative(rootDir, absolutePath);
|
||||
|
||||
expect(testPathPatterns.isMatch(relativePath)).toBe(false);
|
||||
expect(testPathPatterns.isMatch(absolutePath)).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
Generated
Vendored
+5
@@ -0,0 +1,5 @@
|
||||
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
|
||||
|
||||
exports[`TestPathPatterns toPretty renders a human-readable string 1`] = `"a/b|c/d"`;
|
||||
|
||||
exports[`TestPathPatternsExecutor toPretty renders a human-readable string 1`] = `"a/b|c/d"`;
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
/**
|
||||
* 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 {
|
||||
TestPathPatterns,
|
||||
TestPathPatternsExecutor,
|
||||
type TestPathPatternsExecutorOptions,
|
||||
} from './TestPathPatterns';
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"rootDir": "src",
|
||||
"outDir": "build"
|
||||
},
|
||||
"include": ["./src/**/*"],
|
||||
"exclude": ["./**/__tests__/**/*"],
|
||||
"references": [{"path": "../jest-regex-util"}]
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) Facebook, Inc. and its affiliates.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
+104
@@ -0,0 +1,104 @@
|
||||
# `react-is`
|
||||
|
||||
This package allows you to test arbitrary values and see if they're a particular React element type.
|
||||
|
||||
## Installation
|
||||
|
||||
```sh
|
||||
# Yarn
|
||||
yarn add react-is
|
||||
|
||||
# NPM
|
||||
npm install react-is
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### Determining if a Component is Valid
|
||||
|
||||
```js
|
||||
import React from "react";
|
||||
import * as ReactIs from "react-is";
|
||||
|
||||
class ClassComponent extends React.Component {
|
||||
render() {
|
||||
return React.createElement("div");
|
||||
}
|
||||
}
|
||||
|
||||
const FunctionComponent = () => React.createElement("div");
|
||||
|
||||
const ForwardRefComponent = React.forwardRef((props, ref) =>
|
||||
React.createElement(Component, { forwardedRef: ref, ...props })
|
||||
);
|
||||
|
||||
const Context = React.createContext(false);
|
||||
|
||||
ReactIs.isValidElementType("div"); // true
|
||||
ReactIs.isValidElementType(ClassComponent); // true
|
||||
ReactIs.isValidElementType(FunctionComponent); // true
|
||||
ReactIs.isValidElementType(ForwardRefComponent); // true
|
||||
ReactIs.isValidElementType(Context.Provider); // true
|
||||
ReactIs.isValidElementType(Context.Consumer); // true
|
||||
ReactIs.isValidElementType(React.createFactory("div")); // true
|
||||
```
|
||||
|
||||
### Determining an Element's Type
|
||||
|
||||
#### Context
|
||||
|
||||
```js
|
||||
import React from "react";
|
||||
import * as ReactIs from 'react-is';
|
||||
|
||||
const ThemeContext = React.createContext("blue");
|
||||
|
||||
ReactIs.isContextConsumer(<ThemeContext.Consumer />); // true
|
||||
ReactIs.isContextProvider(<ThemeContext.Provider />); // true
|
||||
ReactIs.typeOf(<ThemeContext.Provider />) === ReactIs.ContextProvider; // true
|
||||
ReactIs.typeOf(<ThemeContext.Consumer />) === ReactIs.ContextConsumer; // true
|
||||
```
|
||||
|
||||
#### Element
|
||||
|
||||
```js
|
||||
import React from "react";
|
||||
import * as ReactIs from 'react-is';
|
||||
|
||||
ReactIs.isElement(<div />); // true
|
||||
ReactIs.typeOf(<div />) === ReactIs.Element; // true
|
||||
```
|
||||
|
||||
#### Fragment
|
||||
|
||||
```js
|
||||
import React from "react";
|
||||
import * as ReactIs from 'react-is';
|
||||
|
||||
ReactIs.isFragment(<></>); // true
|
||||
ReactIs.typeOf(<></>) === ReactIs.Fragment; // true
|
||||
```
|
||||
|
||||
#### Portal
|
||||
|
||||
```js
|
||||
import React from "react";
|
||||
import ReactDOM from "react-dom";
|
||||
import * as ReactIs from 'react-is';
|
||||
|
||||
const div = document.createElement("div");
|
||||
const portal = ReactDOM.createPortal(<div />, div);
|
||||
|
||||
ReactIs.isPortal(portal); // true
|
||||
ReactIs.typeOf(portal) === ReactIs.Portal; // true
|
||||
```
|
||||
|
||||
#### StrictMode
|
||||
|
||||
```js
|
||||
import React from "react";
|
||||
import * as ReactIs from 'react-is';
|
||||
|
||||
ReactIs.isStrictMode(<React.StrictMode />); // true
|
||||
ReactIs.typeOf(<React.StrictMode />) === ReactIs.StrictMode; // true
|
||||
```
|
||||
+221
@@ -0,0 +1,221 @@
|
||||
/**
|
||||
* @license React
|
||||
* react-is.development.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
if (process.env.NODE_ENV !== "production") {
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
// ATTENTION
|
||||
// When adding new symbols to this file,
|
||||
// Please consider also adding to 'react-devtools-shared/src/backend/ReactSymbols'
|
||||
// The Symbol used to tag the ReactElement-like types.
|
||||
var REACT_ELEMENT_TYPE = Symbol.for('react.element');
|
||||
var REACT_PORTAL_TYPE = Symbol.for('react.portal');
|
||||
var REACT_FRAGMENT_TYPE = Symbol.for('react.fragment');
|
||||
var REACT_STRICT_MODE_TYPE = Symbol.for('react.strict_mode');
|
||||
var REACT_PROFILER_TYPE = Symbol.for('react.profiler');
|
||||
var REACT_PROVIDER_TYPE = Symbol.for('react.provider');
|
||||
var REACT_CONTEXT_TYPE = Symbol.for('react.context');
|
||||
var REACT_SERVER_CONTEXT_TYPE = Symbol.for('react.server_context');
|
||||
var REACT_FORWARD_REF_TYPE = Symbol.for('react.forward_ref');
|
||||
var REACT_SUSPENSE_TYPE = Symbol.for('react.suspense');
|
||||
var REACT_SUSPENSE_LIST_TYPE = Symbol.for('react.suspense_list');
|
||||
var REACT_MEMO_TYPE = Symbol.for('react.memo');
|
||||
var REACT_LAZY_TYPE = Symbol.for('react.lazy');
|
||||
var REACT_OFFSCREEN_TYPE = Symbol.for('react.offscreen');
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
var enableScopeAPI = false; // Experimental Create Event Handle API.
|
||||
var enableCacheElement = false;
|
||||
var enableTransitionTracing = false; // No known bugs, but needs performance testing
|
||||
|
||||
var enableLegacyHidden = false; // Enables unstable_avoidThisFallback feature in Fiber
|
||||
// stuff. Intended to enable React core members to more easily debug scheduling
|
||||
// issues in DEV builds.
|
||||
|
||||
var enableDebugTracing = false; // Track which Fiber(s) schedule render work.
|
||||
|
||||
var REACT_MODULE_REFERENCE;
|
||||
|
||||
{
|
||||
REACT_MODULE_REFERENCE = Symbol.for('react.module.reference');
|
||||
}
|
||||
|
||||
function isValidElementType(type) {
|
||||
if (typeof type === 'string' || typeof type === 'function') {
|
||||
return true;
|
||||
} // Note: typeof might be other than 'symbol' or 'number' (e.g. if it's a polyfill).
|
||||
|
||||
|
||||
if (type === REACT_FRAGMENT_TYPE || type === REACT_PROFILER_TYPE || enableDebugTracing || type === REACT_STRICT_MODE_TYPE || type === REACT_SUSPENSE_TYPE || type === REACT_SUSPENSE_LIST_TYPE || enableLegacyHidden || type === REACT_OFFSCREEN_TYPE || enableScopeAPI || enableCacheElement || enableTransitionTracing ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (typeof type === 'object' && type !== null) {
|
||||
if (type.$$typeof === REACT_LAZY_TYPE || type.$$typeof === REACT_MEMO_TYPE || type.$$typeof === REACT_PROVIDER_TYPE || type.$$typeof === REACT_CONTEXT_TYPE || type.$$typeof === REACT_FORWARD_REF_TYPE || // This needs to include all possible module reference object
|
||||
// types supported by any Flight configuration anywhere since
|
||||
// we don't know which Flight build this will end up being used
|
||||
// with.
|
||||
type.$$typeof === REACT_MODULE_REFERENCE || type.getModuleId !== undefined) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function typeOf(object) {
|
||||
if (typeof object === 'object' && object !== null) {
|
||||
var $$typeof = object.$$typeof;
|
||||
|
||||
switch ($$typeof) {
|
||||
case REACT_ELEMENT_TYPE:
|
||||
var type = object.type;
|
||||
|
||||
switch (type) {
|
||||
case REACT_FRAGMENT_TYPE:
|
||||
case REACT_PROFILER_TYPE:
|
||||
case REACT_STRICT_MODE_TYPE:
|
||||
case REACT_SUSPENSE_TYPE:
|
||||
case REACT_SUSPENSE_LIST_TYPE:
|
||||
return type;
|
||||
|
||||
default:
|
||||
var $$typeofType = type && type.$$typeof;
|
||||
|
||||
switch ($$typeofType) {
|
||||
case REACT_SERVER_CONTEXT_TYPE:
|
||||
case REACT_CONTEXT_TYPE:
|
||||
case REACT_FORWARD_REF_TYPE:
|
||||
case REACT_LAZY_TYPE:
|
||||
case REACT_MEMO_TYPE:
|
||||
case REACT_PROVIDER_TYPE:
|
||||
return $$typeofType;
|
||||
|
||||
default:
|
||||
return $$typeof;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
case REACT_PORTAL_TYPE:
|
||||
return $$typeof;
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
var ContextConsumer = REACT_CONTEXT_TYPE;
|
||||
var ContextProvider = REACT_PROVIDER_TYPE;
|
||||
var Element = REACT_ELEMENT_TYPE;
|
||||
var ForwardRef = REACT_FORWARD_REF_TYPE;
|
||||
var Fragment = REACT_FRAGMENT_TYPE;
|
||||
var Lazy = REACT_LAZY_TYPE;
|
||||
var Memo = REACT_MEMO_TYPE;
|
||||
var Portal = REACT_PORTAL_TYPE;
|
||||
var Profiler = REACT_PROFILER_TYPE;
|
||||
var StrictMode = REACT_STRICT_MODE_TYPE;
|
||||
var Suspense = REACT_SUSPENSE_TYPE;
|
||||
var SuspenseList = REACT_SUSPENSE_LIST_TYPE;
|
||||
var hasWarnedAboutDeprecatedIsAsyncMode = false;
|
||||
var hasWarnedAboutDeprecatedIsConcurrentMode = false; // AsyncMode should be deprecated
|
||||
|
||||
function isAsyncMode(object) {
|
||||
{
|
||||
if (!hasWarnedAboutDeprecatedIsAsyncMode) {
|
||||
hasWarnedAboutDeprecatedIsAsyncMode = true; // Using console['warn'] to evade Babel and ESLint
|
||||
|
||||
console['warn']('The ReactIs.isAsyncMode() alias has been deprecated, ' + 'and will be removed in React 18+.');
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
function isConcurrentMode(object) {
|
||||
{
|
||||
if (!hasWarnedAboutDeprecatedIsConcurrentMode) {
|
||||
hasWarnedAboutDeprecatedIsConcurrentMode = true; // Using console['warn'] to evade Babel and ESLint
|
||||
|
||||
console['warn']('The ReactIs.isConcurrentMode() alias has been deprecated, ' + 'and will be removed in React 18+.');
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
function isContextConsumer(object) {
|
||||
return typeOf(object) === REACT_CONTEXT_TYPE;
|
||||
}
|
||||
function isContextProvider(object) {
|
||||
return typeOf(object) === REACT_PROVIDER_TYPE;
|
||||
}
|
||||
function isElement(object) {
|
||||
return typeof object === 'object' && object !== null && object.$$typeof === REACT_ELEMENT_TYPE;
|
||||
}
|
||||
function isForwardRef(object) {
|
||||
return typeOf(object) === REACT_FORWARD_REF_TYPE;
|
||||
}
|
||||
function isFragment(object) {
|
||||
return typeOf(object) === REACT_FRAGMENT_TYPE;
|
||||
}
|
||||
function isLazy(object) {
|
||||
return typeOf(object) === REACT_LAZY_TYPE;
|
||||
}
|
||||
function isMemo(object) {
|
||||
return typeOf(object) === REACT_MEMO_TYPE;
|
||||
}
|
||||
function isPortal(object) {
|
||||
return typeOf(object) === REACT_PORTAL_TYPE;
|
||||
}
|
||||
function isProfiler(object) {
|
||||
return typeOf(object) === REACT_PROFILER_TYPE;
|
||||
}
|
||||
function isStrictMode(object) {
|
||||
return typeOf(object) === REACT_STRICT_MODE_TYPE;
|
||||
}
|
||||
function isSuspense(object) {
|
||||
return typeOf(object) === REACT_SUSPENSE_TYPE;
|
||||
}
|
||||
function isSuspenseList(object) {
|
||||
return typeOf(object) === REACT_SUSPENSE_LIST_TYPE;
|
||||
}
|
||||
|
||||
exports.ContextConsumer = ContextConsumer;
|
||||
exports.ContextProvider = ContextProvider;
|
||||
exports.Element = Element;
|
||||
exports.ForwardRef = ForwardRef;
|
||||
exports.Fragment = Fragment;
|
||||
exports.Lazy = Lazy;
|
||||
exports.Memo = Memo;
|
||||
exports.Portal = Portal;
|
||||
exports.Profiler = Profiler;
|
||||
exports.StrictMode = StrictMode;
|
||||
exports.Suspense = Suspense;
|
||||
exports.SuspenseList = SuspenseList;
|
||||
exports.isAsyncMode = isAsyncMode;
|
||||
exports.isConcurrentMode = isConcurrentMode;
|
||||
exports.isContextConsumer = isContextConsumer;
|
||||
exports.isContextProvider = isContextProvider;
|
||||
exports.isElement = isElement;
|
||||
exports.isForwardRef = isForwardRef;
|
||||
exports.isFragment = isFragment;
|
||||
exports.isLazy = isLazy;
|
||||
exports.isMemo = isMemo;
|
||||
exports.isPortal = isPortal;
|
||||
exports.isProfiler = isProfiler;
|
||||
exports.isStrictMode = isStrictMode;
|
||||
exports.isSuspense = isSuspense;
|
||||
exports.isSuspenseList = isSuspenseList;
|
||||
exports.isValidElementType = isValidElementType;
|
||||
exports.typeOf = typeOf;
|
||||
})();
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
/**
|
||||
* @license React
|
||||
* react-is.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
'use strict';var b=Symbol.for("react.element"),c=Symbol.for("react.portal"),d=Symbol.for("react.fragment"),e=Symbol.for("react.strict_mode"),f=Symbol.for("react.profiler"),g=Symbol.for("react.provider"),h=Symbol.for("react.context"),k=Symbol.for("react.server_context"),l=Symbol.for("react.forward_ref"),m=Symbol.for("react.suspense"),n=Symbol.for("react.suspense_list"),p=Symbol.for("react.memo"),q=Symbol.for("react.lazy"),t=Symbol.for("react.offscreen"),u;u=Symbol.for("react.module.reference");
|
||||
function v(a){if("object"===typeof a&&null!==a){var r=a.$$typeof;switch(r){case b:switch(a=a.type,a){case d:case f:case e:case m:case n:return a;default:switch(a=a&&a.$$typeof,a){case k:case h:case l:case q:case p:case g:return a;default:return r}}case c:return r}}}exports.ContextConsumer=h;exports.ContextProvider=g;exports.Element=b;exports.ForwardRef=l;exports.Fragment=d;exports.Lazy=q;exports.Memo=p;exports.Portal=c;exports.Profiler=f;exports.StrictMode=e;exports.Suspense=m;
|
||||
exports.SuspenseList=n;exports.isAsyncMode=function(){return!1};exports.isConcurrentMode=function(){return!1};exports.isContextConsumer=function(a){return v(a)===h};exports.isContextProvider=function(a){return v(a)===g};exports.isElement=function(a){return"object"===typeof a&&null!==a&&a.$$typeof===b};exports.isForwardRef=function(a){return v(a)===l};exports.isFragment=function(a){return v(a)===d};exports.isLazy=function(a){return v(a)===q};exports.isMemo=function(a){return v(a)===p};
|
||||
exports.isPortal=function(a){return v(a)===c};exports.isProfiler=function(a){return v(a)===f};exports.isStrictMode=function(a){return v(a)===e};exports.isSuspense=function(a){return v(a)===m};exports.isSuspenseList=function(a){return v(a)===n};
|
||||
exports.isValidElementType=function(a){return"string"===typeof a||"function"===typeof a||a===d||a===f||a===e||a===m||a===n||a===t||"object"===typeof a&&null!==a&&(a.$$typeof===q||a.$$typeof===p||a.$$typeof===g||a.$$typeof===h||a.$$typeof===l||a.$$typeof===u||void 0!==a.getModuleId)?!0:!1};exports.typeOf=v;
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
if (process.env.NODE_ENV === 'production') {
|
||||
module.exports = require('./cjs/react-is.production.min.js');
|
||||
} else {
|
||||
module.exports = require('./cjs/react-is.development.js');
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"name": "react-is",
|
||||
"version": "18.3.1",
|
||||
"description": "Brand checking of React Elements.",
|
||||
"main": "index.js",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/facebook/react.git",
|
||||
"directory": "packages/react-is"
|
||||
},
|
||||
"keywords": [
|
||||
"react"
|
||||
],
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/facebook/react/issues"
|
||||
},
|
||||
"homepage": "https://reactjs.org/",
|
||||
"files": [
|
||||
"LICENSE",
|
||||
"README.md",
|
||||
"index.js",
|
||||
"cjs/",
|
||||
"umd/"
|
||||
]
|
||||
}
|
||||
+220
@@ -0,0 +1,220 @@
|
||||
/**
|
||||
* @license React
|
||||
* react-is.development.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
(function (global, factory) {
|
||||
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
|
||||
typeof define === 'function' && define.amd ? define(['exports'], factory) :
|
||||
(global = global || self, factory(global.ReactIs = {}));
|
||||
}(this, (function (exports) { 'use strict';
|
||||
|
||||
// ATTENTION
|
||||
// When adding new symbols to this file,
|
||||
// Please consider also adding to 'react-devtools-shared/src/backend/ReactSymbols'
|
||||
// The Symbol used to tag the ReactElement-like types.
|
||||
var REACT_ELEMENT_TYPE = Symbol.for('react.element');
|
||||
var REACT_PORTAL_TYPE = Symbol.for('react.portal');
|
||||
var REACT_FRAGMENT_TYPE = Symbol.for('react.fragment');
|
||||
var REACT_STRICT_MODE_TYPE = Symbol.for('react.strict_mode');
|
||||
var REACT_PROFILER_TYPE = Symbol.for('react.profiler');
|
||||
var REACT_PROVIDER_TYPE = Symbol.for('react.provider');
|
||||
var REACT_CONTEXT_TYPE = Symbol.for('react.context');
|
||||
var REACT_SERVER_CONTEXT_TYPE = Symbol.for('react.server_context');
|
||||
var REACT_FORWARD_REF_TYPE = Symbol.for('react.forward_ref');
|
||||
var REACT_SUSPENSE_TYPE = Symbol.for('react.suspense');
|
||||
var REACT_SUSPENSE_LIST_TYPE = Symbol.for('react.suspense_list');
|
||||
var REACT_MEMO_TYPE = Symbol.for('react.memo');
|
||||
var REACT_LAZY_TYPE = Symbol.for('react.lazy');
|
||||
var REACT_OFFSCREEN_TYPE = Symbol.for('react.offscreen');
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
var enableScopeAPI = false; // Experimental Create Event Handle API.
|
||||
var enableCacheElement = false;
|
||||
var enableTransitionTracing = false; // No known bugs, but needs performance testing
|
||||
|
||||
var enableLegacyHidden = false; // Enables unstable_avoidThisFallback feature in Fiber
|
||||
// stuff. Intended to enable React core members to more easily debug scheduling
|
||||
// issues in DEV builds.
|
||||
|
||||
var enableDebugTracing = false; // Track which Fiber(s) schedule render work.
|
||||
|
||||
var REACT_MODULE_REFERENCE;
|
||||
|
||||
{
|
||||
REACT_MODULE_REFERENCE = Symbol.for('react.module.reference');
|
||||
}
|
||||
|
||||
function isValidElementType(type) {
|
||||
if (typeof type === 'string' || typeof type === 'function') {
|
||||
return true;
|
||||
} // Note: typeof might be other than 'symbol' or 'number' (e.g. if it's a polyfill).
|
||||
|
||||
|
||||
if (type === REACT_FRAGMENT_TYPE || type === REACT_PROFILER_TYPE || enableDebugTracing || type === REACT_STRICT_MODE_TYPE || type === REACT_SUSPENSE_TYPE || type === REACT_SUSPENSE_LIST_TYPE || enableLegacyHidden || type === REACT_OFFSCREEN_TYPE || enableScopeAPI || enableCacheElement || enableTransitionTracing ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (typeof type === 'object' && type !== null) {
|
||||
if (type.$$typeof === REACT_LAZY_TYPE || type.$$typeof === REACT_MEMO_TYPE || type.$$typeof === REACT_PROVIDER_TYPE || type.$$typeof === REACT_CONTEXT_TYPE || type.$$typeof === REACT_FORWARD_REF_TYPE || // This needs to include all possible module reference object
|
||||
// types supported by any Flight configuration anywhere since
|
||||
// we don't know which Flight build this will end up being used
|
||||
// with.
|
||||
type.$$typeof === REACT_MODULE_REFERENCE || type.getModuleId !== undefined) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function typeOf(object) {
|
||||
if (typeof object === 'object' && object !== null) {
|
||||
var $$typeof = object.$$typeof;
|
||||
|
||||
switch ($$typeof) {
|
||||
case REACT_ELEMENT_TYPE:
|
||||
var type = object.type;
|
||||
|
||||
switch (type) {
|
||||
case REACT_FRAGMENT_TYPE:
|
||||
case REACT_PROFILER_TYPE:
|
||||
case REACT_STRICT_MODE_TYPE:
|
||||
case REACT_SUSPENSE_TYPE:
|
||||
case REACT_SUSPENSE_LIST_TYPE:
|
||||
return type;
|
||||
|
||||
default:
|
||||
var $$typeofType = type && type.$$typeof;
|
||||
|
||||
switch ($$typeofType) {
|
||||
case REACT_SERVER_CONTEXT_TYPE:
|
||||
case REACT_CONTEXT_TYPE:
|
||||
case REACT_FORWARD_REF_TYPE:
|
||||
case REACT_LAZY_TYPE:
|
||||
case REACT_MEMO_TYPE:
|
||||
case REACT_PROVIDER_TYPE:
|
||||
return $$typeofType;
|
||||
|
||||
default:
|
||||
return $$typeof;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
case REACT_PORTAL_TYPE:
|
||||
return $$typeof;
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
var ContextConsumer = REACT_CONTEXT_TYPE;
|
||||
var ContextProvider = REACT_PROVIDER_TYPE;
|
||||
var Element = REACT_ELEMENT_TYPE;
|
||||
var ForwardRef = REACT_FORWARD_REF_TYPE;
|
||||
var Fragment = REACT_FRAGMENT_TYPE;
|
||||
var Lazy = REACT_LAZY_TYPE;
|
||||
var Memo = REACT_MEMO_TYPE;
|
||||
var Portal = REACT_PORTAL_TYPE;
|
||||
var Profiler = REACT_PROFILER_TYPE;
|
||||
var StrictMode = REACT_STRICT_MODE_TYPE;
|
||||
var Suspense = REACT_SUSPENSE_TYPE;
|
||||
var SuspenseList = REACT_SUSPENSE_LIST_TYPE;
|
||||
var hasWarnedAboutDeprecatedIsAsyncMode = false;
|
||||
var hasWarnedAboutDeprecatedIsConcurrentMode = false; // AsyncMode should be deprecated
|
||||
|
||||
function isAsyncMode(object) {
|
||||
{
|
||||
if (!hasWarnedAboutDeprecatedIsAsyncMode) {
|
||||
hasWarnedAboutDeprecatedIsAsyncMode = true; // Using console['warn'] to evade Babel and ESLint
|
||||
|
||||
console['warn']('The ReactIs.isAsyncMode() alias has been deprecated, ' + 'and will be removed in React 18+.');
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
function isConcurrentMode(object) {
|
||||
{
|
||||
if (!hasWarnedAboutDeprecatedIsConcurrentMode) {
|
||||
hasWarnedAboutDeprecatedIsConcurrentMode = true; // Using console['warn'] to evade Babel and ESLint
|
||||
|
||||
console['warn']('The ReactIs.isConcurrentMode() alias has been deprecated, ' + 'and will be removed in React 18+.');
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
function isContextConsumer(object) {
|
||||
return typeOf(object) === REACT_CONTEXT_TYPE;
|
||||
}
|
||||
function isContextProvider(object) {
|
||||
return typeOf(object) === REACT_PROVIDER_TYPE;
|
||||
}
|
||||
function isElement(object) {
|
||||
return typeof object === 'object' && object !== null && object.$$typeof === REACT_ELEMENT_TYPE;
|
||||
}
|
||||
function isForwardRef(object) {
|
||||
return typeOf(object) === REACT_FORWARD_REF_TYPE;
|
||||
}
|
||||
function isFragment(object) {
|
||||
return typeOf(object) === REACT_FRAGMENT_TYPE;
|
||||
}
|
||||
function isLazy(object) {
|
||||
return typeOf(object) === REACT_LAZY_TYPE;
|
||||
}
|
||||
function isMemo(object) {
|
||||
return typeOf(object) === REACT_MEMO_TYPE;
|
||||
}
|
||||
function isPortal(object) {
|
||||
return typeOf(object) === REACT_PORTAL_TYPE;
|
||||
}
|
||||
function isProfiler(object) {
|
||||
return typeOf(object) === REACT_PROFILER_TYPE;
|
||||
}
|
||||
function isStrictMode(object) {
|
||||
return typeOf(object) === REACT_STRICT_MODE_TYPE;
|
||||
}
|
||||
function isSuspense(object) {
|
||||
return typeOf(object) === REACT_SUSPENSE_TYPE;
|
||||
}
|
||||
function isSuspenseList(object) {
|
||||
return typeOf(object) === REACT_SUSPENSE_LIST_TYPE;
|
||||
}
|
||||
|
||||
exports.ContextConsumer = ContextConsumer;
|
||||
exports.ContextProvider = ContextProvider;
|
||||
exports.Element = Element;
|
||||
exports.ForwardRef = ForwardRef;
|
||||
exports.Fragment = Fragment;
|
||||
exports.Lazy = Lazy;
|
||||
exports.Memo = Memo;
|
||||
exports.Portal = Portal;
|
||||
exports.Profiler = Profiler;
|
||||
exports.StrictMode = StrictMode;
|
||||
exports.Suspense = Suspense;
|
||||
exports.SuspenseList = SuspenseList;
|
||||
exports.isAsyncMode = isAsyncMode;
|
||||
exports.isConcurrentMode = isConcurrentMode;
|
||||
exports.isContextConsumer = isContextConsumer;
|
||||
exports.isContextProvider = isContextProvider;
|
||||
exports.isElement = isElement;
|
||||
exports.isForwardRef = isForwardRef;
|
||||
exports.isFragment = isFragment;
|
||||
exports.isLazy = isLazy;
|
||||
exports.isMemo = isMemo;
|
||||
exports.isPortal = isPortal;
|
||||
exports.isProfiler = isProfiler;
|
||||
exports.isStrictMode = isStrictMode;
|
||||
exports.isSuspense = isSuspense;
|
||||
exports.isSuspenseList = isSuspenseList;
|
||||
exports.isValidElementType = isValidElementType;
|
||||
exports.typeOf = typeOf;
|
||||
|
||||
})));
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
/**
|
||||
* @license React
|
||||
* react-is.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
(function(){'use strict';(function(b,c){"object"===typeof exports&&"undefined"!==typeof module?c(exports):"function"===typeof define&&define.amd?define(["exports"],c):(b=b||self,c(b.ReactIs={}))})(this,function(b){function c(a){if("object"===typeof a&&null!==a){var b=a.$$typeof;switch(b){case q:switch(a=a.type,a){case d:case e:case f:case g:case h:return a;default:switch(a=a&&a.$$typeof,a){case t:case k:case l:case m:case n:case p:return a;default:return b}}case r:return b}}}var q=Symbol.for("react.element"),
|
||||
r=Symbol.for("react.portal"),d=Symbol.for("react.fragment"),f=Symbol.for("react.strict_mode"),e=Symbol.for("react.profiler"),p=Symbol.for("react.provider"),k=Symbol.for("react.context"),t=Symbol.for("react.server_context"),l=Symbol.for("react.forward_ref"),g=Symbol.for("react.suspense"),h=Symbol.for("react.suspense_list"),n=Symbol.for("react.memo"),m=Symbol.for("react.lazy"),u=Symbol.for("react.offscreen");var v=Symbol.for("react.module.reference");b.ContextConsumer=k;b.ContextProvider=p;b.Element=
|
||||
q;b.ForwardRef=l;b.Fragment=d;b.Lazy=m;b.Memo=n;b.Portal=r;b.Profiler=e;b.StrictMode=f;b.Suspense=g;b.SuspenseList=h;b.isAsyncMode=function(a){return!1};b.isConcurrentMode=function(a){return!1};b.isContextConsumer=function(a){return c(a)===k};b.isContextProvider=function(a){return c(a)===p};b.isElement=function(a){return"object"===typeof a&&null!==a&&a.$$typeof===q};b.isForwardRef=function(a){return c(a)===l};b.isFragment=function(a){return c(a)===d};b.isLazy=function(a){return c(a)===m};b.isMemo=
|
||||
function(a){return c(a)===n};b.isPortal=function(a){return c(a)===r};b.isProfiler=function(a){return c(a)===e};b.isStrictMode=function(a){return c(a)===f};b.isSuspense=function(a){return c(a)===g};b.isSuspenseList=function(a){return c(a)===h};b.isValidElementType=function(a){return"string"===typeof a||"function"===typeof a||a===d||a===e||a===f||a===g||a===h||a===u||"object"===typeof a&&null!==a&&(a.$$typeof===m||a.$$typeof===n||a.$$typeof===p||a.$$typeof===k||a.$$typeof===l||a.$$typeof===v||void 0!==
|
||||
a.getModuleId)?!0:!1};b.typeOf=c});
|
||||
})();
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
+103
@@ -0,0 +1,103 @@
|
||||
# `react-is`
|
||||
|
||||
This package allows you to test arbitrary values and see if they're a particular React element type.
|
||||
|
||||
## Installation
|
||||
|
||||
```sh
|
||||
# Yarn
|
||||
yarn add react-is
|
||||
|
||||
# NPM
|
||||
npm install react-is
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### Determining if a Component is Valid
|
||||
|
||||
```js
|
||||
import React from "react";
|
||||
import * as ReactIs from "react-is";
|
||||
|
||||
class ClassComponent extends React.Component {
|
||||
render() {
|
||||
return React.createElement("div");
|
||||
}
|
||||
}
|
||||
|
||||
const FunctionComponent = () => React.createElement("div");
|
||||
|
||||
const ForwardRefComponent = React.forwardRef((props, ref) =>
|
||||
React.createElement(Component, { forwardedRef: ref, ...props })
|
||||
);
|
||||
|
||||
const Context = React.createContext(false);
|
||||
|
||||
ReactIs.isValidElementType("div"); // true
|
||||
ReactIs.isValidElementType(ClassComponent); // true
|
||||
ReactIs.isValidElementType(FunctionComponent); // true
|
||||
ReactIs.isValidElementType(ForwardRefComponent); // true
|
||||
ReactIs.isValidElementType(Context.Provider); // true
|
||||
ReactIs.isValidElementType(Context.Consumer); // true
|
||||
```
|
||||
|
||||
### Determining an Element's Type
|
||||
|
||||
#### Context
|
||||
|
||||
```js
|
||||
import React from "react";
|
||||
import * as ReactIs from 'react-is';
|
||||
|
||||
const ThemeContext = React.createContext("blue");
|
||||
|
||||
ReactIs.isContextConsumer(<ThemeContext.Consumer />); // true
|
||||
ReactIs.isContextProvider(<ThemeContext.Provider />); // true
|
||||
ReactIs.typeOf(<ThemeContext.Provider />) === ReactIs.ContextProvider; // true
|
||||
ReactIs.typeOf(<ThemeContext.Consumer />) === ReactIs.ContextConsumer; // true
|
||||
```
|
||||
|
||||
#### Element
|
||||
|
||||
```js
|
||||
import React from "react";
|
||||
import * as ReactIs from 'react-is';
|
||||
|
||||
ReactIs.isElement(<div />); // true
|
||||
ReactIs.typeOf(<div />) === ReactIs.Element; // true
|
||||
```
|
||||
|
||||
#### Fragment
|
||||
|
||||
```js
|
||||
import React from "react";
|
||||
import * as ReactIs from 'react-is';
|
||||
|
||||
ReactIs.isFragment(<></>); // true
|
||||
ReactIs.typeOf(<></>) === ReactIs.Fragment; // true
|
||||
```
|
||||
|
||||
#### Portal
|
||||
|
||||
```js
|
||||
import React from "react";
|
||||
import ReactDOM from "react-dom";
|
||||
import * as ReactIs from 'react-is';
|
||||
|
||||
const div = document.createElement("div");
|
||||
const portal = ReactDOM.createPortal(<div />, div);
|
||||
|
||||
ReactIs.isPortal(portal); // true
|
||||
ReactIs.typeOf(portal) === ReactIs.Portal; // true
|
||||
```
|
||||
|
||||
#### StrictMode
|
||||
|
||||
```js
|
||||
import React from "react";
|
||||
import * as ReactIs from 'react-is';
|
||||
|
||||
ReactIs.isStrictMode(<React.StrictMode />); // true
|
||||
ReactIs.typeOf(<React.StrictMode />) === ReactIs.StrictMode; // true
|
||||
```
|
||||
+132
@@ -0,0 +1,132 @@
|
||||
/**
|
||||
* @license React
|
||||
* react-is.development.js
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
"production" !== process.env.NODE_ENV &&
|
||||
(function () {
|
||||
function typeOf(object) {
|
||||
if ("object" === typeof object && null !== object) {
|
||||
var $$typeof = object.$$typeof;
|
||||
switch ($$typeof) {
|
||||
case REACT_ELEMENT_TYPE:
|
||||
switch (((object = object.type), object)) {
|
||||
case REACT_FRAGMENT_TYPE:
|
||||
case REACT_PROFILER_TYPE:
|
||||
case REACT_STRICT_MODE_TYPE:
|
||||
case REACT_SUSPENSE_TYPE:
|
||||
case REACT_SUSPENSE_LIST_TYPE:
|
||||
case REACT_VIEW_TRANSITION_TYPE:
|
||||
return object;
|
||||
default:
|
||||
switch (((object = object && object.$$typeof), object)) {
|
||||
case REACT_CONTEXT_TYPE:
|
||||
case REACT_FORWARD_REF_TYPE:
|
||||
case REACT_LAZY_TYPE:
|
||||
case REACT_MEMO_TYPE:
|
||||
return object;
|
||||
case REACT_CONSUMER_TYPE:
|
||||
return object;
|
||||
default:
|
||||
return $$typeof;
|
||||
}
|
||||
}
|
||||
case REACT_PORTAL_TYPE:
|
||||
return $$typeof;
|
||||
}
|
||||
}
|
||||
}
|
||||
var REACT_ELEMENT_TYPE = Symbol.for("react.transitional.element"),
|
||||
REACT_PORTAL_TYPE = Symbol.for("react.portal"),
|
||||
REACT_FRAGMENT_TYPE = Symbol.for("react.fragment"),
|
||||
REACT_STRICT_MODE_TYPE = Symbol.for("react.strict_mode"),
|
||||
REACT_PROFILER_TYPE = Symbol.for("react.profiler"),
|
||||
REACT_CONSUMER_TYPE = Symbol.for("react.consumer"),
|
||||
REACT_CONTEXT_TYPE = Symbol.for("react.context"),
|
||||
REACT_FORWARD_REF_TYPE = Symbol.for("react.forward_ref"),
|
||||
REACT_SUSPENSE_TYPE = Symbol.for("react.suspense"),
|
||||
REACT_SUSPENSE_LIST_TYPE = Symbol.for("react.suspense_list"),
|
||||
REACT_MEMO_TYPE = Symbol.for("react.memo"),
|
||||
REACT_LAZY_TYPE = Symbol.for("react.lazy"),
|
||||
REACT_VIEW_TRANSITION_TYPE = Symbol.for("react.view_transition"),
|
||||
REACT_CLIENT_REFERENCE = Symbol.for("react.client.reference");
|
||||
exports.ContextConsumer = REACT_CONSUMER_TYPE;
|
||||
exports.ContextProvider = REACT_CONTEXT_TYPE;
|
||||
exports.Element = REACT_ELEMENT_TYPE;
|
||||
exports.ForwardRef = REACT_FORWARD_REF_TYPE;
|
||||
exports.Fragment = REACT_FRAGMENT_TYPE;
|
||||
exports.Lazy = REACT_LAZY_TYPE;
|
||||
exports.Memo = REACT_MEMO_TYPE;
|
||||
exports.Portal = REACT_PORTAL_TYPE;
|
||||
exports.Profiler = REACT_PROFILER_TYPE;
|
||||
exports.StrictMode = REACT_STRICT_MODE_TYPE;
|
||||
exports.Suspense = REACT_SUSPENSE_TYPE;
|
||||
exports.SuspenseList = REACT_SUSPENSE_LIST_TYPE;
|
||||
exports.isContextConsumer = function (object) {
|
||||
return typeOf(object) === REACT_CONSUMER_TYPE;
|
||||
};
|
||||
exports.isContextProvider = function (object) {
|
||||
return typeOf(object) === REACT_CONTEXT_TYPE;
|
||||
};
|
||||
exports.isElement = function (object) {
|
||||
return (
|
||||
"object" === typeof object &&
|
||||
null !== object &&
|
||||
object.$$typeof === REACT_ELEMENT_TYPE
|
||||
);
|
||||
};
|
||||
exports.isForwardRef = function (object) {
|
||||
return typeOf(object) === REACT_FORWARD_REF_TYPE;
|
||||
};
|
||||
exports.isFragment = function (object) {
|
||||
return typeOf(object) === REACT_FRAGMENT_TYPE;
|
||||
};
|
||||
exports.isLazy = function (object) {
|
||||
return typeOf(object) === REACT_LAZY_TYPE;
|
||||
};
|
||||
exports.isMemo = function (object) {
|
||||
return typeOf(object) === REACT_MEMO_TYPE;
|
||||
};
|
||||
exports.isPortal = function (object) {
|
||||
return typeOf(object) === REACT_PORTAL_TYPE;
|
||||
};
|
||||
exports.isProfiler = function (object) {
|
||||
return typeOf(object) === REACT_PROFILER_TYPE;
|
||||
};
|
||||
exports.isStrictMode = function (object) {
|
||||
return typeOf(object) === REACT_STRICT_MODE_TYPE;
|
||||
};
|
||||
exports.isSuspense = function (object) {
|
||||
return typeOf(object) === REACT_SUSPENSE_TYPE;
|
||||
};
|
||||
exports.isSuspenseList = function (object) {
|
||||
return typeOf(object) === REACT_SUSPENSE_LIST_TYPE;
|
||||
};
|
||||
exports.isValidElementType = function (type) {
|
||||
return "string" === typeof type ||
|
||||
"function" === typeof type ||
|
||||
type === REACT_FRAGMENT_TYPE ||
|
||||
type === REACT_PROFILER_TYPE ||
|
||||
type === REACT_STRICT_MODE_TYPE ||
|
||||
type === REACT_SUSPENSE_TYPE ||
|
||||
type === REACT_SUSPENSE_LIST_TYPE ||
|
||||
("object" === typeof type &&
|
||||
null !== type &&
|
||||
(type.$$typeof === REACT_LAZY_TYPE ||
|
||||
type.$$typeof === REACT_MEMO_TYPE ||
|
||||
type.$$typeof === REACT_CONTEXT_TYPE ||
|
||||
type.$$typeof === REACT_CONSUMER_TYPE ||
|
||||
type.$$typeof === REACT_FORWARD_REF_TYPE ||
|
||||
type.$$typeof === REACT_CLIENT_REFERENCE ||
|
||||
void 0 !== type.getModuleId))
|
||||
? !0
|
||||
: !1;
|
||||
};
|
||||
exports.typeOf = typeOf;
|
||||
})();
|
||||
+129
@@ -0,0 +1,129 @@
|
||||
/**
|
||||
* @license React
|
||||
* react-is.production.js
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
var REACT_ELEMENT_TYPE = Symbol.for("react.transitional.element"),
|
||||
REACT_PORTAL_TYPE = Symbol.for("react.portal"),
|
||||
REACT_FRAGMENT_TYPE = Symbol.for("react.fragment"),
|
||||
REACT_STRICT_MODE_TYPE = Symbol.for("react.strict_mode"),
|
||||
REACT_PROFILER_TYPE = Symbol.for("react.profiler"),
|
||||
REACT_CONSUMER_TYPE = Symbol.for("react.consumer"),
|
||||
REACT_CONTEXT_TYPE = Symbol.for("react.context"),
|
||||
REACT_FORWARD_REF_TYPE = Symbol.for("react.forward_ref"),
|
||||
REACT_SUSPENSE_TYPE = Symbol.for("react.suspense"),
|
||||
REACT_SUSPENSE_LIST_TYPE = Symbol.for("react.suspense_list"),
|
||||
REACT_MEMO_TYPE = Symbol.for("react.memo"),
|
||||
REACT_LAZY_TYPE = Symbol.for("react.lazy"),
|
||||
REACT_VIEW_TRANSITION_TYPE = Symbol.for("react.view_transition"),
|
||||
REACT_CLIENT_REFERENCE = Symbol.for("react.client.reference");
|
||||
function typeOf(object) {
|
||||
if ("object" === typeof object && null !== object) {
|
||||
var $$typeof = object.$$typeof;
|
||||
switch ($$typeof) {
|
||||
case REACT_ELEMENT_TYPE:
|
||||
switch (((object = object.type), object)) {
|
||||
case REACT_FRAGMENT_TYPE:
|
||||
case REACT_PROFILER_TYPE:
|
||||
case REACT_STRICT_MODE_TYPE:
|
||||
case REACT_SUSPENSE_TYPE:
|
||||
case REACT_SUSPENSE_LIST_TYPE:
|
||||
case REACT_VIEW_TRANSITION_TYPE:
|
||||
return object;
|
||||
default:
|
||||
switch (((object = object && object.$$typeof), object)) {
|
||||
case REACT_CONTEXT_TYPE:
|
||||
case REACT_FORWARD_REF_TYPE:
|
||||
case REACT_LAZY_TYPE:
|
||||
case REACT_MEMO_TYPE:
|
||||
return object;
|
||||
case REACT_CONSUMER_TYPE:
|
||||
return object;
|
||||
default:
|
||||
return $$typeof;
|
||||
}
|
||||
}
|
||||
case REACT_PORTAL_TYPE:
|
||||
return $$typeof;
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.ContextConsumer = REACT_CONSUMER_TYPE;
|
||||
exports.ContextProvider = REACT_CONTEXT_TYPE;
|
||||
exports.Element = REACT_ELEMENT_TYPE;
|
||||
exports.ForwardRef = REACT_FORWARD_REF_TYPE;
|
||||
exports.Fragment = REACT_FRAGMENT_TYPE;
|
||||
exports.Lazy = REACT_LAZY_TYPE;
|
||||
exports.Memo = REACT_MEMO_TYPE;
|
||||
exports.Portal = REACT_PORTAL_TYPE;
|
||||
exports.Profiler = REACT_PROFILER_TYPE;
|
||||
exports.StrictMode = REACT_STRICT_MODE_TYPE;
|
||||
exports.Suspense = REACT_SUSPENSE_TYPE;
|
||||
exports.SuspenseList = REACT_SUSPENSE_LIST_TYPE;
|
||||
exports.isContextConsumer = function (object) {
|
||||
return typeOf(object) === REACT_CONSUMER_TYPE;
|
||||
};
|
||||
exports.isContextProvider = function (object) {
|
||||
return typeOf(object) === REACT_CONTEXT_TYPE;
|
||||
};
|
||||
exports.isElement = function (object) {
|
||||
return (
|
||||
"object" === typeof object &&
|
||||
null !== object &&
|
||||
object.$$typeof === REACT_ELEMENT_TYPE
|
||||
);
|
||||
};
|
||||
exports.isForwardRef = function (object) {
|
||||
return typeOf(object) === REACT_FORWARD_REF_TYPE;
|
||||
};
|
||||
exports.isFragment = function (object) {
|
||||
return typeOf(object) === REACT_FRAGMENT_TYPE;
|
||||
};
|
||||
exports.isLazy = function (object) {
|
||||
return typeOf(object) === REACT_LAZY_TYPE;
|
||||
};
|
||||
exports.isMemo = function (object) {
|
||||
return typeOf(object) === REACT_MEMO_TYPE;
|
||||
};
|
||||
exports.isPortal = function (object) {
|
||||
return typeOf(object) === REACT_PORTAL_TYPE;
|
||||
};
|
||||
exports.isProfiler = function (object) {
|
||||
return typeOf(object) === REACT_PROFILER_TYPE;
|
||||
};
|
||||
exports.isStrictMode = function (object) {
|
||||
return typeOf(object) === REACT_STRICT_MODE_TYPE;
|
||||
};
|
||||
exports.isSuspense = function (object) {
|
||||
return typeOf(object) === REACT_SUSPENSE_TYPE;
|
||||
};
|
||||
exports.isSuspenseList = function (object) {
|
||||
return typeOf(object) === REACT_SUSPENSE_LIST_TYPE;
|
||||
};
|
||||
exports.isValidElementType = function (type) {
|
||||
return "string" === typeof type ||
|
||||
"function" === typeof type ||
|
||||
type === REACT_FRAGMENT_TYPE ||
|
||||
type === REACT_PROFILER_TYPE ||
|
||||
type === REACT_STRICT_MODE_TYPE ||
|
||||
type === REACT_SUSPENSE_TYPE ||
|
||||
type === REACT_SUSPENSE_LIST_TYPE ||
|
||||
("object" === typeof type &&
|
||||
null !== type &&
|
||||
(type.$$typeof === REACT_LAZY_TYPE ||
|
||||
type.$$typeof === REACT_MEMO_TYPE ||
|
||||
type.$$typeof === REACT_CONTEXT_TYPE ||
|
||||
type.$$typeof === REACT_CONSUMER_TYPE ||
|
||||
type.$$typeof === REACT_FORWARD_REF_TYPE ||
|
||||
type.$$typeof === REACT_CLIENT_REFERENCE ||
|
||||
void 0 !== type.getModuleId))
|
||||
? !0
|
||||
: !1;
|
||||
};
|
||||
exports.typeOf = typeOf;
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
if (process.env.NODE_ENV === 'production') {
|
||||
module.exports = require('./cjs/react-is.production.js');
|
||||
} else {
|
||||
module.exports = require('./cjs/react-is.development.js');
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"name": "react-is",
|
||||
"version": "19.2.8",
|
||||
"description": "Brand checking of React Elements.",
|
||||
"main": "index.js",
|
||||
"sideEffects": false,
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/react/react.git",
|
||||
"directory": "packages/react-is"
|
||||
},
|
||||
"keywords": [
|
||||
"react"
|
||||
],
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/react/react/issues"
|
||||
},
|
||||
"homepage": "https://react.dev/",
|
||||
"files": [
|
||||
"LICENSE",
|
||||
"README.md",
|
||||
"index.js",
|
||||
"cjs/"
|
||||
]
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
Copyright Contributors to the Jest project.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
BIN
Binary file not shown.
|
After Width: | Height: | Size: 3.0 KiB |
+197
@@ -0,0 +1,197 @@
|
||||
/*!
|
||||
* /**
|
||||
* * 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.
|
||||
* * /
|
||||
*/
|
||||
/******/ (() => { // webpackBootstrap
|
||||
/******/ "use strict";
|
||||
/******/ var __webpack_modules__ = ({
|
||||
|
||||
/***/ "./src/generateEmptyCoverage.ts"
|
||||
(__unused_webpack_module, exports) {
|
||||
|
||||
|
||||
|
||||
Object.defineProperty(exports, "__esModule", ({
|
||||
value: true
|
||||
}));
|
||||
exports["default"] = generateEmptyCoverage;
|
||||
function fs() {
|
||||
const data = _interopRequireWildcard(require("graceful-fs"));
|
||||
fs = function () {
|
||||
return data;
|
||||
};
|
||||
return data;
|
||||
}
|
||||
function _istanbulLibCoverage() {
|
||||
const data = require("istanbul-lib-coverage");
|
||||
_istanbulLibCoverage = function () {
|
||||
return data;
|
||||
};
|
||||
return data;
|
||||
}
|
||||
function _istanbulLibInstrument() {
|
||||
const data = require("istanbul-lib-instrument");
|
||||
_istanbulLibInstrument = function () {
|
||||
return data;
|
||||
};
|
||||
return data;
|
||||
}
|
||||
function _transform() {
|
||||
const data = require("@jest/transform");
|
||||
_transform = function () {
|
||||
return data;
|
||||
};
|
||||
return data;
|
||||
}
|
||||
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
async function generateEmptyCoverage(source, filename, globalConfig, config, changedFiles, sourcesRelatedToTestsInChangedFiles) {
|
||||
const coverageOptions = {
|
||||
changedFiles,
|
||||
collectCoverage: globalConfig.collectCoverage,
|
||||
collectCoverageFrom: globalConfig.collectCoverageFrom,
|
||||
coverageProvider: globalConfig.coverageProvider,
|
||||
globalRootDir: globalConfig.rootDir,
|
||||
sourcesRelatedToTestsInChangedFiles
|
||||
};
|
||||
let coverageWorkerResult = null;
|
||||
if ((0, _transform().shouldInstrument)(filename, coverageOptions, config)) {
|
||||
if (coverageOptions.coverageProvider === 'v8') {
|
||||
const stat = fs().statSync(filename);
|
||||
return {
|
||||
kind: 'V8Coverage',
|
||||
result: {
|
||||
functions: [{
|
||||
functionName: '(empty-report)',
|
||||
isBlockCoverage: true,
|
||||
ranges: [{
|
||||
count: 0,
|
||||
endOffset: stat.size,
|
||||
startOffset: 0
|
||||
}]
|
||||
}],
|
||||
scriptId: '0',
|
||||
url: filename
|
||||
}
|
||||
};
|
||||
}
|
||||
const scriptTransformer = await (0, _transform().createScriptTransformer)(config);
|
||||
|
||||
// Transform file with instrumentation to make sure initial coverage data is well mapped to original code.
|
||||
const {
|
||||
code
|
||||
} = await scriptTransformer.transformSourceAsync(filename, source, {
|
||||
instrument: true,
|
||||
supportsDynamicImport: true,
|
||||
supportsExportNamespaceFrom: true,
|
||||
supportsStaticESM: true,
|
||||
supportsTopLevelAwait: true
|
||||
});
|
||||
// TODO: consider passing AST
|
||||
const extracted = (0, _istanbulLibInstrument().readInitialCoverage)(code);
|
||||
// Check extracted initial coverage is not null, this can happen when using /* istanbul ignore file */
|
||||
if (extracted) {
|
||||
coverageWorkerResult = {
|
||||
coverage: (0, _istanbulLibCoverage().createFileCoverage)(extracted.coverageData),
|
||||
kind: 'BabelCoverage'
|
||||
};
|
||||
}
|
||||
}
|
||||
return coverageWorkerResult;
|
||||
}
|
||||
|
||||
/***/ }
|
||||
|
||||
/******/ });
|
||||
/************************************************************************/
|
||||
/******/ // The module cache
|
||||
/******/ const __webpack_module_cache__ = {};
|
||||
/******/
|
||||
/******/ // The require function
|
||||
/******/ function __webpack_require__(moduleId) {
|
||||
/******/ // Check if module is in cache
|
||||
/******/ const cachedModule = __webpack_module_cache__[moduleId];
|
||||
/******/ if (cachedModule !== undefined) {
|
||||
/******/ return cachedModule.exports;
|
||||
/******/ }
|
||||
/******/ // Create a new module (and put it into the cache)
|
||||
/******/ const module = __webpack_module_cache__[moduleId] = {
|
||||
/******/ // no module.id needed
|
||||
/******/ // no module.loaded needed
|
||||
/******/ exports: {}
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // Execute the module function
|
||||
/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
|
||||
/******/
|
||||
/******/ // Return the exports of the module
|
||||
/******/ return module.exports;
|
||||
/******/ }
|
||||
/******/
|
||||
/************************************************************************/
|
||||
let __webpack_exports__ = {};
|
||||
// This entry needs to be wrapped in an IIFE because it uses a non-standard name for the exports (exports).
|
||||
(() => {
|
||||
let exports = __webpack_exports__;
|
||||
|
||||
|
||||
Object.defineProperty(exports, "__esModule", ({
|
||||
value: true
|
||||
}));
|
||||
exports.worker = worker;
|
||||
function _exitX() {
|
||||
const data = _interopRequireDefault(require("exit-x"));
|
||||
_exitX = function () {
|
||||
return data;
|
||||
};
|
||||
return data;
|
||||
}
|
||||
function fs() {
|
||||
const data = _interopRequireWildcard(require("graceful-fs"));
|
||||
fs = function () {
|
||||
return data;
|
||||
};
|
||||
return data;
|
||||
}
|
||||
var _generateEmptyCoverage = _interopRequireDefault(__webpack_require__("./src/generateEmptyCoverage.ts"));
|
||||
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
|
||||
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// Make sure uncaught errors are logged before we exit.
|
||||
process.on('uncaughtException', err => {
|
||||
if (err.stack) {
|
||||
console.error(err.stack);
|
||||
} else {
|
||||
console.error(err);
|
||||
}
|
||||
(0, _exitX().default)(1);
|
||||
});
|
||||
function worker({
|
||||
config,
|
||||
globalConfig,
|
||||
path,
|
||||
context
|
||||
}) {
|
||||
return (0, _generateEmptyCoverage.default)(fs().readFileSync(path, 'utf8'), path, globalConfig, config, context.changedFiles && new Set(context.changedFiles), context.sourcesRelatedToTestsInChangedFiles && new Set(context.sourcesRelatedToTestsInChangedFiles));
|
||||
}
|
||||
})();
|
||||
|
||||
module.exports = __webpack_exports__;
|
||||
/******/ })()
|
||||
;
|
||||
+346
@@ -0,0 +1,346 @@
|
||||
/**
|
||||
* 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 {WriteStream} from 'node:tty';
|
||||
import {
|
||||
AggregatedResult,
|
||||
AssertionResult,
|
||||
SnapshotSummary,
|
||||
Suite,
|
||||
Test,
|
||||
TestCaseResult,
|
||||
TestContext,
|
||||
TestResult,
|
||||
} from '@jest/test-result';
|
||||
import {Circus, Config} from '@jest/types';
|
||||
|
||||
/**
|
||||
* A reporter optimized for AI coding agents that reduces token usage by only
|
||||
* printing failing tests and the final summary. Automatically activated when
|
||||
* an AI agent environment is detected (via the AI_AGENT env var or std-env).
|
||||
*/
|
||||
export declare class AgentReporter extends DefaultReporter {
|
||||
static readonly filename: string;
|
||||
protected __wrapStdio(): void;
|
||||
protected __clearStatus(): void;
|
||||
protected __printStatus(): void;
|
||||
onTestStart(_test: Test): void;
|
||||
onTestCaseResult(_test: Test, _testCaseResult: TestCaseResult): void;
|
||||
onRunStart(
|
||||
aggregatedResults: AggregatedResult,
|
||||
options: ReporterOnStartOptions,
|
||||
): void;
|
||||
onTestResult(
|
||||
test: Test,
|
||||
testResult: TestResult,
|
||||
aggregatedResults: AggregatedResult,
|
||||
): void;
|
||||
}
|
||||
|
||||
export {AggregatedResult};
|
||||
|
||||
export declare class BaseReporter implements Reporter {
|
||||
private _error?;
|
||||
log(message: string): void;
|
||||
onRunStart(
|
||||
_results?: AggregatedResult,
|
||||
_options?: ReporterOnStartOptions,
|
||||
): void;
|
||||
onTestCaseResult(_test: Test, _testCaseResult: TestCaseResult): void;
|
||||
onTestResult(
|
||||
_test?: Test,
|
||||
_testResult?: TestResult,
|
||||
_results?: AggregatedResult,
|
||||
): void;
|
||||
onTestStart(_test?: Test): void;
|
||||
onRunComplete(
|
||||
_testContexts?: Set<TestContext>,
|
||||
_aggregatedResults?: AggregatedResult,
|
||||
): Promise<void> | void;
|
||||
protected _setError(error: Error): void;
|
||||
getLastError(): Error | undefined;
|
||||
protected __beginSynchronizedUpdate(write: WriteStream['write']): void;
|
||||
protected __endSynchronizedUpdate(write: WriteStream['write']): void;
|
||||
}
|
||||
|
||||
export {Config};
|
||||
|
||||
export declare class CoverageReporter extends BaseReporter {
|
||||
private readonly _context;
|
||||
private readonly _coverageMap;
|
||||
private readonly _globalConfig;
|
||||
private readonly _sourceMapStore;
|
||||
private readonly _v8CoverageResults;
|
||||
static readonly filename: string;
|
||||
constructor(globalConfig: Config.GlobalConfig, context: ReporterContext);
|
||||
onTestResult(_test: Test, testResult: TestResult): void;
|
||||
onRunComplete(
|
||||
testContexts: Set<TestContext>,
|
||||
aggregatedResults: AggregatedResult,
|
||||
): Promise<void>;
|
||||
private _addUntestedFiles;
|
||||
private _checkThreshold;
|
||||
private _getCoverageResult;
|
||||
}
|
||||
|
||||
export declare class DefaultReporter extends BaseReporter {
|
||||
private _clear;
|
||||
private readonly _err;
|
||||
protected _globalConfig: Config.GlobalConfig;
|
||||
private readonly _out;
|
||||
private readonly _status;
|
||||
private readonly _bufferedOutput;
|
||||
static readonly filename: string;
|
||||
constructor(globalConfig: Config.GlobalConfig);
|
||||
protected __wrapStdio(stream: NodeJS.WritableStream | WriteStream): void;
|
||||
forceFlushBufferedOutput(): void;
|
||||
protected __clearStatus(): void;
|
||||
protected __printStatus(): void;
|
||||
onRunStart(
|
||||
aggregatedResults: AggregatedResult,
|
||||
options: ReporterOnStartOptions,
|
||||
): void;
|
||||
onTestStart(test: Test): void;
|
||||
onTestCaseResult(test: Test, testCaseResult: TestCaseResult): void;
|
||||
onRunComplete(): void;
|
||||
onTestResult(
|
||||
test: Test,
|
||||
testResult: TestResult,
|
||||
aggregatedResults: AggregatedResult,
|
||||
): void;
|
||||
testFinished(
|
||||
config: Config.ProjectConfig,
|
||||
testResult: TestResult,
|
||||
aggregatedResults: AggregatedResult,
|
||||
): void;
|
||||
printTestFileHeader(
|
||||
testPath: string,
|
||||
config: Config.ProjectConfig,
|
||||
result: TestResult,
|
||||
): void;
|
||||
printTestFileFailureMessage(
|
||||
_testPath: string,
|
||||
_config: Config.ProjectConfig,
|
||||
result: TestResult,
|
||||
): void;
|
||||
}
|
||||
|
||||
declare function formatTestPath(
|
||||
config: Config.GlobalConfig | Config.ProjectConfig,
|
||||
testPath: string,
|
||||
): string;
|
||||
|
||||
declare function getResultHeader(
|
||||
result: TestResult,
|
||||
globalConfig: Config.GlobalConfig,
|
||||
projectConfig?: Config.ProjectConfig,
|
||||
): string;
|
||||
|
||||
declare function getSnapshotStatus(
|
||||
snapshot: TestResult['snapshot'],
|
||||
afterUpdate: boolean,
|
||||
): Array<string>;
|
||||
|
||||
declare function getSnapshotSummary(
|
||||
snapshots: SnapshotSummary,
|
||||
globalConfig: Config.GlobalConfig,
|
||||
updateCommand: string,
|
||||
): Array<string>;
|
||||
|
||||
declare function getSummary(
|
||||
aggregatedResults: AggregatedResult,
|
||||
options?: SummaryOptions,
|
||||
): string;
|
||||
|
||||
export declare class GitHubActionsReporter extends BaseReporter {
|
||||
#private;
|
||||
static readonly filename: string;
|
||||
private readonly options;
|
||||
private readonly globalConfig;
|
||||
constructor(
|
||||
globalConfig: Config.GlobalConfig,
|
||||
reporterOptions?: {
|
||||
silent?: boolean;
|
||||
},
|
||||
);
|
||||
onTestResult(
|
||||
test: Test,
|
||||
testResult: TestResult,
|
||||
aggregatedResults: AggregatedResult,
|
||||
): void;
|
||||
private generateAnnotations;
|
||||
private isLastTestSuite;
|
||||
private printFullResult;
|
||||
private arrayEqual;
|
||||
private arrayChild;
|
||||
private getResultTree;
|
||||
private getResultChildren;
|
||||
private printResultTree;
|
||||
private recursivePrintResultTree;
|
||||
private printFailedTestLogs;
|
||||
private startGroup;
|
||||
private endGroup;
|
||||
}
|
||||
|
||||
export declare class NotifyReporter extends BaseReporter {
|
||||
private readonly _notifier;
|
||||
private readonly _globalConfig;
|
||||
private readonly _context;
|
||||
static readonly filename: string;
|
||||
constructor(globalConfig: Config.GlobalConfig, context: ReporterContext);
|
||||
onRunComplete(testContexts: Set<TestContext>, result: AggregatedResult): void;
|
||||
}
|
||||
|
||||
declare function printDisplayName(config: Config.ProjectConfig): string;
|
||||
|
||||
declare function relativePath(
|
||||
config: Config.GlobalConfig | Config.ProjectConfig,
|
||||
testPath: string,
|
||||
): {
|
||||
basename: string;
|
||||
dirname: string;
|
||||
};
|
||||
|
||||
export declare interface Reporter {
|
||||
readonly onTestResult?: (
|
||||
test: Test,
|
||||
testResult: TestResult,
|
||||
aggregatedResult: AggregatedResult,
|
||||
) => Promise<void> | void;
|
||||
readonly onTestFileResult?: (
|
||||
test: Test,
|
||||
testResult: TestResult,
|
||||
aggregatedResult: AggregatedResult,
|
||||
) => Promise<void> | void;
|
||||
/**
|
||||
* Called before running a spec (prior to `before` hooks)
|
||||
* Not called for `skipped` and `todo` specs
|
||||
*/
|
||||
readonly onTestCaseStart?: (
|
||||
test: Test,
|
||||
testCaseStartInfo: Circus.TestCaseStartInfo,
|
||||
) => Promise<void> | void;
|
||||
readonly onTestCaseResult?: (
|
||||
test: Test,
|
||||
testCaseResult: TestCaseResult,
|
||||
) => Promise<void> | void;
|
||||
readonly onRunStart?: (
|
||||
results: AggregatedResult,
|
||||
options: ReporterOnStartOptions,
|
||||
) => Promise<void> | void;
|
||||
readonly onTestStart?: (test: Test) => Promise<void> | void;
|
||||
readonly onTestFileStart?: (test: Test) => Promise<void> | void;
|
||||
readonly onRunComplete?: (
|
||||
testContexts: Set<TestContext>,
|
||||
results: AggregatedResult,
|
||||
) => Promise<void> | void;
|
||||
readonly getLastError?: () => Error | void;
|
||||
}
|
||||
|
||||
export declare type ReporterContext = {
|
||||
firstRun: boolean;
|
||||
previousSuccess: boolean;
|
||||
changedFiles?: Set<string>;
|
||||
sourcesRelatedToTestsInChangedFiles?: Set<string>;
|
||||
startRun?: (globalConfig: Config.GlobalConfig) => unknown;
|
||||
};
|
||||
|
||||
export declare type ReporterOnStartOptions = {
|
||||
estimatedTime: number;
|
||||
showStatus: boolean;
|
||||
};
|
||||
|
||||
export {SnapshotSummary};
|
||||
|
||||
export declare type SummaryOptions = {
|
||||
currentTestCases?: Array<{
|
||||
test: Test;
|
||||
testCaseResult: TestCaseResult;
|
||||
}>;
|
||||
estimatedTime?: number;
|
||||
roundTime?: boolean;
|
||||
width?: number;
|
||||
showSeed?: boolean;
|
||||
seed?: number;
|
||||
};
|
||||
|
||||
export declare class SummaryReporter extends BaseReporter {
|
||||
private _estimatedTime;
|
||||
private readonly _globalConfig;
|
||||
private readonly _summaryThreshold;
|
||||
static readonly filename: string;
|
||||
constructor(
|
||||
globalConfig: Config.GlobalConfig,
|
||||
options?: SummaryReporterOptions,
|
||||
);
|
||||
private _validateOptions;
|
||||
private _write;
|
||||
onRunStart(
|
||||
aggregatedResults: AggregatedResult,
|
||||
options: ReporterOnStartOptions,
|
||||
): void;
|
||||
onRunComplete(
|
||||
testContexts: Set<TestContext>,
|
||||
aggregatedResults: AggregatedResult,
|
||||
): void;
|
||||
private _printSnapshotSummary;
|
||||
private _printSummary;
|
||||
private _getTestSummary;
|
||||
}
|
||||
|
||||
export declare type SummaryReporterOptions = {
|
||||
summaryThreshold?: number;
|
||||
};
|
||||
|
||||
export {Test};
|
||||
|
||||
export {TestCaseResult};
|
||||
|
||||
export {TestContext};
|
||||
|
||||
export {TestResult};
|
||||
|
||||
declare function trimAndFormatPath(
|
||||
pad: number,
|
||||
config: Config.ProjectConfig | Config.GlobalConfig,
|
||||
testPath: string,
|
||||
columns: number,
|
||||
): string;
|
||||
|
||||
export declare const utils: {
|
||||
formatTestPath: typeof formatTestPath;
|
||||
getResultHeader: typeof getResultHeader;
|
||||
getSnapshotStatus: typeof getSnapshotStatus;
|
||||
getSnapshotSummary: typeof getSnapshotSummary;
|
||||
getSummary: typeof getSummary;
|
||||
printDisplayName: typeof printDisplayName;
|
||||
relativePath: typeof relativePath;
|
||||
trimAndFormatPath: typeof trimAndFormatPath;
|
||||
};
|
||||
|
||||
export declare class VerboseReporter extends DefaultReporter {
|
||||
protected _globalConfig: Config.GlobalConfig;
|
||||
static readonly filename: string;
|
||||
constructor(globalConfig: Config.GlobalConfig);
|
||||
protected __wrapStdio(stream: NodeJS.WritableStream | WriteStream): void;
|
||||
static filterTestResults(
|
||||
testResults: Array<AssertionResult>,
|
||||
): Array<AssertionResult>;
|
||||
static groupTestsBySuites(testResults: Array<AssertionResult>): Suite;
|
||||
onTestResult(
|
||||
test: Test,
|
||||
result: TestResult,
|
||||
aggregatedResults: AggregatedResult,
|
||||
): void;
|
||||
private _logTestResults;
|
||||
private _logSuite;
|
||||
private _getIcon;
|
||||
private _logTest;
|
||||
private _logTests;
|
||||
private _logTodoOrPendingTest;
|
||||
private _logLine;
|
||||
}
|
||||
+2637
File diff suppressed because it is too large
Load Diff
+11
@@ -0,0 +1,11 @@
|
||||
import cjsModule from './index.js';
|
||||
|
||||
export const AgentReporter = cjsModule.AgentReporter;
|
||||
export const BaseReporter = cjsModule.BaseReporter;
|
||||
export const CoverageReporter = cjsModule.CoverageReporter;
|
||||
export const DefaultReporter = cjsModule.DefaultReporter;
|
||||
export const GitHubActionsReporter = cjsModule.GitHubActionsReporter;
|
||||
export const NotifyReporter = cjsModule.NotifyReporter;
|
||||
export const SummaryReporter = cjsModule.SummaryReporter;
|
||||
export const VerboseReporter = cjsModule.VerboseReporter;
|
||||
export const utils = cjsModule.utils;
|
||||
+79
@@ -0,0 +1,79 @@
|
||||
{
|
||||
"name": "@jest/reporters",
|
||||
"description": "Jest's reporters",
|
||||
"version": "30.5.1",
|
||||
"main": "./build/index.js",
|
||||
"types": "./build/index.d.ts",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./build/index.d.ts",
|
||||
"require": "./build/index.js",
|
||||
"import": "./build/index.mjs",
|
||||
"default": "./build/index.js"
|
||||
},
|
||||
"./package.json": "./package.json"
|
||||
},
|
||||
"dependencies": {
|
||||
"@bcoe/v8-coverage": "^0.2.3",
|
||||
"@jest/console": "30.5.1",
|
||||
"@jest/test-result": "30.5.1",
|
||||
"@jest/transform": "30.5.1",
|
||||
"@jest/types": "30.5.1",
|
||||
"@jridgewell/trace-mapping": "^0.3.31",
|
||||
"@types/node": "*",
|
||||
"chalk": "^4.1.2",
|
||||
"collect-v8-coverage": "^1.0.2",
|
||||
"exit-x": "^0.2.2",
|
||||
"glob": "^13.0.6",
|
||||
"graceful-fs": "^4.2.11",
|
||||
"istanbul-lib-coverage": "^3.0.0",
|
||||
"istanbul-lib-instrument": "^6.0.0",
|
||||
"istanbul-lib-report": "^3.0.0",
|
||||
"istanbul-lib-source-maps": "^5.0.0",
|
||||
"istanbul-reports": "^3.1.3",
|
||||
"jest-message-util": "30.5.1",
|
||||
"jest-util": "30.5.1",
|
||||
"jest-worker": "30.5.1",
|
||||
"slash": "^3.0.0",
|
||||
"string-length": "^4.0.2",
|
||||
"v8-to-istanbul": "^9.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@jest/pattern": "30.5.0",
|
||||
"@jest/test-utils": "30.5.1",
|
||||
"@types/graceful-fs": "^4.1.9",
|
||||
"@types/istanbul-lib-coverage": "^2.0.6",
|
||||
"@types/istanbul-lib-instrument": "^1.7.7",
|
||||
"@types/istanbul-lib-report": "^3.0.3",
|
||||
"@types/istanbul-lib-source-maps": "^4.0.4",
|
||||
"@types/istanbul-reports": "^3.0.4",
|
||||
"@types/node-notifier": "^8.0.5",
|
||||
"jest-resolve": "30.5.1",
|
||||
"node-notifier": "^10.0.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"node-notifier": {
|
||||
"optional": true
|
||||
}
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/jestjs/jest.git",
|
||||
"directory": "packages/jest-reporters"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/jestjs/jest/issues"
|
||||
},
|
||||
"homepage": "https://jestjs.io/",
|
||||
"license": "MIT",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"gitHead": "9ab14feccd6c15fec1334dbcb03a53a079d153d3"
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
Copyright Contributors to the Jest project.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
# `@jest/schemas`
|
||||
|
||||
Experimental and currently incomplete module for JSON schemas for [Jest's](https://jestjs.io/) configuration.
|
||||
+392
@@ -0,0 +1,392 @@
|
||||
/**
|
||||
* 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 {
|
||||
Static,
|
||||
TArray,
|
||||
TBoolean,
|
||||
TInteger,
|
||||
TIntersect,
|
||||
TLiteral,
|
||||
TNull,
|
||||
TNumber,
|
||||
TObject,
|
||||
TOptional,
|
||||
TRecord,
|
||||
TString,
|
||||
TTuple,
|
||||
TUnion,
|
||||
TUnknown,
|
||||
TUnsafe,
|
||||
} from '@sinclair/typebox';
|
||||
|
||||
export declare const FakeTimers: TIntersect<
|
||||
[
|
||||
TObject<{
|
||||
enableGlobally: TOptional<TBoolean>;
|
||||
}>,
|
||||
TUnion<
|
||||
[
|
||||
TObject<{
|
||||
advanceTimers: TOptional<TUnion<[TBoolean, TNumber]>>;
|
||||
doNotFake: TOptional<
|
||||
TArray<
|
||||
TUnion<
|
||||
[
|
||||
TLiteral<'Date'>,
|
||||
TLiteral<'hrtime'>,
|
||||
TLiteral<'nextTick'>,
|
||||
TLiteral<'performance'>,
|
||||
TLiteral<'queueMicrotask'>,
|
||||
TLiteral<'requestAnimationFrame'>,
|
||||
TLiteral<'cancelAnimationFrame'>,
|
||||
TLiteral<'requestIdleCallback'>,
|
||||
TLiteral<'cancelIdleCallback'>,
|
||||
TLiteral<'setImmediate'>,
|
||||
TLiteral<'clearImmediate'>,
|
||||
TLiteral<'setInterval'>,
|
||||
TLiteral<'clearInterval'>,
|
||||
TLiteral<'setTimeout'>,
|
||||
TLiteral<'clearTimeout'>,
|
||||
TLiteral<'Temporal'>,
|
||||
]
|
||||
>
|
||||
>
|
||||
>;
|
||||
now: TOptional<TInteger>;
|
||||
timerLimit: TOptional<TNumber>;
|
||||
legacyFakeTimers: TOptional<TLiteral<false>>;
|
||||
}>,
|
||||
TObject<{
|
||||
legacyFakeTimers: TOptional<TLiteral<true>>;
|
||||
}>,
|
||||
]
|
||||
>,
|
||||
]
|
||||
>;
|
||||
|
||||
export declare type FakeTimers = Static<typeof FakeTimers>;
|
||||
|
||||
export declare const InitialOptions: TObject<{
|
||||
automock: TOptional<TBoolean>;
|
||||
bail: TOptional<TUnion<[TBoolean, TNumber]>>;
|
||||
cache: TOptional<TBoolean>;
|
||||
cacheDirectory: TOptional<TString>;
|
||||
ci: TOptional<TBoolean>;
|
||||
clearMocks: TOptional<TBoolean>;
|
||||
changedFilesWithAncestor: TOptional<TBoolean>;
|
||||
changedSince: TOptional<TString>;
|
||||
collectCoverage: TOptional<TBoolean>;
|
||||
collectCoverageFrom: TOptional<TArray<TString>>;
|
||||
collectTests: TOptional<TBoolean>;
|
||||
coverageDirectory: TOptional<TString>;
|
||||
coveragePathIgnorePatterns: TOptional<TArray<TString>>;
|
||||
coverageProvider: TOptional<TUnion<[TLiteral<'babel'>, TLiteral<'v8'>]>>;
|
||||
coverageReporters: TOptional<
|
||||
TArray<
|
||||
TUnion<
|
||||
[
|
||||
TUnion<
|
||||
[
|
||||
TLiteral<'clover'>,
|
||||
TLiteral<'cobertura'>,
|
||||
TLiteral<'html-spa'>,
|
||||
TLiteral<'html'>,
|
||||
TLiteral<'json'>,
|
||||
TLiteral<'json-summary'>,
|
||||
TLiteral<'lcov'>,
|
||||
TLiteral<'lcovonly'>,
|
||||
TLiteral<'none'>,
|
||||
TLiteral<'teamcity'>,
|
||||
TLiteral<'text'>,
|
||||
TLiteral<'text-lcov'>,
|
||||
TLiteral<'text-summary'>,
|
||||
]
|
||||
>,
|
||||
TTuple<
|
||||
[
|
||||
TUnion<
|
||||
[
|
||||
TLiteral<'clover'>,
|
||||
TLiteral<'cobertura'>,
|
||||
TLiteral<'html-spa'>,
|
||||
TLiteral<'html'>,
|
||||
TLiteral<'json'>,
|
||||
TLiteral<'json-summary'>,
|
||||
TLiteral<'lcov'>,
|
||||
TLiteral<'lcovonly'>,
|
||||
TLiteral<'none'>,
|
||||
TLiteral<'teamcity'>,
|
||||
TLiteral<'text'>,
|
||||
TLiteral<'text-lcov'>,
|
||||
TLiteral<'text-summary'>,
|
||||
]
|
||||
>,
|
||||
TRecord<TString, TUnknown>,
|
||||
]
|
||||
>,
|
||||
]
|
||||
>
|
||||
>
|
||||
>;
|
||||
coverageThreshold: TOptional<
|
||||
TUnsafe<{
|
||||
[path: string]: {
|
||||
branches?: number | undefined;
|
||||
functions?: number | undefined;
|
||||
lines?: number | undefined;
|
||||
statements?: number | undefined;
|
||||
};
|
||||
global: Static<
|
||||
TObject<{
|
||||
branches: TOptional<TNumber>;
|
||||
functions: TOptional<TNumber>;
|
||||
lines: TOptional<TNumber>;
|
||||
statements: TOptional<TNumber>;
|
||||
}>
|
||||
>;
|
||||
}>
|
||||
>;
|
||||
dependencyExtractor: TOptional<TString>;
|
||||
detectLeaks: TOptional<TBoolean>;
|
||||
detectOpenHandles: TOptional<TBoolean>;
|
||||
displayName: TOptional<
|
||||
TUnion<
|
||||
[
|
||||
TString,
|
||||
TObject<{
|
||||
name: TString;
|
||||
color: TUnion<
|
||||
[
|
||||
TLiteral<'black'>,
|
||||
TLiteral<'red'>,
|
||||
TLiteral<'green'>,
|
||||
TLiteral<'yellow'>,
|
||||
TLiteral<'blue'>,
|
||||
TLiteral<'magenta'>,
|
||||
TLiteral<'cyan'>,
|
||||
TLiteral<'white'>,
|
||||
TLiteral<'gray'>,
|
||||
TLiteral<'grey'>,
|
||||
TLiteral<'blackBright'>,
|
||||
TLiteral<'redBright'>,
|
||||
TLiteral<'greenBright'>,
|
||||
TLiteral<'yellowBright'>,
|
||||
TLiteral<'blueBright'>,
|
||||
TLiteral<'magentaBright'>,
|
||||
TLiteral<'cyanBright'>,
|
||||
TLiteral<'whiteBright'>,
|
||||
]
|
||||
>;
|
||||
}>,
|
||||
]
|
||||
>
|
||||
>;
|
||||
expand: TOptional<TBoolean>;
|
||||
extensionsToTreatAsEsm: TOptional<TArray<TString>>;
|
||||
fakeTimers: TOptional<
|
||||
TIntersect<
|
||||
[
|
||||
TObject<{
|
||||
enableGlobally: TOptional<TBoolean>;
|
||||
}>,
|
||||
TUnion<
|
||||
[
|
||||
TObject<{
|
||||
advanceTimers: TOptional<TUnion<[TBoolean, TNumber]>>;
|
||||
doNotFake: TOptional<
|
||||
TArray<
|
||||
TUnion<
|
||||
[
|
||||
TLiteral<'Date'>,
|
||||
TLiteral<'hrtime'>,
|
||||
TLiteral<'nextTick'>,
|
||||
TLiteral<'performance'>,
|
||||
TLiteral<'queueMicrotask'>,
|
||||
TLiteral<'requestAnimationFrame'>,
|
||||
TLiteral<'cancelAnimationFrame'>,
|
||||
TLiteral<'requestIdleCallback'>,
|
||||
TLiteral<'cancelIdleCallback'>,
|
||||
TLiteral<'setImmediate'>,
|
||||
TLiteral<'clearImmediate'>,
|
||||
TLiteral<'setInterval'>,
|
||||
TLiteral<'clearInterval'>,
|
||||
TLiteral<'setTimeout'>,
|
||||
TLiteral<'clearTimeout'>,
|
||||
TLiteral<'Temporal'>,
|
||||
]
|
||||
>
|
||||
>
|
||||
>;
|
||||
now: TOptional<TInteger>;
|
||||
timerLimit: TOptional<TNumber>;
|
||||
legacyFakeTimers: TOptional<TLiteral<false>>;
|
||||
}>,
|
||||
TObject<{
|
||||
legacyFakeTimers: TOptional<TLiteral<true>>;
|
||||
}>,
|
||||
]
|
||||
>,
|
||||
]
|
||||
>
|
||||
>;
|
||||
filter: TOptional<TString>;
|
||||
findRelatedTests: TOptional<TBoolean>;
|
||||
forceCoverageMatch: TOptional<TArray<TString>>;
|
||||
forceExit: TOptional<TBoolean>;
|
||||
json: TOptional<TBoolean>;
|
||||
globals: TOptional<TRecord<TString, TUnknown>>;
|
||||
globalSetup: TOptional<TUnion<[TString, TNull]>>;
|
||||
globalTeardown: TOptional<TUnion<[TString, TNull]>>;
|
||||
haste: TOptional<
|
||||
TObject<{
|
||||
computeSha1: TOptional<TBoolean>;
|
||||
defaultPlatform: TOptional<TUnion<[TString, TNull]>>;
|
||||
forceNodeFilesystemAPI: TOptional<TBoolean>;
|
||||
enableSymlinks: TOptional<TBoolean>;
|
||||
hasteImplModulePath: TOptional<TString>;
|
||||
platforms: TOptional<TArray<TString>>;
|
||||
throwOnModuleCollision: TOptional<TBoolean>;
|
||||
hasteMapModulePath: TOptional<TString>;
|
||||
retainAllFiles: TOptional<TBoolean>;
|
||||
}>
|
||||
>;
|
||||
id: TOptional<TString>;
|
||||
injectGlobals: TOptional<TBoolean>;
|
||||
reporters: TOptional<
|
||||
TArray<TUnion<[TString, TTuple<[TString, TRecord<TString, TUnknown>]>]>>
|
||||
>;
|
||||
logHeapUsage: TOptional<TBoolean>;
|
||||
lastCommit: TOptional<TBoolean>;
|
||||
listTests: TOptional<TBoolean>;
|
||||
maxConcurrency: TOptional<TInteger>;
|
||||
maxWorkers: TOptional<TUnion<[TString, TInteger]>>;
|
||||
moduleDirectories: TOptional<TArray<TString>>;
|
||||
moduleFileExtensions: TOptional<TArray<TString>>;
|
||||
moduleNameMapper: TOptional<
|
||||
TRecord<TString, TUnion<[TString, TArray<TString>]>>
|
||||
>;
|
||||
modulePathIgnorePatterns: TOptional<TArray<TString>>;
|
||||
modulePaths: TOptional<TArray<TString>>;
|
||||
noStackTrace: TOptional<TBoolean>;
|
||||
notify: TOptional<TBoolean>;
|
||||
notifyMode: TOptional<TString>;
|
||||
onlyChanged: TOptional<TBoolean>;
|
||||
onlyFailures: TOptional<TBoolean>;
|
||||
openHandlesTimeout: TOptional<TNumber>;
|
||||
outputFile: TOptional<TString>;
|
||||
passWithNoTests: TOptional<TBoolean>;
|
||||
preset: TOptional<TUnion<[TString, TNull]>>;
|
||||
prettierPath: TOptional<TUnion<[TString, TNull]>>;
|
||||
projects: TOptional<TArray<TUnion<[TString, TRecord<TString, TUnknown>]>>>;
|
||||
randomize: TOptional<TBoolean>;
|
||||
replname: TOptional<TUnion<[TString, TNull]>>;
|
||||
resetMocks: TOptional<TBoolean>;
|
||||
resetModules: TOptional<TBoolean>;
|
||||
resolver: TOptional<TUnion<[TString, TNull]>>;
|
||||
restoreMocks: TOptional<TBoolean>;
|
||||
rootDir: TOptional<TString>;
|
||||
roots: TOptional<TArray<TString>>;
|
||||
runner: TOptional<
|
||||
TUnion<[TString, TTuple<[TString, TRecord<TString, TUnknown>]>]>
|
||||
>;
|
||||
runTestsByPath: TOptional<TBoolean>;
|
||||
runtime: TOptional<TString>;
|
||||
sandboxInjectedGlobals: TOptional<TArray<TString>>;
|
||||
setupFiles: TOptional<TArray<TString>>;
|
||||
setupFilesAfterEnv: TOptional<TArray<TString>>;
|
||||
showSeed: TOptional<TBoolean>;
|
||||
silent: TOptional<TBoolean>;
|
||||
skipFilter: TOptional<TBoolean>;
|
||||
skipNodeResolution: TOptional<TBoolean>;
|
||||
slowTestThreshold: TOptional<TNumber>;
|
||||
snapshotResolver: TOptional<TString>;
|
||||
snapshotSerializers: TOptional<TArray<TString>>;
|
||||
snapshotFormat: TOptional<
|
||||
TObject<{
|
||||
callToJSON: TOptional<TBoolean>;
|
||||
compareKeys: TOptional<TNull>;
|
||||
escapeRegex: TOptional<TBoolean>;
|
||||
escapeString: TOptional<TBoolean>;
|
||||
highlight: TOptional<TBoolean>;
|
||||
indent: TOptional<TInteger>;
|
||||
maxDepth: TOptional<TInteger>;
|
||||
maxWidth: TOptional<TInteger>;
|
||||
min: TOptional<TBoolean>;
|
||||
printBasicPrototype: TOptional<TBoolean>;
|
||||
printFunctionName: TOptional<TBoolean>;
|
||||
theme: TOptional<
|
||||
TObject<{
|
||||
comment: TOptional<TString>;
|
||||
content: TOptional<TString>;
|
||||
prop: TOptional<TString>;
|
||||
tag: TOptional<TString>;
|
||||
value: TOptional<TString>;
|
||||
}>
|
||||
>;
|
||||
}>
|
||||
>;
|
||||
errorOnDeprecated: TOptional<TBoolean>;
|
||||
testEnvironment: TOptional<TString>;
|
||||
testEnvironmentOptions: TOptional<TRecord<TString, TUnknown>>;
|
||||
testFailureExitCode: TOptional<TInteger>;
|
||||
testLocationInResults: TOptional<TBoolean>;
|
||||
testMatch: TOptional<TUnion<[TString, TArray<TString>]>>;
|
||||
testNamePattern: TOptional<TString>;
|
||||
testPathIgnorePatterns: TOptional<TArray<TString>>;
|
||||
testRegex: TOptional<TUnion<[TString, TArray<TString>]>>;
|
||||
testResultsProcessor: TOptional<TString>;
|
||||
testRunner: TOptional<TString>;
|
||||
testSequencer: TOptional<TString>;
|
||||
testTimeout: TOptional<TNumber>;
|
||||
transform: TOptional<
|
||||
TRecord<TString, TUnion<[TString, TTuple<[TString, TUnknown]>]>>
|
||||
>;
|
||||
transformIgnorePatterns: TOptional<TArray<TString>>;
|
||||
watchPathIgnorePatterns: TOptional<TArray<TString>>;
|
||||
unmockedModulePathPatterns: TOptional<TArray<TString>>;
|
||||
updateSnapshot: TOptional<TBoolean>;
|
||||
useStderr: TOptional<TBoolean>;
|
||||
verbose: TOptional<TBoolean>;
|
||||
waitForUnhandledRejections: TOptional<TBoolean>;
|
||||
watch: TOptional<TBoolean>;
|
||||
watchAll: TOptional<TBoolean>;
|
||||
watchman: TOptional<TBoolean>;
|
||||
watchPlugins: TOptional<
|
||||
TArray<TUnion<[TString, TTuple<[TString, TUnknown]>]>>
|
||||
>;
|
||||
workerIdleMemoryLimit: TOptional<TUnion<[TNumber, TString]>>;
|
||||
workerThreads: TOptional<TBoolean>;
|
||||
workerGracefulExitTimeout: TOptional<TNumber>;
|
||||
}>;
|
||||
|
||||
export declare type InitialOptions = Static<typeof InitialOptions>;
|
||||
|
||||
export declare const SnapshotFormat: TObject<{
|
||||
callToJSON: TOptional<TBoolean>;
|
||||
compareKeys: TOptional<TNull>;
|
||||
escapeRegex: TOptional<TBoolean>;
|
||||
escapeString: TOptional<TBoolean>;
|
||||
highlight: TOptional<TBoolean>;
|
||||
indent: TOptional<TInteger>;
|
||||
maxDepth: TOptional<TInteger>;
|
||||
maxWidth: TOptional<TInteger>;
|
||||
min: TOptional<TBoolean>;
|
||||
printBasicPrototype: TOptional<TBoolean>;
|
||||
printFunctionName: TOptional<TBoolean>;
|
||||
theme: TOptional<
|
||||
TObject<{
|
||||
comment: TOptional<TString>;
|
||||
content: TOptional<TString>;
|
||||
prop: TOptional<TString>;
|
||||
tag: TOptional<TString>;
|
||||
value: TOptional<TString>;
|
||||
}>
|
||||
>;
|
||||
}>;
|
||||
|
||||
export declare type SnapshotFormat = Static<typeof SnapshotFormat>;
|
||||
+336
@@ -0,0 +1,336 @@
|
||||
/*!
|
||||
* /**
|
||||
* * 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.
|
||||
* * /
|
||||
*/
|
||||
/******/ (() => { // webpackBootstrap
|
||||
/******/ "use strict";
|
||||
/******/ var __webpack_modules__ = ({
|
||||
|
||||
/***/ "./src/raw-types.ts"
|
||||
(__unused_webpack_module, exports) {
|
||||
|
||||
|
||||
|
||||
Object.defineProperty(exports, "__esModule", ({
|
||||
value: true
|
||||
}));
|
||||
exports.SnapshotFormat = exports.InitialOptions = exports.FakeTimers = exports.CoverageReporterNames = exports.ChalkForegroundColors = void 0;
|
||||
function _typebox() {
|
||||
const data = require("@sinclair/typebox");
|
||||
_typebox = function () {
|
||||
return data;
|
||||
};
|
||||
return data;
|
||||
}
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* eslint-disable sort-keys */
|
||||
|
||||
const SnapshotFormat = exports.SnapshotFormat = _typebox().Type.Partial(_typebox().Type.Object({
|
||||
callToJSON: _typebox().Type.Boolean(),
|
||||
compareKeys: _typebox().Type.Null(),
|
||||
escapeRegex: _typebox().Type.Boolean(),
|
||||
escapeString: _typebox().Type.Boolean(),
|
||||
highlight: _typebox().Type.Boolean(),
|
||||
indent: _typebox().Type.Integer({
|
||||
minimum: 0
|
||||
}),
|
||||
maxDepth: _typebox().Type.Integer({
|
||||
minimum: 0
|
||||
}),
|
||||
maxWidth: _typebox().Type.Integer({
|
||||
minimum: 0
|
||||
}),
|
||||
min: _typebox().Type.Boolean(),
|
||||
printBasicPrototype: _typebox().Type.Boolean(),
|
||||
printFunctionName: _typebox().Type.Boolean(),
|
||||
theme: _typebox().Type.Partial(_typebox().Type.Object({
|
||||
comment: _typebox().Type.String(),
|
||||
content: _typebox().Type.String(),
|
||||
prop: _typebox().Type.String(),
|
||||
tag: _typebox().Type.String(),
|
||||
value: _typebox().Type.String()
|
||||
}))
|
||||
}));
|
||||
const CoverageProvider = _typebox().Type.Union([_typebox().Type.Literal('babel'), _typebox().Type.Literal('v8')]);
|
||||
const CoverageThresholdValue = _typebox().Type.Partial(_typebox().Type.Object({
|
||||
branches: _typebox().Type.Number({
|
||||
minimum: 0,
|
||||
maximum: 100
|
||||
}),
|
||||
functions: _typebox().Type.Number({
|
||||
minimum: 0,
|
||||
maximum: 100
|
||||
}),
|
||||
lines: _typebox().Type.Number({
|
||||
minimum: 0,
|
||||
maximum: 100
|
||||
}),
|
||||
statements: _typebox().Type.Number({
|
||||
minimum: 0,
|
||||
maximum: 100
|
||||
})
|
||||
}));
|
||||
const CoverageThresholdBase = _typebox().Type.Object({
|
||||
global: CoverageThresholdValue
|
||||
}, {
|
||||
additionalProperties: CoverageThresholdValue
|
||||
});
|
||||
const CoverageThreshold = _typebox().Type.Unsafe(CoverageThresholdBase);
|
||||
|
||||
// TODO: add type test that these are all the colors available in chalk.ForegroundColor
|
||||
const ChalkForegroundColors = exports.ChalkForegroundColors = _typebox().Type.Union([_typebox().Type.Literal('black'), _typebox().Type.Literal('red'), _typebox().Type.Literal('green'), _typebox().Type.Literal('yellow'), _typebox().Type.Literal('blue'), _typebox().Type.Literal('magenta'), _typebox().Type.Literal('cyan'), _typebox().Type.Literal('white'), _typebox().Type.Literal('gray'), _typebox().Type.Literal('grey'), _typebox().Type.Literal('blackBright'), _typebox().Type.Literal('redBright'), _typebox().Type.Literal('greenBright'), _typebox().Type.Literal('yellowBright'), _typebox().Type.Literal('blueBright'), _typebox().Type.Literal('magentaBright'), _typebox().Type.Literal('cyanBright'), _typebox().Type.Literal('whiteBright')]);
|
||||
const DisplayName = _typebox().Type.Object({
|
||||
name: _typebox().Type.String(),
|
||||
color: ChalkForegroundColors
|
||||
});
|
||||
|
||||
// TODO: verify these are the names of istanbulReport.ReportOptions
|
||||
const CoverageReporterNames = exports.CoverageReporterNames = _typebox().Type.Union([_typebox().Type.Literal('clover'), _typebox().Type.Literal('cobertura'), _typebox().Type.Literal('html-spa'), _typebox().Type.Literal('html'), _typebox().Type.Literal('json'), _typebox().Type.Literal('json-summary'), _typebox().Type.Literal('lcov'), _typebox().Type.Literal('lcovonly'), _typebox().Type.Literal('none'), _typebox().Type.Literal('teamcity'), _typebox().Type.Literal('text'), _typebox().Type.Literal('text-lcov'), _typebox().Type.Literal('text-summary')]);
|
||||
const CoverageReporters = _typebox().Type.Array(_typebox().Type.Union([CoverageReporterNames, _typebox().Type.Tuple([CoverageReporterNames, _typebox().Type.Record(_typebox().Type.String(), _typebox().Type.Unknown())])]));
|
||||
const GlobalFakeTimersConfig = _typebox().Type.Partial(_typebox().Type.Object({
|
||||
enableGlobally: _typebox().Type.Boolean({
|
||||
description: 'Whether fake timers should be enabled globally for all test files.',
|
||||
default: false
|
||||
})
|
||||
}));
|
||||
const FakeableAPI = _typebox().Type.Union([_typebox().Type.Literal('Date'), _typebox().Type.Literal('hrtime'), _typebox().Type.Literal('nextTick'), _typebox().Type.Literal('performance'), _typebox().Type.Literal('queueMicrotask'), _typebox().Type.Literal('requestAnimationFrame'), _typebox().Type.Literal('cancelAnimationFrame'), _typebox().Type.Literal('requestIdleCallback'), _typebox().Type.Literal('cancelIdleCallback'), _typebox().Type.Literal('setImmediate'), _typebox().Type.Literal('clearImmediate'), _typebox().Type.Literal('setInterval'), _typebox().Type.Literal('clearInterval'), _typebox().Type.Literal('setTimeout'), _typebox().Type.Literal('clearTimeout'), _typebox().Type.Literal('Temporal')]);
|
||||
const FakeTimersConfig = _typebox().Type.Partial(_typebox().Type.Object({
|
||||
advanceTimers: _typebox().Type.Union([_typebox().Type.Boolean(), _typebox().Type.Number({
|
||||
minimum: 0
|
||||
})], {
|
||||
description: 'If set to `true` all timers will be advanced automatically by 20 milliseconds every 20 milliseconds. A custom ' + 'time delta may be provided by passing a number.',
|
||||
default: false
|
||||
}),
|
||||
doNotFake: _typebox().Type.Array(FakeableAPI, {
|
||||
description: 'List of names of APIs (e.g. `Date`, `nextTick()`, `setImmediate()`, `setTimeout()`) that should not be faked.' + '\n\nThe default is `[]`, meaning all APIs are faked.',
|
||||
default: []
|
||||
}),
|
||||
now: _typebox().Type.Integer({
|
||||
minimum: 0,
|
||||
description: 'Sets current system time to be used by fake timers.\n\nThe default is `Date.now()`.'
|
||||
}),
|
||||
timerLimit: _typebox().Type.Number({
|
||||
description: 'The maximum number of recursive timers that will be run when calling `jest.runAllTimers()`.',
|
||||
default: 100_000,
|
||||
minimum: 0
|
||||
}),
|
||||
legacyFakeTimers: _typebox().Type.Literal(false, {
|
||||
description: 'Use the old fake timers implementation instead of one backed by `@sinonjs/fake-timers`.',
|
||||
default: false
|
||||
})
|
||||
}));
|
||||
const LegacyFakeTimersConfig = _typebox().Type.Partial(_typebox().Type.Object({
|
||||
legacyFakeTimers: _typebox().Type.Literal(true, {
|
||||
description: 'Use the old fake timers implementation instead of one backed by `@sinonjs/fake-timers`.',
|
||||
default: true
|
||||
})
|
||||
}));
|
||||
const FakeTimers = exports.FakeTimers = _typebox().Type.Intersect([GlobalFakeTimersConfig, _typebox().Type.Union([FakeTimersConfig, LegacyFakeTimersConfig])]);
|
||||
const HasteConfig = _typebox().Type.Partial(_typebox().Type.Object({
|
||||
computeSha1: _typebox().Type.Boolean({
|
||||
description: 'Whether to hash files using SHA-1.'
|
||||
}),
|
||||
defaultPlatform: _typebox().Type.Union([_typebox().Type.String(), _typebox().Type.Null()], {
|
||||
description: 'The platform to use as the default, e.g. `ios`.'
|
||||
}),
|
||||
forceNodeFilesystemAPI: _typebox().Type.Boolean({
|
||||
description: "Whether to force the use of Node's `fs` API when reading files rather than shelling out to `find`."
|
||||
}),
|
||||
enableSymlinks: _typebox().Type.Boolean({
|
||||
description: 'Whether to follow symlinks when crawling for files.' + '\n\tThis option cannot be used in projects which use watchman.' + '\n\tProjects with `watchman` set to true will error if this option is set to true.'
|
||||
}),
|
||||
hasteImplModulePath: _typebox().Type.String({
|
||||
description: 'Path to a custom implementation of Haste.'
|
||||
}),
|
||||
platforms: _typebox().Type.Array(_typebox().Type.String(), {
|
||||
description: "All platforms to target, e.g ['ios', 'android']."
|
||||
}),
|
||||
throwOnModuleCollision: _typebox().Type.Boolean({
|
||||
description: 'Whether to throw an error on module collision.'
|
||||
}),
|
||||
hasteMapModulePath: _typebox().Type.String({
|
||||
description: 'Custom HasteMap module'
|
||||
}),
|
||||
retainAllFiles: _typebox().Type.Boolean({
|
||||
description: 'Whether to retain all files, allowing e.g. search for tests in `node_modules`.'
|
||||
})
|
||||
}));
|
||||
const InitialOptions = exports.InitialOptions = _typebox().Type.Partial(_typebox().Type.Object({
|
||||
automock: _typebox().Type.Boolean(),
|
||||
bail: _typebox().Type.Union([_typebox().Type.Boolean(), _typebox().Type.Number()]),
|
||||
cache: _typebox().Type.Boolean(),
|
||||
cacheDirectory: _typebox().Type.String(),
|
||||
ci: _typebox().Type.Boolean(),
|
||||
clearMocks: _typebox().Type.Boolean(),
|
||||
changedFilesWithAncestor: _typebox().Type.Boolean(),
|
||||
changedSince: _typebox().Type.String(),
|
||||
collectCoverage: _typebox().Type.Boolean(),
|
||||
collectCoverageFrom: _typebox().Type.Array(_typebox().Type.String()),
|
||||
collectTests: _typebox().Type.Boolean(),
|
||||
coverageDirectory: _typebox().Type.String(),
|
||||
coveragePathIgnorePatterns: _typebox().Type.Array(_typebox().Type.String()),
|
||||
coverageProvider: CoverageProvider,
|
||||
coverageReporters: CoverageReporters,
|
||||
coverageThreshold: CoverageThreshold,
|
||||
dependencyExtractor: _typebox().Type.String(),
|
||||
detectLeaks: _typebox().Type.Boolean(),
|
||||
detectOpenHandles: _typebox().Type.Boolean(),
|
||||
displayName: _typebox().Type.Union([_typebox().Type.String(), DisplayName]),
|
||||
expand: _typebox().Type.Boolean(),
|
||||
extensionsToTreatAsEsm: _typebox().Type.Array(_typebox().Type.String()),
|
||||
fakeTimers: FakeTimers,
|
||||
filter: _typebox().Type.String(),
|
||||
findRelatedTests: _typebox().Type.Boolean(),
|
||||
forceCoverageMatch: _typebox().Type.Array(_typebox().Type.String()),
|
||||
forceExit: _typebox().Type.Boolean(),
|
||||
json: _typebox().Type.Boolean(),
|
||||
globals: _typebox().Type.Record(_typebox().Type.String(), _typebox().Type.Unknown()),
|
||||
globalSetup: _typebox().Type.Union([_typebox().Type.String(), _typebox().Type.Null()]),
|
||||
globalTeardown: _typebox().Type.Union([_typebox().Type.String(), _typebox().Type.Null()]),
|
||||
haste: HasteConfig,
|
||||
id: _typebox().Type.String(),
|
||||
injectGlobals: _typebox().Type.Boolean(),
|
||||
reporters: _typebox().Type.Array(_typebox().Type.Union([_typebox().Type.String(), _typebox().Type.Tuple([_typebox().Type.String(), _typebox().Type.Record(_typebox().Type.String(), _typebox().Type.Unknown())])])),
|
||||
logHeapUsage: _typebox().Type.Boolean(),
|
||||
lastCommit: _typebox().Type.Boolean(),
|
||||
listTests: _typebox().Type.Boolean(),
|
||||
maxConcurrency: _typebox().Type.Integer(),
|
||||
maxWorkers: _typebox().Type.Union([_typebox().Type.String(), _typebox().Type.Integer()]),
|
||||
moduleDirectories: _typebox().Type.Array(_typebox().Type.String()),
|
||||
moduleFileExtensions: _typebox().Type.Array(_typebox().Type.String()),
|
||||
moduleNameMapper: _typebox().Type.Record(_typebox().Type.String(), _typebox().Type.Union([_typebox().Type.String(), _typebox().Type.Array(_typebox().Type.String())])),
|
||||
modulePathIgnorePatterns: _typebox().Type.Array(_typebox().Type.String()),
|
||||
modulePaths: _typebox().Type.Array(_typebox().Type.String()),
|
||||
noStackTrace: _typebox().Type.Boolean(),
|
||||
notify: _typebox().Type.Boolean(),
|
||||
notifyMode: _typebox().Type.String(),
|
||||
onlyChanged: _typebox().Type.Boolean(),
|
||||
onlyFailures: _typebox().Type.Boolean(),
|
||||
openHandlesTimeout: _typebox().Type.Number(),
|
||||
outputFile: _typebox().Type.String(),
|
||||
passWithNoTests: _typebox().Type.Boolean(),
|
||||
preset: _typebox().Type.Union([_typebox().Type.String(), _typebox().Type.Null()]),
|
||||
prettierPath: _typebox().Type.Union([_typebox().Type.String(), _typebox().Type.Null()]),
|
||||
projects: _typebox().Type.Array(_typebox().Type.Union([_typebox().Type.String(),
|
||||
// TODO: Make sure to type these correctly
|
||||
_typebox().Type.Record(_typebox().Type.String(), _typebox().Type.Unknown())])),
|
||||
randomize: _typebox().Type.Boolean(),
|
||||
replname: _typebox().Type.Union([_typebox().Type.String(), _typebox().Type.Null()]),
|
||||
resetMocks: _typebox().Type.Boolean(),
|
||||
resetModules: _typebox().Type.Boolean(),
|
||||
resolver: _typebox().Type.Union([_typebox().Type.String(), _typebox().Type.Null()]),
|
||||
restoreMocks: _typebox().Type.Boolean(),
|
||||
rootDir: _typebox().Type.String(),
|
||||
roots: _typebox().Type.Array(_typebox().Type.String()),
|
||||
runner: _typebox().Type.Union([_typebox().Type.String(), _typebox().Type.Tuple([_typebox().Type.String(), _typebox().Type.Record(_typebox().Type.String(), _typebox().Type.Unknown())])]),
|
||||
runTestsByPath: _typebox().Type.Boolean(),
|
||||
runtime: _typebox().Type.String(),
|
||||
sandboxInjectedGlobals: _typebox().Type.Array(_typebox().Type.String()),
|
||||
setupFiles: _typebox().Type.Array(_typebox().Type.String()),
|
||||
setupFilesAfterEnv: _typebox().Type.Array(_typebox().Type.String()),
|
||||
showSeed: _typebox().Type.Boolean(),
|
||||
silent: _typebox().Type.Boolean(),
|
||||
skipFilter: _typebox().Type.Boolean(),
|
||||
skipNodeResolution: _typebox().Type.Boolean(),
|
||||
slowTestThreshold: _typebox().Type.Number(),
|
||||
snapshotResolver: _typebox().Type.String(),
|
||||
snapshotSerializers: _typebox().Type.Array(_typebox().Type.String()),
|
||||
snapshotFormat: SnapshotFormat,
|
||||
errorOnDeprecated: _typebox().Type.Boolean(),
|
||||
testEnvironment: _typebox().Type.String(),
|
||||
testEnvironmentOptions: _typebox().Type.Record(_typebox().Type.String(), _typebox().Type.Unknown()),
|
||||
testFailureExitCode: _typebox().Type.Integer(),
|
||||
testLocationInResults: _typebox().Type.Boolean(),
|
||||
testMatch: _typebox().Type.Union([_typebox().Type.String(), _typebox().Type.Array(_typebox().Type.String())]),
|
||||
testNamePattern: _typebox().Type.String(),
|
||||
testPathIgnorePatterns: _typebox().Type.Array(_typebox().Type.String()),
|
||||
testRegex: _typebox().Type.Union([_typebox().Type.String(), _typebox().Type.Array(_typebox().Type.String())]),
|
||||
testResultsProcessor: _typebox().Type.String(),
|
||||
testRunner: _typebox().Type.String(),
|
||||
testSequencer: _typebox().Type.String(),
|
||||
testTimeout: _typebox().Type.Number(),
|
||||
transform: _typebox().Type.Record(_typebox().Type.String(), _typebox().Type.Union([_typebox().Type.String(), _typebox().Type.Tuple([_typebox().Type.String(), _typebox().Type.Unknown()])])),
|
||||
transformIgnorePatterns: _typebox().Type.Array(_typebox().Type.String()),
|
||||
watchPathIgnorePatterns: _typebox().Type.Array(_typebox().Type.String()),
|
||||
unmockedModulePathPatterns: _typebox().Type.Array(_typebox().Type.String()),
|
||||
updateSnapshot: _typebox().Type.Boolean(),
|
||||
useStderr: _typebox().Type.Boolean(),
|
||||
verbose: _typebox().Type.Boolean(),
|
||||
waitForUnhandledRejections: _typebox().Type.Boolean(),
|
||||
watch: _typebox().Type.Boolean(),
|
||||
watchAll: _typebox().Type.Boolean(),
|
||||
watchman: _typebox().Type.Boolean(),
|
||||
watchPlugins: _typebox().Type.Array(_typebox().Type.Union([_typebox().Type.String(), _typebox().Type.Tuple([_typebox().Type.String(), _typebox().Type.Unknown()])])),
|
||||
workerIdleMemoryLimit: _typebox().Type.Union([_typebox().Type.Number(), _typebox().Type.String()]),
|
||||
workerThreads: _typebox().Type.Boolean(),
|
||||
workerGracefulExitTimeout: _typebox().Type.Number({
|
||||
description: 'Timeout in milliseconds for worker processes to exit gracefully after tests complete. Workers that do not exit in time are force-killed. Default: 500.'
|
||||
})
|
||||
}));
|
||||
|
||||
/***/ }
|
||||
|
||||
/******/ });
|
||||
/************************************************************************/
|
||||
/******/ // The module cache
|
||||
/******/ const __webpack_module_cache__ = {};
|
||||
/******/
|
||||
/******/ // The require function
|
||||
/******/ function __webpack_require__(moduleId) {
|
||||
/******/ // Check if module is in cache
|
||||
/******/ const cachedModule = __webpack_module_cache__[moduleId];
|
||||
/******/ if (cachedModule !== undefined) {
|
||||
/******/ return cachedModule.exports;
|
||||
/******/ }
|
||||
/******/ // Create a new module (and put it into the cache)
|
||||
/******/ const module = __webpack_module_cache__[moduleId] = {
|
||||
/******/ // no module.id needed
|
||||
/******/ // no module.loaded needed
|
||||
/******/ exports: {}
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // Execute the module function
|
||||
/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
|
||||
/******/
|
||||
/******/ // Return the exports of the module
|
||||
/******/ return module.exports;
|
||||
/******/ }
|
||||
/******/
|
||||
/************************************************************************/
|
||||
let __webpack_exports__ = {};
|
||||
// This entry needs to be wrapped in an IIFE because it uses a non-standard name for the exports (exports).
|
||||
(() => {
|
||||
let exports = __webpack_exports__;
|
||||
|
||||
|
||||
Object.defineProperty(exports, "__esModule", ({
|
||||
value: true
|
||||
}));
|
||||
exports.SnapshotFormat = exports.InitialOptions = exports.FakeTimers = void 0;
|
||||
var types = _interopRequireWildcard(__webpack_require__("./src/raw-types.ts"));
|
||||
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
const SnapshotFormat = exports.SnapshotFormat = types.SnapshotFormat;
|
||||
const InitialOptions = exports.InitialOptions = types.InitialOptions;
|
||||
const FakeTimers = exports.FakeTimers = types.FakeTimers;
|
||||
})();
|
||||
|
||||
module.exports = __webpack_exports__;
|
||||
/******/ })()
|
||||
;
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
import cjsModule from './index.js';
|
||||
|
||||
export const FakeTimers = cjsModule.FakeTimers;
|
||||
export const InitialOptions = cjsModule.InitialOptions;
|
||||
export const SnapshotFormat = cjsModule.SnapshotFormat;
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"name": "@jest/schemas",
|
||||
"version": "30.5.0",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/jestjs/jest.git",
|
||||
"directory": "packages/jest-schemas"
|
||||
},
|
||||
"license": "MIT",
|
||||
"main": "./build/index.js",
|
||||
"types": "./build/index.d.ts",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./build/index.d.ts",
|
||||
"require": "./build/index.js",
|
||||
"import": "./build/index.mjs",
|
||||
"default": "./build/index.js"
|
||||
},
|
||||
"./package.json": "./package.json"
|
||||
},
|
||||
"dependencies": {
|
||||
"@sinclair/typebox": "^0.34.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"gitHead": "912baa37afaa979e8179240c238cb493f960527a"
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
Copyright Contributors to the Jest project.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"extends": "../../api-extractor.json",
|
||||
"mainEntryPointFilePath": "/Users/simen/repos/jest/packages/jest-snapshot-utils/build/index.d.ts",
|
||||
"projectFolder": "/Users/simen/repos/jest/packages/jest-snapshot-utils"
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* 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 {Config} from '@jest/types';
|
||||
|
||||
export declare const ensureDirectoryExists: (filePath: string) => void;
|
||||
|
||||
export declare const escapeBacktickString: (str: string) => string;
|
||||
|
||||
export declare const getSnapshotData: (
|
||||
snapshotPath: string,
|
||||
update: Config.SnapshotUpdateState,
|
||||
) => {
|
||||
data: SnapshotData;
|
||||
dirty: boolean;
|
||||
};
|
||||
|
||||
export declare const keyToTestName: (key: string) => string;
|
||||
|
||||
export declare const normalizeNewlines: (string: string) => string;
|
||||
|
||||
export declare const saveSnapshotFile: (
|
||||
snapshotData: SnapshotData,
|
||||
snapshotPath: string,
|
||||
) => void;
|
||||
|
||||
export declare const SNAPSHOT_GUIDE_LINK =
|
||||
'https://jestjs.io/docs/snapshot-testing';
|
||||
|
||||
export declare const SNAPSHOT_VERSION = '1';
|
||||
|
||||
export declare const SNAPSHOT_VERSION_WARNING: string;
|
||||
|
||||
export declare type SnapshotData = Record<string, string>;
|
||||
|
||||
export declare const testNameToKey: (testName: string, count: number) => string;
|
||||
+227
@@ -0,0 +1,227 @@
|
||||
/*!
|
||||
* /**
|
||||
* * 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.
|
||||
* * /
|
||||
*/
|
||||
/******/ (() => { // webpackBootstrap
|
||||
/******/ "use strict";
|
||||
/******/ var __webpack_modules__ = ({
|
||||
|
||||
/***/ "./src/index.ts"
|
||||
(__unused_webpack_module, exports, __webpack_require__) {
|
||||
|
||||
|
||||
|
||||
Object.defineProperty(exports, "__esModule", ({
|
||||
value: true
|
||||
}));
|
||||
var _utils = __webpack_require__("./src/utils.ts");
|
||||
Object.keys(_utils).forEach(function (key) {
|
||||
if (key === "default" || key === "__esModule") return;
|
||||
if (key in exports && exports[key] === _utils[key]) return;
|
||||
Object.defineProperty(exports, key, {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _utils[key];
|
||||
}
|
||||
});
|
||||
});
|
||||
var _types = __webpack_require__("./src/types.ts");
|
||||
Object.keys(_types).forEach(function (key) {
|
||||
if (key === "default" || key === "__esModule") return;
|
||||
if (key in exports && exports[key] === _types[key]) return;
|
||||
Object.defineProperty(exports, key, {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _types[key];
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
/***/ },
|
||||
|
||||
/***/ "./src/types.ts"
|
||||
() {
|
||||
|
||||
|
||||
|
||||
/***/ },
|
||||
|
||||
/***/ "./src/utils.ts"
|
||||
(__unused_webpack_module, exports) {
|
||||
|
||||
|
||||
|
||||
Object.defineProperty(exports, "__esModule", ({
|
||||
value: true
|
||||
}));
|
||||
exports.testNameToKey = exports.saveSnapshotFile = exports.normalizeNewlines = exports.keyToTestName = exports.getSnapshotData = exports.escapeBacktickString = exports.ensureDirectoryExists = exports.SNAPSHOT_VERSION_WARNING = exports.SNAPSHOT_VERSION = exports.SNAPSHOT_GUIDE_LINK = void 0;
|
||||
var path = _interopRequireWildcard(require("node:path"));
|
||||
var _chalk = _interopRequireDefault(require("chalk"));
|
||||
var fs = _interopRequireWildcard(require("graceful-fs"));
|
||||
var _naturalCompare = _interopRequireDefault(require("natural-compare"));
|
||||
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
||||
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
|
||||
var Symbol = globalThis['jest-symbol-do-not-touch'] || globalThis.Symbol;
|
||||
var Symbol = globalThis['jest-symbol-do-not-touch'] || globalThis.Symbol;
|
||||
var jestWriteFile = globalThis[Symbol.for('jest-native-write-file')] || fs.writeFileSync;
|
||||
var Symbol = globalThis['jest-symbol-do-not-touch'] || globalThis.Symbol;
|
||||
var jestReadFile = globalThis[Symbol.for('jest-native-read-file')] || fs.readFileSync;
|
||||
var Symbol = globalThis['jest-symbol-do-not-touch'] || globalThis.Symbol;
|
||||
var jestExistsFile = globalThis[Symbol.for('jest-native-exists-file')] || fs.existsSync;
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
const SNAPSHOT_VERSION = exports.SNAPSHOT_VERSION = '1';
|
||||
const SNAPSHOT_HEADER_REGEXP = /^\/\/ Jest Snapshot v(.+), (.+)$/m;
|
||||
const SNAPSHOT_GUIDE_LINK = exports.SNAPSHOT_GUIDE_LINK = 'https://jestjs.io/docs/snapshot-testing';
|
||||
const SNAPSHOT_VERSION_WARNING = exports.SNAPSHOT_VERSION_WARNING = _chalk.default.yellow(`${_chalk.default.bold('Warning')}: Before you upgrade snapshots, ` + 'we recommend that you revert any local changes to tests or other code, ' + 'to ensure that you do not store invalid state.');
|
||||
const writeSnapshotVersion = () => `// Jest Snapshot v${SNAPSHOT_VERSION}, ${SNAPSHOT_GUIDE_LINK}`;
|
||||
const validateSnapshotHeader = snapshotContents => {
|
||||
const headerTest = SNAPSHOT_HEADER_REGEXP.exec(snapshotContents);
|
||||
const version = headerTest && headerTest[1];
|
||||
const guideLink = headerTest && headerTest[2];
|
||||
if (!version) {
|
||||
return new Error(_chalk.default.red(`${_chalk.default.bold('Outdated snapshot')}: No snapshot header found. ` + 'Jest 19 introduced versioned snapshots to ensure all developers ' + 'on a project are using the same version of Jest. ' + 'Please update all snapshots during this upgrade of Jest.\n\n') + SNAPSHOT_VERSION_WARNING);
|
||||
}
|
||||
if (version < SNAPSHOT_VERSION) {
|
||||
return new Error(
|
||||
// eslint-disable-next-line prefer-template
|
||||
_chalk.default.red(`${_chalk.default.red.bold('Outdated snapshot')}: The version of the snapshot ` + 'file associated with this test is outdated. The snapshot file ' + 'version ensures that all developers on a project are using ' + 'the same version of Jest. ' + 'Please update all snapshots during this upgrade of Jest.') + '\n\n' + `Expected: v${SNAPSHOT_VERSION}\n` + `Received: v${version}\n\n` + SNAPSHOT_VERSION_WARNING);
|
||||
}
|
||||
if (version > SNAPSHOT_VERSION) {
|
||||
return new Error(
|
||||
// eslint-disable-next-line prefer-template
|
||||
_chalk.default.red(`${_chalk.default.red.bold('Outdated Jest version')}: The version of this ` + 'snapshot file indicates that this project is meant to be used ' + 'with a newer version of Jest. The snapshot file version ensures ' + 'that all developers on a project are using the same version of ' + 'Jest. Please update your version of Jest and re-run the tests.') + '\n\n' + `Expected: v${SNAPSHOT_VERSION}\n` + `Received: v${version}`);
|
||||
}
|
||||
if (guideLink !== SNAPSHOT_GUIDE_LINK) {
|
||||
return new Error(
|
||||
// eslint-disable-next-line prefer-template
|
||||
_chalk.default.red(`${_chalk.default.red.bold('Outdated guide link')}: The snapshot guide link at the top of this snapshot is outdated. ` + 'Please update all snapshots during this upgrade of Jest.') + '\n\n' + `Expected: ${SNAPSHOT_GUIDE_LINK}\n` + `Received: ${guideLink}`);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
const normalizeTestNameForKey = testName => testName.replaceAll(/\r\n|\r|\n/g, match => {
|
||||
switch (match) {
|
||||
case '\r\n':
|
||||
return '\\r\\n';
|
||||
case '\r':
|
||||
return '\\r';
|
||||
case '\n':
|
||||
return '\\n';
|
||||
default:
|
||||
return match;
|
||||
}
|
||||
});
|
||||
const denormalizeTestNameFromKey = key => key.replaceAll(/\\r\\n|\\r|\\n/g, match => {
|
||||
switch (match) {
|
||||
case '\\r\\n':
|
||||
return '\r\n';
|
||||
case '\\r':
|
||||
return '\r';
|
||||
case '\\n':
|
||||
return '\n';
|
||||
default:
|
||||
return match;
|
||||
}
|
||||
});
|
||||
const testNameToKey = (testName, count) => `${normalizeTestNameForKey(testName)} ${count}`;
|
||||
exports.testNameToKey = testNameToKey;
|
||||
const keyToTestName = key => {
|
||||
if (!/ \d+$/.test(key)) {
|
||||
throw new Error('Snapshot keys must end with a number.');
|
||||
}
|
||||
const testNameWithoutCount = key.replace(/ \d+$/, '');
|
||||
return denormalizeTestNameFromKey(testNameWithoutCount);
|
||||
};
|
||||
exports.keyToTestName = keyToTestName;
|
||||
const getSnapshotData = (snapshotPath, update) => {
|
||||
const data = Object.create(null);
|
||||
let snapshotContents = '';
|
||||
let dirty = false;
|
||||
if (jestExistsFile(snapshotPath)) {
|
||||
try {
|
||||
snapshotContents = jestReadFile(snapshotPath, 'utf8');
|
||||
// eslint-disable-next-line no-new-func
|
||||
const populate = new Function('exports', snapshotContents);
|
||||
populate(data);
|
||||
} catch {}
|
||||
}
|
||||
const validationResult = validateSnapshotHeader(snapshotContents);
|
||||
const isInvalid = snapshotContents && validationResult;
|
||||
if (update === 'none' && isInvalid) {
|
||||
throw validationResult;
|
||||
}
|
||||
if ((update === 'all' || update === 'new') && isInvalid) {
|
||||
dirty = true;
|
||||
}
|
||||
return {
|
||||
data,
|
||||
dirty
|
||||
};
|
||||
};
|
||||
exports.getSnapshotData = getSnapshotData;
|
||||
const escapeBacktickString = str => str.replaceAll(/`|\\|\${/g, '\\$&');
|
||||
exports.escapeBacktickString = escapeBacktickString;
|
||||
const printBacktickString = str => `\`${escapeBacktickString(str)}\``;
|
||||
const ensureDirectoryExists = filePath => {
|
||||
try {
|
||||
fs.mkdirSync(path.dirname(filePath), {
|
||||
recursive: true
|
||||
});
|
||||
} catch {}
|
||||
};
|
||||
exports.ensureDirectoryExists = ensureDirectoryExists;
|
||||
const normalizeNewlines = string => string.replaceAll(/\r\n|\r/g, '\n');
|
||||
exports.normalizeNewlines = normalizeNewlines;
|
||||
const saveSnapshotFile = (snapshotData, snapshotPath) => {
|
||||
const snapshots = Object.keys(snapshotData).sort(_naturalCompare.default).map(key => `exports[${printBacktickString(key)}] = ${printBacktickString(normalizeNewlines(snapshotData[key]))};`);
|
||||
ensureDirectoryExists(snapshotPath);
|
||||
jestWriteFile(snapshotPath, `${writeSnapshotVersion()}\n\n${snapshots.join('\n\n')}\n`);
|
||||
};
|
||||
exports.saveSnapshotFile = saveSnapshotFile;
|
||||
|
||||
/***/ }
|
||||
|
||||
/******/ });
|
||||
/************************************************************************/
|
||||
/******/ // The module cache
|
||||
/******/ const __webpack_module_cache__ = {};
|
||||
/******/
|
||||
/******/ // The require function
|
||||
/******/ function __webpack_require__(moduleId) {
|
||||
/******/ // Check if module is in cache
|
||||
/******/ const cachedModule = __webpack_module_cache__[moduleId];
|
||||
/******/ if (cachedModule !== undefined) {
|
||||
/******/ return cachedModule.exports;
|
||||
/******/ }
|
||||
/******/ // Create a new module (and put it into the cache)
|
||||
/******/ const module = __webpack_module_cache__[moduleId] = {
|
||||
/******/ // no module.id needed
|
||||
/******/ // no module.loaded needed
|
||||
/******/ exports: {}
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // Execute the module function
|
||||
/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
|
||||
/******/
|
||||
/******/ // Return the exports of the module
|
||||
/******/ return module.exports;
|
||||
/******/ }
|
||||
/******/
|
||||
/************************************************************************/
|
||||
/******/
|
||||
/******/ // startup
|
||||
/******/ // Load entry module and return exports
|
||||
/******/ // This entry module is referenced by other modules so it can't be inlined
|
||||
/******/ let __webpack_exports__ = __webpack_require__("./src/index.ts");
|
||||
/******/ module.exports = __webpack_exports__;
|
||||
/******/
|
||||
/******/ })()
|
||||
;
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
import cjsModule from './index.js';
|
||||
|
||||
export const SNAPSHOT_GUIDE_LINK = cjsModule.SNAPSHOT_GUIDE_LINK;
|
||||
export const SNAPSHOT_VERSION = cjsModule.SNAPSHOT_VERSION;
|
||||
export const SNAPSHOT_VERSION_WARNING = cjsModule.SNAPSHOT_VERSION_WARNING;
|
||||
export const ensureDirectoryExists = cjsModule.ensureDirectoryExists;
|
||||
export const escapeBacktickString = cjsModule.escapeBacktickString;
|
||||
export const getSnapshotData = cjsModule.getSnapshotData;
|
||||
export const keyToTestName = cjsModule.keyToTestName;
|
||||
export const normalizeNewlines = cjsModule.normalizeNewlines;
|
||||
export const saveSnapshotFile = cjsModule.saveSnapshotFile;
|
||||
export const testNameToKey = cjsModule.testNameToKey;
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"name": "@jest/snapshot-utils",
|
||||
"version": "30.5.1",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/jestjs/jest.git",
|
||||
"directory": "packages/jest-snapshot-utils"
|
||||
},
|
||||
"license": "MIT",
|
||||
"main": "./build/index.js",
|
||||
"types": "./build/index.d.ts",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./build/index.d.ts",
|
||||
"require": "./build/index.js",
|
||||
"import": "./build/index.mjs",
|
||||
"default": "./build/index.js"
|
||||
},
|
||||
"./package.json": "./package.json"
|
||||
},
|
||||
"dependencies": {
|
||||
"@jest/types": "30.5.1",
|
||||
"chalk": "^4.1.2",
|
||||
"graceful-fs": "^4.2.11",
|
||||
"natural-compare": "^1.4.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/graceful-fs": "^4.1.9",
|
||||
"@types/natural-compare": "^1.4.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"gitHead": "9ab14feccd6c15fec1334dbcb03a53a079d153d3"
|
||||
}
|
||||
+239
@@ -0,0 +1,239 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
jest.mock('graceful-fs', () => ({
|
||||
...jest.createMockFromModule<typeof import('fs')>('fs'),
|
||||
existsSync: jest.fn().mockReturnValue(true),
|
||||
}));
|
||||
|
||||
import * as path from 'path';
|
||||
import chalk from 'chalk';
|
||||
import * as fs from 'graceful-fs';
|
||||
import {
|
||||
SNAPSHOT_GUIDE_LINK,
|
||||
SNAPSHOT_VERSION,
|
||||
SNAPSHOT_VERSION_WARNING,
|
||||
getSnapshotData,
|
||||
keyToTestName,
|
||||
saveSnapshotFile,
|
||||
testNameToKey,
|
||||
} from '../utils';
|
||||
|
||||
test('keyToTestName()', () => {
|
||||
expect(keyToTestName('abc cde 12')).toBe('abc cde');
|
||||
expect(keyToTestName('abc cde 12')).toBe('abc cde ');
|
||||
expect(keyToTestName('test with\\r\\nCRLF 1')).toBe('test with\r\nCRLF');
|
||||
expect(keyToTestName('test with\\rCR 1')).toBe('test with\rCR');
|
||||
expect(keyToTestName('test with\\nLF 1')).toBe('test with\nLF');
|
||||
expect(() => keyToTestName('abc cde')).toThrow(
|
||||
'Snapshot keys must end with a number.',
|
||||
);
|
||||
});
|
||||
|
||||
test('testNameToKey', () => {
|
||||
expect(testNameToKey('abc cde', 1)).toBe('abc cde 1');
|
||||
expect(testNameToKey('abc cde ', 12)).toBe('abc cde 12');
|
||||
});
|
||||
|
||||
test('testNameToKey escapes line endings to prevent collisions', () => {
|
||||
expect(testNameToKey('test with\r\nCRLF', 1)).toBe('test with\\r\\nCRLF 1');
|
||||
expect(testNameToKey('test with\rCR', 1)).toBe('test with\\rCR 1');
|
||||
expect(testNameToKey('test with\nLF', 1)).toBe('test with\\nLF 1');
|
||||
|
||||
expect(testNameToKey('test\r\n', 1)).not.toBe(testNameToKey('test\r', 1));
|
||||
expect(testNameToKey('test\r\n', 1)).not.toBe(testNameToKey('test\n', 1));
|
||||
expect(testNameToKey('test\r', 1)).not.toBe(testNameToKey('test\n', 1));
|
||||
});
|
||||
|
||||
test('keyToTestName reverses testNameToKey transformation', () => {
|
||||
const testCases = [
|
||||
'simple test',
|
||||
'test with\r\nCRLF',
|
||||
'test with\rCR only',
|
||||
'test with\nLF only',
|
||||
'mixed\r\nline\rendings\n',
|
||||
'test\r',
|
||||
'test\r\n',
|
||||
'test\n',
|
||||
];
|
||||
|
||||
for (const testName of testCases) {
|
||||
const key = testNameToKey(testName, 1);
|
||||
const recovered = keyToTestName(key);
|
||||
expect(recovered).toBe(testName);
|
||||
}
|
||||
});
|
||||
|
||||
test('saveSnapshotFile() works with \r\n', () => {
|
||||
const filename = path.join(__dirname, 'remove-newlines.snap');
|
||||
const data = {
|
||||
myKey: '<div>\r\n</div>',
|
||||
};
|
||||
|
||||
saveSnapshotFile(data, filename);
|
||||
expect(fs.writeFileSync).toHaveBeenCalledWith(
|
||||
filename,
|
||||
`// Jest Snapshot v1, ${SNAPSHOT_GUIDE_LINK}\n\n` +
|
||||
'exports[`myKey`] = `<div>\n</div>`;\n',
|
||||
);
|
||||
});
|
||||
|
||||
test('saveSnapshotFile() works with \r', () => {
|
||||
const filename = path.join(__dirname, 'remove-newlines.snap');
|
||||
const data = {
|
||||
myKey: '<div>\r</div>',
|
||||
};
|
||||
|
||||
saveSnapshotFile(data, filename);
|
||||
expect(fs.writeFileSync).toHaveBeenCalledWith(
|
||||
filename,
|
||||
`// Jest Snapshot v1, ${SNAPSHOT_GUIDE_LINK}\n\n` +
|
||||
'exports[`myKey`] = `<div>\n</div>`;\n',
|
||||
);
|
||||
});
|
||||
|
||||
test('getSnapshotData() throws when no snapshot version', () => {
|
||||
const filename = path.join(__dirname, 'old-snapshot.snap');
|
||||
jest
|
||||
.mocked(fs.readFileSync)
|
||||
.mockReturnValue('exports[`myKey`] = `<div>\n</div>`;\n');
|
||||
const update = 'none';
|
||||
|
||||
expect(() => getSnapshotData(filename, update)).toThrow(
|
||||
chalk.red(
|
||||
`${chalk.bold('Outdated snapshot')}: No snapshot header found. ` +
|
||||
'Jest 19 introduced versioned snapshots to ensure all developers on ' +
|
||||
'a project are using the same version of Jest. ' +
|
||||
'Please update all snapshots during this upgrade of Jest.\n\n',
|
||||
) + SNAPSHOT_VERSION_WARNING,
|
||||
);
|
||||
});
|
||||
|
||||
test('getSnapshotData() throws for older snapshot version', () => {
|
||||
const filename = path.join(__dirname, 'old-snapshot.snap');
|
||||
jest
|
||||
.mocked(fs.readFileSync)
|
||||
.mockReturnValue(
|
||||
`// Jest Snapshot v0.99, ${SNAPSHOT_GUIDE_LINK}\n\n` +
|
||||
'exports[`myKey`] = `<div>\n</div>`;\n',
|
||||
);
|
||||
const update = 'none';
|
||||
|
||||
expect(() => getSnapshotData(filename, update)).toThrow(
|
||||
`${chalk.red(
|
||||
`${chalk.red.bold('Outdated snapshot')}: The version of the snapshot ` +
|
||||
'file associated with this test is outdated. The snapshot file ' +
|
||||
'version ensures that all developers on a project are using ' +
|
||||
'the same version of Jest. ' +
|
||||
'Please update all snapshots during this upgrade of Jest.',
|
||||
)}\n\nExpected: v${SNAPSHOT_VERSION}\n` +
|
||||
`Received: v0.99\n\n${SNAPSHOT_VERSION_WARNING}`,
|
||||
);
|
||||
});
|
||||
|
||||
test.each([
|
||||
['Linux', '\n'],
|
||||
['Windows', '\r\n'],
|
||||
])(
|
||||
'getSnapshotData() throws for newer snapshot version with %s line endings',
|
||||
(_: string, fileEol: string) => {
|
||||
const filename = path.join(__dirname, 'old-snapshot.snap');
|
||||
jest
|
||||
.mocked(fs.readFileSync)
|
||||
.mockReturnValue(
|
||||
`// Jest Snapshot v2, ${SNAPSHOT_GUIDE_LINK}${fileEol}${fileEol}` +
|
||||
`exports[\`myKey\`] = \`<div>${fileEol}</div>\`;${fileEol}`,
|
||||
);
|
||||
const update = 'none';
|
||||
|
||||
expect(() => getSnapshotData(filename, update)).toThrow(
|
||||
`${chalk.red(
|
||||
`${chalk.red.bold('Outdated Jest version')}: The version of this ` +
|
||||
'snapshot file indicates that this project is meant to be used ' +
|
||||
'with a newer version of Jest. ' +
|
||||
'The snapshot file version ensures that all developers on a project ' +
|
||||
'are using the same version of Jest. ' +
|
||||
'Please update your version of Jest and re-run the tests.',
|
||||
)}\n\nExpected: v${SNAPSHOT_VERSION}\nReceived: v2`,
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
test('getSnapshotData() throws for deprecated snapshot guide link', () => {
|
||||
const deprecatedGuideLink = 'https://goo.gl/fbAQLP';
|
||||
const filename = path.join(__dirname, 'old-snapshot.snap');
|
||||
jest
|
||||
.mocked(fs.readFileSync)
|
||||
.mockReturnValue(
|
||||
`// Jest Snapshot v1, ${deprecatedGuideLink}\n\n` +
|
||||
'exports[`myKey`] = `<div>\n</div>`;\n',
|
||||
);
|
||||
const update = 'none';
|
||||
|
||||
expect(() => getSnapshotData(filename, update)).toThrow(
|
||||
`${chalk.red(
|
||||
`${chalk.red.bold(
|
||||
'Outdated guide link',
|
||||
)}: The snapshot guide link at the top of this snapshot is outdated. ` +
|
||||
'Please update all snapshots during this upgrade of Jest.',
|
||||
)}\n\nExpected: ${SNAPSHOT_GUIDE_LINK}\n` +
|
||||
`Received: ${deprecatedGuideLink}`,
|
||||
);
|
||||
});
|
||||
|
||||
test('getSnapshotData() does not throw for when updating', () => {
|
||||
const filename = path.join(__dirname, 'old-snapshot.snap');
|
||||
jest
|
||||
.mocked(fs.readFileSync)
|
||||
.mockReturnValue('exports[`myKey`] = `<div>\n</div>`;\n');
|
||||
const update = 'all';
|
||||
|
||||
expect(() => getSnapshotData(filename, update)).not.toThrow();
|
||||
});
|
||||
|
||||
test('getSnapshotData() marks invalid snapshot dirty when updating', () => {
|
||||
const filename = path.join(__dirname, 'old-snapshot.snap');
|
||||
jest
|
||||
.mocked(fs.readFileSync)
|
||||
.mockReturnValue('exports[`myKey`] = `<div>\n</div>`;\n');
|
||||
const update = 'all';
|
||||
|
||||
expect(getSnapshotData(filename, update)).toMatchObject({dirty: true});
|
||||
});
|
||||
|
||||
test('getSnapshotData() marks valid snapshot not dirty when updating', () => {
|
||||
const filename = path.join(__dirname, 'old-snapshot.snap');
|
||||
jest
|
||||
.mocked(fs.readFileSync)
|
||||
.mockReturnValue(
|
||||
`// Jest Snapshot v${SNAPSHOT_VERSION}, ${SNAPSHOT_GUIDE_LINK}\n\n` +
|
||||
'exports[`myKey`] = `<div>\n</div>`;\n',
|
||||
);
|
||||
const update = 'all';
|
||||
|
||||
expect(getSnapshotData(filename, update)).toMatchObject({dirty: false});
|
||||
});
|
||||
|
||||
test('escaping', () => {
|
||||
const filename = path.join(__dirname, 'escaping.snap');
|
||||
const data = '"\'\\';
|
||||
const writeFileSync = jest.mocked(fs.writeFileSync);
|
||||
|
||||
writeFileSync.mockReset();
|
||||
saveSnapshotFile({key: data}, filename);
|
||||
const writtenData = writeFileSync.mock.calls[0][1];
|
||||
expect(writtenData).toBe(
|
||||
`// Jest Snapshot v1, ${SNAPSHOT_GUIDE_LINK}\n\n` +
|
||||
'exports[`key`] = `"\'\\\\`;\n',
|
||||
);
|
||||
|
||||
// eslint-disable-next-line no-eval
|
||||
const readData = eval(`var exports = {}; ${writtenData} exports`);
|
||||
expect(readData).toEqual({key: data});
|
||||
const snapshotData = readData.key;
|
||||
expect(data).toEqual(snapshotData);
|
||||
});
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
/**
|
||||
* 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 * from './utils';
|
||||
export * from './types';
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
/**
|
||||
* 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 type SnapshotData = Record<string, string>;
|
||||
+200
@@ -0,0 +1,200 @@
|
||||
/**
|
||||
* 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 * as path from 'node:path';
|
||||
import chalk from 'chalk';
|
||||
import * as fs from 'graceful-fs';
|
||||
import naturalCompare from 'natural-compare';
|
||||
import type {Config} from '@jest/types';
|
||||
import type {SnapshotData} from './types';
|
||||
|
||||
export const SNAPSHOT_VERSION = '1';
|
||||
const SNAPSHOT_HEADER_REGEXP = /^\/\/ Jest Snapshot v(.+), (.+)$/m;
|
||||
export const SNAPSHOT_GUIDE_LINK = 'https://jestjs.io/docs/snapshot-testing';
|
||||
export const SNAPSHOT_VERSION_WARNING = chalk.yellow(
|
||||
`${chalk.bold('Warning')}: Before you upgrade snapshots, ` +
|
||||
'we recommend that you revert any local changes to tests or other code, ' +
|
||||
'to ensure that you do not store invalid state.',
|
||||
);
|
||||
|
||||
const writeSnapshotVersion = () =>
|
||||
`// Jest Snapshot v${SNAPSHOT_VERSION}, ${SNAPSHOT_GUIDE_LINK}`;
|
||||
|
||||
const validateSnapshotHeader = (snapshotContents: string) => {
|
||||
const headerTest = SNAPSHOT_HEADER_REGEXP.exec(snapshotContents);
|
||||
const version = headerTest && headerTest[1];
|
||||
const guideLink = headerTest && headerTest[2];
|
||||
|
||||
if (!version) {
|
||||
return new Error(
|
||||
chalk.red(
|
||||
`${chalk.bold('Outdated snapshot')}: No snapshot header found. ` +
|
||||
'Jest 19 introduced versioned snapshots to ensure all developers ' +
|
||||
'on a project are using the same version of Jest. ' +
|
||||
'Please update all snapshots during this upgrade of Jest.\n\n',
|
||||
) + SNAPSHOT_VERSION_WARNING,
|
||||
);
|
||||
}
|
||||
|
||||
if (version < SNAPSHOT_VERSION) {
|
||||
return new Error(
|
||||
// eslint-disable-next-line prefer-template
|
||||
chalk.red(
|
||||
`${chalk.red.bold('Outdated snapshot')}: The version of the snapshot ` +
|
||||
'file associated with this test is outdated. The snapshot file ' +
|
||||
'version ensures that all developers on a project are using ' +
|
||||
'the same version of Jest. ' +
|
||||
'Please update all snapshots during this upgrade of Jest.',
|
||||
) +
|
||||
'\n\n' +
|
||||
`Expected: v${SNAPSHOT_VERSION}\n` +
|
||||
`Received: v${version}\n\n` +
|
||||
SNAPSHOT_VERSION_WARNING,
|
||||
);
|
||||
}
|
||||
|
||||
if (version > SNAPSHOT_VERSION) {
|
||||
return new Error(
|
||||
// eslint-disable-next-line prefer-template
|
||||
chalk.red(
|
||||
`${chalk.red.bold('Outdated Jest version')}: The version of this ` +
|
||||
'snapshot file indicates that this project is meant to be used ' +
|
||||
'with a newer version of Jest. The snapshot file version ensures ' +
|
||||
'that all developers on a project are using the same version of ' +
|
||||
'Jest. Please update your version of Jest and re-run the tests.',
|
||||
) +
|
||||
'\n\n' +
|
||||
`Expected: v${SNAPSHOT_VERSION}\n` +
|
||||
`Received: v${version}`,
|
||||
);
|
||||
}
|
||||
|
||||
if (guideLink !== SNAPSHOT_GUIDE_LINK) {
|
||||
return new Error(
|
||||
// eslint-disable-next-line prefer-template
|
||||
chalk.red(
|
||||
`${chalk.red.bold(
|
||||
'Outdated guide link',
|
||||
)}: The snapshot guide link at the top of this snapshot is outdated. ` +
|
||||
'Please update all snapshots during this upgrade of Jest.',
|
||||
) +
|
||||
'\n\n' +
|
||||
`Expected: ${SNAPSHOT_GUIDE_LINK}\n` +
|
||||
`Received: ${guideLink}`,
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
const normalizeTestNameForKey = (testName: string): string =>
|
||||
testName.replaceAll(/\r\n|\r|\n/g, match => {
|
||||
switch (match) {
|
||||
case '\r\n':
|
||||
return '\\r\\n';
|
||||
case '\r':
|
||||
return '\\r';
|
||||
case '\n':
|
||||
return '\\n';
|
||||
default:
|
||||
return match;
|
||||
}
|
||||
});
|
||||
|
||||
const denormalizeTestNameFromKey = (key: string): string =>
|
||||
key.replaceAll(/\\r\\n|\\r|\\n/g, match => {
|
||||
switch (match) {
|
||||
case '\\r\\n':
|
||||
return '\r\n';
|
||||
case '\\r':
|
||||
return '\r';
|
||||
case '\\n':
|
||||
return '\n';
|
||||
default:
|
||||
return match;
|
||||
}
|
||||
});
|
||||
|
||||
export const testNameToKey = (testName: string, count: number): string =>
|
||||
`${normalizeTestNameForKey(testName)} ${count}`;
|
||||
|
||||
export const keyToTestName = (key: string): string => {
|
||||
if (!/ \d+$/.test(key)) {
|
||||
throw new Error('Snapshot keys must end with a number.');
|
||||
}
|
||||
const testNameWithoutCount = key.replace(/ \d+$/, '');
|
||||
return denormalizeTestNameFromKey(testNameWithoutCount);
|
||||
};
|
||||
|
||||
export const getSnapshotData = (
|
||||
snapshotPath: string,
|
||||
update: Config.SnapshotUpdateState,
|
||||
): {
|
||||
data: SnapshotData;
|
||||
dirty: boolean;
|
||||
} => {
|
||||
const data = Object.create(null);
|
||||
let snapshotContents = '';
|
||||
let dirty = false;
|
||||
|
||||
if (fs.existsSync(snapshotPath)) {
|
||||
try {
|
||||
snapshotContents = fs.readFileSync(snapshotPath, 'utf8');
|
||||
// eslint-disable-next-line no-new-func
|
||||
const populate = new Function('exports', snapshotContents);
|
||||
populate(data);
|
||||
} catch {}
|
||||
}
|
||||
|
||||
const validationResult = validateSnapshotHeader(snapshotContents);
|
||||
const isInvalid = snapshotContents && validationResult;
|
||||
|
||||
if (update === 'none' && isInvalid) {
|
||||
throw validationResult;
|
||||
}
|
||||
|
||||
if ((update === 'all' || update === 'new') && isInvalid) {
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
return {data, dirty};
|
||||
};
|
||||
|
||||
export const escapeBacktickString = (str: string): string =>
|
||||
str.replaceAll(/`|\\|\${/g, '\\$&');
|
||||
|
||||
const printBacktickString = (str: string): string =>
|
||||
`\`${escapeBacktickString(str)}\``;
|
||||
|
||||
export const ensureDirectoryExists = (filePath: string): void => {
|
||||
try {
|
||||
fs.mkdirSync(path.dirname(filePath), {recursive: true});
|
||||
} catch {}
|
||||
};
|
||||
|
||||
export const normalizeNewlines = (string: string): string =>
|
||||
string.replaceAll(/\r\n|\r/g, '\n');
|
||||
|
||||
export const saveSnapshotFile = (
|
||||
snapshotData: SnapshotData,
|
||||
snapshotPath: string,
|
||||
): void => {
|
||||
const snapshots = Object.keys(snapshotData)
|
||||
.sort(naturalCompare)
|
||||
.map(
|
||||
key =>
|
||||
`exports[${printBacktickString(key)}] = ${printBacktickString(
|
||||
normalizeNewlines(snapshotData[key]),
|
||||
)};`,
|
||||
);
|
||||
|
||||
ensureDirectoryExists(snapshotPath);
|
||||
fs.writeFileSync(
|
||||
snapshotPath,
|
||||
`${writeSnapshotVersion()}\n\n${snapshots.join('\n\n')}\n`,
|
||||
);
|
||||
};
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"rootDir": "src",
|
||||
"outDir": "build"
|
||||
},
|
||||
"include": ["./src/**/*"],
|
||||
"exclude": ["./**/__mocks__/**/*", "./**/__tests__/**/*"],
|
||||
"references": [{"path": "../jest-types"}]
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
Copyright Contributors to the Jest project.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
# @jest/source-map
|
||||
|
||||
Applies source maps to stack traces, so a failing test points at the code you wrote rather than at the code Jest ran.
|
||||
|
||||
This is a module used internally by Jest. It exists because `--enable-source-maps` and `module.setSourceMapsSupport()` do not cover code compiled through `vm`, which is how Jest evaluates test files, and because Node offers no way to register a map for a filename — Jest serves maps from its own transform pipeline rather than from `sourceMappingURL` comments on disk.
|
||||
|
||||
## Install
|
||||
|
||||
```sh
|
||||
$ npm install --save @jest/source-map
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
### `SourceMapSupport#install(sourceMaps?: SourceMapRegistry | null, options?: SourceMapSupportInstallOptions): void`
|
||||
|
||||
Replaces `Error.prepareStackTrace` in the current realm, so reading `.stack` on any error renders frames against the original sources. `jest-runner` holds one instance per worker and installs once per test file.
|
||||
|
||||
`sourceMaps` maps a transformed file to the `.map` file Jest wrote into its transform cache — inside Jest, `runtime.getSourceMaps()`. The `sources` inside a map resolve with URL semantics against the transformed file, not against the map's own location. Files missing from the registry fall back to a `sourceMappingURL` comment on the file itself, which covers pre-compiled output that ships its own map.
|
||||
|
||||
```javascript
|
||||
import {SourceMapSupport} from '@jest/source-map';
|
||||
|
||||
const sourceMapSupport = new SourceMapSupport();
|
||||
sourceMapSupport.install(new Map([['/build/app.js', '/cache/app.js.map']]));
|
||||
|
||||
new Error('boom').stack;
|
||||
// Error: boom
|
||||
// at greet (/src/app.ts:12:9)
|
||||
```
|
||||
|
||||
The formatter stays installed for the lifetime of the process, and each call swaps in a new registry. Nothing is restored, deliberately: an error thrown after a test finishes — a stray timer, a floating promise — is the one users have the hardest time placing, and it would otherwise report a position in the transformed file.
|
||||
|
||||
A map that cannot be parsed is reported once via `console.warn`; pass `{suppressWarnings: true}` to turn that off.
|
||||
|
||||
### `SourceMapSupport#getCallsite(level: number, sourceMaps?: SourceMapRegistry | null): CallSite`
|
||||
|
||||
Returns a single remapped [`CallSite`](https://v8.dev/docs/stack-trace-api#customizing-stack-traces), `level` frames above the caller. Used for `--testLocationInResults`. Shares its parsed maps with the installed formatter, so each `.map` file is read once.
|
||||
|
||||
### `getCallsite(level: number, sourceMaps?: SourceMapRegistry | null): CallSite`
|
||||
|
||||
Deprecated free-function alias of `SourceMapSupport#getCallsite`.
|
||||
|
||||
### `SourceMapRegistry`
|
||||
|
||||
`Map<string, string>` — transformed file path to source map path.
|
||||
|
||||
## Function names are chosen for readability, not for the spec
|
||||
|
||||
A frame is named after the source map's `name` at the frame's **own** position. That name is the identifier being _called_ there rather than the enclosing function, so every frame gets annotated with the call on its line:
|
||||
|
||||
```
|
||||
at Object.toBeTruthy (assertionCount.test.js:12:17)
|
||||
at Object.setTimeout (inside.js:9:3)
|
||||
```
|
||||
|
||||
The spec-correct reading takes the name from the _caller's_ position instead. It is what [`source-map-support@0.5.14`](https://github.com/evanw/node-source-map-support/pull/253) switched to, and it collapses the frames above to `Object.<anonymous>`, because V8 has no name of its own for a module-level frame. Positions are identical either way — only names differ, and only where V8 could not name the frame.
|
||||
|
||||
This package optimises for reading a test failure, so it keeps the annotation. If you need the spec semantics, `getCallsite` hands back a `CallSite` you can map yourself.
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
/**
|
||||
* 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 callsites from 'callsites';
|
||||
|
||||
/**
|
||||
* One remapped `CallSite`, `level` frames above the caller.
|
||||
*
|
||||
* @deprecated Use `SourceMapSupport#getCallsite` instead.
|
||||
*/
|
||||
export declare function getCallsite(
|
||||
level: number,
|
||||
sourceMaps?: SourceMapRegistry | null,
|
||||
): callsites.CallSite;
|
||||
|
||||
/** Transformed file path to the map file written for it. */
|
||||
export declare type SourceMapRegistry = ReadonlyMap<string, string>;
|
||||
|
||||
export declare class SourceMapSupport {
|
||||
private activeCache;
|
||||
private nullCache;
|
||||
private readonly cachesByRegistry;
|
||||
private suppressWarnings;
|
||||
private readonly reportedMapPaths;
|
||||
private readonly boundFormatStackTrace;
|
||||
constructor();
|
||||
/**
|
||||
* Replaces `Error.prepareStackTrace` in the current realm, so `error.stack`
|
||||
* renders frames against the original sources.
|
||||
*
|
||||
* Stays installed for the lifetime of the worker — each call swaps in its
|
||||
* own cache. There is deliberately no `uninstall`: restoring V8's formatter
|
||||
* at teardown would leave an error thrown after the environment is torn
|
||||
* down pointing into the transformed file. Holding the cache does not
|
||||
* retain the environment: it only ever references path strings and parsed
|
||||
* source maps.
|
||||
*/
|
||||
install(
|
||||
sourceMaps?: SourceMapRegistry | null,
|
||||
options?: SourceMapSupportInstallOptions,
|
||||
): void;
|
||||
/** One remapped `CallSite`, `level` frames above the caller. */
|
||||
getCallsite(
|
||||
level: number,
|
||||
sourceMaps?: SourceMapRegistry | null,
|
||||
): callsites.CallSite;
|
||||
private cacheFor;
|
||||
private reportUnparsable;
|
||||
private formatStackTrace;
|
||||
}
|
||||
|
||||
export declare interface SourceMapSupportInstallOptions {
|
||||
/** Turns off the once-per-map warning about maps that cannot be parsed. */
|
||||
suppressWarnings?: boolean;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user