This commit is contained in:
Iliyan Angelov
2025-09-14 23:24:25 +03:00
commit c67067a2a4
71311 changed files with 6800714 additions and 0 deletions

21
frontend/node_modules/jest-snapshot/LICENSE generated vendored Normal file
View File

@@ -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.

View File

@@ -0,0 +1,15 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import type { Expression } from '@babel/types';
import type { Config } from '@jest/types';
import type { Frame } from 'jest-message-util';
export declare type InlineSnapshot = {
snapshot: string;
frame: Frame;
node?: Expression;
};
export declare function saveInlineSnapshots(snapshots: Array<InlineSnapshot>, prettierPath: Config.Path): void;

View File

@@ -0,0 +1,503 @@
'use strict';
Object.defineProperty(exports, '__esModule', {
value: true
});
exports.saveInlineSnapshots = saveInlineSnapshots;
var path = _interopRequireWildcard(require('path'));
var fs = _interopRequireWildcard(require('graceful-fs'));
var _semver = _interopRequireDefault(require('semver'));
var _utils = require('./utils');
function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : {default: obj};
}
function _getRequireWildcardCache(nodeInterop) {
if (typeof WeakMap !== 'function') return null;
var cacheBabelInterop = new WeakMap();
var cacheNodeInterop = new WeakMap();
return (_getRequireWildcardCache = function (nodeInterop) {
return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
})(nodeInterop);
}
function _interopRequireWildcard(obj, nodeInterop) {
if (!nodeInterop && obj && obj.__esModule) {
return obj;
}
if (obj === null || (typeof obj !== 'object' && typeof obj !== 'function')) {
return {default: obj};
}
var cache = _getRequireWildcardCache(nodeInterop);
if (cache && cache.has(obj)) {
return cache.get(obj);
}
var newObj = {};
var hasPropertyDescriptor =
Object.defineProperty && Object.getOwnPropertyDescriptor;
for (var key in obj) {
if (key !== 'default' && Object.prototype.hasOwnProperty.call(obj, key)) {
var desc = hasPropertyDescriptor
? Object.getOwnPropertyDescriptor(obj, key)
: null;
if (desc && (desc.get || desc.set)) {
Object.defineProperty(newObj, key, desc);
} else {
newObj[key] = obj[key];
}
}
}
newObj.default = obj;
if (cache) {
cache.set(obj, newObj);
}
return newObj;
}
var global = (function () {
if (typeof globalThis !== 'undefined') {
return globalThis;
} else if (typeof global !== 'undefined') {
return global;
} else if (typeof self !== 'undefined') {
return self;
} else if (typeof window !== 'undefined') {
return window;
} else {
return Function('return this')();
}
})();
var Symbol = global['jest-symbol-do-not-touch'] || global.Symbol;
var global = (function () {
if (typeof globalThis !== 'undefined') {
return globalThis;
} else if (typeof global !== 'undefined') {
return global;
} else if (typeof self !== 'undefined') {
return self;
} else if (typeof window !== 'undefined') {
return window;
} else {
return Function('return this')();
}
})();
var Symbol = global['jest-symbol-do-not-touch'] || global.Symbol;
var global = (function () {
if (typeof globalThis !== 'undefined') {
return globalThis;
} else if (typeof global !== 'undefined') {
return global;
} else if (typeof self !== 'undefined') {
return self;
} else if (typeof window !== 'undefined') {
return window;
} else {
return Function('return this')();
}
})();
var jestWriteFile =
global[Symbol.for('jest-native-write-file')] || fs.writeFileSync;
var global = (function () {
if (typeof globalThis !== 'undefined') {
return globalThis;
} else if (typeof global !== 'undefined') {
return global;
} else if (typeof self !== 'undefined') {
return self;
} else if (typeof window !== 'undefined') {
return window;
} else {
return Function('return this')();
}
})();
var Symbol = global['jest-symbol-do-not-touch'] || global.Symbol;
var global = (function () {
if (typeof globalThis !== 'undefined') {
return globalThis;
} else if (typeof global !== 'undefined') {
return global;
} else if (typeof self !== 'undefined') {
return self;
} else if (typeof window !== 'undefined') {
return window;
} else {
return Function('return this')();
}
})();
var jestReadFile =
global[Symbol.for('jest-native-read-file')] || fs.readFileSync;
// prettier-ignore
const babelTraverse = // @ts-expect-error requireOutside Babel transform
require(require.resolve('@babel/traverse', {
[(global['jest-symbol-do-not-touch'] || global.Symbol).for('jest-resolve-outside-vm-option')]: true
})).default; // prettier-ignore
const generate = require(require.resolve('@babel/generator', { // @ts-expect-error requireOutside Babel transform
[(global['jest-symbol-do-not-touch'] || global.Symbol).for(
'jest-resolve-outside-vm-option'
)]: true
})).default; // @ts-expect-error requireOutside Babel transform
const {file, templateElement, templateLiteral} = require(require.resolve(
'@babel/types',
{
[(global['jest-symbol-do-not-touch'] || global.Symbol).for(
'jest-resolve-outside-vm-option'
)]: true
}
)); // @ts-expect-error requireOutside Babel transform
const {parseSync} = require(require.resolve('@babel/core', {
[(global['jest-symbol-do-not-touch'] || global.Symbol).for(
'jest-resolve-outside-vm-option'
)]: true
}));
function saveInlineSnapshots(snapshots, prettierPath) {
let prettier = null;
if (prettierPath) {
try {
// @ts-expect-error requireOutside Babel transform
prettier = require(require.resolve(prettierPath, {
[(global['jest-symbol-do-not-touch'] || global.Symbol).for(
'jest-resolve-outside-vm-option'
)]: true
}));
} catch {
// Continue even if prettier is not installed.
}
}
const snapshotsByFile = groupSnapshotsByFile(snapshots);
for (const sourceFilePath of Object.keys(snapshotsByFile)) {
saveSnapshotsForFile(
snapshotsByFile[sourceFilePath],
sourceFilePath,
prettier && _semver.default.gte(prettier.version, '1.5.0')
? prettier
: undefined
);
}
}
const saveSnapshotsForFile = (snapshots, sourceFilePath, prettier) => {
const sourceFile = jestReadFile(sourceFilePath, 'utf8'); // TypeScript projects may not have a babel config; make sure they can be parsed anyway.
const presets = [require.resolve('babel-preset-current-node-syntax')];
const plugins = [];
if (/\.tsx?$/.test(sourceFilePath)) {
plugins.push([
require.resolve('@babel/plugin-syntax-typescript'),
{
isTSX: sourceFilePath.endsWith('x')
}, // unique name to make sure Babel does not complain about a possible duplicate plugin.
'TypeScript syntax plugin added by Jest snapshot'
]);
} // Record the matcher names seen during traversal and pass them down one
// by one to formatting parser.
const snapshotMatcherNames = [];
const ast = parseSync(sourceFile, {
filename: sourceFilePath,
plugins,
presets,
root: path.dirname(sourceFilePath)
});
if (!ast) {
throw new Error(`jest-snapshot: Failed to parse ${sourceFilePath}`);
}
traverseAst(snapshots, ast, snapshotMatcherNames); // substitute in the snapshots in reverse order, so slice calculations aren't thrown off.
const sourceFileWithSnapshots = snapshots.reduceRight(
(sourceSoFar, nextSnapshot) => {
if (
!nextSnapshot.node ||
typeof nextSnapshot.node.start !== 'number' ||
typeof nextSnapshot.node.end !== 'number'
) {
throw new Error('Jest: no snapshot insert location found');
}
return (
sourceSoFar.slice(0, nextSnapshot.node.start) +
generate(nextSnapshot.node, {
retainLines: true
}).code.trim() +
sourceSoFar.slice(nextSnapshot.node.end)
);
},
sourceFile
);
const newSourceFile = prettier
? runPrettier(
prettier,
sourceFilePath,
sourceFileWithSnapshots,
snapshotMatcherNames
)
: sourceFileWithSnapshots;
if (newSourceFile !== sourceFile) {
jestWriteFile(sourceFilePath, newSourceFile);
}
};
const groupSnapshotsBy = createKey => snapshots =>
snapshots.reduce((object, inlineSnapshot) => {
const key = createKey(inlineSnapshot);
return {...object, [key]: (object[key] || []).concat(inlineSnapshot)};
}, {});
const groupSnapshotsByFrame = groupSnapshotsBy(({frame: {line, column}}) =>
typeof line === 'number' && typeof column === 'number'
? `${line}:${column - 1}`
: ''
);
const groupSnapshotsByFile = groupSnapshotsBy(({frame: {file}}) => file);
const indent = (snapshot, numIndents, indentation) => {
const lines = snapshot.split('\n'); // Prevent re-indentation of inline snapshots.
if (
lines.length >= 2 &&
lines[1].startsWith(indentation.repeat(numIndents + 1))
) {
return snapshot;
}
return lines
.map((line, index) => {
if (index === 0) {
// First line is either a 1-line snapshot or a blank line.
return line;
} else if (index !== lines.length - 1) {
// Do not indent empty lines.
if (line === '') {
return line;
} // Not last line, indent one level deeper than expect call.
return indentation.repeat(numIndents + 1) + line;
} else {
// The last line should be placed on the same level as the expect call.
return indentation.repeat(numIndents) + line;
}
})
.join('\n');
};
const resolveAst = fileOrProgram => {
// Flow uses a 'Program' parent node, babel expects a 'File'.
let ast = fileOrProgram;
if (ast.type !== 'File') {
ast = file(ast, ast.comments, ast.tokens);
delete ast.program.comments;
}
return ast;
};
const traverseAst = (snapshots, fileOrProgram, snapshotMatcherNames) => {
const ast = resolveAst(fileOrProgram);
const groupedSnapshots = groupSnapshotsByFrame(snapshots);
const remainingSnapshots = new Set(snapshots.map(({snapshot}) => snapshot));
babelTraverse(ast, {
CallExpression({node}) {
const {arguments: args, callee} = node;
if (
callee.type !== 'MemberExpression' ||
callee.property.type !== 'Identifier' ||
callee.property.loc == null
) {
return;
}
const {line, column} = callee.property.loc.start;
const snapshotsForFrame = groupedSnapshots[`${line}:${column}`];
if (!snapshotsForFrame) {
return;
}
if (snapshotsForFrame.length > 1) {
throw new Error(
'Jest: Multiple inline snapshots for the same call are not supported.'
);
}
snapshotMatcherNames.push(callee.property.name);
const snapshotIndex = args.findIndex(
({type}) => type === 'TemplateLiteral'
);
const values = snapshotsForFrame.map(inlineSnapshot => {
inlineSnapshot.node = node;
const {snapshot} = inlineSnapshot;
remainingSnapshots.delete(snapshot);
return templateLiteral(
[
templateElement({
raw: (0, _utils.escapeBacktickString)(snapshot)
})
],
[]
);
});
const replacementNode = values[0];
if (snapshotIndex > -1) {
args[snapshotIndex] = replacementNode;
} else {
args.push(replacementNode);
}
}
});
if (remainingSnapshots.size) {
throw new Error("Jest: Couldn't locate all inline snapshots.");
}
};
const runPrettier = (
prettier,
sourceFilePath,
sourceFileWithSnapshots,
snapshotMatcherNames
) => {
// Resolve project configuration.
// For older versions of Prettier, do not load configuration.
const config = prettier.resolveConfig
? prettier.resolveConfig.sync(sourceFilePath, {
editorconfig: true
})
: null; // Detect the parser for the test file.
// For older versions of Prettier, fallback to a simple parser detection.
// @ts-expect-error
const inferredParser = prettier.getFileInfo
? prettier.getFileInfo.sync(sourceFilePath).inferredParser
: (config && typeof config.parser === 'string' && config.parser) ||
simpleDetectParser(sourceFilePath);
if (!inferredParser) {
throw new Error(
`Could not infer Prettier parser for file ${sourceFilePath}`
);
} // Snapshots have now been inserted. Run prettier to make sure that the code is
// formatted, except snapshot indentation. Snapshots cannot be formatted until
// after the initial format because we don't know where the call expression
// will be placed (specifically its indentation), so we have to do two
// prettier.format calls back-to-back.
return prettier.format(
prettier.format(sourceFileWithSnapshots, {
...config,
filepath: sourceFilePath
}),
{
...config,
filepath: sourceFilePath,
parser: createFormattingParser(snapshotMatcherNames, inferredParser)
}
);
}; // This parser formats snapshots to the correct indentation.
const createFormattingParser =
(snapshotMatcherNames, inferredParser) => (text, parsers, options) => {
// Workaround for https://github.com/prettier/prettier/issues/3150
options.parser = inferredParser;
const ast = resolveAst(parsers[inferredParser](text, options));
babelTraverse(ast, {
CallExpression({node: {arguments: args, callee}}) {
var _options$tabWidth, _options$tabWidth2;
if (
callee.type !== 'MemberExpression' ||
callee.property.type !== 'Identifier' ||
!snapshotMatcherNames.includes(callee.property.name) ||
!callee.loc ||
callee.computed
) {
return;
}
let snapshotIndex;
let snapshot;
for (let i = 0; i < args.length; i++) {
const node = args[i];
if (node.type === 'TemplateLiteral') {
snapshotIndex = i;
snapshot = node.quasis[0].value.raw;
}
}
if (snapshot === undefined || snapshotIndex === undefined) {
return;
}
const useSpaces = !options.useTabs;
snapshot = indent(
snapshot,
Math.ceil(
useSpaces
? callee.loc.start.column /
((_options$tabWidth = options.tabWidth) !== null &&
_options$tabWidth !== void 0
? _options$tabWidth
: 1)
: callee.loc.start.column / 2 // Each tab is 2 characters.
),
useSpaces
? ' '.repeat(
(_options$tabWidth2 = options.tabWidth) !== null &&
_options$tabWidth2 !== void 0
? _options$tabWidth2
: 1
)
: '\t'
);
const replacementNode = templateLiteral(
[
templateElement({
raw: snapshot
})
],
[]
);
args[snapshotIndex] = replacementNode;
}
});
return ast;
};
const simpleDetectParser = filePath => {
const extname = path.extname(filePath);
if (/\.tsx?$/.test(extname)) {
return 'typescript';
}
return 'babel';
};

View File

@@ -0,0 +1,18 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import type { Config } from '@jest/types';
export declare type SnapshotResolver = {
testPathForConsistencyCheck: string;
resolveSnapshotPath(testPath: Config.Path, extension?: string): Config.Path;
resolveTestPath(snapshotPath: Config.Path, extension?: string): Config.Path;
};
export declare const EXTENSION = "snap";
export declare const DOT_EXTENSION: string;
export declare const isSnapshotPath: (path: string) => boolean;
declare type LocalRequire = (module: string) => unknown;
export declare const buildSnapshotResolver: (config: Config.ProjectConfig, localRequire?: Promise<LocalRequire> | LocalRequire) => Promise<SnapshotResolver>;
export {};

View File

@@ -0,0 +1,179 @@
'use strict';
Object.defineProperty(exports, '__esModule', {
value: true
});
exports.isSnapshotPath =
exports.buildSnapshotResolver =
exports.EXTENSION =
exports.DOT_EXTENSION =
void 0;
var path = _interopRequireWildcard(require('path'));
var _chalk = _interopRequireDefault(require('chalk'));
var _transform = require('@jest/transform');
var _jestUtil = require('jest-util');
function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : {default: obj};
}
function _getRequireWildcardCache(nodeInterop) {
if (typeof WeakMap !== 'function') return null;
var cacheBabelInterop = new WeakMap();
var cacheNodeInterop = new WeakMap();
return (_getRequireWildcardCache = function (nodeInterop) {
return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
})(nodeInterop);
}
function _interopRequireWildcard(obj, nodeInterop) {
if (!nodeInterop && obj && obj.__esModule) {
return obj;
}
if (obj === null || (typeof obj !== 'object' && typeof obj !== 'function')) {
return {default: obj};
}
var cache = _getRequireWildcardCache(nodeInterop);
if (cache && cache.has(obj)) {
return cache.get(obj);
}
var newObj = {};
var hasPropertyDescriptor =
Object.defineProperty && Object.getOwnPropertyDescriptor;
for (var key in obj) {
if (key !== 'default' && Object.prototype.hasOwnProperty.call(obj, key)) {
var desc = hasPropertyDescriptor
? Object.getOwnPropertyDescriptor(obj, key)
: null;
if (desc && (desc.get || desc.set)) {
Object.defineProperty(newObj, key, desc);
} else {
newObj[key] = obj[key];
}
}
}
newObj.default = obj;
if (cache) {
cache.set(obj, newObj);
}
return newObj;
}
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
const EXTENSION = 'snap';
exports.EXTENSION = EXTENSION;
const DOT_EXTENSION = '.' + EXTENSION;
exports.DOT_EXTENSION = DOT_EXTENSION;
const isSnapshotPath = path => path.endsWith(DOT_EXTENSION);
exports.isSnapshotPath = isSnapshotPath;
const cache = new Map();
const buildSnapshotResolver = async (
config,
localRequire = (0, _transform.createTranspilingRequire)(config)
) => {
var _cache$get;
const key = config.rootDir;
const resolver =
(_cache$get = cache.get(key)) !== null && _cache$get !== void 0
? _cache$get
: await createSnapshotResolver(
await localRequire,
config.snapshotResolver
);
cache.set(key, resolver);
return resolver;
};
exports.buildSnapshotResolver = buildSnapshotResolver;
async function createSnapshotResolver(localRequire, snapshotResolverPath) {
return typeof snapshotResolverPath === 'string'
? await createCustomSnapshotResolver(snapshotResolverPath, localRequire)
: createDefaultSnapshotResolver();
}
function createDefaultSnapshotResolver() {
return {
resolveSnapshotPath: testPath =>
path.join(
path.join(path.dirname(testPath), '__snapshots__'),
path.basename(testPath) + DOT_EXTENSION
),
resolveTestPath: snapshotPath =>
path.resolve(
path.dirname(snapshotPath),
'..',
path.basename(snapshotPath, DOT_EXTENSION)
),
testPathForConsistencyCheck: path.posix.join(
'consistency_check',
'__tests__',
'example.test.js'
)
};
}
async function createCustomSnapshotResolver(
snapshotResolverPath,
localRequire
) {
const custom = (0, _jestUtil.interopRequireDefault)(
await localRequire(snapshotResolverPath)
).default;
const keys = [
['resolveSnapshotPath', 'function'],
['resolveTestPath', 'function'],
['testPathForConsistencyCheck', 'string']
];
keys.forEach(([propName, requiredType]) => {
if (typeof custom[propName] !== requiredType) {
throw new TypeError(mustImplement(propName, requiredType));
}
});
const customResolver = {
resolveSnapshotPath: testPath =>
custom.resolveSnapshotPath(testPath, DOT_EXTENSION),
resolveTestPath: snapshotPath =>
custom.resolveTestPath(snapshotPath, DOT_EXTENSION),
testPathForConsistencyCheck: custom.testPathForConsistencyCheck
};
verifyConsistentTransformations(customResolver);
return customResolver;
}
function mustImplement(propName, requiredType) {
return (
_chalk.default.bold(
`Custom snapshot resolver must implement a \`${propName}\` as a ${requiredType}.`
) +
'\nDocumentation: https://jestjs.io/docs/configuration#snapshotresolver-string'
);
}
function verifyConsistentTransformations(custom) {
const resolvedSnapshotPath = custom.resolveSnapshotPath(
custom.testPathForConsistencyCheck
);
const resolvedTestPath = custom.resolveTestPath(resolvedSnapshotPath);
if (resolvedTestPath !== custom.testPathForConsistencyCheck) {
throw new Error(
_chalk.default.bold(
`Custom snapshot resolver functions must transform paths consistently, i.e. expects resolveTestPath(resolveSnapshotPath('${custom.testPathForConsistencyCheck}')) === ${resolvedTestPath}`
)
);
}
}

62
frontend/node_modules/jest-snapshot/build/State.d.ts generated vendored Normal file
View File

@@ -0,0 +1,62 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import type { Config } from '@jest/types';
import type { OptionsReceived as PrettyFormatOptions } from 'pretty-format';
export declare type SnapshotStateOptions = {
updateSnapshot: Config.SnapshotUpdateState;
prettierPath: Config.Path;
expand?: boolean;
snapshotFormat: PrettyFormatOptions;
};
export declare type SnapshotMatchOptions = {
testName: string;
received: unknown;
key?: string;
inlineSnapshot?: string;
isInline: boolean;
error?: Error;
};
declare type SnapshotReturnOptions = {
actual: string;
count: number;
expected?: string;
key: string;
pass: boolean;
};
declare type SaveStatus = {
deleted: boolean;
saved: boolean;
};
export default class SnapshotState {
private _counters;
private _dirty;
private _index;
private _updateSnapshot;
private _snapshotData;
private _initialData;
private _snapshotPath;
private _inlineSnapshots;
private _uncheckedKeys;
private _prettierPath;
private _snapshotFormat;
added: number;
expand: boolean;
matched: number;
unmatched: number;
updated: number;
constructor(snapshotPath: Config.Path, options: SnapshotStateOptions);
markSnapshotsAsCheckedForTest(testName: string): void;
private _addSnapshot;
clear(): void;
save(): SaveStatus;
getUncheckedCount(): number;
getUncheckedKeys(): Array<string>;
removeUncheckedKeys(): void;
match({ testName, received, key, inlineSnapshot, isInline, error, }: SnapshotMatchOptions): SnapshotReturnOptions;
fail(testName: string, _received: unknown, key?: string): string;
}
export {};

389
frontend/node_modules/jest-snapshot/build/State.js generated vendored Normal file
View File

@@ -0,0 +1,389 @@
'use strict';
var global = (function () {
if (typeof globalThis !== 'undefined') {
return globalThis;
} else if (typeof global !== 'undefined') {
return global;
} else if (typeof self !== 'undefined') {
return self;
} else if (typeof window !== 'undefined') {
return window;
} else {
return Function('return this')();
}
})();
var Symbol = global['jest-symbol-do-not-touch'] || global.Symbol;
Object.defineProperty(exports, '__esModule', {
value: true
});
exports.default = void 0;
var fs = _interopRequireWildcard(require('graceful-fs'));
var _jestMessageUtil = require('jest-message-util');
var _InlineSnapshots = require('./InlineSnapshots');
var _utils = require('./utils');
function _getRequireWildcardCache(nodeInterop) {
if (typeof WeakMap !== 'function') return null;
var cacheBabelInterop = new WeakMap();
var cacheNodeInterop = new WeakMap();
return (_getRequireWildcardCache = function (nodeInterop) {
return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
})(nodeInterop);
}
function _interopRequireWildcard(obj, nodeInterop) {
if (!nodeInterop && obj && obj.__esModule) {
return obj;
}
if (obj === null || (typeof obj !== 'object' && typeof obj !== 'function')) {
return {default: obj};
}
var cache = _getRequireWildcardCache(nodeInterop);
if (cache && cache.has(obj)) {
return cache.get(obj);
}
var newObj = {};
var hasPropertyDescriptor =
Object.defineProperty && Object.getOwnPropertyDescriptor;
for (var key in obj) {
if (key !== 'default' && Object.prototype.hasOwnProperty.call(obj, key)) {
var desc = hasPropertyDescriptor
? Object.getOwnPropertyDescriptor(obj, key)
: null;
if (desc && (desc.get || desc.set)) {
Object.defineProperty(newObj, key, desc);
} else {
newObj[key] = obj[key];
}
}
}
newObj.default = obj;
if (cache) {
cache.set(obj, newObj);
}
return newObj;
}
var global = (function () {
if (typeof globalThis !== 'undefined') {
return globalThis;
} else if (typeof global !== 'undefined') {
return global;
} else if (typeof self !== 'undefined') {
return self;
} else if (typeof window !== 'undefined') {
return window;
} else {
return Function('return this')();
}
})();
var Symbol = global['jest-symbol-do-not-touch'] || global.Symbol;
var global = (function () {
if (typeof globalThis !== 'undefined') {
return globalThis;
} else if (typeof global !== 'undefined') {
return global;
} else if (typeof self !== 'undefined') {
return self;
} else if (typeof window !== 'undefined') {
return window;
} else {
return Function('return this')();
}
})();
var jestExistsFile =
global[Symbol.for('jest-native-exists-file')] || fs.existsSync;
function _defineProperty(obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
}
class SnapshotState {
// @ts-expect-error
constructor(snapshotPath, options) {
_defineProperty(this, '_counters', void 0);
_defineProperty(this, '_dirty', void 0);
_defineProperty(this, '_index', void 0);
_defineProperty(this, '_updateSnapshot', void 0);
_defineProperty(this, '_snapshotData', void 0);
_defineProperty(this, '_initialData', void 0);
_defineProperty(this, '_snapshotPath', void 0);
_defineProperty(this, '_inlineSnapshots', void 0);
_defineProperty(this, '_uncheckedKeys', void 0);
_defineProperty(this, '_prettierPath', void 0);
_defineProperty(this, '_snapshotFormat', void 0);
_defineProperty(this, 'added', void 0);
_defineProperty(this, 'expand', void 0);
_defineProperty(this, 'matched', void 0);
_defineProperty(this, 'unmatched', void 0);
_defineProperty(this, 'updated', void 0);
this._snapshotPath = snapshotPath;
const {data, dirty} = (0, _utils.getSnapshotData)(
this._snapshotPath,
options.updateSnapshot
);
this._initialData = data;
this._snapshotData = data;
this._dirty = dirty;
this._prettierPath = options.prettierPath;
this._inlineSnapshots = [];
this._uncheckedKeys = new Set(Object.keys(this._snapshotData));
this._counters = new Map();
this._index = 0;
this.expand = options.expand || false;
this.added = 0;
this.matched = 0;
this.unmatched = 0;
this._updateSnapshot = options.updateSnapshot;
this.updated = 0;
this._snapshotFormat = options.snapshotFormat;
}
markSnapshotsAsCheckedForTest(testName) {
this._uncheckedKeys.forEach(uncheckedKey => {
if ((0, _utils.keyToTestName)(uncheckedKey) === testName) {
this._uncheckedKeys.delete(uncheckedKey);
}
});
}
_addSnapshot(key, receivedSerialized, options) {
this._dirty = true;
if (options.isInline) {
const error = options.error || new Error();
const lines = (0, _jestMessageUtil.getStackTraceLines)(
(0, _utils.removeLinesBeforeExternalMatcherTrap)(error.stack || '')
);
const frame = (0, _jestMessageUtil.getTopFrame)(lines);
if (!frame) {
throw new Error(
"Jest: Couldn't infer stack frame for inline snapshot."
);
}
this._inlineSnapshots.push({
frame,
snapshot: receivedSerialized
});
} else {
this._snapshotData[key] = receivedSerialized;
}
}
clear() {
this._snapshotData = this._initialData;
this._inlineSnapshots = [];
this._counters = new Map();
this._index = 0;
this.added = 0;
this.matched = 0;
this.unmatched = 0;
this.updated = 0;
}
save() {
const hasExternalSnapshots = Object.keys(this._snapshotData).length;
const hasInlineSnapshots = this._inlineSnapshots.length;
const isEmpty = !hasExternalSnapshots && !hasInlineSnapshots;
const status = {
deleted: false,
saved: false
};
if ((this._dirty || this._uncheckedKeys.size) && !isEmpty) {
if (hasExternalSnapshots) {
(0, _utils.saveSnapshotFile)(this._snapshotData, this._snapshotPath);
}
if (hasInlineSnapshots) {
(0, _InlineSnapshots.saveInlineSnapshots)(
this._inlineSnapshots,
this._prettierPath
);
}
status.saved = true;
} else if (!hasExternalSnapshots && jestExistsFile(this._snapshotPath)) {
if (this._updateSnapshot === 'all') {
fs.unlinkSync(this._snapshotPath);
}
status.deleted = true;
}
return status;
}
getUncheckedCount() {
return this._uncheckedKeys.size || 0;
}
getUncheckedKeys() {
return Array.from(this._uncheckedKeys);
}
removeUncheckedKeys() {
if (this._updateSnapshot === 'all' && this._uncheckedKeys.size) {
this._dirty = true;
this._uncheckedKeys.forEach(key => delete this._snapshotData[key]);
this._uncheckedKeys.clear();
}
}
match({testName, received, key, inlineSnapshot, isInline, error}) {
this._counters.set(testName, (this._counters.get(testName) || 0) + 1);
const count = Number(this._counters.get(testName));
if (!key) {
key = (0, _utils.testNameToKey)(testName, count);
} // Do not mark the snapshot as "checked" if the snapshot is inline and
// there's an external snapshot. This way the external snapshot can be
// removed with `--updateSnapshot`.
if (!(isInline && this._snapshotData[key] !== undefined)) {
this._uncheckedKeys.delete(key);
}
const receivedSerialized = (0, _utils.addExtraLineBreaks)(
(0, _utils.serialize)(received, undefined, this._snapshotFormat)
);
const expected = isInline ? inlineSnapshot : this._snapshotData[key];
const pass = expected === receivedSerialized;
const hasSnapshot = expected !== undefined;
const snapshotIsPersisted = isInline || fs.existsSync(this._snapshotPath);
if (pass && !isInline) {
// Executing a snapshot file as JavaScript and writing the strings back
// when other snapshots have changed loses the proper escaping for some
// characters. Since we check every snapshot in every test, use the newly
// generated formatted string.
// Note that this is only relevant when a snapshot is added and the dirty
// flag is set.
this._snapshotData[key] = receivedSerialized;
} // These are the conditions on when to write snapshots:
// * There's no snapshot file in a non-CI environment.
// * There is a snapshot file and we decided to update the snapshot.
// * There is a snapshot file, but it doesn't have this snaphsot.
// These are the conditions on when not to write snapshots:
// * The update flag is set to 'none'.
// * There's no snapshot file or a file without this snapshot on a CI environment.
if (
(hasSnapshot && this._updateSnapshot === 'all') ||
((!hasSnapshot || !snapshotIsPersisted) &&
(this._updateSnapshot === 'new' || this._updateSnapshot === 'all'))
) {
if (this._updateSnapshot === 'all') {
if (!pass) {
if (hasSnapshot) {
this.updated++;
} else {
this.added++;
}
this._addSnapshot(key, receivedSerialized, {
error,
isInline
});
} else {
this.matched++;
}
} else {
this._addSnapshot(key, receivedSerialized, {
error,
isInline
});
this.added++;
}
return {
actual: '',
count,
expected: '',
key,
pass: true
};
} else {
if (!pass) {
this.unmatched++;
return {
actual: (0, _utils.removeExtraLineBreaks)(receivedSerialized),
count,
expected:
expected !== undefined
? (0, _utils.removeExtraLineBreaks)(expected)
: undefined,
key,
pass: false
};
} else {
this.matched++;
return {
actual: '',
count,
expected: '',
key,
pass: true
};
}
}
}
fail(testName, _received, key) {
this._counters.set(testName, (this._counters.get(testName) || 0) + 1);
const count = Number(this._counters.get(testName));
if (!key) {
key = (0, _utils.testNameToKey)(testName, count);
}
this._uncheckedKeys.delete(key);
this.unmatched++;
return key;
}
}
exports.default = SnapshotState;

15
frontend/node_modules/jest-snapshot/build/colors.d.ts generated vendored Normal file
View File

@@ -0,0 +1,15 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* 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 aForeground2 = 90;
export declare const aBackground2 = 225;
export declare const bForeground2 = 23;
export declare const bBackground2 = 195;
export declare type RGB = [number, number, number];
export declare const aForeground3: RGB;
export declare const aBackground3: RGB;
export declare const bForeground3: RGB;
export declare const bBackground3: RGB;

38
frontend/node_modules/jest-snapshot/build/colors.js generated vendored Normal file
View File

@@ -0,0 +1,38 @@
'use strict';
Object.defineProperty(exports, '__esModule', {
value: true
});
exports.bForeground3 =
exports.bForeground2 =
exports.bBackground3 =
exports.bBackground2 =
exports.aForeground3 =
exports.aForeground2 =
exports.aBackground3 =
exports.aBackground2 =
void 0;
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
// https://jonasjacek.github.io/colors/
const aForeground2 = 90;
exports.aForeground2 = aForeground2;
const aBackground2 = 225;
exports.aBackground2 = aBackground2;
const bForeground2 = 23;
exports.bForeground2 = bForeground2;
const bBackground2 = 195;
exports.bBackground2 = bBackground2;
const aForeground3 = [0x80, 0, 0x80];
exports.aForeground3 = aForeground3;
const aBackground3 = [0xff, 0xd7, 0xff];
exports.aBackground3 = aBackground3;
const bForeground3 = [0, 0x5f, 0x5f];
exports.bForeground3 = bForeground3;
const bBackground3 = [0xd7, 0xff, 0xff];
exports.bBackground3 = bBackground3;

View File

@@ -0,0 +1,7 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* 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 dedentLines: (input: Array<string>) => Array<string> | null;

View File

@@ -0,0 +1,149 @@
'use strict';
Object.defineProperty(exports, '__esModule', {
value: true
});
exports.dedentLines = void 0;
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
const getIndentationLength = line => {
const result = /^( {2})+/.exec(line);
return result === null ? 0 : result[0].length;
};
const dedentLine = line => line.slice(getIndentationLength(line)); // Return true if:
// "key": "value has multiple lines\n…
// "key has multiple lines\n…
const hasUnmatchedDoubleQuoteMarks = string => {
let n = 0;
let i = string.indexOf('"', 0);
while (i !== -1) {
if (i === 0 || string[i - 1] !== '\\') {
n += 1;
}
i = string.indexOf('"', i + 1);
}
return n % 2 !== 0;
};
const isFirstLineOfTag = line => /^( {2})*\</.test(line); // The length of the output array is the index of the next input line.
// Push dedented lines of start tag onto output and return true;
// otherwise return false because:
// * props include a multiline string (or text node, if props have markup)
// * start tag does not close
const dedentStartTag = (input, output) => {
let line = input[output.length];
output.push(dedentLine(line));
if (line.includes('>')) {
return true;
}
while (output.length < input.length) {
line = input[output.length];
if (hasUnmatchedDoubleQuoteMarks(line)) {
return false; // because props include a multiline string
} else if (isFirstLineOfTag(line)) {
// Recursion only if props have markup.
if (!dedentMarkup(input, output)) {
return false;
}
} else {
output.push(dedentLine(line));
if (line.includes('>')) {
return true;
}
}
}
return false;
}; // Push dedented lines of markup onto output and return true;
// otherwise return false because:
// * props include a multiline string
// * text has more than one adjacent line
// * markup does not close
const dedentMarkup = (input, output) => {
let line = input[output.length];
if (!dedentStartTag(input, output)) {
return false;
}
if (input[output.length - 1].includes('/>')) {
return true;
}
let isText = false;
const stack = [];
stack.push(getIndentationLength(line));
while (stack.length > 0 && output.length < input.length) {
line = input[output.length];
if (isFirstLineOfTag(line)) {
if (line.includes('</')) {
output.push(dedentLine(line));
stack.pop();
} else {
if (!dedentStartTag(input, output)) {
return false;
}
if (!input[output.length - 1].includes('/>')) {
stack.push(getIndentationLength(line));
}
}
isText = false;
} else {
if (isText) {
return false; // because text has more than one adjacent line
}
const indentationLengthOfTag = stack[stack.length - 1];
output.push(line.slice(indentationLengthOfTag + 2));
isText = true;
}
}
return stack.length === 0;
}; // Return lines unindented by heuristic;
// otherwise return null because:
// * props include a multiline string
// * text has more than one adjacent line
// * markup does not close
const dedentLines = input => {
const output = [];
while (output.length < input.length) {
const line = input[output.length];
if (hasUnmatchedDoubleQuoteMarks(line)) {
return null;
} else if (isFirstLineOfTag(line)) {
if (!dedentMarkup(input, output)) {
return null;
}
} else {
output.push(dedentLine(line));
}
}
return output;
};
exports.dedentLines = dedentLines;

34
frontend/node_modules/jest-snapshot/build/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1,34 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import type { Config } from '@jest/types';
import type { FS as HasteFS } from 'jest-haste-map';
import { SnapshotResolver as JestSnapshotResolver } from './SnapshotResolver';
import SnapshotState from './State';
import type { Context, ExpectationResult } from './types';
import * as utils from './utils';
declare const JestSnapshot: {
EXTENSION: string;
SnapshotState: typeof SnapshotState;
addSerializer: (plugin: import("pretty-format").Plugin) => void;
buildSnapshotResolver: (config: Config.ProjectConfig, localRequire?: ((module: string) => unknown) | Promise<(module: string) => unknown>) => Promise<JestSnapshotResolver>;
cleanup: (hasteFS: HasteFS, update: Config.SnapshotUpdateState, snapshotResolver: JestSnapshotResolver, testPathIgnorePatterns?: string[] | undefined) => {
filesRemoved: number;
filesRemovedList: Array<string>;
};
getSerializers: () => import("pretty-format").Plugins;
isSnapshotPath: (path: string) => boolean;
toMatchInlineSnapshot: (this: Context, received: unknown, propertiesOrSnapshot?: string | object | undefined, inlineSnapshot?: string | undefined) => ExpectationResult;
toMatchSnapshot: (this: Context, received: unknown, propertiesOrHint?: string | object | undefined, hint?: string | undefined) => ExpectationResult;
toThrowErrorMatchingInlineSnapshot: (this: Context, received: unknown, inlineSnapshot?: string | undefined, fromPromise?: boolean | undefined) => ExpectationResult;
toThrowErrorMatchingSnapshot: (this: Context, received: unknown, hint: string | undefined, fromPromise: boolean) => ExpectationResult;
utils: typeof utils;
};
declare namespace JestSnapshot {
type SnapshotResolver = JestSnapshotResolver;
type SnapshotStateType = SnapshotState;
}
export = JestSnapshot;

645
frontend/node_modules/jest-snapshot/build/index.js generated vendored Normal file
View File

@@ -0,0 +1,645 @@
'use strict';
var fs = _interopRequireWildcard(require('graceful-fs'));
var _jestMatcherUtils = require('jest-matcher-utils');
var _SnapshotResolver = require('./SnapshotResolver');
var _State = _interopRequireDefault(require('./State'));
var _plugins = require('./plugins');
var _printSnapshot = require('./printSnapshot');
var utils = _interopRequireWildcard(require('./utils'));
function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : {default: obj};
}
function _getRequireWildcardCache(nodeInterop) {
if (typeof WeakMap !== 'function') return null;
var cacheBabelInterop = new WeakMap();
var cacheNodeInterop = new WeakMap();
return (_getRequireWildcardCache = function (nodeInterop) {
return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
})(nodeInterop);
}
function _interopRequireWildcard(obj, nodeInterop) {
if (!nodeInterop && obj && obj.__esModule) {
return obj;
}
if (obj === null || (typeof obj !== 'object' && typeof obj !== 'function')) {
return {default: obj};
}
var cache = _getRequireWildcardCache(nodeInterop);
if (cache && cache.has(obj)) {
return cache.get(obj);
}
var newObj = {};
var hasPropertyDescriptor =
Object.defineProperty && Object.getOwnPropertyDescriptor;
for (var key in obj) {
if (key !== 'default' && Object.prototype.hasOwnProperty.call(obj, key)) {
var desc = hasPropertyDescriptor
? Object.getOwnPropertyDescriptor(obj, key)
: null;
if (desc && (desc.get || desc.set)) {
Object.defineProperty(newObj, key, desc);
} else {
newObj[key] = obj[key];
}
}
}
newObj.default = obj;
if (cache) {
cache.set(obj, newObj);
}
return newObj;
}
var global = (function () {
if (typeof globalThis !== 'undefined') {
return globalThis;
} else if (typeof global !== 'undefined') {
return global;
} else if (typeof self !== 'undefined') {
return self;
} else if (typeof window !== 'undefined') {
return window;
} else {
return Function('return this')();
}
})();
var Symbol = global['jest-symbol-do-not-touch'] || global.Symbol;
var global = (function () {
if (typeof globalThis !== 'undefined') {
return globalThis;
} else if (typeof global !== 'undefined') {
return global;
} else if (typeof self !== 'undefined') {
return self;
} else if (typeof window !== 'undefined') {
return window;
} else {
return Function('return this')();
}
})();
var Symbol = global['jest-symbol-do-not-touch'] || global.Symbol;
var global = (function () {
if (typeof globalThis !== 'undefined') {
return globalThis;
} else if (typeof global !== 'undefined') {
return global;
} else if (typeof self !== 'undefined') {
return self;
} else if (typeof window !== 'undefined') {
return window;
} else {
return Function('return this')();
}
})();
var jestExistsFile =
global[Symbol.for('jest-native-exists-file')] || fs.existsSync;
const DID_NOT_THROW = 'Received function did not throw'; // same as toThrow
const NOT_SNAPSHOT_MATCHERS = `Snapshot matchers cannot be used with ${(0,
_jestMatcherUtils.BOLD_WEIGHT)('not')}`;
const INDENTATION_REGEX = /^([^\S\n]*)\S/m; // Display name in report when matcher fails same as in snapshot file,
// but with optional hint argument in bold weight.
const printSnapshotName = (concatenatedBlockNames = '', hint = '', count) => {
const hasNames = concatenatedBlockNames.length !== 0;
const hasHint = hint.length !== 0;
return (
'Snapshot name: `' +
(hasNames ? utils.escapeBacktickString(concatenatedBlockNames) : '') +
(hasNames && hasHint ? ': ' : '') +
(hasHint
? (0, _jestMatcherUtils.BOLD_WEIGHT)(utils.escapeBacktickString(hint))
: '') +
' ' +
count +
'`'
);
};
function stripAddedIndentation(inlineSnapshot) {
// Find indentation if exists.
const match = inlineSnapshot.match(INDENTATION_REGEX);
if (!match || !match[1]) {
// No indentation.
return inlineSnapshot;
}
const indentation = match[1];
const lines = inlineSnapshot.split('\n');
if (lines.length <= 2) {
// Must be at least 3 lines.
return inlineSnapshot;
}
if (lines[0].trim() !== '' || lines[lines.length - 1].trim() !== '') {
// If not blank first and last lines, abort.
return inlineSnapshot;
}
for (let i = 1; i < lines.length - 1; i++) {
if (lines[i] !== '') {
if (lines[i].indexOf(indentation) !== 0) {
// All lines except first and last should either be blank or have the same
// indent as the first line (or more). If this isn't the case we don't
// want to touch the snapshot at all.
return inlineSnapshot;
}
lines[i] = lines[i].substring(indentation.length);
}
} // Last line is a special case because it won't have the same indent as others
// but may still have been given some indent to line up.
lines[lines.length - 1] = ''; // Return inline snapshot, now at indent 0.
inlineSnapshot = lines.join('\n');
return inlineSnapshot;
}
const fileExists = (filePath, hasteFS) =>
hasteFS.exists(filePath) || jestExistsFile(filePath);
const cleanup = (hasteFS, update, snapshotResolver, testPathIgnorePatterns) => {
const pattern = '\\.' + _SnapshotResolver.EXTENSION + '$';
const files = hasteFS.matchFiles(pattern);
let testIgnorePatternsRegex = null;
if (testPathIgnorePatterns && testPathIgnorePatterns.length > 0) {
testIgnorePatternsRegex = new RegExp(testPathIgnorePatterns.join('|'));
}
const list = files.filter(snapshotFile => {
const testPath = snapshotResolver.resolveTestPath(snapshotFile); // ignore snapshots of ignored tests
if (testIgnorePatternsRegex && testIgnorePatternsRegex.test(testPath)) {
return false;
}
if (!fileExists(testPath, hasteFS)) {
if (update === 'all') {
fs.unlinkSync(snapshotFile);
}
return true;
}
return false;
});
return {
filesRemoved: list.length,
filesRemovedList: list
};
};
const toMatchSnapshot = function (received, propertiesOrHint, hint) {
const matcherName = 'toMatchSnapshot';
let properties;
const length = arguments.length;
if (length === 2 && typeof propertiesOrHint === 'string') {
hint = propertiesOrHint;
} else if (length >= 2) {
if (typeof propertiesOrHint !== 'object' || propertiesOrHint === null) {
const options = {
isNot: this.isNot,
promise: this.promise
};
let printedWithType = (0, _jestMatcherUtils.printWithType)(
'Expected properties',
propertiesOrHint,
_printSnapshot.printExpected
);
if (length === 3) {
options.secondArgument = 'hint';
options.secondArgumentColor = _jestMatcherUtils.BOLD_WEIGHT;
if (propertiesOrHint == null) {
printedWithType +=
"\n\nTo provide a hint without properties: toMatchSnapshot('hint')";
}
}
throw new Error(
(0, _jestMatcherUtils.matcherErrorMessage)(
(0, _jestMatcherUtils.matcherHint)(
matcherName,
undefined,
_printSnapshot.PROPERTIES_ARG,
options
),
`Expected ${(0, _jestMatcherUtils.EXPECTED_COLOR)(
'properties'
)} must be an object`,
printedWithType
)
);
} // Future breaking change: Snapshot hint must be a string
// if (arguments.length === 3 && typeof hint !== 'string') {}
properties = propertiesOrHint;
}
return _toMatchSnapshot({
context: this,
hint,
isInline: false,
matcherName,
properties,
received
});
};
const toMatchInlineSnapshot = function (
received,
propertiesOrSnapshot,
inlineSnapshot
) {
const matcherName = 'toMatchInlineSnapshot';
let properties;
const length = arguments.length;
if (length === 2 && typeof propertiesOrSnapshot === 'string') {
inlineSnapshot = propertiesOrSnapshot;
} else if (length >= 2) {
const options = {
isNot: this.isNot,
promise: this.promise
};
if (length === 3) {
options.secondArgument = _printSnapshot.SNAPSHOT_ARG;
options.secondArgumentColor = _printSnapshot.noColor;
}
if (
typeof propertiesOrSnapshot !== 'object' ||
propertiesOrSnapshot === null
) {
throw new Error(
(0, _jestMatcherUtils.matcherErrorMessage)(
(0, _jestMatcherUtils.matcherHint)(
matcherName,
undefined,
_printSnapshot.PROPERTIES_ARG,
options
),
`Expected ${(0, _jestMatcherUtils.EXPECTED_COLOR)(
'properties'
)} must be an object`,
(0, _jestMatcherUtils.printWithType)(
'Expected properties',
propertiesOrSnapshot,
_printSnapshot.printExpected
)
)
);
}
if (length === 3 && typeof inlineSnapshot !== 'string') {
throw new Error(
(0, _jestMatcherUtils.matcherErrorMessage)(
(0, _jestMatcherUtils.matcherHint)(
matcherName,
undefined,
_printSnapshot.PROPERTIES_ARG,
options
),
'Inline snapshot must be a string',
(0, _jestMatcherUtils.printWithType)(
'Inline snapshot',
inlineSnapshot,
utils.serialize
)
)
);
}
properties = propertiesOrSnapshot;
}
return _toMatchSnapshot({
context: this,
inlineSnapshot:
inlineSnapshot !== undefined
? stripAddedIndentation(inlineSnapshot)
: undefined,
isInline: true,
matcherName,
properties,
received
});
};
const _toMatchSnapshot = config => {
const {context, hint, inlineSnapshot, isInline, matcherName, properties} =
config;
let {received} = config;
context.dontThrow && context.dontThrow();
const {currentTestName, isNot, snapshotState} = context;
if (isNot) {
throw new Error(
(0, _jestMatcherUtils.matcherErrorMessage)(
(0, _printSnapshot.matcherHintFromConfig)(config, false),
NOT_SNAPSHOT_MATCHERS
)
);
}
if (snapshotState == null) {
// Because the state is the problem, this is not a matcher error.
// Call generic stringify from jest-matcher-utils package
// because uninitialized snapshot state does not need snapshot serializers.
throw new Error(
(0, _printSnapshot.matcherHintFromConfig)(config, false) +
'\n\n' +
'Snapshot state must be initialized' +
'\n\n' +
(0, _jestMatcherUtils.printWithType)(
'Snapshot state',
snapshotState,
_jestMatcherUtils.stringify
)
);
}
const fullTestName =
currentTestName && hint
? `${currentTestName}: ${hint}`
: currentTestName || ''; // future BREAKING change: || hint
if (typeof properties === 'object') {
if (typeof received !== 'object' || received === null) {
throw new Error(
(0, _jestMatcherUtils.matcherErrorMessage)(
(0, _printSnapshot.matcherHintFromConfig)(config, false),
`${(0, _jestMatcherUtils.RECEIVED_COLOR)(
'received'
)} value must be an object when the matcher has ${(0,
_jestMatcherUtils.EXPECTED_COLOR)('properties')}`,
(0, _jestMatcherUtils.printWithType)(
'Received',
received,
_printSnapshot.printReceived
)
)
);
}
const propertyPass = context.equals(received, properties, [
context.utils.iterableEquality,
context.utils.subsetEquality
]);
if (!propertyPass) {
const key = snapshotState.fail(fullTestName, received);
const matched = /(\d+)$/.exec(key);
const count = matched === null ? 1 : Number(matched[1]);
const message = () =>
(0, _printSnapshot.matcherHintFromConfig)(config, false) +
'\n\n' +
printSnapshotName(currentTestName, hint, count) +
'\n\n' +
(0, _printSnapshot.printPropertiesAndReceived)(
properties,
received,
snapshotState.expand
);
return {
message,
name: matcherName,
pass: false
};
} else {
received = utils.deepMerge(received, properties);
}
}
const result = snapshotState.match({
error: context.error,
inlineSnapshot,
isInline,
received,
testName: fullTestName
});
const {actual, count, expected, pass} = result;
if (pass) {
return {
message: () => '',
pass: true
};
}
const message =
expected === undefined
? () =>
(0, _printSnapshot.matcherHintFromConfig)(config, true) +
'\n\n' +
printSnapshotName(currentTestName, hint, count) +
'\n\n' +
`New snapshot was ${(0, _jestMatcherUtils.BOLD_WEIGHT)(
'not written'
)}. The update flag ` +
'must be explicitly passed to write a new snapshot.\n\n' +
'This is likely because this test is run in a continuous integration ' +
'(CI) environment in which snapshots are not written by default.\n\n' +
`Received:${actual.includes('\n') ? '\n' : ' '}${(0,
_printSnapshot.bReceivedColor)(actual)}`
: () =>
(0, _printSnapshot.matcherHintFromConfig)(config, true) +
'\n\n' +
printSnapshotName(currentTestName, hint, count) +
'\n\n' +
(0, _printSnapshot.printSnapshotAndReceived)(
expected,
actual,
received,
snapshotState.expand
); // Passing the actual and expected objects so that a custom reporter
// could access them, for example in order to display a custom visual diff,
// or create a different error message
return {
actual,
expected,
message,
name: matcherName,
pass: false
};
};
const toThrowErrorMatchingSnapshot = function (
received,
hint, // because error TS1016 for hint?: string
fromPromise
) {
const matcherName = 'toThrowErrorMatchingSnapshot'; // Future breaking change: Snapshot hint must be a string
// if (hint !== undefined && typeof hint !== string) {}
return _toThrowErrorMatchingSnapshot(
{
context: this,
hint,
isInline: false,
matcherName,
received
},
fromPromise
);
};
const toThrowErrorMatchingInlineSnapshot = function (
received,
inlineSnapshot,
fromPromise
) {
const matcherName = 'toThrowErrorMatchingInlineSnapshot';
if (inlineSnapshot !== undefined && typeof inlineSnapshot !== 'string') {
const options = {
expectedColor: _printSnapshot.noColor,
isNot: this.isNot,
promise: this.promise
};
throw new Error(
(0, _jestMatcherUtils.matcherErrorMessage)(
(0, _jestMatcherUtils.matcherHint)(
matcherName,
undefined,
_printSnapshot.SNAPSHOT_ARG,
options
),
'Inline snapshot must be a string',
(0, _jestMatcherUtils.printWithType)(
'Inline snapshot',
inlineSnapshot,
utils.serialize
)
)
);
}
return _toThrowErrorMatchingSnapshot(
{
context: this,
inlineSnapshot:
inlineSnapshot !== undefined
? stripAddedIndentation(inlineSnapshot)
: undefined,
isInline: true,
matcherName,
received
},
fromPromise
);
};
const _toThrowErrorMatchingSnapshot = (config, fromPromise) => {
const {context, hint, inlineSnapshot, isInline, matcherName, received} =
config;
context.dontThrow && context.dontThrow();
const {isNot, promise} = context;
if (!fromPromise) {
if (typeof received !== 'function') {
const options = {
isNot,
promise
};
throw new Error(
(0, _jestMatcherUtils.matcherErrorMessage)(
(0, _jestMatcherUtils.matcherHint)(
matcherName,
undefined,
'',
options
),
`${(0, _jestMatcherUtils.RECEIVED_COLOR)(
'received'
)} value must be a function`,
(0, _jestMatcherUtils.printWithType)(
'Received',
received,
_printSnapshot.printReceived
)
)
);
}
}
if (isNot) {
throw new Error(
(0, _jestMatcherUtils.matcherErrorMessage)(
(0, _printSnapshot.matcherHintFromConfig)(config, false),
NOT_SNAPSHOT_MATCHERS
)
);
}
let error;
if (fromPromise) {
error = received;
} else {
try {
received();
} catch (e) {
error = e;
}
}
if (error === undefined) {
// Because the received value is a function, this is not a matcher error.
throw new Error(
(0, _printSnapshot.matcherHintFromConfig)(config, false) +
'\n\n' +
DID_NOT_THROW
);
}
return _toMatchSnapshot({
context,
hint,
inlineSnapshot,
isInline,
matcherName,
received: error.message
});
};
const JestSnapshot = {
EXTENSION: _SnapshotResolver.EXTENSION,
SnapshotState: _State.default,
addSerializer: _plugins.addSerializer,
buildSnapshotResolver: _SnapshotResolver.buildSnapshotResolver,
cleanup,
getSerializers: _plugins.getSerializers,
isSnapshotPath: _SnapshotResolver.isSnapshotPath,
toMatchInlineSnapshot,
toMatchSnapshot,
toThrowErrorMatchingInlineSnapshot,
toThrowErrorMatchingSnapshot,
utils
};
module.exports = JestSnapshot;

View File

@@ -0,0 +1,11 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import type { NewPlugin } from 'pretty-format';
export declare const serialize: NewPlugin['serialize'];
export declare const test: NewPlugin['test'];
declare const plugin: NewPlugin;
export default plugin;

View File

@@ -0,0 +1,52 @@
'use strict';
Object.defineProperty(exports, '__esModule', {
value: true
});
exports.test = exports.serialize = exports.default = void 0;
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
const serialize = (val, config, indentation, depth, refs, printer) => {
// Serialize a non-default name, even if config.printFunctionName is false.
const name = val.getMockName();
const nameString = name === 'jest.fn()' ? '' : ' ' + name;
let callsString = '';
if (val.mock.calls.length !== 0) {
const indentationNext = indentation + config.indent;
callsString =
' {' +
config.spacingOuter +
indentationNext +
'"calls": ' +
printer(val.mock.calls, config, indentationNext, depth, refs) +
(config.min ? ', ' : ',') +
config.spacingOuter +
indentationNext +
'"results": ' +
printer(val.mock.results, config, indentationNext, depth, refs) +
(config.min ? '' : ',') +
config.spacingOuter +
indentation +
'}';
}
return '[MockFunction' + nameString + ']' + callsString;
};
exports.serialize = serialize;
const test = val => val && !!val._isMockFunction;
exports.test = test;
const plugin = {
serialize,
test
};
var _default = plugin;
exports.default = _default;

View File

@@ -0,0 +1,9 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import { Plugin as PrettyFormatPlugin, Plugins as PrettyFormatPlugins } from 'pretty-format';
export declare const addSerializer: (plugin: PrettyFormatPlugin) => void;
export declare const getSerializers: () => PrettyFormatPlugins;

48
frontend/node_modules/jest-snapshot/build/plugins.js generated vendored Normal file
View File

@@ -0,0 +1,48 @@
'use strict';
Object.defineProperty(exports, '__esModule', {
value: true
});
exports.getSerializers = exports.addSerializer = void 0;
var _prettyFormat = require('pretty-format');
var _mockSerializer = _interopRequireDefault(require('./mockSerializer'));
function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : {default: obj};
}
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
const {
DOMCollection,
DOMElement,
Immutable,
ReactElement,
ReactTestComponent,
AsymmetricMatcher
} = _prettyFormat.plugins;
let PLUGINS = [
ReactTestComponent,
ReactElement,
DOMElement,
DOMCollection,
Immutable,
_mockSerializer.default,
AsymmetricMatcher
]; // Prepend to list so the last added is the first tested.
const addSerializer = plugin => {
PLUGINS = [plugin].concat(PLUGINS);
};
exports.addSerializer = addSerializer;
const getSerializers = () => PLUGINS;
exports.getSerializers = getSerializers;

View File

@@ -0,0 +1,24 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import chalk = require('chalk');
import { DiffOptionsColor } from 'jest-diff';
import type { MatchSnapshotConfig } from './types';
declare type Chalk = chalk.Chalk;
export declare const getSnapshotColorForChalkInstance: (chalkInstance: Chalk) => DiffOptionsColor;
export declare const getReceivedColorForChalkInstance: (chalkInstance: Chalk) => DiffOptionsColor;
export declare const aSnapshotColor: DiffOptionsColor;
export declare const bReceivedColor: DiffOptionsColor;
export declare const noColor: (string: string) => string;
export declare const HINT_ARG = "hint";
export declare const SNAPSHOT_ARG = "snapshot";
export declare const PROPERTIES_ARG = "properties";
export declare const matcherHintFromConfig: ({ context: { isNot, promise }, hint, inlineSnapshot, matcherName, properties, }: MatchSnapshotConfig, isUpdatable: boolean) => string;
export declare const printExpected: (val: unknown) => string;
export declare const printReceived: (val: unknown) => string;
export declare const printPropertiesAndReceived: (properties: object, received: object, expand: boolean) => string;
export declare const printSnapshotAndReceived: (a: string, b: string, received: unknown, expand: boolean) => string;
export {};

View File

@@ -0,0 +1,407 @@
'use strict';
Object.defineProperty(exports, '__esModule', {
value: true
});
exports.printSnapshotAndReceived =
exports.printReceived =
exports.printPropertiesAndReceived =
exports.printExpected =
exports.noColor =
exports.matcherHintFromConfig =
exports.getSnapshotColorForChalkInstance =
exports.getReceivedColorForChalkInstance =
exports.bReceivedColor =
exports.aSnapshotColor =
exports.SNAPSHOT_ARG =
exports.PROPERTIES_ARG =
exports.HINT_ARG =
void 0;
var _chalk = _interopRequireDefault(require('chalk'));
var _utils = require('expect/build/utils');
var _jestDiff = require('jest-diff');
var _jestGetType = require('jest-get-type');
var _jestMatcherUtils = require('jest-matcher-utils');
var _prettyFormat = require('pretty-format');
var _colors = require('./colors');
var _dedentLines = require('./dedentLines');
var _utils2 = require('./utils');
function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : {default: obj};
}
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* 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/ban-types-eventually */
// Temporary hack because getObjectSubset has known limitations,
// is not in the public interface of the expect package,
// and the long-term goal is to use a non-serialization diff.
// Make sure to remove file from `exports` in `expect/package.json`.
const getSnapshotColorForChalkInstance = chalkInstance => {
const level = chalkInstance.level;
if (level === 3) {
return chalkInstance
.rgb(
_colors.aForeground3[0],
_colors.aForeground3[1],
_colors.aForeground3[2]
)
.bgRgb(
_colors.aBackground3[0],
_colors.aBackground3[1],
_colors.aBackground3[2]
);
}
if (level === 2) {
return chalkInstance
.ansi256(_colors.aForeground2)
.bgAnsi256(_colors.aBackground2);
}
return chalkInstance.magenta.bgYellowBright;
};
exports.getSnapshotColorForChalkInstance = getSnapshotColorForChalkInstance;
const getReceivedColorForChalkInstance = chalkInstance => {
const level = chalkInstance.level;
if (level === 3) {
return chalkInstance
.rgb(
_colors.bForeground3[0],
_colors.bForeground3[1],
_colors.bForeground3[2]
)
.bgRgb(
_colors.bBackground3[0],
_colors.bBackground3[1],
_colors.bBackground3[2]
);
}
if (level === 2) {
return chalkInstance
.ansi256(_colors.bForeground2)
.bgAnsi256(_colors.bBackground2);
}
return chalkInstance.cyan.bgWhiteBright; // also known as teal
};
exports.getReceivedColorForChalkInstance = getReceivedColorForChalkInstance;
const aSnapshotColor = getSnapshotColorForChalkInstance(_chalk.default);
exports.aSnapshotColor = aSnapshotColor;
const bReceivedColor = getReceivedColorForChalkInstance(_chalk.default);
exports.bReceivedColor = bReceivedColor;
const noColor = string => string;
exports.noColor = noColor;
const HINT_ARG = 'hint';
exports.HINT_ARG = HINT_ARG;
const SNAPSHOT_ARG = 'snapshot';
exports.SNAPSHOT_ARG = SNAPSHOT_ARG;
const PROPERTIES_ARG = 'properties';
exports.PROPERTIES_ARG = PROPERTIES_ARG;
const matcherHintFromConfig = (
{context: {isNot, promise}, hint, inlineSnapshot, matcherName, properties},
isUpdatable
) => {
const options = {
isNot,
promise
};
if (isUpdatable) {
options.receivedColor = bReceivedColor;
}
let expectedArgument = '';
if (typeof properties === 'object') {
expectedArgument = PROPERTIES_ARG;
if (isUpdatable) {
options.expectedColor = noColor;
}
if (typeof hint === 'string' && hint.length !== 0) {
options.secondArgument = HINT_ARG;
options.secondArgumentColor = _jestMatcherUtils.BOLD_WEIGHT;
} else if (typeof inlineSnapshot === 'string') {
options.secondArgument = SNAPSHOT_ARG;
if (isUpdatable) {
options.secondArgumentColor = aSnapshotColor;
} else {
options.secondArgumentColor = noColor;
}
}
} else {
if (typeof hint === 'string' && hint.length !== 0) {
expectedArgument = HINT_ARG;
options.expectedColor = _jestMatcherUtils.BOLD_WEIGHT;
} else if (typeof inlineSnapshot === 'string') {
expectedArgument = SNAPSHOT_ARG;
if (isUpdatable) {
options.expectedColor = aSnapshotColor;
}
}
}
return (0, _jestMatcherUtils.matcherHint)(
matcherName,
undefined,
expectedArgument,
options
);
}; // Given array of diffs, return string:
// * include common substrings
// * exclude change substrings which have opposite op
// * include change substrings which have argument op
// with change color only if there is a common substring
exports.matcherHintFromConfig = matcherHintFromConfig;
const joinDiffs = (diffs, op, hasCommon) =>
diffs.reduce(
(reduced, diff) =>
reduced +
(diff[0] === _jestDiff.DIFF_EQUAL
? diff[1]
: diff[0] !== op
? ''
: hasCommon
? (0, _jestMatcherUtils.INVERTED_COLOR)(diff[1])
: diff[1]),
''
);
const isLineDiffable = received => {
const receivedType = (0, _jestGetType.getType)(received);
if ((0, _jestGetType.isPrimitive)(received)) {
return typeof received === 'string';
}
if (
receivedType === 'date' ||
receivedType === 'function' ||
receivedType === 'regexp'
) {
return false;
}
if (received instanceof Error) {
return false;
}
if (
receivedType === 'object' &&
typeof received.asymmetricMatch === 'function'
) {
return false;
}
return true;
};
const printExpected = val =>
(0, _jestMatcherUtils.EXPECTED_COLOR)((0, _utils2.minify)(val));
exports.printExpected = printExpected;
const printReceived = val =>
(0, _jestMatcherUtils.RECEIVED_COLOR)((0, _utils2.minify)(val));
exports.printReceived = printReceived;
const printPropertiesAndReceived = (
properties,
received,
expand // CLI options: true if `--expand` or false if `--no-expand`
) => {
const aAnnotation = 'Expected properties';
const bAnnotation = 'Received value';
if (isLineDiffable(properties) && isLineDiffable(received)) {
return (0, _jestDiff.diffLinesUnified)(
(0, _utils2.serialize)(properties).split('\n'),
(0, _utils2.serialize)(
(0, _utils.getObjectSubset)(received, properties)
).split('\n'),
{
aAnnotation,
aColor: _jestMatcherUtils.EXPECTED_COLOR,
bAnnotation,
bColor: _jestMatcherUtils.RECEIVED_COLOR,
changeLineTrailingSpaceColor: _chalk.default.bgYellow,
commonLineTrailingSpaceColor: _chalk.default.bgYellow,
emptyFirstOrLastLinePlaceholder: '↵',
// U+21B5
expand,
includeChangeCounts: true
}
);
}
const printLabel = (0, _jestMatcherUtils.getLabelPrinter)(
aAnnotation,
bAnnotation
);
return (
printLabel(aAnnotation) +
printExpected(properties) +
'\n' +
printLabel(bAnnotation) +
printReceived(received)
);
};
exports.printPropertiesAndReceived = printPropertiesAndReceived;
const MAX_DIFF_STRING_LENGTH = 20000;
const printSnapshotAndReceived = (
a,
b,
received,
expand // CLI options: true if `--expand` or false if `--no-expand`
) => {
const aAnnotation = 'Snapshot';
const bAnnotation = 'Received';
const aColor = aSnapshotColor;
const bColor = bReceivedColor;
const options = {
aAnnotation,
aColor,
bAnnotation,
bColor,
changeLineTrailingSpaceColor: noColor,
commonLineTrailingSpaceColor: _chalk.default.bgYellow,
emptyFirstOrLastLinePlaceholder: '↵',
// U+21B5
expand,
includeChangeCounts: true
};
if (typeof received === 'string') {
if (
a.length >= 2 &&
a.startsWith('"') &&
a.endsWith('"') &&
b === (0, _prettyFormat.format)(received)
) {
// If snapshot looks like default serialization of a string
// and received is string which has default serialization.
if (!a.includes('\n') && !b.includes('\n')) {
// If neither string is multiline,
// display as labels and quoted strings.
let aQuoted = a;
let bQuoted = b;
if (
a.length - 2 <= MAX_DIFF_STRING_LENGTH &&
b.length - 2 <= MAX_DIFF_STRING_LENGTH
) {
const diffs = (0, _jestDiff.diffStringsRaw)(
a.slice(1, -1),
b.slice(1, -1),
true
);
const hasCommon = diffs.some(
diff => diff[0] === _jestDiff.DIFF_EQUAL
);
aQuoted =
'"' + joinDiffs(diffs, _jestDiff.DIFF_DELETE, hasCommon) + '"';
bQuoted =
'"' + joinDiffs(diffs, _jestDiff.DIFF_INSERT, hasCommon) + '"';
}
const printLabel = (0, _jestMatcherUtils.getLabelPrinter)(
aAnnotation,
bAnnotation
);
return (
printLabel(aAnnotation) +
aColor(aQuoted) +
'\n' +
printLabel(bAnnotation) +
bColor(bQuoted)
);
} // Else either string is multiline, so display as unquoted strings.
a = (0, _utils2.deserializeString)(a); // hypothetical expected string
b = received; // not serialized
} // Else expected had custom serialization or was not a string
// or received has custom serialization.
return a.length <= MAX_DIFF_STRING_LENGTH &&
b.length <= MAX_DIFF_STRING_LENGTH
? (0, _jestDiff.diffStringsUnified)(a, b, options)
: (0, _jestDiff.diffLinesUnified)(a.split('\n'), b.split('\n'), options);
}
if (isLineDiffable(received)) {
const aLines2 = a.split('\n');
const bLines2 = b.split('\n'); // Fall through to fix a regression for custom serializers
// like jest-snapshot-serializer-raw that ignore the indent option.
const b0 = (0, _utils2.serialize)(received, 0);
if (b0 !== b) {
const aLines0 = (0, _dedentLines.dedentLines)(aLines2);
if (aLines0 !== null) {
// Compare lines without indentation.
const bLines0 = b0.split('\n');
return (0, _jestDiff.diffLinesUnified2)(
aLines2,
bLines2,
aLines0,
bLines0,
options
);
}
} // Fall back because:
// * props include a multiline string
// * text has more than one adjacent line
// * markup does not close
return (0, _jestDiff.diffLinesUnified)(aLines2, bLines2, options);
}
const printLabel = (0, _jestMatcherUtils.getLabelPrinter)(
aAnnotation,
bAnnotation
);
return (
printLabel(aAnnotation) +
aColor(a) +
'\n' +
printLabel(bAnnotation) +
bColor(b)
);
};
exports.printSnapshotAndReceived = printSnapshotAndReceived;

25
frontend/node_modules/jest-snapshot/build/types.d.ts generated vendored Normal file
View File

@@ -0,0 +1,25 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import type { MatcherState } from 'expect';
import type SnapshotState from './State';
export declare type Context = MatcherState & {
snapshotState: SnapshotState;
};
export declare type MatchSnapshotConfig = {
context: Context;
hint?: string;
inlineSnapshot?: string;
isInline: boolean;
matcherName: string;
properties?: object;
received: any;
};
export declare type SnapshotData = Record<string, string>;
export declare type ExpectationResult = {
pass: boolean;
message: () => string;
};

1
frontend/node_modules/jest-snapshot/build/types.js generated vendored Normal file
View File

@@ -0,0 +1 @@
'use strict';

28
frontend/node_modules/jest-snapshot/build/utils.d.ts generated vendored Normal file
View File

@@ -0,0 +1,28 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import type { Config } from '@jest/types';
import { OptionsReceived as PrettyFormatOptions } from 'pretty-format';
import type { SnapshotData } from './types';
export declare const SNAPSHOT_VERSION = "1";
export declare const SNAPSHOT_GUIDE_LINK = "https://goo.gl/fbAQLP";
export declare const SNAPSHOT_VERSION_WARNING: string;
export declare const testNameToKey: (testName: Config.Path, count: number) => string;
export declare const keyToTestName: (key: string) => string;
export declare const getSnapshotData: (snapshotPath: Config.Path, update: Config.SnapshotUpdateState) => {
data: SnapshotData;
dirty: boolean;
};
export declare const addExtraLineBreaks: (string: string) => string;
export declare const removeExtraLineBreaks: (string: string) => string;
export declare const removeLinesBeforeExternalMatcherTrap: (stack: string) => string;
export declare const serialize: (val: unknown, indent?: number, formatOverrides?: PrettyFormatOptions) => string;
export declare const minify: (val: unknown) => string;
export declare const deserializeString: (stringified: string) => string;
export declare const escapeBacktickString: (str: string) => string;
export declare const ensureDirectoryExists: (filePath: Config.Path) => void;
export declare const saveSnapshotFile: (snapshotData: SnapshotData, snapshotPath: Config.Path) => void;
export declare const deepMerge: (target: any, source: any) => any;

460
frontend/node_modules/jest-snapshot/build/utils.js generated vendored Normal file
View File

@@ -0,0 +1,460 @@
'use strict';
Object.defineProperty(exports, '__esModule', {
value: true
});
exports.testNameToKey =
exports.serialize =
exports.saveSnapshotFile =
exports.removeLinesBeforeExternalMatcherTrap =
exports.removeExtraLineBreaks =
exports.minify =
exports.keyToTestName =
exports.getSnapshotData =
exports.escapeBacktickString =
exports.ensureDirectoryExists =
exports.deserializeString =
exports.deepMerge =
exports.addExtraLineBreaks =
exports.SNAPSHOT_VERSION_WARNING =
exports.SNAPSHOT_VERSION =
exports.SNAPSHOT_GUIDE_LINK =
void 0;
var path = _interopRequireWildcard(require('path'));
var _chalk = _interopRequireDefault(require('chalk'));
var fs = _interopRequireWildcard(require('graceful-fs'));
var _naturalCompare = _interopRequireDefault(require('natural-compare'));
var _prettyFormat = require('pretty-format');
var _plugins = require('./plugins');
function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : {default: obj};
}
function _getRequireWildcardCache(nodeInterop) {
if (typeof WeakMap !== 'function') return null;
var cacheBabelInterop = new WeakMap();
var cacheNodeInterop = new WeakMap();
return (_getRequireWildcardCache = function (nodeInterop) {
return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
})(nodeInterop);
}
function _interopRequireWildcard(obj, nodeInterop) {
if (!nodeInterop && obj && obj.__esModule) {
return obj;
}
if (obj === null || (typeof obj !== 'object' && typeof obj !== 'function')) {
return {default: obj};
}
var cache = _getRequireWildcardCache(nodeInterop);
if (cache && cache.has(obj)) {
return cache.get(obj);
}
var newObj = {};
var hasPropertyDescriptor =
Object.defineProperty && Object.getOwnPropertyDescriptor;
for (var key in obj) {
if (key !== 'default' && Object.prototype.hasOwnProperty.call(obj, key)) {
var desc = hasPropertyDescriptor
? Object.getOwnPropertyDescriptor(obj, key)
: null;
if (desc && (desc.get || desc.set)) {
Object.defineProperty(newObj, key, desc);
} else {
newObj[key] = obj[key];
}
}
}
newObj.default = obj;
if (cache) {
cache.set(obj, newObj);
}
return newObj;
}
var global = (function () {
if (typeof globalThis !== 'undefined') {
return globalThis;
} else if (typeof global !== 'undefined') {
return global;
} else if (typeof self !== 'undefined') {
return self;
} else if (typeof window !== 'undefined') {
return window;
} else {
return Function('return this')();
}
})();
var Symbol = global['jest-symbol-do-not-touch'] || global.Symbol;
var global = (function () {
if (typeof globalThis !== 'undefined') {
return globalThis;
} else if (typeof global !== 'undefined') {
return global;
} else if (typeof self !== 'undefined') {
return self;
} else if (typeof window !== 'undefined') {
return window;
} else {
return Function('return this')();
}
})();
var Symbol = global['jest-symbol-do-not-touch'] || global.Symbol;
var global = (function () {
if (typeof globalThis !== 'undefined') {
return globalThis;
} else if (typeof global !== 'undefined') {
return global;
} else if (typeof self !== 'undefined') {
return self;
} else if (typeof window !== 'undefined') {
return window;
} else {
return Function('return this')();
}
})();
var jestWriteFile =
global[Symbol.for('jest-native-write-file')] || fs.writeFileSync;
var global = (function () {
if (typeof globalThis !== 'undefined') {
return globalThis;
} else if (typeof global !== 'undefined') {
return global;
} else if (typeof self !== 'undefined') {
return self;
} else if (typeof window !== 'undefined') {
return window;
} else {
return Function('return this')();
}
})();
var Symbol = global['jest-symbol-do-not-touch'] || global.Symbol;
var global = (function () {
if (typeof globalThis !== 'undefined') {
return globalThis;
} else if (typeof global !== 'undefined') {
return global;
} else if (typeof self !== 'undefined') {
return self;
} else if (typeof window !== 'undefined') {
return window;
} else {
return Function('return this')();
}
})();
var jestReadFile =
global[Symbol.for('jest-native-read-file')] || fs.readFileSync;
var global = (function () {
if (typeof globalThis !== 'undefined') {
return globalThis;
} else if (typeof global !== 'undefined') {
return global;
} else if (typeof self !== 'undefined') {
return self;
} else if (typeof window !== 'undefined') {
return window;
} else {
return Function('return this')();
}
})();
var Symbol = global['jest-symbol-do-not-touch'] || global.Symbol;
var global = (function () {
if (typeof globalThis !== 'undefined') {
return globalThis;
} else if (typeof global !== 'undefined') {
return global;
} else if (typeof self !== 'undefined') {
return self;
} else if (typeof window !== 'undefined') {
return window;
} else {
return Function('return this')();
}
})();
var jestExistsFile =
global[Symbol.for('jest-native-exists-file')] || fs.existsSync;
const SNAPSHOT_VERSION = '1';
exports.SNAPSHOT_VERSION = SNAPSHOT_VERSION;
const SNAPSHOT_VERSION_REGEXP = /^\/\/ Jest Snapshot v(.+),/;
const SNAPSHOT_GUIDE_LINK = 'https://goo.gl/fbAQLP';
exports.SNAPSHOT_GUIDE_LINK = SNAPSHOT_GUIDE_LINK;
const 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.'
);
exports.SNAPSHOT_VERSION_WARNING = SNAPSHOT_VERSION_WARNING;
const writeSnapshotVersion = () =>
`// Jest Snapshot v${SNAPSHOT_VERSION}, ${SNAPSHOT_GUIDE_LINK}`;
const validateSnapshotVersion = snapshotContents => {
const versionTest = SNAPSHOT_VERSION_REGEXP.exec(snapshotContents);
const version = versionTest && versionTest[1];
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(
_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(
_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}`
);
}
return null;
};
function isObject(item) {
return item != null && typeof item === 'object' && !Array.isArray(item);
}
const testNameToKey = (testName, count) => testName + ' ' + count;
exports.testNameToKey = testNameToKey;
const keyToTestName = key => {
if (!/ \d+$/.test(key)) {
throw new Error('Snapshot keys must end with a number.');
}
return key.replace(/ \d+$/, '');
};
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 = validateSnapshotVersion(snapshotContents);
const isInvalid = snapshotContents && validationResult;
if (update === 'none' && isInvalid) {
throw validationResult;
}
if ((update === 'all' || update === 'new') && isInvalid) {
dirty = true;
}
return {
data,
dirty
};
}; // Add extra line breaks at beginning and end of multiline snapshot
// to make the content easier to read.
exports.getSnapshotData = getSnapshotData;
const addExtraLineBreaks = string =>
string.includes('\n') ? `\n${string}\n` : string; // Remove extra line breaks at beginning and end of multiline snapshot.
// Instead of trim, which can remove additional newlines or spaces
// at beginning or end of the content from a custom serializer.
exports.addExtraLineBreaks = addExtraLineBreaks;
const removeExtraLineBreaks = string =>
string.length > 2 && string.startsWith('\n') && string.endsWith('\n')
? string.slice(1, -1)
: string;
exports.removeExtraLineBreaks = removeExtraLineBreaks;
const removeLinesBeforeExternalMatcherTrap = stack => {
const lines = stack.split('\n');
for (let i = 0; i < lines.length; i += 1) {
// It's a function name specified in `packages/expect/src/index.ts`
// for external custom matchers.
if (lines[i].includes('__EXTERNAL_MATCHER_TRAP__')) {
return lines.slice(i + 1).join('\n');
}
}
return stack;
};
exports.removeLinesBeforeExternalMatcherTrap =
removeLinesBeforeExternalMatcherTrap;
const escapeRegex = true;
const printFunctionName = false;
const serialize = (val, indent = 2, formatOverrides = {}) =>
normalizeNewlines(
(0, _prettyFormat.format)(val, {
escapeRegex,
indent,
plugins: (0, _plugins.getSerializers)(),
printFunctionName,
...formatOverrides
})
);
exports.serialize = serialize;
const minify = val =>
(0, _prettyFormat.format)(val, {
escapeRegex,
min: true,
plugins: (0, _plugins.getSerializers)(),
printFunctionName
}); // Remove double quote marks and unescape double quotes and backslashes.
exports.minify = minify;
const deserializeString = stringified =>
stringified.slice(1, -1).replace(/\\("|\\)/g, '$1');
exports.deserializeString = deserializeString;
const escapeBacktickString = str => str.replace(/`|\\|\${/g, '\\$&');
exports.escapeBacktickString = escapeBacktickString;
const printBacktickString = str => '`' + escapeBacktickString(str) + '`';
const ensureDirectoryExists = filePath => {
try {
fs.mkdirSync(path.join(path.dirname(filePath)), {
recursive: true
});
} catch {}
};
exports.ensureDirectoryExists = ensureDirectoryExists;
const normalizeNewlines = string => string.replace(/\r\n|\r/g, '\n');
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;
const deepMergeArray = (target, source) => {
const mergedOutput = Array.from(target);
source.forEach((sourceElement, index) => {
const targetElement = mergedOutput[index];
if (Array.isArray(target[index])) {
mergedOutput[index] = deepMergeArray(target[index], sourceElement);
} else if (isObject(targetElement)) {
mergedOutput[index] = deepMerge(target[index], sourceElement);
} else {
// Source does not exist in target or target is primitive and cannot be deep merged
mergedOutput[index] = sourceElement;
}
});
return mergedOutput;
}; // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
const deepMerge = (target, source) => {
if (isObject(target) && isObject(source)) {
const mergedOutput = {...target};
Object.keys(source).forEach(key => {
if (isObject(source[key]) && !source[key].$$typeof) {
if (!(key in target))
Object.assign(mergedOutput, {
[key]: source[key]
});
else mergedOutput[key] = deepMerge(target[key], source[key]);
} else if (Array.isArray(source[key])) {
mergedOutput[key] = deepMergeArray(target[key], source[key]);
} else {
Object.assign(mergedOutput, {
[key]: source[key]
});
}
});
return mergedOutput;
} else if (Array.isArray(target) && Array.isArray(source)) {
return deepMergeArray(target, source);
}
return target;
};
exports.deepMerge = deepMerge;

View File

@@ -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.

View File

@@ -0,0 +1,193 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/// <reference types="node" />
import type * as Global from './Global';
declare type Process = NodeJS.Process;
export declare type DoneFn = Global.DoneFn;
export declare type BlockFn = Global.BlockFn;
export declare type BlockName = Global.BlockName;
export declare type BlockMode = void | 'skip' | 'only' | 'todo';
export declare type TestMode = BlockMode;
export declare type TestName = Global.TestName;
export declare type TestFn = Global.TestFn;
export declare type HookFn = Global.HookFn;
export declare type AsyncFn = TestFn | HookFn;
export declare type SharedHookType = 'afterAll' | 'beforeAll';
export declare type HookType = SharedHookType | 'afterEach' | 'beforeEach';
export declare type TestContext = Global.TestContext;
export declare type Exception = any;
export declare type FormattedError = string;
export declare type Hook = {
asyncError: Error;
fn: HookFn;
type: HookType;
parent: DescribeBlock;
seenDone: boolean;
timeout: number | undefined | null;
};
export interface EventHandler {
(event: AsyncEvent, state: State): void | Promise<void>;
(event: SyncEvent, state: State): void;
}
export declare type Event = SyncEvent | AsyncEvent;
interface JestGlobals extends Global.TestFrameworkGlobals {
expect: unknown;
}
export declare type SyncEvent = {
asyncError: Error;
mode: BlockMode;
name: 'start_describe_definition';
blockName: BlockName;
} | {
mode: BlockMode;
name: 'finish_describe_definition';
blockName: BlockName;
} | {
asyncError: Error;
name: 'add_hook';
hookType: HookType;
fn: HookFn;
timeout: number | undefined;
} | {
asyncError: Error;
name: 'add_test';
testName: TestName;
fn: TestFn;
mode?: TestMode;
timeout: number | undefined;
} | {
name: 'error';
error: Exception;
};
export declare type AsyncEvent = {
name: 'setup';
testNamePattern?: string;
runtimeGlobals: JestGlobals;
parentProcess: Process;
} | {
name: 'include_test_location_in_result';
} | {
name: 'hook_start';
hook: Hook;
} | {
name: 'hook_success';
describeBlock?: DescribeBlock;
test?: TestEntry;
hook: Hook;
} | {
name: 'hook_failure';
error: string | Exception;
describeBlock?: DescribeBlock;
test?: TestEntry;
hook: Hook;
} | {
name: 'test_fn_start';
test: TestEntry;
} | {
name: 'test_fn_success';
test: TestEntry;
} | {
name: 'test_fn_failure';
error: Exception;
test: TestEntry;
} | {
name: 'test_retry';
test: TestEntry;
} | {
name: 'test_start';
test: TestEntry;
} | {
name: 'test_skip';
test: TestEntry;
} | {
name: 'test_todo';
test: TestEntry;
} | {
name: 'test_done';
test: TestEntry;
} | {
name: 'run_describe_start';
describeBlock: DescribeBlock;
} | {
name: 'run_describe_finish';
describeBlock: DescribeBlock;
} | {
name: 'run_start';
} | {
name: 'run_finish';
} | {
name: 'teardown';
};
export declare type MatcherResults = {
actual: unknown;
expected: unknown;
name: string;
pass: boolean;
};
export declare type TestStatus = 'skip' | 'done' | 'todo';
export declare type TestResult = {
duration?: number | null;
errors: Array<FormattedError>;
errorsDetailed: Array<MatcherResults | unknown>;
invocations: number;
status: TestStatus;
location?: {
column: number;
line: number;
} | null;
testPath: Array<TestName | BlockName>;
};
export declare type RunResult = {
unhandledErrors: Array<FormattedError>;
testResults: TestResults;
};
export declare type TestResults = Array<TestResult>;
export declare type GlobalErrorHandlers = {
uncaughtException: Array<(exception: Exception) => void>;
unhandledRejection: Array<(exception: Exception, promise: Promise<unknown>) => void>;
};
export declare type State = {
currentDescribeBlock: DescribeBlock;
currentlyRunningTest?: TestEntry | null;
expand?: boolean;
hasFocusedTests: boolean;
hasStarted: boolean;
originalGlobalErrorHandlers?: GlobalErrorHandlers;
parentProcess: Process | null;
rootDescribeBlock: DescribeBlock;
testNamePattern?: RegExp | null;
testTimeout: number;
unhandledErrors: Array<Exception>;
includeTestLocationInResult: boolean;
};
export declare type DescribeBlock = {
type: 'describeBlock';
children: Array<DescribeBlock | TestEntry>;
hooks: Array<Hook>;
mode: BlockMode;
name: BlockName;
parent?: DescribeBlock;
/** @deprecated Please get from `children` array instead */
tests: Array<TestEntry>;
};
export declare type TestError = Exception | [Exception | undefined, Exception];
export declare type TestEntry = {
type: 'test';
asyncError: Exception;
errors: Array<TestError>;
fn: TestFn;
invocations: number;
mode: TestMode;
name: TestName;
parent: DescribeBlock;
startedAt?: number | null;
duration?: number | null;
seenDone: boolean;
status?: TestStatus | null;
timeout?: number;
};
export {};

View File

@@ -0,0 +1 @@
'use strict';

View File

@@ -0,0 +1,462 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import type { ForegroundColor } from 'chalk';
import type { ReportOptions } from 'istanbul-reports';
import type { Arguments } from 'yargs';
declare type CoverageProvider = 'babel' | 'v8';
declare type Timers = 'real' | 'fake' | 'modern' | 'legacy';
export declare type Path = string;
export declare type Glob = string;
export declare type HasteConfig = {
/** Whether to hash files using SHA-1. */
computeSha1?: boolean;
/** The platform to use as the default, e.g. 'ios'. */
defaultPlatform?: string | null;
/** Force use of Node's `fs` APIs rather than shelling out to `find` */
forceNodeFilesystemAPI?: boolean;
/**
* Whether to follow symlinks when crawling for files.
* This options cannot be used in projects which use watchman.
* Projects with `watchman` set to true will error if this option is set to true.
*/
enableSymlinks?: boolean;
/** Path to a custom implementation of Haste. */
hasteImplModulePath?: string;
/** All platforms to target, e.g ['ios', 'android']. */
platforms?: Array<string>;
/** Whether to throw on error on module collision. */
throwOnModuleCollision?: boolean;
/** Custom HasteMap module */
hasteMapModulePath?: string;
};
export declare type CoverageReporterName = keyof ReportOptions;
export declare type CoverageReporterWithOptions<K = CoverageReporterName> = K extends CoverageReporterName ? ReportOptions[K] extends never ? never : [K, Partial<ReportOptions[K]>] : never;
export declare type CoverageReporters = Array<CoverageReporterName | CoverageReporterWithOptions>;
export declare type ReporterConfig = [string, Record<string, unknown>];
export declare type TransformerConfig = [string, Record<string, unknown>];
export interface ConfigGlobals {
[K: string]: unknown;
}
export interface PrettyFormatOptions {
}
export declare type DefaultOptions = {
automock: boolean;
bail: number;
cache: boolean;
cacheDirectory: Path;
changedFilesWithAncestor: boolean;
ci: boolean;
clearMocks: boolean;
collectCoverage: boolean;
coveragePathIgnorePatterns: Array<string>;
coverageReporters: Array<CoverageReporterName>;
coverageProvider: CoverageProvider;
detectLeaks: boolean;
detectOpenHandles: boolean;
errorOnDeprecated: boolean;
expand: boolean;
extensionsToTreatAsEsm: Array<Path>;
forceCoverageMatch: Array<Glob>;
globals: ConfigGlobals;
haste: HasteConfig;
injectGlobals: boolean;
listTests: boolean;
maxConcurrency: number;
maxWorkers: number | string;
moduleDirectories: Array<string>;
moduleFileExtensions: Array<string>;
moduleNameMapper: Record<string, string | Array<string>>;
modulePathIgnorePatterns: Array<string>;
noStackTrace: boolean;
notify: boolean;
notifyMode: NotifyMode;
passWithNoTests: boolean;
prettierPath: string;
resetMocks: boolean;
resetModules: boolean;
restoreMocks: boolean;
roots: Array<Path>;
runTestsByPath: boolean;
runner: string;
setupFiles: Array<Path>;
setupFilesAfterEnv: Array<Path>;
skipFilter: boolean;
slowTestThreshold: number;
snapshotSerializers: Array<Path>;
testEnvironment: string;
testEnvironmentOptions: Record<string, unknown>;
testFailureExitCode: string | number;
testLocationInResults: boolean;
testMatch: Array<Glob>;
testPathIgnorePatterns: Array<string>;
testRegex: Array<string>;
testRunner: string;
testSequencer: string;
testURL: string;
timers: Timers;
transformIgnorePatterns: Array<Glob>;
useStderr: boolean;
watch: boolean;
watchPathIgnorePatterns: Array<string>;
watchman: boolean;
};
export declare type DisplayName = {
name: string;
color: typeof ForegroundColor;
};
export declare type InitialOptionsWithRootDir = InitialOptions & Required<Pick<InitialOptions, 'rootDir'>>;
export declare type InitialProjectOptions = Pick<InitialOptions & {
cwd?: string;
}, keyof ProjectConfig>;
export declare type InitialOptions = Partial<{
automock: boolean;
bail: boolean | number;
cache: boolean;
cacheDirectory: Path;
ci: boolean;
clearMocks: boolean;
changedFilesWithAncestor: boolean;
changedSince: string;
collectCoverage: boolean;
collectCoverageFrom: Array<Glob>;
collectCoverageOnlyFrom: {
[key: string]: boolean;
};
coverageDirectory: string;
coveragePathIgnorePatterns: Array<string>;
coverageProvider: CoverageProvider;
coverageReporters: CoverageReporters;
coverageThreshold: CoverageThreshold;
dependencyExtractor: string;
detectLeaks: boolean;
detectOpenHandles: boolean;
displayName: string | DisplayName;
expand: boolean;
extensionsToTreatAsEsm: Array<Path>;
extraGlobals: Array<string>;
filter: Path;
findRelatedTests: boolean;
forceCoverageMatch: Array<Glob>;
forceExit: boolean;
json: boolean;
globals: ConfigGlobals;
globalSetup: string | null | undefined;
globalTeardown: string | null | undefined;
haste: HasteConfig;
injectGlobals: boolean;
reporters: Array<string | ReporterConfig>;
logHeapUsage: boolean;
lastCommit: boolean;
listTests: boolean;
maxConcurrency: number;
maxWorkers: number | string;
moduleDirectories: Array<string>;
moduleFileExtensions: Array<string>;
moduleLoader: Path;
moduleNameMapper: {
[key: string]: string | Array<string>;
};
modulePathIgnorePatterns: Array<string>;
modulePaths: Array<string>;
name: string;
noStackTrace: boolean;
notify: boolean;
notifyMode: string;
onlyChanged: boolean;
onlyFailures: boolean;
outputFile: Path;
passWithNoTests: boolean;
/**
* @deprecated Use `transformIgnorePatterns` options instead.
*/
preprocessorIgnorePatterns: Array<Glob>;
preset: string | null | undefined;
prettierPath: string | null | undefined;
projects: Array<Glob | InitialProjectOptions>;
replname: string | null | undefined;
resetMocks: boolean;
resetModules: boolean;
resolver: Path | null | undefined;
restoreMocks: boolean;
rootDir: Path;
roots: Array<Path>;
runner: string;
runTestsByPath: boolean;
/**
* @deprecated Use `transform` options instead.
*/
scriptPreprocessor: string;
setupFiles: Array<Path>;
/**
* @deprecated Use `setupFilesAfterEnv` options instead.
*/
setupTestFrameworkScriptFile: Path;
setupFilesAfterEnv: Array<Path>;
silent: boolean;
skipFilter: boolean;
skipNodeResolution: boolean;
slowTestThreshold: number;
snapshotResolver: Path;
snapshotSerializers: Array<Path>;
snapshotFormat: PrettyFormatOptions;
errorOnDeprecated: boolean;
testEnvironment: string;
testEnvironmentOptions: Record<string, unknown>;
testFailureExitCode: string | number;
testLocationInResults: boolean;
testMatch: Array<Glob>;
testNamePattern: string;
/**
* @deprecated Use `roots` options instead.
*/
testPathDirs: Array<Path>;
testPathIgnorePatterns: Array<string>;
testRegex: string | Array<string>;
testResultsProcessor: string;
testRunner: string;
testSequencer: string;
testURL: string;
testTimeout: number;
timers: Timers;
transform: {
[regex: string]: Path | TransformerConfig;
};
transformIgnorePatterns: Array<Glob>;
watchPathIgnorePatterns: Array<string>;
unmockedModulePathPatterns: Array<string>;
updateSnapshot: boolean;
useStderr: boolean;
verbose?: boolean;
watch: boolean;
watchAll: boolean;
watchman: boolean;
watchPlugins: Array<string | [string, Record<string, unknown>]>;
}>;
export declare type SnapshotUpdateState = 'all' | 'new' | 'none';
declare type NotifyMode = 'always' | 'failure' | 'success' | 'change' | 'success-change' | 'failure-change';
export declare type CoverageThresholdValue = {
branches?: number;
functions?: number;
lines?: number;
statements?: number;
};
declare type CoverageThreshold = {
[path: string]: CoverageThresholdValue;
global: CoverageThresholdValue;
};
export declare type GlobalConfig = {
bail: number;
changedSince?: string;
changedFilesWithAncestor: boolean;
collectCoverage: boolean;
collectCoverageFrom: Array<Glob>;
collectCoverageOnlyFrom?: {
[key: string]: boolean;
};
coverageDirectory: string;
coveragePathIgnorePatterns?: Array<string>;
coverageProvider: CoverageProvider;
coverageReporters: CoverageReporters;
coverageThreshold?: CoverageThreshold;
detectLeaks: boolean;
detectOpenHandles: boolean;
expand: boolean;
filter?: Path;
findRelatedTests: boolean;
forceExit: boolean;
json: boolean;
globalSetup?: string;
globalTeardown?: string;
lastCommit: boolean;
logHeapUsage: boolean;
listTests: boolean;
maxConcurrency: number;
maxWorkers: number;
noStackTrace: boolean;
nonFlagArgs: Array<string>;
noSCM?: boolean;
notify: boolean;
notifyMode: NotifyMode;
outputFile?: Path;
onlyChanged: boolean;
onlyFailures: boolean;
passWithNoTests: boolean;
projects: Array<Glob>;
replname?: string;
reporters?: Array<string | ReporterConfig>;
runTestsByPath: boolean;
rootDir: Path;
silent?: boolean;
skipFilter: boolean;
snapshotFormat: PrettyFormatOptions;
errorOnDeprecated: boolean;
testFailureExitCode: number;
testNamePattern?: string;
testPathPattern: string;
testResultsProcessor?: string;
testSequencer: string;
testTimeout?: number;
updateSnapshot: SnapshotUpdateState;
useStderr: boolean;
verbose?: boolean;
watch: boolean;
watchAll: boolean;
watchman: boolean;
watchPlugins?: Array<{
path: string;
config: Record<string, unknown>;
}> | null;
};
export declare type ProjectConfig = {
automock: boolean;
cache: boolean;
cacheDirectory: Path;
clearMocks: boolean;
coveragePathIgnorePatterns: Array<string>;
cwd: Path;
dependencyExtractor?: string;
detectLeaks: boolean;
detectOpenHandles: boolean;
displayName?: DisplayName;
errorOnDeprecated: boolean;
extensionsToTreatAsEsm: Array<Path>;
extraGlobals: Array<keyof typeof globalThis>;
filter?: Path;
forceCoverageMatch: Array<Glob>;
globalSetup?: string;
globalTeardown?: string;
globals: ConfigGlobals;
haste: HasteConfig;
injectGlobals: boolean;
moduleDirectories: Array<string>;
moduleFileExtensions: Array<string>;
moduleLoader?: Path;
moduleNameMapper: Array<[string, string]>;
modulePathIgnorePatterns: Array<string>;
modulePaths?: Array<string>;
name: string;
prettierPath: string;
resetMocks: boolean;
resetModules: boolean;
resolver?: Path;
restoreMocks: boolean;
rootDir: Path;
roots: Array<Path>;
runner: string;
setupFiles: Array<Path>;
setupFilesAfterEnv: Array<Path>;
skipFilter: boolean;
skipNodeResolution?: boolean;
slowTestThreshold: number;
snapshotResolver?: Path;
snapshotSerializers: Array<Path>;
snapshotFormat: PrettyFormatOptions;
testEnvironment: string;
testEnvironmentOptions: Record<string, unknown>;
testMatch: Array<Glob>;
testLocationInResults: boolean;
testPathIgnorePatterns: Array<string>;
testRegex: Array<string | RegExp>;
testRunner: string;
testURL: string;
timers: Timers;
transform: Array<[string, Path, Record<string, unknown>]>;
transformIgnorePatterns: Array<Glob>;
watchPathIgnorePatterns: Array<string>;
unmockedModulePathPatterns?: Array<string>;
};
export declare type Argv = Arguments<Partial<{
all: boolean;
automock: boolean;
bail: boolean | number;
cache: boolean;
cacheDirectory: string;
changedFilesWithAncestor: boolean;
changedSince: string;
ci: boolean;
clearCache: boolean;
clearMocks: boolean;
collectCoverage: boolean;
collectCoverageFrom: string;
collectCoverageOnlyFrom: Array<string>;
color: boolean;
colors: boolean;
config: string;
coverage: boolean;
coverageDirectory: string;
coveragePathIgnorePatterns: Array<string>;
coverageReporters: Array<string>;
coverageThreshold: string;
debug: boolean;
env: string;
expand: boolean;
findRelatedTests: boolean;
forceExit: boolean;
globals: string;
globalSetup: string | null | undefined;
globalTeardown: string | null | undefined;
haste: string;
init: boolean;
injectGlobals: boolean;
json: boolean;
lastCommit: boolean;
logHeapUsage: boolean;
maxWorkers: number | string;
moduleDirectories: Array<string>;
moduleFileExtensions: Array<string>;
moduleNameMapper: string;
modulePathIgnorePatterns: Array<string>;
modulePaths: Array<string>;
noStackTrace: boolean;
notify: boolean;
notifyMode: string;
onlyChanged: boolean;
onlyFailures: boolean;
outputFile: string;
preset: string | null | undefined;
projects: Array<string>;
prettierPath: string | null | undefined;
resetMocks: boolean;
resetModules: boolean;
resolver: string | null | undefined;
restoreMocks: boolean;
rootDir: string;
roots: Array<string>;
runInBand: boolean;
selectProjects: Array<string>;
setupFiles: Array<string>;
setupFilesAfterEnv: Array<string>;
showConfig: boolean;
silent: boolean;
snapshotSerializers: Array<string>;
testEnvironment: string;
testEnvironmentOptions: string;
testFailureExitCode: string | null | undefined;
testMatch: Array<string>;
testNamePattern: string;
testPathIgnorePatterns: Array<string>;
testPathPattern: Array<string>;
testRegex: string | Array<string>;
testResultsProcessor: string;
testRunner: string;
testSequencer: string;
testURL: string;
testTimeout: number | null | undefined;
timers: string;
transform: string;
transformIgnorePatterns: Array<string>;
unmockedModulePathPatterns: Array<string> | null | undefined;
updateSnapshot: boolean;
useStderr: boolean;
verbose: boolean;
version: boolean;
watch: boolean;
watchAll: boolean;
watchman: boolean;
watchPathIgnorePatterns: Array<string>;
}>>;
export {};

View File

@@ -0,0 +1 @@
'use strict';

View File

@@ -0,0 +1,95 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import type { CoverageMapData } from 'istanbul-lib-coverage';
export declare type ValidTestReturnValues = void | undefined;
declare type TestReturnValuePromise = Promise<unknown>;
declare type TestReturnValueGenerator = Generator<void, unknown, void>;
export declare type TestReturnValue = ValidTestReturnValues | TestReturnValuePromise;
export declare type TestContext = Record<string, unknown>;
export declare type DoneFn = (reason?: string | Error) => void;
export declare type DoneTakingTestFn = (this: TestContext | undefined, done: DoneFn) => ValidTestReturnValues;
export declare type PromiseReturningTestFn = (this: TestContext | undefined) => TestReturnValue;
export declare type GeneratorReturningTestFn = (this: TestContext | undefined) => TestReturnValueGenerator;
export declare type TestName = string;
export declare type TestFn = PromiseReturningTestFn | GeneratorReturningTestFn | DoneTakingTestFn;
export declare type ConcurrentTestFn = () => TestReturnValuePromise;
export declare type BlockFn = () => void;
export declare type BlockName = string;
export declare type HookFn = TestFn;
export declare type Col = unknown;
export declare type Row = ReadonlyArray<Col>;
export declare type Table = ReadonlyArray<Row>;
export declare type ArrayTable = Table | Row;
export declare type TemplateTable = TemplateStringsArray;
export declare type TemplateData = ReadonlyArray<unknown>;
export declare type EachTable = ArrayTable | TemplateTable;
export declare type TestCallback = BlockFn | TestFn | ConcurrentTestFn;
export declare type EachTestFn<EachCallback extends TestCallback> = (...args: ReadonlyArray<any>) => ReturnType<EachCallback>;
declare type Jasmine = {
_DEFAULT_TIMEOUT_INTERVAL?: number;
addMatchers: (matchers: Record<string, unknown>) => void;
};
declare type Each<EachCallback extends TestCallback> = ((table: EachTable, ...taggedTemplateData: TemplateData) => (name: BlockName | TestName, test: EachTestFn<EachCallback>, timeout?: number) => void) | (() => () => void);
export interface HookBase {
(fn: HookFn, timeout?: number): void;
}
export interface ItBase {
(testName: TestName, fn: TestFn, timeout?: number): void;
each: Each<TestFn>;
}
export interface It extends ItBase {
only: ItBase;
skip: ItBase;
todo: (testName: TestName) => void;
}
export interface ItConcurrentBase {
(testName: TestName, testFn: ConcurrentTestFn, timeout?: number): void;
each: Each<ConcurrentTestFn>;
}
export interface ItConcurrentExtended extends ItConcurrentBase {
only: ItConcurrentBase;
skip: ItConcurrentBase;
}
export interface ItConcurrent extends It {
concurrent: ItConcurrentExtended;
}
export interface DescribeBase {
(blockName: BlockName, blockFn: BlockFn): void;
each: Each<BlockFn>;
}
export interface Describe extends DescribeBase {
only: DescribeBase;
skip: DescribeBase;
}
export interface TestFrameworkGlobals {
it: ItConcurrent;
test: ItConcurrent;
fit: ItBase & {
concurrent?: ItConcurrentBase;
};
xit: ItBase;
xtest: ItBase;
describe: Describe;
xdescribe: DescribeBase;
fdescribe: DescribeBase;
beforeAll: HookBase;
beforeEach: HookBase;
afterEach: HookBase;
afterAll: HookBase;
}
export interface GlobalAdditions extends TestFrameworkGlobals {
__coverage__: CoverageMapData;
jasmine: Jasmine;
fail: () => void;
pending: () => void;
spyOn: () => void;
spyOnProperty: () => void;
}
export interface Global extends GlobalAdditions, Omit<typeof globalThis, keyof GlobalAdditions> {
[extras: string]: unknown;
}
export {};

View File

@@ -0,0 +1 @@
'use strict';

View File

@@ -0,0 +1,31 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* 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 Milliseconds = number;
declare type Status = 'passed' | 'failed' | 'skipped' | 'pending' | 'todo' | 'disabled';
declare type Callsite = {
column: number;
line: number;
};
export declare type AssertionResult = {
ancestorTitles: Array<string>;
duration?: Milliseconds | null;
failureDetails: Array<unknown>;
failureMessages: Array<string>;
fullName: string;
invocations?: number;
location?: Callsite | null;
numPassingAsserts: number;
status: Status;
title: string;
};
export declare type SerializableError = {
code?: unknown;
message: string;
stack: string | null | undefined;
type?: string;
};
export {};

View File

@@ -0,0 +1 @@
'use strict';

View File

@@ -0,0 +1,11 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* 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 TransformResult = {
code: string;
originalCode: string;
sourceMapPath: string | null;
};

View File

@@ -0,0 +1 @@
'use strict';

View File

@@ -0,0 +1,12 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import type * as Circus from './Circus';
import type * as Config from './Config';
import type * as Global from './Global';
import type * as TestResult from './TestResult';
import type * as TransformTypes from './Transform';
export type { Circus, Config, Global, TestResult, TransformTypes };

View File

@@ -0,0 +1 @@
'use strict';

View File

@@ -0,0 +1,37 @@
{
"name": "@jest/types",
"version": "27.5.1",
"repository": {
"type": "git",
"url": "https://github.com/facebook/jest.git",
"directory": "packages/jest-types"
},
"engines": {
"node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.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": {
"@types/istanbul-lib-coverage": "^2.0.0",
"@types/istanbul-reports": "^3.0.0",
"@types/node": "*",
"@types/yargs": "^16.0.0",
"chalk": "^4.0.0"
},
"devDependencies": {
"@tsd/typescript": "~4.1.5",
"tsd-lite": "^0.5.1"
},
"publishConfig": {
"access": "public"
},
"gitHead": "67c1aa20c5fec31366d733e901fee2b981cb1850"
}

View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) Microsoft Corporation.
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

View File

@@ -0,0 +1,15 @@
# Installation
> `npm install --save @types/yargs`
# Summary
This package contains type definitions for yargs (https://github.com/chevex/yargs).
# Details
Files were exported from https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/yargs/v16.
### Additional Details
* Last updated: Mon, 20 Nov 2023 23:36:24 GMT
* Dependencies: [@types/yargs-parser](https://npmjs.com/package/@types/yargs-parser)
# Credits
These definitions were written by [Martin Poelstra](https://github.com/poelstra), [Mizunashi Mana](https://github.com/mizunashi-mana), [Jeffery Grajkowski](https://github.com/pushplay), [Jimi (Dimitris) Charalampidis](https://github.com/JimiC), [Steffen Viken Valvåg](https://github.com/steffenvv), [Emily Marigold Klassen](https://github.com/forivall), [ExE Boss](https://github.com/ExE-Boss), and [Aankhen](https://github.com/Aankhen).

View File

@@ -0,0 +1,5 @@
import * as Parser from "yargs-parser";
export function applyExtends(config: Record<string, any>, cwd: string, mergeExtends: boolean): Record<string, any>;
export function hideBin(argv: string[]): string[];
export { Parser };

View File

@@ -0,0 +1,917 @@
// The following TSLint rules have been disabled:
// unified-signatures: Because there is useful information in the argument names of the overloaded signatures
// Convention:
// Use 'union types' when:
// - parameter types have similar signature type (i.e. 'string | ReadonlyArray<string>')
// - parameter names have the same semantic meaning (i.e. ['command', 'commands'] , ['key', 'keys'])
// An example for not using 'union types' is the declaration of 'env' where `prefix` and `enable` parameters
// have different semantics. On the other hand, in the declaration of 'usage', a `command: string` parameter
// has the same semantic meaning with declaring an overload method by using `commands: ReadonlyArray<string>`,
// thus it's preferred to use `command: string | ReadonlyArray<string>`
// Use parameterless declaration instead of declaring all parameters optional,
// when all parameters are optional and more than one
import { Configuration, DetailedArguments } from "yargs-parser";
declare namespace yargs {
type BuilderCallback<T, R> =
| ((args: Argv<T>) => PromiseLike<Argv<R>>)
| ((args: Argv<T>) => Argv<R>)
| ((args: Argv<T>) => void);
type ParserConfigurationOptions = Configuration & {
/** Sort commands alphabetically. Default is `false` */
"sort-commands": boolean;
};
/**
* The type parameter `T` is the expected shape of the parsed options.
* `Arguments<T>` is those options plus `_` and `$0`, and an indexer falling
* back to `unknown` for unknown options.
*
* For the return type / `argv` property, we create a mapped type over
* `Arguments<T>` to simplify the inferred type signature in client code.
*/
interface Argv<T = {}> {
(): { [key in keyof Arguments<T>]: Arguments<T>[key] };
(args: readonly string[], cwd?: string): Argv<T>;
/**
* Set key names as equivalent such that updates to a key will propagate to aliases and vice-versa.
*
* Optionally `.alias()` can take an object that maps keys to aliases.
* Each key of this object should be the canonical version of the option, and each value should be a string or an array of strings.
*/
// Aliases for previously declared options can inherit the types of those options.
alias<K1 extends keyof T, K2 extends string>(
shortName: K1,
longName: K2 | readonly K2[],
): Argv<T & { [key in K2]: T[K1] }>;
alias<K1 extends keyof T, K2 extends string>(
shortName: K2,
longName: K1 | readonly K1[],
): Argv<T & { [key in K2]: T[K1] }>;
alias(shortName: string | readonly string[], longName: string | readonly string[]): Argv<T>;
alias(aliases: { [shortName: string]: string | readonly string[] }): Argv<T>;
/**
* Get the arguments as a plain old object.
*
* Arguments without a corresponding flag show up in the `argv._` array.
*
* The script name or node command is available at `argv.$0` similarly to how `$0` works in bash or perl.
*
* If `yargs` is executed in an environment that embeds node and there's no script name (e.g. Electron or nw.js),
* it will ignore the first parameter since it expects it to be the script name. In order to override
* this behavior, use `.parse(process.argv.slice(1))` instead of .argv and the first parameter won't be ignored.
*/
argv: { [key in keyof Arguments<T>]: Arguments<T>[key] };
/**
* Tell the parser to interpret `key` as an array.
* If `.array('foo')` is set, `--foo foo bar` will be parsed as `['foo', 'bar']` rather than as `'foo'`.
* Also, if you use the option multiple times all the values will be flattened in one array so `--foo foo --foo bar` will be parsed as `['foo', 'bar']`
*
* When the option is used with a positional, use `--` to tell `yargs` to stop adding values to the array.
*/
array<K extends keyof T>(key: K | readonly K[]): Argv<Omit<T, K> & { [key in K]: ToArray<T[key]> }>;
array<K extends string>(
key: K | readonly K[],
): Argv<T & { [key in K]: Array<string | number> | undefined }>;
/**
* Interpret `key` as a boolean. If a non-flag option follows `key` in `process.argv`, that string won't get set as the value of `key`.
*
* `key` will default to `false`, unless a `default(key, undefined)` is explicitly set.
*
* If `key` is an array, interpret all the elements as booleans.
*/
boolean<K extends keyof T>(key: K | readonly K[]): Argv<Omit<T, K> & { [key in K]: boolean | undefined }>;
boolean<K extends string>(key: K | readonly K[]): Argv<T & { [key in K]: boolean | undefined }>;
/**
* Check that certain conditions are met in the provided arguments.
* @param func Called with two arguments, the parsed `argv` hash and an array of options and their aliases.
* If `func` throws or returns a non-truthy value, show the thrown error, usage information, and exit.
* @param global Indicates whether `check()` should be enabled both at the top-level and for each sub-command.
*/
check(func: (argv: Arguments<T>, aliases: { [alias: string]: string }) => any, global?: boolean): Argv<T>;
/**
* Limit valid values for key to a predefined set of choices, given as an array or as an individual value.
* If this method is called multiple times, all enumerated values will be merged together.
* Choices are generally strings or numbers, and value matching is case-sensitive.
*
* Optionally `.choices()` can take an object that maps multiple keys to their choices.
*
* Choices can also be specified as choices in the object given to `option()`.
*/
choices<K extends keyof T, C extends readonly any[]>(
key: K,
values: C,
): Argv<Omit<T, K> & { [key in K]: C[number] | undefined }>;
choices<K extends string, C extends readonly any[]>(
key: K,
values: C,
): Argv<T & { [key in K]: C[number] | undefined }>;
choices<C extends { [key: string]: readonly any[] }>(
choices: C,
): Argv<Omit<T, keyof C> & { [key in keyof C]: C[key][number] | undefined }>;
/**
* Provide a synchronous function to coerce or transform the value(s) given on the command line for `key`.
*
* The coercion function should accept one argument, representing the parsed value from the command line, and should return a new value or throw an error.
* The returned value will be used as the value for `key` (or one of its aliases) in `argv`.
*
* If the function throws, the error will be treated as a validation failure, delegating to either a custom `.fail()` handler or printing the error message in the console.
*
* Coercion will be applied to a value after all other modifications, such as `.normalize()`.
*
* Optionally `.coerce()` can take an object that maps several keys to their respective coercion function.
*
* You can also map the same function to several keys at one time. Just pass an array of keys as the first argument to `.coerce()`.
*
* If you are using dot-notion or arrays, .e.g., `user.email` and `user.password`, coercion will be applied to the final object that has been parsed
*/
coerce<K extends keyof T, V>(
key: K | readonly K[],
func: (arg: any) => V,
): Argv<Omit<T, K> & { [key in K]: V | undefined }>;
coerce<K extends string, V>(
key: K | readonly K[],
func: (arg: any) => V,
): Argv<T & { [key in K]: V | undefined }>;
coerce<O extends { [key: string]: (arg: any) => any }>(
opts: O,
): Argv<Omit<T, keyof O> & { [key in keyof O]: ReturnType<O[key]> | undefined }>;
/**
* Define the commands exposed by your application.
* @param command Should be a string representing the command or an array of strings representing the command and its aliases.
* @param description Use to provide a description for each command your application accepts (the values stored in `argv._`).
* Set `description` to false to create a hidden command. Hidden commands don't show up in the help output and aren't available for completion.
* @param [builder] Object to give hints about the options that your command accepts.
* Can also be a function. This function is executed with a yargs instance, and can be used to provide advanced command specific help.
*
* Note that when `void` is returned, the handler `argv` object type will not include command-specific arguments.
* @param [handler] Function, which will be executed with the parsed `argv` object.
*/
command<U = T>(
command: string | readonly string[],
description: string,
builder?: BuilderCallback<T, U>,
handler?: (args: Arguments<U>) => void,
middlewares?: Array<MiddlewareFunction<U>>,
deprecated?: boolean | string,
): Argv<U>;
command<O extends { [key: string]: Options }>(
command: string | readonly string[],
description: string,
builder?: O,
handler?: (args: Arguments<InferredOptionTypes<O>>) => void,
middlewares?: Array<MiddlewareFunction<O>>,
deprecated?: boolean | string,
): Argv<T>;
command<U>(command: string | readonly string[], description: string, module: CommandModule<T, U>): Argv<U>;
command<U = T>(
command: string | readonly string[],
showInHelp: false,
builder?: BuilderCallback<T, U>,
handler?: (args: Arguments<U>) => void,
middlewares?: Array<MiddlewareFunction<U>>,
deprecated?: boolean | string,
): Argv<T>;
command<O extends { [key: string]: Options }>(
command: string | readonly string[],
showInHelp: false,
builder?: O,
handler?: (args: Arguments<InferredOptionTypes<O>>) => void,
): Argv<T>;
command<U>(command: string | readonly string[], showInHelp: false, module: CommandModule<T, U>): Argv<U>;
command<U>(module: CommandModule<T, U>): Argv<U>;
// Advanced API
/** Apply command modules from a directory relative to the module calling this method. */
commandDir(dir: string, opts?: RequireDirectoryOptions): Argv<T>;
/**
* Enable bash/zsh-completion shortcuts for commands and options.
*
* If invoked without parameters, `.completion()` will make completion the command to output the completion script.
*
* @param [cmd] When present in `argv._`, will result in the `.bashrc` or `.zshrc` completion script being outputted.
* To enable bash/zsh completions, concat the generated script to your `.bashrc` or `.bash_profile` (or `.zshrc` for zsh).
* @param [description] Provide a description in your usage instructions for the command that generates the completion scripts.
* @param [func] Rather than relying on yargs' default completion functionality, which shiver me timbers is pretty awesome, you can provide your own completion method.
*/
completion(): Argv<T>;
completion(cmd: string, func?: AsyncCompletionFunction): Argv<T>;
completion(cmd: string, func?: SyncCompletionFunction): Argv<T>;
completion(cmd: string, func?: PromiseCompletionFunction): Argv<T>;
completion(cmd: string, description?: string | false, func?: AsyncCompletionFunction): Argv<T>;
completion(cmd: string, description?: string | false, func?: SyncCompletionFunction): Argv<T>;
completion(cmd: string, description?: string | false, func?: PromiseCompletionFunction): Argv<T>;
/**
* Tells the parser that if the option specified by `key` is passed in, it should be interpreted as a path to a JSON config file.
* The file is loaded and parsed, and its properties are set as arguments.
* Because the file is loaded using Node's require(), the filename MUST end in `.json` to be interpreted correctly.
*
* If invoked without parameters, `.config()` will make --config the option to pass the JSON config file.
*
* @param [description] Provided to customize the config (`key`) option in the usage string.
* @param [explicitConfigurationObject] An explicit configuration `object`
*/
config(): Argv<T>;
config(
key: string | readonly string[],
description?: string,
parseFn?: (configPath: string) => object,
): Argv<T>;
config(key: string | readonly string[], parseFn: (configPath: string) => object): Argv<T>;
config(explicitConfigurationObject: object): Argv<T>;
/**
* Given the key `x` is set, the key `y` must not be set. `y` can either be a single string or an array of argument names that `x` conflicts with.
*
* Optionally `.conflicts()` can accept an object specifying multiple conflicting keys.
*/
conflicts(key: string, value: string | readonly string[]): Argv<T>;
conflicts(conflicts: { [key: string]: string | readonly string[] }): Argv<T>;
/**
* Interpret `key` as a boolean flag, but set its parsed value to the number of flag occurrences rather than `true` or `false`. Default value is thus `0`.
*/
count<K extends keyof T>(key: K | readonly K[]): Argv<Omit<T, K> & { [key in K]: number }>;
count<K extends string>(key: K | readonly K[]): Argv<T & { [key in K]: number }>;
/**
* Set `argv[key]` to `value` if no option was specified in `process.argv`.
*
* Optionally `.default()` can take an object that maps keys to default values.
*
* The default value can be a `function` which returns a value. The name of the function will be used in the usage string.
*
* Optionally, `description` can also be provided and will take precedence over displaying the value in the usage instructions.
*/
default<K extends keyof T, V>(key: K, value: V, description?: string): Argv<Omit<T, K> & { [key in K]: V }>;
default<K extends string, V>(key: K, value: V, description?: string): Argv<T & { [key in K]: V }>;
default<D extends { [key: string]: any }>(defaults: D, description?: string): Argv<Omit<T, keyof D> & D>;
/**
* @deprecated since version 6.6.0
* Use '.demandCommand()' or '.demandOption()' instead
*/
demand<K extends keyof T>(key: K | readonly K[], msg?: string | true): Argv<Defined<T, K>>;
demand<K extends string>(key: K | readonly K[], msg?: string | true): Argv<T & { [key in K]: unknown }>;
demand(key: string | readonly string[], required?: boolean): Argv<T>;
demand(positionals: number, msg: string): Argv<T>;
demand(positionals: number, required?: boolean): Argv<T>;
demand(positionals: number, max: number, msg?: string): Argv<T>;
/**
* @param key If is a string, show the usage information and exit if key wasn't specified in `process.argv`.
* If is an array, demand each element.
* @param msg If string is given, it will be printed when the argument is missing, instead of the standard error message.
* @param demand Controls whether the option is demanded; this is useful when using .options() to specify command line parameters.
*/
demandOption<K extends keyof T>(key: K | readonly K[], msg?: string | true): Argv<Defined<T, K>>;
demandOption<K extends string>(
key: K | readonly K[],
msg?: string | true,
): Argv<T & { [key in K]: unknown }>;
demandOption(key: string | readonly string[], demand?: boolean): Argv<T>;
/**
* Demand in context of commands.
* You can demand a minimum and a maximum number a user can have within your program, as well as provide corresponding error messages if either of the demands is not met.
*/
demandCommand(): Argv<T>;
demandCommand(min: number, minMsg?: string): Argv<T>;
demandCommand(min: number, max?: number, minMsg?: string, maxMsg?: string): Argv<T>;
/**
* Shows a [deprecated] notice in front of the option
*/
deprecateOption(option: string, msg?: string): Argv<T>;
/**
* Describe a `key` for the generated usage information.
*
* Optionally `.describe()` can take an object that maps keys to descriptions.
*/
describe(key: string | readonly string[], description: string): Argv<T>;
describe(descriptions: { [key: string]: string }): Argv<T>;
/** Should yargs attempt to detect the os' locale? Defaults to `true`. */
detectLocale(detect: boolean): Argv<T>;
/**
* Tell yargs to parse environment variables matching the given prefix and apply them to argv as though they were command line arguments.
*
* Use the "__" separator in the environment variable to indicate nested options. (e.g. prefix_nested__foo => nested.foo)
*
* If this method is called with no argument or with an empty string or with true, then all env vars will be applied to argv.
*
* Program arguments are defined in this order of precedence:
* 1. Command line args
* 2. Env vars
* 3. Config file/objects
* 4. Configured defaults
*
* Env var parsing is disabled by default, but you can also explicitly disable it by calling `.env(false)`, e.g. if you need to undo previous configuration.
*/
env(): Argv<T>;
env(prefix: string): Argv<T>;
env(enable: boolean): Argv<T>;
/** A message to print at the end of the usage instructions */
epilog(msg: string): Argv<T>;
/** A message to print at the end of the usage instructions */
epilogue(msg: string): Argv<T>;
/**
* Give some example invocations of your program.
* Inside `cmd`, the string `$0` will get interpolated to the current script name or node command for the present script similar to how `$0` works in bash or perl.
* Examples will be printed out as part of the help message.
*/
example(command: string, description: string): Argv<T>;
example(command: ReadonlyArray<[string, string?]>): Argv<T>;
/** Manually indicate that the program should exit, and provide context about why we wanted to exit. Follows the behavior set by `.exitProcess().` */
exit(code: number, err: Error): void;
/**
* By default, yargs exits the process when the user passes a help flag, the user uses the `.version` functionality, validation fails, or the command handler fails.
* Calling `.exitProcess(false)` disables this behavior, enabling further actions after yargs have been validated.
*/
exitProcess(enabled: boolean): Argv<T>;
/**
* Method to execute when a failure occurs, rather than printing the failure message.
* @param func Is called with the failure message that would have been printed, the Error instance originally thrown and yargs state when the failure occurred.
*/
fail(func: (msg: string, err: Error, yargs: Argv<T>) => any): Argv<T>;
/**
* Allows to programmatically get completion choices for any line.
* @param args An array of the words in the command line to complete.
* @param done The callback to be called with the resulting completions.
*/
getCompletion(args: readonly string[], done: (completions: readonly string[]) => void): Argv<T>;
/**
* Indicate that an option (or group of options) should not be reset when a command is executed
*
* Options default to being global.
*/
global(key: string | readonly string[]): Argv<T>;
/** Given a key, or an array of keys, places options under an alternative heading when displaying usage instructions */
group(key: string | readonly string[], groupName: string): Argv<T>;
/** Hides a key from the generated usage information. Unless a `--show-hidden` option is also passed with `--help` (see `showHidden()`). */
hide(key: string): Argv<T>;
/**
* Configure an (e.g. `--help`) and implicit command that displays the usage string and exits the process.
* By default yargs enables help on the `--help` option.
*
* Note that any multi-char aliases (e.g. `help`) used for the help option will also be used for the implicit command.
* If there are no multi-char aliases (e.g. `h`), then all single-char aliases will be used for the command.
*
* If invoked without parameters, `.help()` will use `--help` as the option and help as the implicit command to trigger help output.
*
* @param [description] Customizes the description of the help option in the usage string.
* @param [enableExplicit] If `false` is provided, it will disable --help.
*/
help(): Argv<T>;
help(enableExplicit: boolean): Argv<T>;
help(option: string, enableExplicit: boolean): Argv<T>;
help(option: string, description?: string, enableExplicit?: boolean): Argv<T>;
/**
* Given the key `x` is set, it is required that the key `y` is set.
* y` can either be the name of an argument to imply, a number indicating the position of an argument or an array of multiple implications to associate with `x`.
*
* Optionally `.implies()` can accept an object specifying multiple implications.
*/
implies(key: string, value: string | readonly string[]): Argv<T>;
implies(implies: { [key: string]: string | readonly string[] }): Argv<T>;
/**
* Return the locale that yargs is currently using.
*
* By default, yargs will auto-detect the operating system's locale so that yargs-generated help content will display in the user's language.
*/
locale(): string;
/**
* Override the auto-detected locale from the user's operating system with a static locale.
* Note that the OS locale can be modified by setting/exporting the `LC_ALL` environment variable.
*/
locale(loc: string): Argv<T>;
/**
* Define global middleware functions to be called first, in list order, for all cli command.
* @param callbacks Can be a function or a list of functions. Each callback gets passed a reference to argv.
* @param [applyBeforeValidation] Set to `true` to apply middleware before validation. This will execute the middleware prior to validation checks, but after parsing.
*/
middleware(
callbacks: MiddlewareFunction<T> | ReadonlyArray<MiddlewareFunction<T>>,
applyBeforeValidation?: boolean,
): Argv<T>;
/**
* The number of arguments that should be consumed after a key. This can be a useful hint to prevent parsing ambiguity.
*
* Optionally `.nargs()` can take an object of `key`/`narg` pairs.
*/
nargs(key: string, count: number): Argv<T>;
nargs(nargs: { [key: string]: number }): Argv<T>;
/** The key provided represents a path and should have `path.normalize()` applied. */
normalize<K extends keyof T>(key: K | readonly K[]): Argv<Omit<T, K> & { [key in K]: ToString<T[key]> }>;
normalize<K extends string>(key: K | readonly K[]): Argv<T & { [key in K]: string | undefined }>;
/**
* Tell the parser to always interpret key as a number.
*
* If `key` is an array, all elements will be parsed as numbers.
*
* If the option is given on the command line without a value, `argv` will be populated with `undefined`.
*
* If the value given on the command line cannot be parsed as a number, `argv` will be populated with `NaN`.
*
* Note that decimals, hexadecimals, and scientific notation are all accepted.
*/
number<K extends keyof T>(key: K | readonly K[]): Argv<Omit<T, K> & { [key in K]: ToNumber<T[key]> }>;
number<K extends string>(key: K | readonly K[]): Argv<T & { [key in K]: number | undefined }>;
/**
* Method to execute when a command finishes successfully.
* @param func Is called with the successful result of the command that finished.
*/
onFinishCommand(func: (result: any) => void): Argv<T>;
/**
* This method can be used to make yargs aware of options that could exist.
* You can also pass an opt object which can hold further customization, like `.alias()`, `.demandOption()` etc. for that option.
*/
option<K extends keyof T, O extends Options>(
key: K,
options: O,
): Argv<Omit<T, K> & { [key in K]: InferredOptionType<O> }>;
option<K extends string, O extends Options>(
key: K,
options: O,
): Argv<T & { [key in K]: InferredOptionType<O> }>;
option<O extends { [key: string]: Options }>(options: O): Argv<Omit<T, keyof O> & InferredOptionTypes<O>>;
/**
* This method can be used to make yargs aware of options that could exist.
* You can also pass an opt object which can hold further customization, like `.alias()`, `.demandOption()` etc. for that option.
*/
options<K extends keyof T, O extends Options>(
key: K,
options: O,
): Argv<Omit<T, K> & { [key in K]: InferredOptionType<O> }>;
options<K extends string, O extends Options>(
key: K,
options: O,
): Argv<T & { [key in K]: InferredOptionType<O> }>;
options<O extends { [key: string]: Options }>(options: O): Argv<Omit<T, keyof O> & InferredOptionTypes<O>>;
/**
* Parse `args` instead of `process.argv`. Returns the `argv` object. `args` may either be a pre-processed argv array, or a raw argument string.
*
* Note: Providing a callback to parse() disables the `exitProcess` setting until after the callback is invoked.
* @param [context] Provides a useful mechanism for passing state information to commands
*/
parse(): { [key in keyof Arguments<T>]: Arguments<T>[key] };
parse(
arg: string | readonly string[],
context?: object,
parseCallback?: ParseCallback<T>,
): { [key in keyof Arguments<T>]: Arguments<T>[key] };
/**
* If the arguments have not been parsed, this property is `false`.
*
* If the arguments have been parsed, this contain detailed parsed arguments.
*/
parsed: DetailedArguments | false;
/** Allows to configure advanced yargs features. */
parserConfiguration(configuration: Partial<ParserConfigurationOptions>): Argv<T>;
/**
* Similar to `config()`, indicates that yargs should interpret the object from the specified key in package.json as a configuration object.
* @param [cwd] If provided, the package.json will be read from this location
*/
pkgConf(key: string | readonly string[], cwd?: string): Argv<T>;
/**
* Allows you to configure a command's positional arguments with an API similar to `.option()`.
* `.positional()` should be called in a command's builder function, and is not available on the top-level yargs instance. If so, it will throw an error.
*/
positional<K extends keyof T, O extends PositionalOptions>(
key: K,
opt: O,
): Argv<Omit<T, K> & { [key in K]: InferredOptionType<O> }>;
positional<K extends string, O extends PositionalOptions>(
key: K,
opt: O,
): Argv<T & { [key in K]: InferredOptionType<O> }>;
/** Should yargs provide suggestions regarding similar commands if no matching command is found? */
recommendCommands(): Argv<T>;
/**
* @deprecated since version 6.6.0
* Use '.demandCommand()' or '.demandOption()' instead
*/
require<K extends keyof T>(key: K | readonly K[], msg?: string | true): Argv<Defined<T, K>>;
require(key: string, msg: string): Argv<T>;
require(key: string, required: boolean): Argv<T>;
require(keys: readonly number[], msg: string): Argv<T>;
require(keys: readonly number[], required: boolean): Argv<T>;
require(positionals: number, required: boolean): Argv<T>;
require(positionals: number, msg: string): Argv<T>;
/**
* @deprecated since version 6.6.0
* Use '.demandCommand()' or '.demandOption()' instead
*/
required<K extends keyof T>(key: K | readonly K[], msg?: string | true): Argv<Defined<T, K>>;
required(key: string, msg: string): Argv<T>;
required(key: string, required: boolean): Argv<T>;
required(keys: readonly number[], msg: string): Argv<T>;
required(keys: readonly number[], required: boolean): Argv<T>;
required(positionals: number, required: boolean): Argv<T>;
required(positionals: number, msg: string): Argv<T>;
requiresArg(key: string | readonly string[]): Argv<T>;
/**
* @deprecated since version 6.6.0
* Use '.global()' instead
*/
reset(): Argv<T>;
/** Set the name of your script ($0). Default is the base filename executed by node (`process.argv[1]`) */
scriptName($0: string): Argv<T>;
/**
* Generate a bash completion script.
* Users of your application can install this script in their `.bashrc`, and yargs will provide completion shortcuts for commands and options.
*/
showCompletionScript(): Argv<T>;
/**
* Configure the `--show-hidden` option that displays the hidden keys (see `hide()`).
* @param option If `boolean`, it enables/disables this option altogether. i.e. hidden keys will be permanently hidden if first argument is `false`.
* If `string` it changes the key name ("--show-hidden").
* @param description Changes the default description ("Show hidden options")
*/
showHidden(option?: string | boolean): Argv<T>;
showHidden(option: string, description?: string): Argv<T>;
/**
* Print the usage data using the console function consoleLevel for printing.
* @param [consoleLevel='error']
*/
showHelp(consoleLevel?: string): Argv<T>;
/**
* Provide the usage data as a string.
* @param printCallback a function with a single argument.
*/
showHelp(printCallback: (s: string) => void): Argv<T>;
/**
* By default, yargs outputs a usage string if any error is detected.
* Use the `.showHelpOnFail()` method to customize this behavior.
* @param enable If `false`, the usage string is not output.
* @param [message] Message that is output after the error message.
*/
showHelpOnFail(enable: boolean, message?: string): Argv<T>;
/** Specifies either a single option key (string), or an array of options. If any of the options is present, yargs validation is skipped. */
skipValidation(key: string | readonly string[]): Argv<T>;
/**
* Any command-line argument given that is not demanded, or does not have a corresponding description, will be reported as an error.
*
* Unrecognized commands will also be reported as errors.
*/
strict(): Argv<T>;
strict(enabled: boolean): Argv<T>;
/**
* Similar to .strict(), except that it only applies to unrecognized commands.
* A user can still provide arbitrary options, but unknown positional commands
* will raise an error.
*/
strictCommands(): Argv<T>;
strictCommands(enabled: boolean): Argv<T>;
/**
* Similar to `.strict()`, except that it only applies to unrecognized options. A
* user can still provide arbitrary positional options, but unknown options
* will raise an error.
*/
strictOptions(): Argv<T>;
strictOptions(enabled: boolean): Argv<T>;
/**
* Tell the parser logic not to interpret `key` as a number or boolean. This can be useful if you need to preserve leading zeros in an input.
*
* If `key` is an array, interpret all the elements as strings.
*
* `.string('_')` will result in non-hyphenated arguments being interpreted as strings, regardless of whether they resemble numbers.
*/
string<K extends keyof T>(key: K | readonly K[]): Argv<Omit<T, K> & { [key in K]: ToString<T[key]> }>;
string<K extends string>(key: K | readonly K[]): Argv<T & { [key in K]: string | undefined }>;
// Intended to be used with '.wrap()'
terminalWidth(): number;
updateLocale(obj: { [key: string]: string }): Argv<T>;
/**
* Override the default strings used by yargs with the key/value pairs provided in obj
*
* If you explicitly specify a locale(), you should do so before calling `updateStrings()`.
*/
updateStrings(obj: { [key: string]: string }): Argv<T>;
/**
* Set a usage message to show which commands to use.
* Inside `message`, the string `$0` will get interpolated to the current script name or node command for the present script similar to how `$0` works in bash or perl.
*
* If the optional `description`/`builder`/`handler` are provided, `.usage()` acts an an alias for `.command()`.
* This allows you to use `.usage()` to configure the default command that will be run as an entry-point to your application
* and allows you to provide configuration for the positional arguments accepted by your program:
*/
usage(message: string): Argv<T>;
usage<U>(
command: string | readonly string[],
description: string,
builder?: (args: Argv<T>) => Argv<U>,
handler?: (args: Arguments<U>) => void,
): Argv<T>;
usage<U>(
command: string | readonly string[],
showInHelp: boolean,
builder?: (args: Argv<T>) => Argv<U>,
handler?: (args: Arguments<U>) => void,
): Argv<T>;
usage<O extends { [key: string]: Options }>(
command: string | readonly string[],
description: string,
builder?: O,
handler?: (args: Arguments<InferredOptionTypes<O>>) => void,
): Argv<T>;
usage<O extends { [key: string]: Options }>(
command: string | readonly string[],
showInHelp: boolean,
builder?: O,
handler?: (args: Arguments<InferredOptionTypes<O>>) => void,
): Argv<T>;
/**
* Add an option (e.g. `--version`) that displays the version number (given by the version parameter) and exits the process.
* By default yargs enables version for the `--version` option.
*
* If no arguments are passed to version (`.version()`), yargs will parse the package.json of your module and use its version value.
*
* If the boolean argument `false` is provided, it will disable `--version`.
*/
version(): Argv<T>;
version(version: string): Argv<T>;
version(enable: boolean): Argv<T>;
version(optionKey: string, version: string): Argv<T>;
version(optionKey: string, description: string, version: string): Argv<T>;
/**
* Format usage output to wrap at columns many columns.
*
* By default wrap will be set to `Math.min(80, windowWidth)`. Use `.wrap(null)` to specify no column limit (no right-align).
* Use `.wrap(yargs.terminalWidth())` to maximize the width of yargs' usage instructions.
*/
wrap(columns: number | null): Argv<T>;
}
type Arguments<T = {}> = T & {
/** Non-option arguments */
_: Array<string | number>;
/** The script name or node command */
$0: string;
/** All remaining options */
[argName: string]: unknown;
};
interface RequireDirectoryOptions {
/** Look for command modules in all subdirectories and apply them as a flattened (non-hierarchical) list. */
recurse?: boolean | undefined;
/** The types of files to look for when requiring command modules. */
extensions?: readonly string[] | undefined;
/**
* A synchronous function called for each command module encountered.
* Accepts `commandObject`, `pathToFile`, and `filename` as arguments.
* Returns `commandObject` to include the command; any falsy value to exclude/skip it.
*/
visit?: ((commandObject: any, pathToFile?: string, filename?: string) => any) | undefined;
/** Whitelist certain modules */
include?: RegExp | ((pathToFile: string) => boolean) | undefined;
/** Blacklist certain modules. */
exclude?: RegExp | ((pathToFile: string) => boolean) | undefined;
}
interface Options {
/** string or array of strings, alias(es) for the canonical option key, see `alias()` */
alias?: string | readonly string[] | undefined;
/** boolean, interpret option as an array, see `array()` */
array?: boolean | undefined;
/** boolean, interpret option as a boolean flag, see `boolean()` */
boolean?: boolean | undefined;
/** value or array of values, limit valid option arguments to a predefined set, see `choices()` */
choices?: Choices | undefined;
/** function, coerce or transform parsed command line values into another value, see `coerce()` */
coerce?: ((arg: any) => any) | undefined;
/** boolean, interpret option as a path to a JSON config file, see `config()` */
config?: boolean | undefined;
/** function, provide a custom config parsing function, see `config()` */
configParser?: ((configPath: string) => object) | undefined;
/** string or object, require certain keys not to be set, see `conflicts()` */
conflicts?: string | readonly string[] | { [key: string]: string | readonly string[] } | undefined;
/** boolean, interpret option as a count of boolean flags, see `count()` */
count?: boolean | undefined;
/** value, set a default value for the option, see `default()` */
default?: any;
/** string, use this description for the default value in help content, see `default()` */
defaultDescription?: string | undefined;
/**
* @deprecated since version 6.6.0
* Use 'demandOption' instead
*/
demand?: boolean | string | undefined;
/** boolean or string, mark the argument as deprecated, see `deprecateOption()` */
deprecate?: boolean | string | undefined;
/** boolean or string, mark the argument as deprecated, see `deprecateOption()` */
deprecated?: boolean | string | undefined;
/** boolean or string, demand the option be given, with optional error message, see `demandOption()` */
demandOption?: boolean | string | undefined;
/** string, the option description for help content, see `describe()` */
desc?: string | undefined;
/** string, the option description for help content, see `describe()` */
describe?: string | undefined;
/** string, the option description for help content, see `describe()` */
description?: string | undefined;
/** boolean, indicate that this key should not be reset when a command is invoked, see `global()` */
global?: boolean | undefined;
/** string, when displaying usage instructions place the option under an alternative group heading, see `group()` */
group?: string | undefined;
/** don't display option in help output. */
hidden?: boolean | undefined;
/** string or object, require certain keys to be set, see `implies()` */
implies?: string | readonly string[] | { [key: string]: string | readonly string[] } | undefined;
/** number, specify how many arguments should be consumed for the option, see `nargs()` */
nargs?: number | undefined;
/** boolean, apply path.normalize() to the option, see `normalize()` */
normalize?: boolean | undefined;
/** boolean, interpret option as a number, `number()` */
number?: boolean | undefined;
/**
* @deprecated since version 6.6.0
* Use 'demandOption' instead
*/
require?: boolean | string | undefined;
/**
* @deprecated since version 6.6.0
* Use 'demandOption' instead
*/
required?: boolean | string | undefined;
/** boolean, require the option be specified with a value, see `requiresArg()` */
requiresArg?: boolean | undefined;
/** boolean, skips validation if the option is present, see `skipValidation()` */
skipValidation?: boolean | undefined;
/** boolean, interpret option as a string, see `string()` */
string?: boolean | undefined;
type?: "array" | "count" | PositionalOptionsType | undefined;
}
interface PositionalOptions {
/** string or array of strings, see `alias()` */
alias?: string | readonly string[] | undefined;
/** boolean, interpret option as an array, see `array()` */
array?: boolean | undefined;
/** value or array of values, limit valid option arguments to a predefined set, see `choices()` */
choices?: Choices | undefined;
/** function, coerce or transform parsed command line values into another value, see `coerce()` */
coerce?: ((arg: any) => any) | undefined;
/** string or object, require certain keys not to be set, see `conflicts()` */
conflicts?: string | readonly string[] | { [key: string]: string | readonly string[] } | undefined;
/** value, set a default value for the option, see `default()` */
default?: any;
/** boolean or string, demand the option be given, with optional error message, see `demandOption()` */
demandOption?: boolean | string | undefined;
/** string, the option description for help content, see `describe()` */
desc?: string | undefined;
/** string, the option description for help content, see `describe()` */
describe?: string | undefined;
/** string, the option description for help content, see `describe()` */
description?: string | undefined;
/** string or object, require certain keys to be set, see `implies()` */
implies?: string | readonly string[] | { [key: string]: string | readonly string[] } | undefined;
/** boolean, apply path.normalize() to the option, see normalize() */
normalize?: boolean | undefined;
type?: PositionalOptionsType | undefined;
}
/** Remove keys K in T */
type Omit<T, K> = { [key in Exclude<keyof T, K>]: T[key] };
/** Remove undefined as a possible value for keys K in T */
type Defined<T, K extends keyof T> = Omit<T, K> & { [key in K]: Exclude<T[key], undefined> };
/** Convert T to T[] and T | undefined to T[] | undefined */
type ToArray<T> = Array<Exclude<T, undefined>> | Extract<T, undefined>;
/** Gives string[] if T is an array type, otherwise string. Preserves | undefined. */
type ToString<T> = (Exclude<T, undefined> extends any[] ? string[] : string) | Extract<T, undefined>;
/** Gives number[] if T is an array type, otherwise number. Preserves | undefined. */
type ToNumber<T> = (Exclude<T, undefined> extends any[] ? number[] : number) | Extract<T, undefined>;
type InferredOptionType<O extends Options | PositionalOptions> = O extends
{ default: any; coerce: (arg: any) => infer T } ? T
: O extends { default: infer D } ? D
: O extends { type: "count" } ? number
: O extends { count: true } ? number
: O extends { required: string | true } ? RequiredOptionType<O>
: O extends { require: string | true } ? RequiredOptionType<O>
: O extends { demand: string | true } ? RequiredOptionType<O>
: O extends { demandOption: string | true } ? RequiredOptionType<O>
: RequiredOptionType<O> | undefined;
type RequiredOptionType<O extends Options | PositionalOptions> = O extends { type: "array"; string: true }
? string[]
: O extends { type: "array"; number: true } ? number[]
: O extends { type: "array"; normalize: true } ? string[]
: O extends { type: "string"; array: true } ? string[]
: O extends { type: "number"; array: true } ? number[]
: O extends { string: true; array: true } ? string[]
: O extends { number: true; array: true } ? number[]
: O extends { normalize: true; array: true } ? string[]
: O extends { type: "array" } ? Array<string | number>
: O extends { type: "boolean" } ? boolean
: O extends { type: "number" } ? number
: O extends { type: "string" } ? string
: O extends { array: true } ? Array<string | number>
: O extends { boolean: true } ? boolean
: O extends { number: true } ? number
: O extends { string: true } ? string
: O extends { normalize: true } ? string
: O extends { choices: ReadonlyArray<infer C> } ? C
: O extends { coerce: (arg: any) => infer T } ? T
: unknown;
type InferredOptionTypes<O extends { [key: string]: Options }> = { [key in keyof O]: InferredOptionType<O[key]> };
interface CommandModule<T = {}, U = {}> {
/** array of strings (or a single string) representing aliases of `exports.command`, positional args defined in an alias are ignored */
aliases?: readonly string[] | string | undefined;
/** object declaring the options the command accepts, or a function accepting and returning a yargs instance */
builder?: CommandBuilder<T, U> | undefined;
/** string (or array of strings) that executes this command when given on the command line, first string may contain positional args */
command?: readonly string[] | string | undefined;
/** boolean (or string) to show deprecation notice */
deprecated?: boolean | string | undefined;
/** string used as the description for the command in help text, use `false` for a hidden command */
describe?: string | false | undefined;
/** a function which will be passed the parsed argv. */
handler: (args: Arguments<U>) => void;
}
type ParseCallback<T = {}> = (err: Error | undefined, argv: Arguments<T>, output: string) => void;
type CommandBuilder<T = {}, U = {}> =
| { [key: string]: Options }
| ((args: Argv<T>) => Argv<U>)
| ((args: Argv<T>) => PromiseLike<Argv<U>>);
type SyncCompletionFunction = (current: string, argv: any) => string[];
type AsyncCompletionFunction = (
current: string,
argv: any,
done: (completion: readonly string[]) => void,
) => void;
type PromiseCompletionFunction = (current: string, argv: any) => Promise<string[]>;
type MiddlewareFunction<T = {}> = (args: Arguments<T>) => void;
type Choices = ReadonlyArray<string | number | true | undefined>;
type PositionalOptionsType = "boolean" | "number" | "string";
}
declare var yargs: yargs.Argv;
export = yargs;

View File

@@ -0,0 +1,62 @@
{
"name": "@types/yargs",
"version": "16.0.9",
"description": "TypeScript definitions for yargs",
"homepage": "https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/yargs",
"license": "MIT",
"contributors": [
{
"name": "Martin Poelstra",
"githubUsername": "poelstra",
"url": "https://github.com/poelstra"
},
{
"name": "Mizunashi Mana",
"githubUsername": "mizunashi-mana",
"url": "https://github.com/mizunashi-mana"
},
{
"name": "Jeffery Grajkowski",
"githubUsername": "pushplay",
"url": "https://github.com/pushplay"
},
{
"name": "Jimi (Dimitris) Charalampidis",
"githubUsername": "JimiC",
"url": "https://github.com/JimiC"
},
{
"name": "Steffen Viken Valvåg",
"githubUsername": "steffenvv",
"url": "https://github.com/steffenvv"
},
{
"name": "Emily Marigold Klassen",
"githubUsername": "forivall",
"url": "https://github.com/forivall"
},
{
"name": "ExE Boss",
"githubUsername": "ExE-Boss",
"url": "https://github.com/ExE-Boss"
},
{
"name": "Aankhen",
"githubUsername": "Aankhen",
"url": "https://github.com/Aankhen"
}
],
"main": "",
"types": "index.d.ts",
"repository": {
"type": "git",
"url": "https://github.com/DefinitelyTyped/DefinitelyTyped.git",
"directory": "types/yargs"
},
"scripts": {},
"dependencies": {
"@types/yargs-parser": "*"
},
"typesPublisherContentHash": "cb1afff2e12b5d722156de0eabb2bd446fd1eb57638052e13771b041d96e0e52",
"typeScriptVersion": "4.5"
}

View File

@@ -0,0 +1,9 @@
import { Argv } from ".";
export = Yargs;
declare function Yargs(
processArgs?: readonly string[],
cwd?: string,
parentRequire?: NodeRequire,
): Argv;

View File

@@ -0,0 +1,415 @@
/**
Basic foreground colors.
[More colors here.](https://github.com/chalk/chalk/blob/master/readme.md#256-and-truecolor-color-support)
*/
declare type ForegroundColor =
| 'black'
| 'red'
| 'green'
| 'yellow'
| 'blue'
| 'magenta'
| 'cyan'
| 'white'
| 'gray'
| 'grey'
| 'blackBright'
| 'redBright'
| 'greenBright'
| 'yellowBright'
| 'blueBright'
| 'magentaBright'
| 'cyanBright'
| 'whiteBright';
/**
Basic background colors.
[More colors here.](https://github.com/chalk/chalk/blob/master/readme.md#256-and-truecolor-color-support)
*/
declare type BackgroundColor =
| 'bgBlack'
| 'bgRed'
| 'bgGreen'
| 'bgYellow'
| 'bgBlue'
| 'bgMagenta'
| 'bgCyan'
| 'bgWhite'
| 'bgGray'
| 'bgGrey'
| 'bgBlackBright'
| 'bgRedBright'
| 'bgGreenBright'
| 'bgYellowBright'
| 'bgBlueBright'
| 'bgMagentaBright'
| 'bgCyanBright'
| 'bgWhiteBright';
/**
Basic colors.
[More colors here.](https://github.com/chalk/chalk/blob/master/readme.md#256-and-truecolor-color-support)
*/
declare type Color = ForegroundColor | BackgroundColor;
declare type Modifiers =
| 'reset'
| 'bold'
| 'dim'
| 'italic'
| 'underline'
| 'inverse'
| 'hidden'
| 'strikethrough'
| 'visible';
declare namespace chalk {
/**
Levels:
- `0` - All colors disabled.
- `1` - Basic 16 colors support.
- `2` - ANSI 256 colors support.
- `3` - Truecolor 16 million colors support.
*/
type Level = 0 | 1 | 2 | 3;
interface Options {
/**
Specify the color support for Chalk.
By default, color support is automatically detected based on the environment.
Levels:
- `0` - All colors disabled.
- `1` - Basic 16 colors support.
- `2` - ANSI 256 colors support.
- `3` - Truecolor 16 million colors support.
*/
level?: Level;
}
/**
Return a new Chalk instance.
*/
type Instance = new (options?: Options) => Chalk;
/**
Detect whether the terminal supports color.
*/
interface ColorSupport {
/**
The color level used by Chalk.
*/
level: Level;
/**
Return whether Chalk supports basic 16 colors.
*/
hasBasic: boolean;
/**
Return whether Chalk supports ANSI 256 colors.
*/
has256: boolean;
/**
Return whether Chalk supports Truecolor 16 million colors.
*/
has16m: boolean;
}
interface ChalkFunction {
/**
Use a template string.
@remarks Template literals are unsupported for nested calls (see [issue #341](https://github.com/chalk/chalk/issues/341))
@example
```
import chalk = require('chalk');
log(chalk`
CPU: {red ${cpu.totalPercent}%}
RAM: {green ${ram.used / ram.total * 100}%}
DISK: {rgb(255,131,0) ${disk.used / disk.total * 100}%}
`);
```
@example
```
import chalk = require('chalk');
log(chalk.red.bgBlack`2 + 3 = {bold ${2 + 3}}`)
```
*/
(text: TemplateStringsArray, ...placeholders: unknown[]): string;
(...text: unknown[]): string;
}
interface Chalk extends ChalkFunction {
/**
Return a new Chalk instance.
*/
Instance: Instance;
/**
The color support for Chalk.
By default, color support is automatically detected based on the environment.
Levels:
- `0` - All colors disabled.
- `1` - Basic 16 colors support.
- `2` - ANSI 256 colors support.
- `3` - Truecolor 16 million colors support.
*/
level: Level;
/**
Use HEX value to set text color.
@param color - Hexadecimal value representing the desired color.
@example
```
import chalk = require('chalk');
chalk.hex('#DEADED');
```
*/
hex(color: string): Chalk;
/**
Use keyword color value to set text color.
@param color - Keyword value representing the desired color.
@example
```
import chalk = require('chalk');
chalk.keyword('orange');
```
*/
keyword(color: string): Chalk;
/**
Use RGB values to set text color.
*/
rgb(red: number, green: number, blue: number): Chalk;
/**
Use HSL values to set text color.
*/
hsl(hue: number, saturation: number, lightness: number): Chalk;
/**
Use HSV values to set text color.
*/
hsv(hue: number, saturation: number, value: number): Chalk;
/**
Use HWB values to set text color.
*/
hwb(hue: number, whiteness: number, blackness: number): Chalk;
/**
Use a [Select/Set Graphic Rendition](https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_parameters) (SGR) [color code number](https://en.wikipedia.org/wiki/ANSI_escape_code#3/4_bit) to set text color.
30 <= code && code < 38 || 90 <= code && code < 98
For example, 31 for red, 91 for redBright.
*/
ansi(code: number): Chalk;
/**
Use a [8-bit unsigned number](https://en.wikipedia.org/wiki/ANSI_escape_code#8-bit) to set text color.
*/
ansi256(index: number): Chalk;
/**
Use HEX value to set background color.
@param color - Hexadecimal value representing the desired color.
@example
```
import chalk = require('chalk');
chalk.bgHex('#DEADED');
```
*/
bgHex(color: string): Chalk;
/**
Use keyword color value to set background color.
@param color - Keyword value representing the desired color.
@example
```
import chalk = require('chalk');
chalk.bgKeyword('orange');
```
*/
bgKeyword(color: string): Chalk;
/**
Use RGB values to set background color.
*/
bgRgb(red: number, green: number, blue: number): Chalk;
/**
Use HSL values to set background color.
*/
bgHsl(hue: number, saturation: number, lightness: number): Chalk;
/**
Use HSV values to set background color.
*/
bgHsv(hue: number, saturation: number, value: number): Chalk;
/**
Use HWB values to set background color.
*/
bgHwb(hue: number, whiteness: number, blackness: number): Chalk;
/**
Use a [Select/Set Graphic Rendition](https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_parameters) (SGR) [color code number](https://en.wikipedia.org/wiki/ANSI_escape_code#3/4_bit) to set background color.
30 <= code && code < 38 || 90 <= code && code < 98
For example, 31 for red, 91 for redBright.
Use the foreground code, not the background code (for example, not 41, nor 101).
*/
bgAnsi(code: number): Chalk;
/**
Use a [8-bit unsigned number](https://en.wikipedia.org/wiki/ANSI_escape_code#8-bit) to set background color.
*/
bgAnsi256(index: number): Chalk;
/**
Modifier: Resets the current color chain.
*/
readonly reset: Chalk;
/**
Modifier: Make text bold.
*/
readonly bold: Chalk;
/**
Modifier: Emitting only a small amount of light.
*/
readonly dim: Chalk;
/**
Modifier: Make text italic. (Not widely supported)
*/
readonly italic: Chalk;
/**
Modifier: Make text underline. (Not widely supported)
*/
readonly underline: Chalk;
/**
Modifier: Inverse background and foreground colors.
*/
readonly inverse: Chalk;
/**
Modifier: Prints the text, but makes it invisible.
*/
readonly hidden: Chalk;
/**
Modifier: Puts a horizontal line through the center of the text. (Not widely supported)
*/
readonly strikethrough: Chalk;
/**
Modifier: Prints the text only when Chalk has a color support level > 0.
Can be useful for things that are purely cosmetic.
*/
readonly visible: Chalk;
readonly black: Chalk;
readonly red: Chalk;
readonly green: Chalk;
readonly yellow: Chalk;
readonly blue: Chalk;
readonly magenta: Chalk;
readonly cyan: Chalk;
readonly white: Chalk;
/*
Alias for `blackBright`.
*/
readonly gray: Chalk;
/*
Alias for `blackBright`.
*/
readonly grey: Chalk;
readonly blackBright: Chalk;
readonly redBright: Chalk;
readonly greenBright: Chalk;
readonly yellowBright: Chalk;
readonly blueBright: Chalk;
readonly magentaBright: Chalk;
readonly cyanBright: Chalk;
readonly whiteBright: Chalk;
readonly bgBlack: Chalk;
readonly bgRed: Chalk;
readonly bgGreen: Chalk;
readonly bgYellow: Chalk;
readonly bgBlue: Chalk;
readonly bgMagenta: Chalk;
readonly bgCyan: Chalk;
readonly bgWhite: Chalk;
/*
Alias for `bgBlackBright`.
*/
readonly bgGray: Chalk;
/*
Alias for `bgBlackBright`.
*/
readonly bgGrey: Chalk;
readonly bgBlackBright: Chalk;
readonly bgRedBright: Chalk;
readonly bgGreenBright: Chalk;
readonly bgYellowBright: Chalk;
readonly bgBlueBright: Chalk;
readonly bgMagentaBright: Chalk;
readonly bgCyanBright: Chalk;
readonly bgWhiteBright: Chalk;
}
}
/**
Main Chalk object that allows to chain styles together.
Call the last one as a method with a string argument.
Order doesn't matter, and later styles take precedent in case of a conflict.
This simply means that `chalk.red.yellow.green` is equivalent to `chalk.green`.
*/
declare const chalk: chalk.Chalk & chalk.ChalkFunction & {
supportsColor: chalk.ColorSupport | false;
Level: chalk.Level;
Color: Color;
ForegroundColor: ForegroundColor;
BackgroundColor: BackgroundColor;
Modifiers: Modifiers;
stderr: chalk.Chalk & {supportsColor: chalk.ColorSupport | false};
};
export = chalk;

View File

@@ -0,0 +1,9 @@
MIT License
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
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.

View File

@@ -0,0 +1,68 @@
{
"name": "chalk",
"version": "4.1.2",
"description": "Terminal string styling done right",
"license": "MIT",
"repository": "chalk/chalk",
"funding": "https://github.com/chalk/chalk?sponsor=1",
"main": "source",
"engines": {
"node": ">=10"
},
"scripts": {
"test": "xo && nyc ava && tsd",
"bench": "matcha benchmark.js"
},
"files": [
"source",
"index.d.ts"
],
"keywords": [
"color",
"colour",
"colors",
"terminal",
"console",
"cli",
"string",
"str",
"ansi",
"style",
"styles",
"tty",
"formatting",
"rgb",
"256",
"shell",
"xterm",
"log",
"logging",
"command-line",
"text"
],
"dependencies": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
},
"devDependencies": {
"ava": "^2.4.0",
"coveralls": "^3.0.7",
"execa": "^4.0.0",
"import-fresh": "^3.1.0",
"matcha": "^0.7.0",
"nyc": "^15.0.0",
"resolve-from": "^5.0.0",
"tsd": "^0.7.4",
"xo": "^0.28.2"
},
"xo": {
"rules": {
"unicorn/prefer-string-slice": "off",
"unicorn/prefer-includes": "off",
"@typescript-eslint/member-ordering": "off",
"no-redeclare": "off",
"unicorn/string-content": "off",
"unicorn/better-regex": "off"
}
}
}

View File

@@ -0,0 +1,341 @@
<h1 align="center">
<br>
<br>
<img width="320" src="media/logo.svg" alt="Chalk">
<br>
<br>
<br>
</h1>
> Terminal string styling done right
[![Build Status](https://travis-ci.org/chalk/chalk.svg?branch=master)](https://travis-ci.org/chalk/chalk) [![Coverage Status](https://coveralls.io/repos/github/chalk/chalk/badge.svg?branch=master)](https://coveralls.io/github/chalk/chalk?branch=master) [![npm dependents](https://badgen.net/npm/dependents/chalk)](https://www.npmjs.com/package/chalk?activeTab=dependents) [![Downloads](https://badgen.net/npm/dt/chalk)](https://www.npmjs.com/package/chalk) [![](https://img.shields.io/badge/unicorn-approved-ff69b4.svg)](https://www.youtube.com/watch?v=9auOCbH5Ns4) [![XO code style](https://img.shields.io/badge/code_style-XO-5ed9c7.svg)](https://github.com/xojs/xo) ![TypeScript-ready](https://img.shields.io/npm/types/chalk.svg) [![run on repl.it](https://repl.it/badge/github/chalk/chalk)](https://repl.it/github/chalk/chalk)
<img src="https://cdn.jsdelivr.net/gh/chalk/ansi-styles@8261697c95bf34b6c7767e2cbe9941a851d59385/screenshot.svg" width="900">
<br>
---
<div align="center">
<p>
<p>
<sup>
Sindre Sorhus' open source work is supported by the community on <a href="https://github.com/sponsors/sindresorhus">GitHub Sponsors</a> and <a href="https://stakes.social/0x44d871aebF0126Bf646753E2C976Aa7e68A66c15">Dev</a>
</sup>
</p>
<sup>Special thanks to:</sup>
<br>
<br>
<a href="https://standardresume.co/tech">
<img src="https://sindresorhus.com/assets/thanks/standard-resume-logo.svg" width="160"/>
</a>
<br>
<br>
<a href="https://retool.com/?utm_campaign=sindresorhus">
<img src="https://sindresorhus.com/assets/thanks/retool-logo.svg" width="230"/>
</a>
<br>
<br>
<a href="https://doppler.com/?utm_campaign=github_repo&utm_medium=referral&utm_content=chalk&utm_source=github">
<div>
<img src="https://dashboard.doppler.com/imgs/logo-long.svg" width="240" alt="Doppler">
</div>
<b>All your environment variables, in one place</b>
<div>
<span>Stop struggling with scattered API keys, hacking together home-brewed tools,</span>
<br>
<span>and avoiding access controls. Keep your team and servers in sync with Doppler.</span>
</div>
</a>
<br>
<a href="https://uibakery.io/?utm_source=chalk&utm_medium=sponsor&utm_campaign=github">
<div>
<img src="https://sindresorhus.com/assets/thanks/uibakery-logo.jpg" width="270" alt="UI Bakery">
</div>
</a>
</p>
</div>
---
<br>
## Highlights
- Expressive API
- Highly performant
- Ability to nest styles
- [256/Truecolor color support](#256-and-truecolor-color-support)
- Auto-detects color support
- Doesn't extend `String.prototype`
- Clean and focused
- Actively maintained
- [Used by ~50,000 packages](https://www.npmjs.com/browse/depended/chalk) as of January 1, 2020
## Install
```console
$ npm install chalk
```
## Usage
```js
const chalk = require('chalk');
console.log(chalk.blue('Hello world!'));
```
Chalk comes with an easy to use composable API where you just chain and nest the styles you want.
```js
const chalk = require('chalk');
const log = console.log;
// Combine styled and normal strings
log(chalk.blue('Hello') + ' World' + chalk.red('!'));
// Compose multiple styles using the chainable API
log(chalk.blue.bgRed.bold('Hello world!'));
// Pass in multiple arguments
log(chalk.blue('Hello', 'World!', 'Foo', 'bar', 'biz', 'baz'));
// Nest styles
log(chalk.red('Hello', chalk.underline.bgBlue('world') + '!'));
// Nest styles of the same type even (color, underline, background)
log(chalk.green(
'I am a green line ' +
chalk.blue.underline.bold('with a blue substring') +
' that becomes green again!'
));
// ES2015 template literal
log(`
CPU: ${chalk.red('90%')}
RAM: ${chalk.green('40%')}
DISK: ${chalk.yellow('70%')}
`);
// ES2015 tagged template literal
log(chalk`
CPU: {red ${cpu.totalPercent}%}
RAM: {green ${ram.used / ram.total * 100}%}
DISK: {rgb(255,131,0) ${disk.used / disk.total * 100}%}
`);
// Use RGB colors in terminal emulators that support it.
log(chalk.keyword('orange')('Yay for orange colored text!'));
log(chalk.rgb(123, 45, 67).underline('Underlined reddish color'));
log(chalk.hex('#DEADED').bold('Bold gray!'));
```
Easily define your own themes:
```js
const chalk = require('chalk');
const error = chalk.bold.red;
const warning = chalk.keyword('orange');
console.log(error('Error!'));
console.log(warning('Warning!'));
```
Take advantage of console.log [string substitution](https://nodejs.org/docs/latest/api/console.html#console_console_log_data_args):
```js
const name = 'Sindre';
console.log(chalk.green('Hello %s'), name);
//=> 'Hello Sindre'
```
## API
### chalk.`<style>[.<style>...](string, [string...])`
Example: `chalk.red.bold.underline('Hello', 'world');`
Chain [styles](#styles) and call the last one as a method with a string argument. Order doesn't matter, and later styles take precedent in case of a conflict. This simply means that `chalk.red.yellow.green` is equivalent to `chalk.green`.
Multiple arguments will be separated by space.
### chalk.level
Specifies the level of color support.
Color support is automatically detected, but you can override it by setting the `level` property. You should however only do this in your own code as it applies globally to all Chalk consumers.
If you need to change this in a reusable module, create a new instance:
```js
const ctx = new chalk.Instance({level: 0});
```
| Level | Description |
| :---: | :--- |
| `0` | All colors disabled |
| `1` | Basic color support (16 colors) |
| `2` | 256 color support |
| `3` | Truecolor support (16 million colors) |
### chalk.supportsColor
Detect whether the terminal [supports color](https://github.com/chalk/supports-color). Used internally and handled for you, but exposed for convenience.
Can be overridden by the user with the flags `--color` and `--no-color`. For situations where using `--color` is not possible, use the environment variable `FORCE_COLOR=1` (level 1), `FORCE_COLOR=2` (level 2), or `FORCE_COLOR=3` (level 3) to forcefully enable color, or `FORCE_COLOR=0` to forcefully disable. The use of `FORCE_COLOR` overrides all other color support checks.
Explicit 256/Truecolor mode can be enabled using the `--color=256` and `--color=16m` flags, respectively.
### chalk.stderr and chalk.stderr.supportsColor
`chalk.stderr` contains a separate instance configured with color support detected for `stderr` stream instead of `stdout`. Override rules from `chalk.supportsColor` apply to this too. `chalk.stderr.supportsColor` is exposed for convenience.
## Styles
### Modifiers
- `reset` - Resets the current color chain.
- `bold` - Make text bold.
- `dim` - Emitting only a small amount of light.
- `italic` - Make text italic. *(Not widely supported)*
- `underline` - Make text underline. *(Not widely supported)*
- `inverse`- Inverse background and foreground colors.
- `hidden` - Prints the text, but makes it invisible.
- `strikethrough` - Puts a horizontal line through the center of the text. *(Not widely supported)*
- `visible`- Prints the text only when Chalk has a color level > 0. Can be useful for things that are purely cosmetic.
### Colors
- `black`
- `red`
- `green`
- `yellow`
- `blue`
- `magenta`
- `cyan`
- `white`
- `blackBright` (alias: `gray`, `grey`)
- `redBright`
- `greenBright`
- `yellowBright`
- `blueBright`
- `magentaBright`
- `cyanBright`
- `whiteBright`
### Background colors
- `bgBlack`
- `bgRed`
- `bgGreen`
- `bgYellow`
- `bgBlue`
- `bgMagenta`
- `bgCyan`
- `bgWhite`
- `bgBlackBright` (alias: `bgGray`, `bgGrey`)
- `bgRedBright`
- `bgGreenBright`
- `bgYellowBright`
- `bgBlueBright`
- `bgMagentaBright`
- `bgCyanBright`
- `bgWhiteBright`
## Tagged template literal
Chalk can be used as a [tagged template literal](https://exploringjs.com/es6/ch_template-literals.html#_tagged-template-literals).
```js
const chalk = require('chalk');
const miles = 18;
const calculateFeet = miles => miles * 5280;
console.log(chalk`
There are {bold 5280 feet} in a mile.
In {bold ${miles} miles}, there are {green.bold ${calculateFeet(miles)} feet}.
`);
```
Blocks are delimited by an opening curly brace (`{`), a style, some content, and a closing curly brace (`}`).
Template styles are chained exactly like normal Chalk styles. The following three statements are equivalent:
```js
console.log(chalk.bold.rgb(10, 100, 200)('Hello!'));
console.log(chalk.bold.rgb(10, 100, 200)`Hello!`);
console.log(chalk`{bold.rgb(10,100,200) Hello!}`);
```
Note that function styles (`rgb()`, `hsl()`, `keyword()`, etc.) may not contain spaces between parameters.
All interpolated values (`` chalk`${foo}` ``) are converted to strings via the `.toString()` method. All curly braces (`{` and `}`) in interpolated value strings are escaped.
## 256 and Truecolor color support
Chalk supports 256 colors and [Truecolor](https://gist.github.com/XVilka/8346728) (16 million colors) on supported terminal apps.
Colors are downsampled from 16 million RGB values to an ANSI color format that is supported by the terminal emulator (or by specifying `{level: n}` as a Chalk option). For example, Chalk configured to run at level 1 (basic color support) will downsample an RGB value of #FF0000 (red) to 31 (ANSI escape for red).
Examples:
- `chalk.hex('#DEADED').underline('Hello, world!')`
- `chalk.keyword('orange')('Some orange text')`
- `chalk.rgb(15, 100, 204).inverse('Hello!')`
Background versions of these models are prefixed with `bg` and the first level of the module capitalized (e.g. `keyword` for foreground colors and `bgKeyword` for background colors).
- `chalk.bgHex('#DEADED').underline('Hello, world!')`
- `chalk.bgKeyword('orange')('Some orange text')`
- `chalk.bgRgb(15, 100, 204).inverse('Hello!')`
The following color models can be used:
- [`rgb`](https://en.wikipedia.org/wiki/RGB_color_model) - Example: `chalk.rgb(255, 136, 0).bold('Orange!')`
- [`hex`](https://en.wikipedia.org/wiki/Web_colors#Hex_triplet) - Example: `chalk.hex('#FF8800').bold('Orange!')`
- [`keyword`](https://www.w3.org/wiki/CSS/Properties/color/keywords) (CSS keywords) - Example: `chalk.keyword('orange').bold('Orange!')`
- [`hsl`](https://en.wikipedia.org/wiki/HSL_and_HSV) - Example: `chalk.hsl(32, 100, 50).bold('Orange!')`
- [`hsv`](https://en.wikipedia.org/wiki/HSL_and_HSV) - Example: `chalk.hsv(32, 100, 100).bold('Orange!')`
- [`hwb`](https://en.wikipedia.org/wiki/HWB_color_model) - Example: `chalk.hwb(32, 0, 50).bold('Orange!')`
- [`ansi`](https://en.wikipedia.org/wiki/ANSI_escape_code#3/4_bit) - Example: `chalk.ansi(31).bgAnsi(93)('red on yellowBright')`
- [`ansi256`](https://en.wikipedia.org/wiki/ANSI_escape_code#8-bit) - Example: `chalk.bgAnsi256(194)('Honeydew, more or less')`
## Windows
If you're on Windows, do yourself a favor and use [Windows Terminal](https://github.com/microsoft/terminal) instead of `cmd.exe`.
## Origin story
[colors.js](https://github.com/Marak/colors.js) used to be the most popular string styling module, but it has serious deficiencies like extending `String.prototype` which causes all kinds of [problems](https://github.com/yeoman/yo/issues/68) and the package is unmaintained. Although there are other packages, they either do too much or not enough. Chalk is a clean and focused alternative.
## chalk for enterprise
Available as part of the Tidelift Subscription.
The maintainers of chalk and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. [Learn more.](https://tidelift.com/subscription/pkg/npm-chalk?utm_source=npm-chalk&utm_medium=referral&utm_campaign=enterprise&utm_term=repo)
## Related
- [chalk-cli](https://github.com/chalk/chalk-cli) - CLI for this module
- [ansi-styles](https://github.com/chalk/ansi-styles) - ANSI escape codes for styling strings in the terminal
- [supports-color](https://github.com/chalk/supports-color) - Detect whether a terminal supports color
- [strip-ansi](https://github.com/chalk/strip-ansi) - Strip ANSI escape codes
- [strip-ansi-stream](https://github.com/chalk/strip-ansi-stream) - Strip ANSI escape codes from a stream
- [has-ansi](https://github.com/chalk/has-ansi) - Check if a string has ANSI escape codes
- [ansi-regex](https://github.com/chalk/ansi-regex) - Regular expression for matching ANSI escape codes
- [wrap-ansi](https://github.com/chalk/wrap-ansi) - Wordwrap a string with ANSI escape codes
- [slice-ansi](https://github.com/chalk/slice-ansi) - Slice a string with ANSI escape codes
- [color-convert](https://github.com/qix-/color-convert) - Converts colors between different models
- [chalk-animation](https://github.com/bokub/chalk-animation) - Animate strings in the terminal
- [gradient-string](https://github.com/bokub/gradient-string) - Apply color gradients to strings
- [chalk-pipe](https://github.com/LitoMore/chalk-pipe) - Create chalk style schemes with simpler style strings
- [terminal-link](https://github.com/sindresorhus/terminal-link) - Create clickable links in the terminal
## Maintainers
- [Sindre Sorhus](https://github.com/sindresorhus)
- [Josh Junon](https://github.com/qix-)

View File

@@ -0,0 +1,229 @@
'use strict';
const ansiStyles = require('ansi-styles');
const {stdout: stdoutColor, stderr: stderrColor} = require('supports-color');
const {
stringReplaceAll,
stringEncaseCRLFWithFirstIndex
} = require('./util');
const {isArray} = Array;
// `supportsColor.level` → `ansiStyles.color[name]` mapping
const levelMapping = [
'ansi',
'ansi',
'ansi256',
'ansi16m'
];
const styles = Object.create(null);
const applyOptions = (object, options = {}) => {
if (options.level && !(Number.isInteger(options.level) && options.level >= 0 && options.level <= 3)) {
throw new Error('The `level` option should be an integer from 0 to 3');
}
// Detect level if not set manually
const colorLevel = stdoutColor ? stdoutColor.level : 0;
object.level = options.level === undefined ? colorLevel : options.level;
};
class ChalkClass {
constructor(options) {
// eslint-disable-next-line no-constructor-return
return chalkFactory(options);
}
}
const chalkFactory = options => {
const chalk = {};
applyOptions(chalk, options);
chalk.template = (...arguments_) => chalkTag(chalk.template, ...arguments_);
Object.setPrototypeOf(chalk, Chalk.prototype);
Object.setPrototypeOf(chalk.template, chalk);
chalk.template.constructor = () => {
throw new Error('`chalk.constructor()` is deprecated. Use `new chalk.Instance()` instead.');
};
chalk.template.Instance = ChalkClass;
return chalk.template;
};
function Chalk(options) {
return chalkFactory(options);
}
for (const [styleName, style] of Object.entries(ansiStyles)) {
styles[styleName] = {
get() {
const builder = createBuilder(this, createStyler(style.open, style.close, this._styler), this._isEmpty);
Object.defineProperty(this, styleName, {value: builder});
return builder;
}
};
}
styles.visible = {
get() {
const builder = createBuilder(this, this._styler, true);
Object.defineProperty(this, 'visible', {value: builder});
return builder;
}
};
const usedModels = ['rgb', 'hex', 'keyword', 'hsl', 'hsv', 'hwb', 'ansi', 'ansi256'];
for (const model of usedModels) {
styles[model] = {
get() {
const {level} = this;
return function (...arguments_) {
const styler = createStyler(ansiStyles.color[levelMapping[level]][model](...arguments_), ansiStyles.color.close, this._styler);
return createBuilder(this, styler, this._isEmpty);
};
}
};
}
for (const model of usedModels) {
const bgModel = 'bg' + model[0].toUpperCase() + model.slice(1);
styles[bgModel] = {
get() {
const {level} = this;
return function (...arguments_) {
const styler = createStyler(ansiStyles.bgColor[levelMapping[level]][model](...arguments_), ansiStyles.bgColor.close, this._styler);
return createBuilder(this, styler, this._isEmpty);
};
}
};
}
const proto = Object.defineProperties(() => {}, {
...styles,
level: {
enumerable: true,
get() {
return this._generator.level;
},
set(level) {
this._generator.level = level;
}
}
});
const createStyler = (open, close, parent) => {
let openAll;
let closeAll;
if (parent === undefined) {
openAll = open;
closeAll = close;
} else {
openAll = parent.openAll + open;
closeAll = close + parent.closeAll;
}
return {
open,
close,
openAll,
closeAll,
parent
};
};
const createBuilder = (self, _styler, _isEmpty) => {
const builder = (...arguments_) => {
if (isArray(arguments_[0]) && isArray(arguments_[0].raw)) {
// Called as a template literal, for example: chalk.red`2 + 3 = {bold ${2+3}}`
return applyStyle(builder, chalkTag(builder, ...arguments_));
}
// Single argument is hot path, implicit coercion is faster than anything
// eslint-disable-next-line no-implicit-coercion
return applyStyle(builder, (arguments_.length === 1) ? ('' + arguments_[0]) : arguments_.join(' '));
};
// We alter the prototype because we must return a function, but there is
// no way to create a function with a different prototype
Object.setPrototypeOf(builder, proto);
builder._generator = self;
builder._styler = _styler;
builder._isEmpty = _isEmpty;
return builder;
};
const applyStyle = (self, string) => {
if (self.level <= 0 || !string) {
return self._isEmpty ? '' : string;
}
let styler = self._styler;
if (styler === undefined) {
return string;
}
const {openAll, closeAll} = styler;
if (string.indexOf('\u001B') !== -1) {
while (styler !== undefined) {
// Replace any instances already present with a re-opening code
// otherwise only the part of the string until said closing code
// will be colored, and the rest will simply be 'plain'.
string = stringReplaceAll(string, styler.close, styler.open);
styler = styler.parent;
}
}
// We can move both next actions out of loop, because remaining actions in loop won't have
// any/visible effect on parts we add here. Close the styling before a linebreak and reopen
// after next line to fix a bleed issue on macOS: https://github.com/chalk/chalk/pull/92
const lfIndex = string.indexOf('\n');
if (lfIndex !== -1) {
string = stringEncaseCRLFWithFirstIndex(string, closeAll, openAll, lfIndex);
}
return openAll + string + closeAll;
};
let template;
const chalkTag = (chalk, ...strings) => {
const [firstString] = strings;
if (!isArray(firstString) || !isArray(firstString.raw)) {
// If chalk() was called by itself or with a string,
// return the string itself as a string.
return strings.join(' ');
}
const arguments_ = strings.slice(1);
const parts = [firstString.raw[0]];
for (let i = 1; i < firstString.length; i++) {
parts.push(
String(arguments_[i - 1]).replace(/[{}\\]/g, '\\$&'),
String(firstString.raw[i])
);
}
if (template === undefined) {
template = require('./templates');
}
return template(chalk, parts.join(''));
};
Object.defineProperties(Chalk.prototype, styles);
const chalk = Chalk(); // eslint-disable-line new-cap
chalk.supportsColor = stdoutColor;
chalk.stderr = Chalk({level: stderrColor ? stderrColor.level : 0}); // eslint-disable-line new-cap
chalk.stderr.supportsColor = stderrColor;
module.exports = chalk;

View File

@@ -0,0 +1,134 @@
'use strict';
const TEMPLATE_REGEX = /(?:\\(u(?:[a-f\d]{4}|\{[a-f\d]{1,6}\})|x[a-f\d]{2}|.))|(?:\{(~)?(\w+(?:\([^)]*\))?(?:\.\w+(?:\([^)]*\))?)*)(?:[ \t]|(?=\r?\n)))|(\})|((?:.|[\r\n\f])+?)/gi;
const STYLE_REGEX = /(?:^|\.)(\w+)(?:\(([^)]*)\))?/g;
const STRING_REGEX = /^(['"])((?:\\.|(?!\1)[^\\])*)\1$/;
const ESCAPE_REGEX = /\\(u(?:[a-f\d]{4}|{[a-f\d]{1,6}})|x[a-f\d]{2}|.)|([^\\])/gi;
const ESCAPES = new Map([
['n', '\n'],
['r', '\r'],
['t', '\t'],
['b', '\b'],
['f', '\f'],
['v', '\v'],
['0', '\0'],
['\\', '\\'],
['e', '\u001B'],
['a', '\u0007']
]);
function unescape(c) {
const u = c[0] === 'u';
const bracket = c[1] === '{';
if ((u && !bracket && c.length === 5) || (c[0] === 'x' && c.length === 3)) {
return String.fromCharCode(parseInt(c.slice(1), 16));
}
if (u && bracket) {
return String.fromCodePoint(parseInt(c.slice(2, -1), 16));
}
return ESCAPES.get(c) || c;
}
function parseArguments(name, arguments_) {
const results = [];
const chunks = arguments_.trim().split(/\s*,\s*/g);
let matches;
for (const chunk of chunks) {
const number = Number(chunk);
if (!Number.isNaN(number)) {
results.push(number);
} else if ((matches = chunk.match(STRING_REGEX))) {
results.push(matches[2].replace(ESCAPE_REGEX, (m, escape, character) => escape ? unescape(escape) : character));
} else {
throw new Error(`Invalid Chalk template style argument: ${chunk} (in style '${name}')`);
}
}
return results;
}
function parseStyle(style) {
STYLE_REGEX.lastIndex = 0;
const results = [];
let matches;
while ((matches = STYLE_REGEX.exec(style)) !== null) {
const name = matches[1];
if (matches[2]) {
const args = parseArguments(name, matches[2]);
results.push([name].concat(args));
} else {
results.push([name]);
}
}
return results;
}
function buildStyle(chalk, styles) {
const enabled = {};
for (const layer of styles) {
for (const style of layer.styles) {
enabled[style[0]] = layer.inverse ? null : style.slice(1);
}
}
let current = chalk;
for (const [styleName, styles] of Object.entries(enabled)) {
if (!Array.isArray(styles)) {
continue;
}
if (!(styleName in current)) {
throw new Error(`Unknown Chalk style: ${styleName}`);
}
current = styles.length > 0 ? current[styleName](...styles) : current[styleName];
}
return current;
}
module.exports = (chalk, temporary) => {
const styles = [];
const chunks = [];
let chunk = [];
// eslint-disable-next-line max-params
temporary.replace(TEMPLATE_REGEX, (m, escapeCharacter, inverse, style, close, character) => {
if (escapeCharacter) {
chunk.push(unescape(escapeCharacter));
} else if (style) {
const string = chunk.join('');
chunk = [];
chunks.push(styles.length === 0 ? string : buildStyle(chalk, styles)(string));
styles.push({inverse, styles: parseStyle(style)});
} else if (close) {
if (styles.length === 0) {
throw new Error('Found extraneous } in Chalk template literal');
}
chunks.push(buildStyle(chalk, styles)(chunk.join('')));
chunk = [];
styles.pop();
} else {
chunk.push(character);
}
});
chunks.push(chunk.join(''));
if (styles.length > 0) {
const errMessage = `Chalk template literal is missing ${styles.length} closing bracket${styles.length === 1 ? '' : 's'} (\`}\`)`;
throw new Error(errMessage);
}
return chunks.join('');
};

View File

@@ -0,0 +1,39 @@
'use strict';
const stringReplaceAll = (string, substring, replacer) => {
let index = string.indexOf(substring);
if (index === -1) {
return string;
}
const substringLength = substring.length;
let endIndex = 0;
let returnValue = '';
do {
returnValue += string.substr(endIndex, index - endIndex) + substring + replacer;
endIndex = index + substringLength;
index = string.indexOf(substring, endIndex);
} while (index !== -1);
returnValue += string.substr(endIndex);
return returnValue;
};
const stringEncaseCRLFWithFirstIndex = (string, prefix, postfix, index) => {
let endIndex = 0;
let returnValue = '';
do {
const gotCR = string[index - 1] === '\r';
returnValue += string.substr(endIndex, (gotCR ? index - 1 : index) - endIndex) + prefix + (gotCR ? '\r\n' : '\n') + postfix;
endIndex = index + 1;
index = string.indexOf('\n', endIndex);
} while (index !== -1);
returnValue += string.substr(endIndex);
return returnValue;
};
module.exports = {
stringReplaceAll,
stringEncaseCRLFWithFirstIndex
};

View File

@@ -0,0 +1,178 @@
# Changelog
## v3.9.0
- better support for Azure Pipelines ([#116](https://github.com/watson/ci-info/pull/116)), [5ea8d85](https://github.com/watson/ci-info/commit/5ea8d85)
- detect PullRequest in Azure Pipelines [5ea8d85](https://github.com/watson/ci-info/commit/5ea8d85)
## v3.8.0
- support Harness CI [76a2867](https://github.com/watson/ci-info/commit/76a2867)
## v3.7.1
- ignore ci detection when CI is set to `'false'` [24cc450](https://github.com/watson/ci-info/commit/24cc450)
## v3.7.0
- support Sourcehut CI [85b96ea](https://github.com/watson/ci-info/commit/85b96ea)
- support ReleaseHub CI [409d886](https://github.com/watson/ci-info/commit/409d886)
## v3.6.2
- fix VERCEL environment detection ([#98](https://github.com/watson/ci-info/pull/98))
## v3.6.1
- fix error in typings [357b454](https://github.com/watson/ci-info/commit/357b454)
## v3.6.0
This release attempts to bring parity with [@npmcli/ci-detect](https://github.com/npm/ci-detect). See [#95](https://github.com/watson/ci-info/pull/95) for more details.
- support gerrit ([#95](https://github.com/watson/ci-info/pull/95))
- support google cloud build ([#95](https://github.com/watson/ci-info/pull/95))
- support heroku ([#95](https://github.com/watson/ci-info/pull/95))
- support anonymous CI's that exposes BUILD_ID and CI_NAME env vars ([#95](https://github.com/watson/ci-info/pull/95))
- support more vercel environments ([#95](https://github.com/watson/ci-info/pull/95))
## v3.5.0
- support Woodpecker CI ([#90](https://github.com/watson/ci-info/pull/90))
## v3.4.0
- partial support Appflow CI (only CI detection) ([#84](https://github.com/watson/ci-info/pull/84))
- support Codemagic CI ([#85](https://github.com/watson/ci-info/pull/85))
- support Xcode Server CI ([#86](https://github.com/watson/ci-info/pull/86))
- support Xcode Cloud CI ([#86](https://github.com/watson/ci-info/pull/86))
## v3.3.2
- fix: export correct typings for `EAS`
## v3.3.1
- fix: export `EAS_BUILD` constant in typings
- Add support for nodejs v18
## v3.3.0
- support Expo Application Services ([#70](https://github.com/watson/ci-info/pull/70))
## v3.2.0
- support LayerCI ([#68](https://github.com/watson/ci-info/pull/68))
- support Appcircle ([#69](https://github.com/watson/ci-info/pull/69))
- support Codefresh CI ([#65](https://github.com/watson/ci-info/pull/65))
- add support for nodejs v16
## v3.1.1
Bug Fixes:
- remove duplicate declaration in typings
## v3.1.0
Features:
- add typings
## v3.0.0
Features:
- Add support nodejs versions: 14, 15
- support Nevercode ([#30](https://github.com/watson/ci-info/pull/30))
- support Render CI ([#36](https://github.com/watson/ci-info/pull/36))
- support Now CI ([#37](https://github.com/watson/ci-info/pull/37))
- support GitLab PR ([#59](https://github.com/watson/ci-info/pull/59))
- support Screwdriver CD ([#60](https://github.com/watson/ci-info/pull/60))
- support Visual Studio App Center ([#61](https://github.com/watson/ci-info/pull/61))
Bug Fixes:
- update Netlify env constant ([#47](https://github.com/watson/ci-info/pull/47))
Breaking changes:
- Drop support for Node.js end-of-life versions: 6, 13
- replace `Zeit Now` with `Vercel` ([#55](https://github.com/watson/ci-info/pull/55))
## v2.0.0
Breaking changes:
- Drop support for Node.js end-of-life versions: 0.10, 0.12, 4, 5, 7, and 9
- Team Foundation Server will now be detected as Azure Pipelines. The constant `ci.TFS` no longer exists - use
`ci.AZURE_PIPELINES` instead
- Remove deprecated `ci.TDDIUM` constant - use `ci.SOLANDO` instead
New features:
- feat: support Azure Pipelines ([#23](https://github.com/watson/ci-info/pull/23))
- feat: support Netlify CI ([#26](https://github.com/watson/ci-info/pull/26))
- feat: support Bitbucket pipelines PR detection ([#27](https://github.com/watson/ci-info/pull/27))
## v1.6.0
- feat: add Sail CI support
- feat: add Buddy support
- feat: add Bitrise support
- feat: detect Jenkins PRs
- feat: detect Drone PRs
## v1.5.1
- fix: use full path to vendors.json
## v1.5.0
- feat: add dsari detection ([#15](https://github.com/watson/ci-info/pull/15))
- feat: add ci.isPR ([#16](https://github.com/watson/ci-info/pull/16))
## v1.4.0
- feat: add Cirrus CI detection ([#13](https://github.com/watson/ci-info/pull/13))
- feat: add Shippable CI detection ([#14](https://github.com/watson/ci-info/pull/14))
## v1.3.1
- chore: reduce npm package size by not including `.github` folder content
([#11](https://github.com/watson/ci-info/pull/11))
## v1.3.0
- feat: add support for Strider CD
- chore: deprecate vendor constant `TDDIUM` in favor of `SOLANO`
- docs: add missing vendor constant to docs
## v1.2.0
- feat: detect solano-ci ([#9](https://github.com/watson/ci-info/pull/9))
## v1.1.3
- fix: fix spelling of Hunson in `ci.name`
## v1.1.2
- fix: no more false positive matches for Jenkins
## v1.1.1
- docs: sort lists of CI servers in README.md
- docs: add missing AWS CodeBuild to the docs
## v1.1.0
- feat: add AWS CodeBuild to CI detection ([#2](https://github.com/watson/ci-info/pull/2))
## v1.0.1
- chore: reduce npm package size by using an `.npmignore` file ([#3](https://github.com/watson/ci-info/pull/3))
## v1.0.0
- Initial release

View File

@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2016 Thomas Watson Steen
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.

View File

@@ -0,0 +1,135 @@
# ci-info
Get details about the current Continuous Integration environment.
Please [open an
issue](https://github.com/watson/ci-info/issues/new?template=ci-server-not-detected.md)
if your CI server isn't properly detected :)
[![npm](https://img.shields.io/npm/v/ci-info.svg)](https://www.npmjs.com/package/ci-info)
[![Tests](https://github.com/watson/ci-info/workflows/Tests/badge.svg)](https://github.com/watson/ci-info/actions)
[![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat)](https://github.com/feross/standard)
## Installation
```bash
npm install ci-info --save
```
## Usage
```js
var ci = require('ci-info')
if (ci.isCI) {
console.log('The name of the CI server is:', ci.name)
} else {
console.log('This program is not running on a CI server')
}
```
## Supported CI tools
Officially supported CI servers:
| Name | Constant | isPR |
| ------------------------------------------------------------------------------- | ----------------------- | ---- |
| [AWS CodeBuild](https://aws.amazon.com/codebuild/) | `ci.CODEBUILD` | 🚫 |
| [AppVeyor](http://www.appveyor.com) | `ci.APPVEYOR` | ✅ |
| [Azure Pipelines](https://azure.microsoft.com/en-us/services/devops/pipelines/) | `ci.AZURE_PIPELINES` | ✅ |
| [Appcircle](https://appcircle.io/) | `ci.APPCIRCLE` | 🚫 |
| [Bamboo](https://www.atlassian.com/software/bamboo) by Atlassian | `ci.BAMBOO` | 🚫 |
| [Bitbucket Pipelines](https://bitbucket.org/product/features/pipelines) | `ci.BITBUCKET` | ✅ |
| [Bitrise](https://www.bitrise.io/) | `ci.BITRISE` | ✅ |
| [Buddy](https://buddy.works/) | `ci.BUDDY` | ✅ |
| [Buildkite](https://buildkite.com) | `ci.BUILDKITE` | ✅ |
| [CircleCI](http://circleci.com) | `ci.CIRCLE` | ✅ |
| [Cirrus CI](https://cirrus-ci.org) | `ci.CIRRUS` | ✅ |
| [Codefresh](https://codefresh.io/) | `ci.CODEFRESH` | ✅ |
| [Codeship](https://codeship.com) | `ci.CODESHIP` | 🚫 |
| [Drone](https://drone.io) | `ci.DRONE` | ✅ |
| [dsari](https://github.com/rfinnie/dsari) | `ci.DSARI` | 🚫 |
| [Expo Application Services](https://expo.dev/eas) | `ci.EAS` | 🚫 |
| [Gerrit CI](https://www.gerritcodereview.com) | `ci.GERRIT` | 🚫 |
| [GitHub Actions](https://github.com/features/actions/) | `ci.GITHUB_ACTIONS` | ✅ |
| [GitLab CI](https://about.gitlab.com/gitlab-ci/) | `ci.GITLAB` | ✅ |
| [GoCD](https://www.go.cd/) | `ci.GOCD` | 🚫 |
| [Google Cloud Build](https://cloud.google.com/build) | `ci.GOOGLE_CLOUD_BUILD` | 🚫 |
| [Harness CI](https://www.harness.io/products/continuous-integration) | `ci.HARNESS` | 🚫 |
| [Heroku](https://www.heroku.com) | `ci.HEROKU` | 🚫 |
| [Hudson](http://hudson-ci.org) | `ci.HUDSON` | 🚫 |
| [Jenkins CI](https://jenkins-ci.org) | `ci.JENKINS` | ✅ |
| [LayerCI](https://layerci.com/) | `ci.LAYERCI` | ✅ |
| [Magnum CI](https://magnum-ci.com) | `ci.MAGNUM` | 🚫 |
| [Netlify CI](https://www.netlify.com/) | `ci.NETLIFY` | ✅ |
| [Nevercode](http://nevercode.io/) | `ci.NEVERCODE` | ✅ |
| [ReleaseHub](https://releasehub.com/) | `ci.RELEASEHUB` | 🚫 |
| [Render](https://render.com/) | `ci.RENDER` | ✅ |
| [Sail CI](https://sail.ci/) | `ci.SAIL` | ✅ |
| [Screwdriver](https://screwdriver.cd/) | `ci.SCREWDRIVER` | ✅ |
| [Semaphore](https://semaphoreci.com) | `ci.SEMAPHORE` | ✅ |
| [Shippable](https://www.shippable.com/) | `ci.SHIPPABLE` | ✅ |
| [Solano CI](https://www.solanolabs.com/) | `ci.SOLANO` | ✅ |
| [Sourcehut](https://sourcehut.org/) | `ci.SOURCEHUT` | 🚫 |
| [Strider CD](https://strider-cd.github.io/) | `ci.STRIDER` | 🚫 |
| [TaskCluster](http://docs.taskcluster.net) | `ci.TASKCLUSTER` | 🚫 |
| [TeamCity](https://www.jetbrains.com/teamcity/) by JetBrains | `ci.TEAMCITY` | 🚫 |
| [Travis CI](http://travis-ci.org) | `ci.TRAVIS` | ✅ |
| [Vercel](https://vercel.com/) | `ci.VERCEL` | ✅ |
| [Visual Studio App Center](https://appcenter.ms/) | `ci.APPCENTER` | 🚫 |
| [Woodpecker](https://woodpecker-ci.org/) | `ci.WOODPECKER` | ✅ |
## API
### `ci.name`
Returns a string containing name of the CI server the code is running on.
If CI server is not detected, it returns `null`.
Don't depend on the value of this string not to change for a specific
vendor. If you find your self writing `ci.name === 'Travis CI'`, you
most likely want to use `ci.TRAVIS` instead.
### `ci.isCI`
Returns a boolean. Will be `true` if the code is running on a CI server,
otherwise `false`.
Some CI servers not listed here might still trigger the `ci.isCI`
boolean to be set to `true` if they use certain vendor neutral
environment variables. In those cases `ci.name` will be `null` and no
vendor specific boolean will be set to `true`.
### `ci.isPR`
Returns a boolean if PR detection is supported for the current CI server. Will
be `true` if a PR is being tested, otherwise `false`. If PR detection is
not supported for the current CI server, the value will be `null`.
### `ci.<VENDOR-CONSTANT>`
A vendor specific boolean constant is exposed for each support CI
vendor. A constant will be `true` if the code is determined to run on
the given CI server, otherwise `false`.
Examples of vendor constants are `ci.TRAVIS` or `ci.APPVEYOR`. For a
complete list, see the support table above.
Deprecated vendor constants that will be removed in the next major
release:
- `ci.TDDIUM` (Solano CI) This have been renamed `ci.SOLANO`
## Ports
ci-info has been ported to the following languages
| Language | Repository |
|----------|------------|
| Go | https://github.com/hofstadter-io/cinful |
| Rust | https://github.com/sagiegurari/ci_info |
| Kotlin | https://github.com/cloudflightio/ci-info |
## License
[MIT](LICENSE)

View File

@@ -0,0 +1,75 @@
// This file is generated at pre-commit by running `node create-typings.js`.
/**
* Returns a boolean. Will be `true` if the code is running on a CI server,
* otherwise `false`.
*
* Some CI servers not listed here might still trigger the `ci.isCI`
* boolean to be set to `true` if they use certain vendor neutral environment
* variables. In those cases `ci.name` will be `null` and no vendor specific
* boolean will be set to `true`.
*/
export const isCI: boolean;
/**
* Returns a boolean if PR detection is supported for the current CI server.
* Will be `true` if a PR is being tested, otherwise `false`. If PR detection is
* not supported for the current CI server, the value will be `null`.
*/
export const isPR: boolean | null;
/**
* Returns a string containing name of the CI server the code is running on. If
* CI server is not detected, it returns `null`.
*
* Don't depend on the value of this string not to change for a specific vendor.
* If you find your self writing `ci.name === 'Travis CI'`, you most likely want
* to use `ci.TRAVIS` instead.
*/
export const name: string | null;
export const APPCIRCLE: boolean;
export const APPVEYOR: boolean;
export const CODEBUILD: boolean;
export const AZURE_PIPELINES: boolean;
export const BAMBOO: boolean;
export const BITBUCKET: boolean;
export const BITRISE: boolean;
export const BUDDY: boolean;
export const BUILDKITE: boolean;
export const CIRCLE: boolean;
export const CIRRUS: boolean;
export const CODEFRESH: boolean;
export const CODEMAGIC: boolean;
export const CODESHIP: boolean;
export const DRONE: boolean;
export const DSARI: boolean;
export const EAS: boolean;
export const GERRIT: boolean;
export const GITHUB_ACTIONS: boolean;
export const GITLAB: boolean;
export const GOCD: boolean;
export const GOOGLE_CLOUD_BUILD: boolean;
export const HARNESS: boolean;
export const HEROKU: boolean;
export const HUDSON: boolean;
export const JENKINS: boolean;
export const LAYERCI: boolean;
export const MAGNUM: boolean;
export const NETLIFY: boolean;
export const NEVERCODE: boolean;
export const RELEASEHUB: boolean;
export const RENDER: boolean;
export const SAIL: boolean;
export const SCREWDRIVER: boolean;
export const SEMAPHORE: boolean;
export const SHIPPABLE: boolean;
export const SOLANO: boolean;
export const SOURCEHUT: boolean;
export const STRIDER: boolean;
export const TASKCLUSTER: boolean;
export const TEAMCITY: boolean;
export const TRAVIS: boolean;
export const VERCEL: boolean;
export const APPCENTER: boolean;
export const WOODPECKER: boolean;
export const XCODE_CLOUD: boolean;
export const XCODE_SERVER: boolean;

View File

@@ -0,0 +1,90 @@
'use strict'
const vendors = require('./vendors.json')
const env = process.env
// Used for testing only
Object.defineProperty(exports, '_vendors', {
value: vendors.map(function (v) {
return v.constant
})
})
exports.name = null
exports.isPR = null
vendors.forEach(function (vendor) {
const envs = Array.isArray(vendor.env) ? vendor.env : [vendor.env]
const isCI = envs.every(function (obj) {
return checkEnv(obj)
})
exports[vendor.constant] = isCI
if (!isCI) {
return
}
exports.name = vendor.name
switch (typeof vendor.pr) {
case 'string':
// "pr": "CIRRUS_PR"
exports.isPR = !!env[vendor.pr]
break
case 'object':
if ('env' in vendor.pr) {
// "pr": { "env": "BUILDKITE_PULL_REQUEST", "ne": "false" }
exports.isPR = vendor.pr.env in env && env[vendor.pr.env] !== vendor.pr.ne
} else if ('any' in vendor.pr) {
// "pr": { "any": ["ghprbPullId", "CHANGE_ID"] }
exports.isPR = vendor.pr.any.some(function (key) {
return !!env[key]
})
} else {
// "pr": { "DRONE_BUILD_EVENT": "pull_request" }
exports.isPR = checkEnv(vendor.pr)
}
break
default:
// PR detection not supported for this vendor
exports.isPR = null
}
})
exports.isCI = !!(
env.CI !== 'false' && // Bypass all checks if CI env is explicitly set to 'false'
(env.BUILD_ID || // Jenkins, Cloudbees
env.BUILD_NUMBER || // Jenkins, TeamCity
env.CI || // Travis CI, CircleCI, Cirrus CI, Gitlab CI, Appveyor, CodeShip, dsari
env.CI_APP_ID || // Appflow
env.CI_BUILD_ID || // Appflow
env.CI_BUILD_NUMBER || // Appflow
env.CI_NAME || // Codeship and others
env.CONTINUOUS_INTEGRATION || // Travis CI, Cirrus CI
env.RUN_ID || // TaskCluster, dsari
exports.name ||
false)
)
function checkEnv (obj) {
// "env": "CIRRUS"
if (typeof obj === 'string') return !!env[obj]
// "env": { "env": "NODE", "includes": "/app/.heroku/node/bin/node" }
if ('env' in obj) {
// Currently there are no other types, uncomment when there are
// if ('includes' in obj) {
return env[obj.env] && env[obj.env].includes(obj.includes)
// }
}
if ('any' in obj) {
return obj.any.some(function (k) {
return !!env[k]
})
}
return Object.keys(obj).every(function (k) {
return env[k] === obj[k]
})
}

View File

@@ -0,0 +1,45 @@
{
"name": "ci-info",
"version": "3.9.0",
"description": "Get details about the current Continuous Integration environment",
"main": "index.js",
"typings": "index.d.ts",
"author": "Thomas Watson Steen <w@tson.dk> (https://twitter.com/wa7son)",
"license": "MIT",
"repository": "https://github.com/watson/ci-info.git",
"bugs": "https://github.com/watson/ci-info/issues",
"homepage": "https://github.com/watson/ci-info",
"keywords": [
"ci",
"continuous",
"integration",
"test",
"detect"
],
"files": [
"vendors.json",
"index.js",
"index.d.ts",
"CHANGELOG.md"
],
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/sibiraj-s"
}
],
"scripts": {
"lint:fix": "standard --fix",
"test": "standard && node test.js",
"prepare": "husky install"
},
"devDependencies": {
"clear-module": "^4.1.2",
"husky": "^8.0.3",
"standard": "^17.1.0",
"tape": "^5.7.0"
},
"engines": {
"node": ">=8"
}
}

View File

@@ -0,0 +1,321 @@
[
{
"name": "Appcircle",
"constant": "APPCIRCLE",
"env": "AC_APPCIRCLE"
},
{
"name": "AppVeyor",
"constant": "APPVEYOR",
"env": "APPVEYOR",
"pr": "APPVEYOR_PULL_REQUEST_NUMBER"
},
{
"name": "AWS CodeBuild",
"constant": "CODEBUILD",
"env": "CODEBUILD_BUILD_ARN"
},
{
"name": "Azure Pipelines",
"constant": "AZURE_PIPELINES",
"env": "TF_BUILD",
"pr": {
"BUILD_REASON": "PullRequest"
}
},
{
"name": "Bamboo",
"constant": "BAMBOO",
"env": "bamboo_planKey"
},
{
"name": "Bitbucket Pipelines",
"constant": "BITBUCKET",
"env": "BITBUCKET_COMMIT",
"pr": "BITBUCKET_PR_ID"
},
{
"name": "Bitrise",
"constant": "BITRISE",
"env": "BITRISE_IO",
"pr": "BITRISE_PULL_REQUEST"
},
{
"name": "Buddy",
"constant": "BUDDY",
"env": "BUDDY_WORKSPACE_ID",
"pr": "BUDDY_EXECUTION_PULL_REQUEST_ID"
},
{
"name": "Buildkite",
"constant": "BUILDKITE",
"env": "BUILDKITE",
"pr": {
"env": "BUILDKITE_PULL_REQUEST",
"ne": "false"
}
},
{
"name": "CircleCI",
"constant": "CIRCLE",
"env": "CIRCLECI",
"pr": "CIRCLE_PULL_REQUEST"
},
{
"name": "Cirrus CI",
"constant": "CIRRUS",
"env": "CIRRUS_CI",
"pr": "CIRRUS_PR"
},
{
"name": "Codefresh",
"constant": "CODEFRESH",
"env": "CF_BUILD_ID",
"pr": {
"any": [
"CF_PULL_REQUEST_NUMBER",
"CF_PULL_REQUEST_ID"
]
}
},
{
"name": "Codemagic",
"constant": "CODEMAGIC",
"env": "CM_BUILD_ID",
"pr": "CM_PULL_REQUEST"
},
{
"name": "Codeship",
"constant": "CODESHIP",
"env": {
"CI_NAME": "codeship"
}
},
{
"name": "Drone",
"constant": "DRONE",
"env": "DRONE",
"pr": {
"DRONE_BUILD_EVENT": "pull_request"
}
},
{
"name": "dsari",
"constant": "DSARI",
"env": "DSARI"
},
{
"name": "Expo Application Services",
"constant": "EAS",
"env": "EAS_BUILD"
},
{
"name": "Gerrit",
"constant": "GERRIT",
"env": "GERRIT_PROJECT"
},
{
"name": "GitHub Actions",
"constant": "GITHUB_ACTIONS",
"env": "GITHUB_ACTIONS",
"pr": {
"GITHUB_EVENT_NAME": "pull_request"
}
},
{
"name": "GitLab CI",
"constant": "GITLAB",
"env": "GITLAB_CI",
"pr": "CI_MERGE_REQUEST_ID"
},
{
"name": "GoCD",
"constant": "GOCD",
"env": "GO_PIPELINE_LABEL"
},
{
"name": "Google Cloud Build",
"constant": "GOOGLE_CLOUD_BUILD",
"env": "BUILDER_OUTPUT"
},
{
"name": "Harness CI",
"constant": "HARNESS",
"env": "HARNESS_BUILD_ID"
},
{
"name": "Heroku",
"constant": "HEROKU",
"env": {
"env": "NODE",
"includes": "/app/.heroku/node/bin/node"
}
},
{
"name": "Hudson",
"constant": "HUDSON",
"env": "HUDSON_URL"
},
{
"name": "Jenkins",
"constant": "JENKINS",
"env": [
"JENKINS_URL",
"BUILD_ID"
],
"pr": {
"any": [
"ghprbPullId",
"CHANGE_ID"
]
}
},
{
"name": "LayerCI",
"constant": "LAYERCI",
"env": "LAYERCI",
"pr": "LAYERCI_PULL_REQUEST"
},
{
"name": "Magnum CI",
"constant": "MAGNUM",
"env": "MAGNUM"
},
{
"name": "Netlify CI",
"constant": "NETLIFY",
"env": "NETLIFY",
"pr": {
"env": "PULL_REQUEST",
"ne": "false"
}
},
{
"name": "Nevercode",
"constant": "NEVERCODE",
"env": "NEVERCODE",
"pr": {
"env": "NEVERCODE_PULL_REQUEST",
"ne": "false"
}
},
{
"name": "ReleaseHub",
"constant": "RELEASEHUB",
"env": "RELEASE_BUILD_ID"
},
{
"name": "Render",
"constant": "RENDER",
"env": "RENDER",
"pr": {
"IS_PULL_REQUEST": "true"
}
},
{
"name": "Sail CI",
"constant": "SAIL",
"env": "SAILCI",
"pr": "SAIL_PULL_REQUEST_NUMBER"
},
{
"name": "Screwdriver",
"constant": "SCREWDRIVER",
"env": "SCREWDRIVER",
"pr": {
"env": "SD_PULL_REQUEST",
"ne": "false"
}
},
{
"name": "Semaphore",
"constant": "SEMAPHORE",
"env": "SEMAPHORE",
"pr": "PULL_REQUEST_NUMBER"
},
{
"name": "Shippable",
"constant": "SHIPPABLE",
"env": "SHIPPABLE",
"pr": {
"IS_PULL_REQUEST": "true"
}
},
{
"name": "Solano CI",
"constant": "SOLANO",
"env": "TDDIUM",
"pr": "TDDIUM_PR_ID"
},
{
"name": "Sourcehut",
"constant": "SOURCEHUT",
"env": {
"CI_NAME": "sourcehut"
}
},
{
"name": "Strider CD",
"constant": "STRIDER",
"env": "STRIDER"
},
{
"name": "TaskCluster",
"constant": "TASKCLUSTER",
"env": [
"TASK_ID",
"RUN_ID"
]
},
{
"name": "TeamCity",
"constant": "TEAMCITY",
"env": "TEAMCITY_VERSION"
},
{
"name": "Travis CI",
"constant": "TRAVIS",
"env": "TRAVIS",
"pr": {
"env": "TRAVIS_PULL_REQUEST",
"ne": "false"
}
},
{
"name": "Vercel",
"constant": "VERCEL",
"env": {
"any": [
"NOW_BUILDER",
"VERCEL"
]
},
"pr": "VERCEL_GIT_PULL_REQUEST_ID"
},
{
"name": "Visual Studio App Center",
"constant": "APPCENTER",
"env": "APPCENTER_BUILD_ID"
},
{
"name": "Woodpecker",
"constant": "WOODPECKER",
"env": {
"CI": "woodpecker"
},
"pr": {
"CI_BUILD_EVENT": "pull_request"
}
},
{
"name": "Xcode Cloud",
"constant": "XCODE_CLOUD",
"env": "CI_XCODE_PROJECT",
"pr": "CI_PULL_REQUEST_NUMBER"
},
{
"name": "Xcode Server",
"constant": "XCODE_SERVER",
"env": "XCS"
}
]

View File

@@ -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.

View File

@@ -0,0 +1,3 @@
# expect
This package exports the `expect` function used in [Jest](https://jestjs.io/). You can find its documentation [on Jest's website](https://jestjs.io/docs/expect).

View File

@@ -0,0 +1,75 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*/
import type { AsymmetricMatcher as AsymmetricMatcherInterface, MatcherState } from './types';
export declare abstract class AsymmetricMatcher<T, State extends MatcherState = MatcherState> implements AsymmetricMatcherInterface {
protected sample: T;
protected inverse: boolean;
$$typeof: symbol;
constructor(sample: T, inverse?: boolean);
protected getMatcherContext(): State;
abstract asymmetricMatch(other: unknown): boolean;
abstract toString(): string;
getExpectedType?(): string;
toAsymmetricMatcher?(): string;
}
declare class Any extends AsymmetricMatcher<any> {
constructor(sample: unknown);
asymmetricMatch(other: unknown): boolean;
toString(): string;
getExpectedType(): string;
toAsymmetricMatcher(): string;
}
declare class Anything extends AsymmetricMatcher<void> {
asymmetricMatch(other: unknown): boolean;
toString(): string;
toAsymmetricMatcher(): string;
}
declare class ArrayContaining extends AsymmetricMatcher<Array<unknown>> {
constructor(sample: Array<unknown>, inverse?: boolean);
asymmetricMatch(other: Array<unknown>): boolean;
toString(): string;
getExpectedType(): string;
}
declare class ObjectContaining extends AsymmetricMatcher<Record<string, unknown>> {
constructor(sample: Record<string, unknown>, inverse?: boolean);
asymmetricMatch(other: any): boolean;
toString(): string;
getExpectedType(): string;
}
declare class StringContaining extends AsymmetricMatcher<string> {
constructor(sample: string, inverse?: boolean);
asymmetricMatch(other: string): boolean;
toString(): string;
getExpectedType(): string;
}
declare class StringMatching extends AsymmetricMatcher<RegExp> {
constructor(sample: string | RegExp, inverse?: boolean);
asymmetricMatch(other: string): boolean;
toString(): string;
getExpectedType(): string;
}
declare class CloseTo extends AsymmetricMatcher<number> {
private precision;
constructor(sample: number, precision?: number, inverse?: boolean);
asymmetricMatch(other: number): boolean;
toString(): string;
getExpectedType(): string;
}
export declare const any: (expectedObject: unknown) => Any;
export declare const anything: () => Anything;
export declare const arrayContaining: (sample: Array<unknown>) => ArrayContaining;
export declare const arrayNotContaining: (sample: Array<unknown>) => ArrayContaining;
export declare const objectContaining: (sample: Record<string, unknown>) => ObjectContaining;
export declare const objectNotContaining: (sample: Record<string, unknown>) => ObjectContaining;
export declare const stringContaining: (expected: string) => StringContaining;
export declare const stringNotContaining: (expected: string) => StringContaining;
export declare const stringMatching: (expected: string | RegExp) => StringMatching;
export declare const stringNotMatching: (expected: string | RegExp) => StringMatching;
export declare const closeTo: (expected: number, precision?: number | undefined) => CloseTo;
export declare const notCloseTo: (expected: number, precision?: number | undefined) => CloseTo;
export {};

View File

@@ -0,0 +1,432 @@
'use strict';
Object.defineProperty(exports, '__esModule', {
value: true
});
exports.stringNotMatching =
exports.stringNotContaining =
exports.stringMatching =
exports.stringContaining =
exports.objectNotContaining =
exports.objectContaining =
exports.notCloseTo =
exports.closeTo =
exports.arrayNotContaining =
exports.arrayContaining =
exports.anything =
exports.any =
exports.AsymmetricMatcher =
void 0;
var matcherUtils = _interopRequireWildcard(require('jest-matcher-utils'));
var _jasmineUtils = require('./jasmineUtils');
var _jestMatchersObject = require('./jestMatchersObject');
var _utils = require('./utils');
function _getRequireWildcardCache(nodeInterop) {
if (typeof WeakMap !== 'function') return null;
var cacheBabelInterop = new WeakMap();
var cacheNodeInterop = new WeakMap();
return (_getRequireWildcardCache = function (nodeInterop) {
return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
})(nodeInterop);
}
function _interopRequireWildcard(obj, nodeInterop) {
if (!nodeInterop && obj && obj.__esModule) {
return obj;
}
if (obj === null || (typeof obj !== 'object' && typeof obj !== 'function')) {
return {default: obj};
}
var cache = _getRequireWildcardCache(nodeInterop);
if (cache && cache.has(obj)) {
return cache.get(obj);
}
var newObj = {};
var hasPropertyDescriptor =
Object.defineProperty && Object.getOwnPropertyDescriptor;
for (var key in obj) {
if (key !== 'default' && Object.prototype.hasOwnProperty.call(obj, key)) {
var desc = hasPropertyDescriptor
? Object.getOwnPropertyDescriptor(obj, key)
: null;
if (desc && (desc.get || desc.set)) {
Object.defineProperty(newObj, key, desc);
} else {
newObj[key] = obj[key];
}
}
}
newObj.default = obj;
if (cache) {
cache.set(obj, newObj);
}
return newObj;
}
var global = (function () {
if (typeof globalThis !== 'undefined') {
return globalThis;
} else if (typeof global !== 'undefined') {
return global;
} else if (typeof self !== 'undefined') {
return self;
} else if (typeof window !== 'undefined') {
return window;
} else {
return Function('return this')();
}
})();
var Symbol = global['jest-symbol-do-not-touch'] || global.Symbol;
function _defineProperty(obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
}
const utils = Object.freeze({
...matcherUtils,
iterableEquality: _utils.iterableEquality,
subsetEquality: _utils.subsetEquality
});
class AsymmetricMatcher {
constructor(sample, inverse = false) {
_defineProperty(this, '$$typeof', Symbol.for('jest.asymmetricMatcher'));
this.sample = sample;
this.inverse = inverse;
}
getMatcherContext() {
return {
...(0, _jestMatchersObject.getState)(),
equals: _jasmineUtils.equals,
isNot: this.inverse,
utils
};
}
}
exports.AsymmetricMatcher = AsymmetricMatcher;
class Any extends AsymmetricMatcher {
constructor(sample) {
if (typeof sample === 'undefined') {
throw new TypeError(
'any() expects to be passed a constructor function. ' +
'Please pass one or use anything() to match any object.'
);
}
super(sample);
}
asymmetricMatch(other) {
if (this.sample == String) {
return typeof other == 'string' || other instanceof String;
}
if (this.sample == Number) {
return typeof other == 'number' || other instanceof Number;
}
if (this.sample == Function) {
return typeof other == 'function' || other instanceof Function;
}
if (this.sample == Boolean) {
return typeof other == 'boolean' || other instanceof Boolean;
}
if (this.sample == BigInt) {
return typeof other == 'bigint' || other instanceof BigInt;
}
if (this.sample == Symbol) {
return typeof other == 'symbol' || other instanceof Symbol;
}
if (this.sample == Object) {
return typeof other == 'object';
}
return other instanceof this.sample;
}
toString() {
return 'Any';
}
getExpectedType() {
if (this.sample == String) {
return 'string';
}
if (this.sample == Number) {
return 'number';
}
if (this.sample == Function) {
return 'function';
}
if (this.sample == Object) {
return 'object';
}
if (this.sample == Boolean) {
return 'boolean';
}
return (0, _jasmineUtils.fnNameFor)(this.sample);
}
toAsymmetricMatcher() {
return 'Any<' + (0, _jasmineUtils.fnNameFor)(this.sample) + '>';
}
}
class Anything extends AsymmetricMatcher {
asymmetricMatch(other) {
return !(0, _jasmineUtils.isUndefined)(other) && other !== null;
}
toString() {
return 'Anything';
} // No getExpectedType method, because it matches either null or undefined.
toAsymmetricMatcher() {
return 'Anything';
}
}
class ArrayContaining extends AsymmetricMatcher {
constructor(sample, inverse = false) {
super(sample, inverse);
}
asymmetricMatch(other) {
if (!Array.isArray(this.sample)) {
throw new Error(
`You must provide an array to ${this.toString()}, not '` +
typeof this.sample +
"'."
);
}
const result =
this.sample.length === 0 ||
(Array.isArray(other) &&
this.sample.every(item =>
other.some(another => (0, _jasmineUtils.equals)(item, another))
));
return this.inverse ? !result : result;
}
toString() {
return `Array${this.inverse ? 'Not' : ''}Containing`;
}
getExpectedType() {
return 'array';
}
}
class ObjectContaining extends AsymmetricMatcher {
constructor(sample, inverse = false) {
super(sample, inverse);
}
asymmetricMatch(other) {
if (typeof this.sample !== 'object') {
throw new Error(
`You must provide an object to ${this.toString()}, not '` +
typeof this.sample +
"'."
);
}
let result = true;
for (const property in this.sample) {
if (
!(0, _jasmineUtils.hasProperty)(other, property) ||
!(0, _jasmineUtils.equals)(this.sample[property], other[property])
) {
result = false;
break;
}
}
return this.inverse ? !result : result;
}
toString() {
return `Object${this.inverse ? 'Not' : ''}Containing`;
}
getExpectedType() {
return 'object';
}
}
class StringContaining extends AsymmetricMatcher {
constructor(sample, inverse = false) {
if (!(0, _jasmineUtils.isA)('String', sample)) {
throw new Error('Expected is not a string');
}
super(sample, inverse);
}
asymmetricMatch(other) {
const result =
(0, _jasmineUtils.isA)('String', other) && other.includes(this.sample);
return this.inverse ? !result : result;
}
toString() {
return `String${this.inverse ? 'Not' : ''}Containing`;
}
getExpectedType() {
return 'string';
}
}
class StringMatching extends AsymmetricMatcher {
constructor(sample, inverse = false) {
if (
!(0, _jasmineUtils.isA)('String', sample) &&
!(0, _jasmineUtils.isA)('RegExp', sample)
) {
throw new Error('Expected is not a String or a RegExp');
}
super(new RegExp(sample), inverse);
}
asymmetricMatch(other) {
const result =
(0, _jasmineUtils.isA)('String', other) && this.sample.test(other);
return this.inverse ? !result : result;
}
toString() {
return `String${this.inverse ? 'Not' : ''}Matching`;
}
getExpectedType() {
return 'string';
}
}
class CloseTo extends AsymmetricMatcher {
constructor(sample, precision = 2, inverse = false) {
if (!(0, _jasmineUtils.isA)('Number', sample)) {
throw new Error('Expected is not a Number');
}
if (!(0, _jasmineUtils.isA)('Number', precision)) {
throw new Error('Precision is not a Number');
}
super(sample);
_defineProperty(this, 'precision', void 0);
this.inverse = inverse;
this.precision = precision;
}
asymmetricMatch(other) {
if (!(0, _jasmineUtils.isA)('Number', other)) {
return false;
}
let result = false;
if (other === Infinity && this.sample === Infinity) {
result = true; // Infinity - Infinity is NaN
} else if (other === -Infinity && this.sample === -Infinity) {
result = true; // -Infinity - -Infinity is NaN
} else {
result =
Math.abs(this.sample - other) < Math.pow(10, -this.precision) / 2;
}
return this.inverse ? !result : result;
}
toString() {
return `Number${this.inverse ? 'Not' : ''}CloseTo`;
}
getExpectedType() {
return 'number';
}
}
const any = expectedObject => new Any(expectedObject);
exports.any = any;
const anything = () => new Anything();
exports.anything = anything;
const arrayContaining = sample => new ArrayContaining(sample);
exports.arrayContaining = arrayContaining;
const arrayNotContaining = sample => new ArrayContaining(sample, true);
exports.arrayNotContaining = arrayNotContaining;
const objectContaining = sample => new ObjectContaining(sample);
exports.objectContaining = objectContaining;
const objectNotContaining = sample => new ObjectContaining(sample, true);
exports.objectNotContaining = objectNotContaining;
const stringContaining = expected => new StringContaining(expected);
exports.stringContaining = stringContaining;
const stringNotContaining = expected => new StringContaining(expected, true);
exports.stringNotContaining = stringNotContaining;
const stringMatching = expected => new StringMatching(expected);
exports.stringMatching = stringMatching;
const stringNotMatching = expected => new StringMatching(expected, true);
exports.stringNotMatching = stringNotMatching;
const closeTo = (expected, precision) => new CloseTo(expected, precision);
exports.closeTo = closeTo;
const notCloseTo = (expected, precision) =>
new CloseTo(expected, precision, true);
exports.notCloseTo = notCloseTo;

View File

@@ -0,0 +1,10 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*/
import type { Expect } from './types';
declare const extractExpectedAssertionsErrors: Expect['extractExpectedAssertionsErrors'];
export default extractExpectedAssertionsErrors;

View File

@@ -0,0 +1,90 @@
'use strict';
Object.defineProperty(exports, '__esModule', {
value: true
});
exports.default = void 0;
var _jestMatcherUtils = require('jest-matcher-utils');
var _jestMatchersObject = require('./jestMatchersObject');
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*/
const resetAssertionsLocalState = () => {
(0, _jestMatchersObject.setState)({
assertionCalls: 0,
expectedAssertionsNumber: null,
isExpectingAssertions: false
});
}; // Create and format all errors related to the mismatched number of `expect`
// calls and reset the matcher's state.
const extractExpectedAssertionsErrors = () => {
const result = [];
const {
assertionCalls,
expectedAssertionsNumber,
expectedAssertionsNumberError,
isExpectingAssertions,
isExpectingAssertionsError
} = (0, _jestMatchersObject.getState)();
resetAssertionsLocalState();
if (
typeof expectedAssertionsNumber === 'number' &&
assertionCalls !== expectedAssertionsNumber
) {
const numOfAssertionsExpected = (0, _jestMatcherUtils.EXPECTED_COLOR)(
(0, _jestMatcherUtils.pluralize)('assertion', expectedAssertionsNumber)
);
expectedAssertionsNumberError.message =
(0, _jestMatcherUtils.matcherHint)(
'.assertions',
'',
String(expectedAssertionsNumber),
{
isDirectExpectCall: true
}
) +
'\n\n' +
`Expected ${numOfAssertionsExpected} to be called but received ` +
(0, _jestMatcherUtils.RECEIVED_COLOR)(
(0, _jestMatcherUtils.pluralize)('assertion call', assertionCalls || 0)
) +
'.';
result.push({
actual: assertionCalls.toString(),
error: expectedAssertionsNumberError,
expected: expectedAssertionsNumber.toString()
});
}
if (isExpectingAssertions && assertionCalls === 0) {
const expected = (0, _jestMatcherUtils.EXPECTED_COLOR)(
'at least one assertion'
);
const received = (0, _jestMatcherUtils.RECEIVED_COLOR)('received none');
isExpectingAssertionsError.message =
(0, _jestMatcherUtils.matcherHint)('.hasAssertions', '', '', {
isDirectExpectCall: true
}) +
'\n\n' +
`Expected ${expected} to be called but ${received}.`;
result.push({
actual: 'none',
error: isExpectingAssertionsError,
expected: 'at least one'
});
}
return result;
};
var _default = extractExpectedAssertionsErrors;
exports.default = _default;

View File

@@ -0,0 +1,15 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*/
import type { Expect, MatcherState as JestMatcherState, Matchers as MatcherInterface } from './types';
declare const expectExport: Expect<JestMatcherState>;
declare namespace expectExport {
type MatcherState = JestMatcherState;
interface Matchers<R, T = unknown> extends MatcherInterface<R, T> {
}
}
export = expectExport;

View File

@@ -0,0 +1,485 @@
'use strict';
var global = (function () {
if (typeof globalThis !== 'undefined') {
return globalThis;
} else if (typeof global !== 'undefined') {
return global;
} else if (typeof self !== 'undefined') {
return self;
} else if (typeof window !== 'undefined') {
return window;
} else {
return Function('return this')();
}
})();
var Symbol = global['jest-symbol-do-not-touch'] || global.Symbol;
var matcherUtils = _interopRequireWildcard(require('jest-matcher-utils'));
var _asymmetricMatchers = require('./asymmetricMatchers');
var _extractExpectedAssertionsErrors = _interopRequireDefault(
require('./extractExpectedAssertionsErrors')
);
var _jasmineUtils = require('./jasmineUtils');
var _jestMatchersObject = require('./jestMatchersObject');
var _matchers = _interopRequireDefault(require('./matchers'));
var _spyMatchers = _interopRequireDefault(require('./spyMatchers'));
var _toThrowMatchers = _interopRequireWildcard(require('./toThrowMatchers'));
var _utils = require('./utils');
function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : {default: obj};
}
function _getRequireWildcardCache(nodeInterop) {
if (typeof WeakMap !== 'function') return null;
var cacheBabelInterop = new WeakMap();
var cacheNodeInterop = new WeakMap();
return (_getRequireWildcardCache = function (nodeInterop) {
return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
})(nodeInterop);
}
function _interopRequireWildcard(obj, nodeInterop) {
if (!nodeInterop && obj && obj.__esModule) {
return obj;
}
if (obj === null || (typeof obj !== 'object' && typeof obj !== 'function')) {
return {default: obj};
}
var cache = _getRequireWildcardCache(nodeInterop);
if (cache && cache.has(obj)) {
return cache.get(obj);
}
var newObj = {};
var hasPropertyDescriptor =
Object.defineProperty && Object.getOwnPropertyDescriptor;
for (var key in obj) {
if (key !== 'default' && Object.prototype.hasOwnProperty.call(obj, key)) {
var desc = hasPropertyDescriptor
? Object.getOwnPropertyDescriptor(obj, key)
: null;
if (desc && (desc.get || desc.set)) {
Object.defineProperty(newObj, key, desc);
} else {
newObj[key] = obj[key];
}
}
}
newObj.default = obj;
if (cache) {
cache.set(obj, newObj);
}
return newObj;
}
var global = (function () {
if (typeof globalThis !== 'undefined') {
return globalThis;
} else if (typeof global !== 'undefined') {
return global;
} else if (typeof self !== 'undefined') {
return self;
} else if (typeof window !== 'undefined') {
return window;
} else {
return Function('return this')();
}
})();
var Symbol = global['jest-symbol-do-not-touch'] || global.Symbol;
var global = (function () {
if (typeof globalThis !== 'undefined') {
return globalThis;
} else if (typeof global !== 'undefined') {
return global;
} else if (typeof self !== 'undefined') {
return self;
} else if (typeof window !== 'undefined') {
return window;
} else {
return Function('return this')();
}
})();
var Promise = global[Symbol.for('jest-native-promise')] || global.Promise;
function _defineProperty(obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
}
class JestAssertionError extends Error {
constructor(...args) {
super(...args);
_defineProperty(this, 'matcherResult', void 0);
}
}
const isPromise = obj =>
!!obj &&
(typeof obj === 'object' || typeof obj === 'function') &&
typeof obj.then === 'function';
const createToThrowErrorMatchingSnapshotMatcher = function (matcher) {
return function (received, testNameOrInlineSnapshot) {
return matcher.apply(this, [received, testNameOrInlineSnapshot, true]);
};
};
const getPromiseMatcher = (name, matcher) => {
if (name === 'toThrow' || name === 'toThrowError') {
return (0, _toThrowMatchers.createMatcher)(name, true);
} else if (
name === 'toThrowErrorMatchingSnapshot' ||
name === 'toThrowErrorMatchingInlineSnapshot'
) {
return createToThrowErrorMatchingSnapshotMatcher(matcher);
}
return null;
};
const expect = (actual, ...rest) => {
if (rest.length !== 0) {
throw new Error('Expect takes at most one argument.');
}
const allMatchers = (0, _jestMatchersObject.getMatchers)();
const expectation = {
not: {},
rejects: {
not: {}
},
resolves: {
not: {}
}
};
const err = new JestAssertionError();
Object.keys(allMatchers).forEach(name => {
const matcher = allMatchers[name];
const promiseMatcher = getPromiseMatcher(name, matcher) || matcher;
expectation[name] = makeThrowingMatcher(matcher, false, '', actual);
expectation.not[name] = makeThrowingMatcher(matcher, true, '', actual);
expectation.resolves[name] = makeResolveMatcher(
name,
promiseMatcher,
false,
actual,
err
);
expectation.resolves.not[name] = makeResolveMatcher(
name,
promiseMatcher,
true,
actual,
err
);
expectation.rejects[name] = makeRejectMatcher(
name,
promiseMatcher,
false,
actual,
err
);
expectation.rejects.not[name] = makeRejectMatcher(
name,
promiseMatcher,
true,
actual,
err
);
});
return expectation;
};
const getMessage = message =>
(message && message()) ||
matcherUtils.RECEIVED_COLOR('No message was specified for this matcher.');
const makeResolveMatcher =
(matcherName, matcher, isNot, actual, outerErr) =>
(...args) => {
const options = {
isNot,
promise: 'resolves'
};
if (!isPromise(actual)) {
throw new JestAssertionError(
matcherUtils.matcherErrorMessage(
matcherUtils.matcherHint(matcherName, undefined, '', options),
`${matcherUtils.RECEIVED_COLOR('received')} value must be a promise`,
matcherUtils.printWithType(
'Received',
actual,
matcherUtils.printReceived
)
)
);
}
const innerErr = new JestAssertionError();
return actual.then(
result =>
makeThrowingMatcher(matcher, isNot, 'resolves', result, innerErr).apply(
null,
args
),
reason => {
outerErr.message =
matcherUtils.matcherHint(matcherName, undefined, '', options) +
'\n\n' +
'Received promise rejected instead of resolved\n' +
`Rejected to value: ${matcherUtils.printReceived(reason)}`;
return Promise.reject(outerErr);
}
);
};
const makeRejectMatcher =
(matcherName, matcher, isNot, actual, outerErr) =>
(...args) => {
const options = {
isNot,
promise: 'rejects'
};
const actualWrapper = typeof actual === 'function' ? actual() : actual;
if (!isPromise(actualWrapper)) {
throw new JestAssertionError(
matcherUtils.matcherErrorMessage(
matcherUtils.matcherHint(matcherName, undefined, '', options),
`${matcherUtils.RECEIVED_COLOR(
'received'
)} value must be a promise or a function returning a promise`,
matcherUtils.printWithType(
'Received',
actual,
matcherUtils.printReceived
)
)
);
}
const innerErr = new JestAssertionError();
return actualWrapper.then(
result => {
outerErr.message =
matcherUtils.matcherHint(matcherName, undefined, '', options) +
'\n\n' +
'Received promise resolved instead of rejected\n' +
`Resolved to value: ${matcherUtils.printReceived(result)}`;
return Promise.reject(outerErr);
},
reason =>
makeThrowingMatcher(matcher, isNot, 'rejects', reason, innerErr).apply(
null,
args
)
);
};
const makeThrowingMatcher = (matcher, isNot, promise, actual, err) =>
function throwingMatcher(...args) {
let throws = true;
const utils = {
...matcherUtils,
iterableEquality: _utils.iterableEquality,
subsetEquality: _utils.subsetEquality
};
const matcherContext = {
// When throws is disabled, the matcher will not throw errors during test
// execution but instead add them to the global matcher state. If a
// matcher throws, test execution is normally stopped immediately. The
// snapshot matcher uses it because we want to log all snapshot
// failures in a test.
dontThrow: () => (throws = false),
...(0, _jestMatchersObject.getState)(),
equals: _jasmineUtils.equals,
error: err,
isNot,
promise,
utils
};
const processResult = (result, asyncError) => {
_validateResult(result);
(0, _jestMatchersObject.getState)().assertionCalls++;
if ((result.pass && isNot) || (!result.pass && !isNot)) {
// XOR
const message = getMessage(result.message);
let error;
if (err) {
error = err;
error.message = message;
} else if (asyncError) {
error = asyncError;
error.message = message;
} else {
error = new JestAssertionError(message); // Try to remove this function from the stack trace frame.
// Guard for some environments (browsers) that do not support this feature.
if (Error.captureStackTrace) {
Error.captureStackTrace(error, throwingMatcher);
}
} // Passing the result of the matcher with the error so that a custom
// reporter could access the actual and expected objects of the result
// for example in order to display a custom visual diff
error.matcherResult = {...result, message};
if (throws) {
throw error;
} else {
(0, _jestMatchersObject.getState)().suppressedErrors.push(error);
}
}
};
const handleError = error => {
if (
matcher[_jestMatchersObject.INTERNAL_MATCHER_FLAG] === true &&
!(error instanceof JestAssertionError) &&
error.name !== 'PrettyFormatPluginError' && // Guard for some environments (browsers) that do not support this feature.
Error.captureStackTrace
) {
// Try to remove this and deeper functions from the stack trace frame.
Error.captureStackTrace(error, throwingMatcher);
}
throw error;
};
let potentialResult;
try {
potentialResult =
matcher[_jestMatchersObject.INTERNAL_MATCHER_FLAG] === true
? matcher.call(matcherContext, actual, ...args) // It's a trap specifically for inline snapshot to capture this name
: // in the stack trace, so that it can correctly get the custom matcher
// function call.
(function __EXTERNAL_MATCHER_TRAP__() {
return matcher.call(matcherContext, actual, ...args);
})();
if (isPromise(potentialResult)) {
const asyncResult = potentialResult;
const asyncError = new JestAssertionError();
if (Error.captureStackTrace) {
Error.captureStackTrace(asyncError, throwingMatcher);
}
return asyncResult
.then(aResult => processResult(aResult, asyncError))
.catch(handleError);
} else {
const syncResult = potentialResult;
return processResult(syncResult);
}
} catch (error) {
return handleError(error);
}
};
expect.extend = matchers =>
(0, _jestMatchersObject.setMatchers)(matchers, false, expect);
expect.anything = _asymmetricMatchers.anything;
expect.any = _asymmetricMatchers.any;
expect.not = {
arrayContaining: _asymmetricMatchers.arrayNotContaining,
closeTo: _asymmetricMatchers.notCloseTo,
objectContaining: _asymmetricMatchers.objectNotContaining,
stringContaining: _asymmetricMatchers.stringNotContaining,
stringMatching: _asymmetricMatchers.stringNotMatching
};
expect.arrayContaining = _asymmetricMatchers.arrayContaining;
expect.closeTo = _asymmetricMatchers.closeTo;
expect.objectContaining = _asymmetricMatchers.objectContaining;
expect.stringContaining = _asymmetricMatchers.stringContaining;
expect.stringMatching = _asymmetricMatchers.stringMatching;
const _validateResult = result => {
if (
typeof result !== 'object' ||
typeof result.pass !== 'boolean' ||
(result.message &&
typeof result.message !== 'string' &&
typeof result.message !== 'function')
) {
throw new Error(
'Unexpected return from a matcher function.\n' +
'Matcher functions should ' +
'return an object in the following format:\n' +
' {message?: string | function, pass: boolean}\n' +
`'${matcherUtils.stringify(result)}' was returned`
);
}
};
function assertions(expected) {
const error = new Error();
if (Error.captureStackTrace) {
Error.captureStackTrace(error, assertions);
}
(0, _jestMatchersObject.setState)({
expectedAssertionsNumber: expected,
expectedAssertionsNumberError: error
});
}
function hasAssertions(...args) {
const error = new Error();
if (Error.captureStackTrace) {
Error.captureStackTrace(error, hasAssertions);
}
matcherUtils.ensureNoExpected(args[0], '.hasAssertions');
(0, _jestMatchersObject.setState)({
isExpectingAssertions: true,
isExpectingAssertionsError: error
});
} // add default jest matchers
(0, _jestMatchersObject.setMatchers)(_matchers.default, true, expect);
(0, _jestMatchersObject.setMatchers)(_spyMatchers.default, true, expect);
(0, _jestMatchersObject.setMatchers)(_toThrowMatchers.default, true, expect);
expect.addSnapshotSerializer = () => void 0;
expect.assertions = assertions;
expect.hasAssertions = hasAssertions;
expect.getState = _jestMatchersObject.getState;
expect.setState = _jestMatchersObject.setState;
expect.extractExpectedAssertionsErrors =
_extractExpectedAssertionsErrors.default;
const expectExport = expect;
module.exports = expectExport;

View File

@@ -0,0 +1,8 @@
import type { Tester } from './types';
export declare function equals(a: unknown, b: unknown, customTesters?: Array<Tester>, strictCheck?: boolean): boolean;
export declare function isA(typeName: string, value: unknown): boolean;
export declare function fnNameFor(func: Function): string;
export declare function isUndefined(obj: any): boolean;
export declare function hasProperty(obj: object | null, property: string): boolean;
export declare function isImmutableUnorderedKeyed(maybeKeyed: any): boolean;
export declare function isImmutableUnorderedSet(maybeSet: any): boolean;

View File

@@ -0,0 +1,279 @@
'use strict';
Object.defineProperty(exports, '__esModule', {
value: true
});
exports.equals = equals;
exports.fnNameFor = fnNameFor;
exports.hasProperty = hasProperty;
exports.isA = isA;
exports.isImmutableUnorderedKeyed = isImmutableUnorderedKeyed;
exports.isImmutableUnorderedSet = isImmutableUnorderedSet;
exports.isUndefined = isUndefined;
/*
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.
*/
/* eslint-disable */
// Extracted out of jasmine 2.5.2
function equals(a, b, customTesters, strictCheck) {
customTesters = customTesters || [];
return eq(a, b, [], [], customTesters, strictCheck ? hasKey : hasDefinedKey);
}
const functionToString = Function.prototype.toString;
function isAsymmetric(obj) {
return !!obj && isA('Function', obj.asymmetricMatch);
}
function asymmetricMatch(a, b) {
var asymmetricA = isAsymmetric(a),
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, hasKey) {
var result = true;
var asymmetricResult = asymmetricMatch(a, b);
if (asymmetricResult !== undefined) {
return asymmetricResult;
}
for (var i = 0; i < customTesters.length; i++) {
var customTesterResult = customTesters[i](a, b);
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 a === b;
}
var 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 Object.is(a, b);
} 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;
}
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.
var 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 (className == '[object Array]' && a.length !== b.length) {
return false;
} // Deep compare objects.
var aKeys = keys(a, hasKey),
key;
var size = aKeys.length; // Ensure that both objects contain the same number of properties before comparing deep equality.
if (keys(b, hasKey).length !== size) {
return false;
}
while (size--) {
key = aKeys[size]; // Deep compare each member
result =
hasKey(b, key) &&
eq(a[key], b[key], aStack, bStack, customTesters, hasKey);
if (!result) {
return false;
}
} // Remove the first object from the stack of traversed objects.
aStack.pop();
bStack.pop();
return result;
}
function keys(obj, hasKey) {
var keys = [];
for (var key in obj) {
if (hasKey(obj, key)) {
keys.push(key);
}
}
return keys.concat(
Object.getOwnPropertySymbols(obj).filter(
symbol => Object.getOwnPropertyDescriptor(obj, symbol).enumerable
)
);
}
function hasDefinedKey(obj, key) {
return hasKey(obj, key) && obj[key] !== undefined;
}
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'
);
}
function fnNameFor(func) {
if (func.name) {
return func.name;
}
const matches = functionToString
.call(func)
.match(/^(?:async)?\s*function\s*\*?\s*([\w$]+)\s*\(/);
return matches ? matches[1] : '<anonymous>';
}
function isUndefined(obj) {
return obj === void 0;
}
function getPrototype(obj) {
if (Object.getPrototypeOf) {
return Object.getPrototypeOf(obj);
}
if (obj.constructor.prototype == obj) {
return null;
}
return obj.constructor.prototype;
}
function hasProperty(obj, property) {
if (!obj) {
return false;
}
if (Object.prototype.hasOwnProperty.call(obj, property)) {
return true;
}
return hasProperty(getPrototype(obj), property);
} // SENTINEL constants are from https://github.com/facebook/immutable-js
const IS_KEYED_SENTINEL = '@@__IMMUTABLE_KEYED__@@';
const IS_SET_SENTINEL = '@@__IMMUTABLE_SET__@@';
const IS_ORDERED_SENTINEL = '@@__IMMUTABLE_ORDERED__@@';
function isImmutableUnorderedKeyed(maybeKeyed) {
return !!(
maybeKeyed &&
maybeKeyed[IS_KEYED_SENTINEL] &&
!maybeKeyed[IS_ORDERED_SENTINEL]
);
}
function isImmutableUnorderedSet(maybeSet) {
return !!(
maybeSet &&
maybeSet[IS_SET_SENTINEL] &&
!maybeSet[IS_ORDERED_SENTINEL]
);
}

View File

@@ -0,0 +1,13 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*/
import type { Expect, MatcherState, MatchersObject } from './types';
export declare const INTERNAL_MATCHER_FLAG: unique symbol;
export declare const getState: <State extends MatcherState = MatcherState>() => State;
export declare const setState: <State extends MatcherState = MatcherState>(state: Partial<State>) => void;
export declare const getMatchers: <State extends MatcherState = MatcherState>() => MatchersObject<State>;
export declare const setMatchers: <State extends MatcherState = MatcherState>(matchers: MatchersObject<State>, isInternal: boolean, expect: Expect) => void;

View File

@@ -0,0 +1,120 @@
'use strict';
Object.defineProperty(exports, '__esModule', {
value: true
});
exports.setState =
exports.setMatchers =
exports.getState =
exports.getMatchers =
exports.INTERNAL_MATCHER_FLAG =
void 0;
var _asymmetricMatchers = require('./asymmetricMatchers');
var global = (function () {
if (typeof globalThis !== 'undefined') {
return globalThis;
} else if (typeof global !== 'undefined') {
return global;
} else if (typeof self !== 'undefined') {
return self;
} else if (typeof window !== 'undefined') {
return window;
} else {
return Function('return this')();
}
})();
var Symbol = global['jest-symbol-do-not-touch'] || global.Symbol;
// Global matchers object holds the list of available matchers and
// the state, that can hold matcher specific values that change over time.
const JEST_MATCHERS_OBJECT = Symbol.for('$$jest-matchers-object'); // Notes a built-in/internal Jest matcher.
// Jest may override the stack trace of Errors thrown by internal matchers.
const INTERNAL_MATCHER_FLAG = Symbol.for('$$jest-internal-matcher');
exports.INTERNAL_MATCHER_FLAG = INTERNAL_MATCHER_FLAG;
if (!global.hasOwnProperty(JEST_MATCHERS_OBJECT)) {
const defaultState = {
assertionCalls: 0,
expectedAssertionsNumber: null,
isExpectingAssertions: false,
suppressedErrors: [] // errors that are not thrown immediately.
};
Object.defineProperty(global, JEST_MATCHERS_OBJECT, {
value: {
matchers: Object.create(null),
state: defaultState
}
});
}
const getState = () => global[JEST_MATCHERS_OBJECT].state;
exports.getState = getState;
const setState = state => {
Object.assign(global[JEST_MATCHERS_OBJECT].state, state);
};
exports.setState = setState;
const getMatchers = () => global[JEST_MATCHERS_OBJECT].matchers;
exports.getMatchers = getMatchers;
const setMatchers = (matchers, isInternal, expect) => {
Object.keys(matchers).forEach(key => {
const matcher = matchers[key];
Object.defineProperty(matcher, INTERNAL_MATCHER_FLAG, {
value: isInternal
});
if (!isInternal) {
// expect is defined
class CustomMatcher extends _asymmetricMatchers.AsymmetricMatcher {
constructor(inverse = false, ...sample) {
super(sample, inverse);
}
asymmetricMatch(other) {
const {pass} = matcher.call(
this.getMatcherContext(),
other,
...this.sample
);
return this.inverse ? !pass : pass;
}
toString() {
return `${this.inverse ? 'not.' : ''}${key}`;
}
getExpectedType() {
return 'any';
}
toAsymmetricMatcher() {
return `${this.toString()}<${this.sample.map(String).join(', ')}>`;
}
}
Object.defineProperty(expect, key, {
configurable: true,
enumerable: true,
value: (...sample) => new CustomMatcher(false, ...sample),
writable: true
});
Object.defineProperty(expect.not, key, {
configurable: true,
enumerable: true,
value: (...sample) => new CustomMatcher(true, ...sample),
writable: true
});
}
});
Object.assign(global[JEST_MATCHERS_OBJECT].matchers, matchers);
};
exports.setMatchers = setMatchers;

View File

@@ -0,0 +1,10 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*/
import type { MatchersObject } from './types';
declare const matchers: MatchersObject;
export default matchers;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,15 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* 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 printReceivedStringContainExpectedSubstring: (received: string, start: number, length: number) => string;
export declare const printReceivedStringContainExpectedResult: (received: string, result: RegExpExecArray | null) => string;
export declare const printReceivedArrayContainExpectedItem: (received: Array<unknown>, index: number) => string;
export declare const printCloseTo: (receivedDiff: number, expectedDiff: number, precision: number, isNot: boolean) => string;
export declare const printExpectedConstructorName: (label: string, expected: Function) => string;
export declare const printExpectedConstructorNameNot: (label: string, expected: Function) => string;
export declare const printReceivedConstructorName: (label: string, received: Function) => string;
export declare const printReceivedConstructorNameNot: (label: string, received: Function, expected: Function) => string;

View File

@@ -0,0 +1,141 @@
'use strict';
Object.defineProperty(exports, '__esModule', {
value: true
});
exports.printReceivedStringContainExpectedSubstring =
exports.printReceivedStringContainExpectedResult =
exports.printReceivedConstructorNameNot =
exports.printReceivedConstructorName =
exports.printReceivedArrayContainExpectedItem =
exports.printExpectedConstructorNameNot =
exports.printExpectedConstructorName =
exports.printCloseTo =
void 0;
var _jestMatcherUtils = require('jest-matcher-utils');
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* 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/ban-types-eventually */
// Format substring but do not enclose in double quote marks.
// The replacement is compatible with pretty-format package.
const printSubstring = val => val.replace(/"|\\/g, '\\$&');
const printReceivedStringContainExpectedSubstring = (
received,
start,
length // not end
) =>
(0, _jestMatcherUtils.RECEIVED_COLOR)(
'"' +
printSubstring(received.slice(0, start)) +
(0, _jestMatcherUtils.INVERTED_COLOR)(
printSubstring(received.slice(start, start + length))
) +
printSubstring(received.slice(start + length)) +
'"'
);
exports.printReceivedStringContainExpectedSubstring =
printReceivedStringContainExpectedSubstring;
const printReceivedStringContainExpectedResult = (received, result) =>
result === null
? (0, _jestMatcherUtils.printReceived)(received)
: printReceivedStringContainExpectedSubstring(
received,
result.index,
result[0].length
); // The serialized array is compatible with pretty-format package min option.
// However, items have default stringify depth (instead of depth - 1)
// so expected item looks consistent by itself and enclosed in the array.
exports.printReceivedStringContainExpectedResult =
printReceivedStringContainExpectedResult;
const printReceivedArrayContainExpectedItem = (received, index) =>
(0, _jestMatcherUtils.RECEIVED_COLOR)(
'[' +
received
.map((item, i) => {
const stringified = (0, _jestMatcherUtils.stringify)(item);
return i === index
? (0, _jestMatcherUtils.INVERTED_COLOR)(stringified)
: stringified;
})
.join(', ') +
']'
);
exports.printReceivedArrayContainExpectedItem =
printReceivedArrayContainExpectedItem;
const printCloseTo = (receivedDiff, expectedDiff, precision, isNot) => {
const receivedDiffString = (0, _jestMatcherUtils.stringify)(receivedDiff);
const expectedDiffString = receivedDiffString.includes('e') // toExponential arg is number of digits after the decimal point.
? expectedDiff.toExponential(0)
: 0 <= precision && precision < 20 // toFixed arg is number of digits after the decimal point.
? // It may be a value between 0 and 20 inclusive.
// Implementations may optionally support a larger range of values.
expectedDiff.toFixed(precision + 1)
: (0, _jestMatcherUtils.stringify)(expectedDiff);
return (
`Expected precision: ${isNot ? ' ' : ''} ${(0,
_jestMatcherUtils.stringify)(precision)}\n` +
`Expected difference: ${isNot ? 'not ' : ''}< ${(0,
_jestMatcherUtils.EXPECTED_COLOR)(expectedDiffString)}\n` +
`Received difference: ${isNot ? ' ' : ''} ${(0,
_jestMatcherUtils.RECEIVED_COLOR)(receivedDiffString)}`
);
};
exports.printCloseTo = printCloseTo;
const printExpectedConstructorName = (label, expected) =>
printConstructorName(label, expected, false, true) + '\n';
exports.printExpectedConstructorName = printExpectedConstructorName;
const printExpectedConstructorNameNot = (label, expected) =>
printConstructorName(label, expected, true, true) + '\n';
exports.printExpectedConstructorNameNot = printExpectedConstructorNameNot;
const printReceivedConstructorName = (label, received) =>
printConstructorName(label, received, false, false) + '\n'; // Do not call function if received is equal to expected.
exports.printReceivedConstructorName = printReceivedConstructorName;
const printReceivedConstructorNameNot = (label, received, expected) =>
typeof expected.name === 'string' &&
expected.name.length !== 0 &&
typeof received.name === 'string' &&
received.name.length !== 0
? printConstructorName(label, received, true, false) +
` ${
Object.getPrototypeOf(received) === expected
? 'extends'
: 'extends … extends'
} ${(0, _jestMatcherUtils.EXPECTED_COLOR)(expected.name)}` +
'\n'
: printConstructorName(label, received, false, false) + '\n';
exports.printReceivedConstructorNameNot = printReceivedConstructorNameNot;
const printConstructorName = (label, constructor, isNot, isExpected) =>
typeof constructor.name !== 'string'
? `${label} name is not a string`
: constructor.name.length === 0
? `${label} name is an empty string`
: `${label}: ${!isNot ? '' : isExpected ? 'not ' : ' '}${
isExpected
? (0, _jestMatcherUtils.EXPECTED_COLOR)(constructor.name)
: (0, _jestMatcherUtils.RECEIVED_COLOR)(constructor.name)
}`;

View File

@@ -0,0 +1,9 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import type { MatchersObject } from './types';
declare const spyMatchers: MatchersObject;
export default spyMatchers;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,11 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*/
import type { MatchersObject, RawMatcherFn } from './types';
export declare const createMatcher: (matcherName: string, fromPromise?: boolean | undefined) => RawMatcherFn;
declare const matchers: MatchersObject;
export default matchers;

View File

@@ -0,0 +1,464 @@
'use strict';
Object.defineProperty(exports, '__esModule', {
value: true
});
exports.default = exports.createMatcher = void 0;
var _jestMatcherUtils = require('jest-matcher-utils');
var _jestMessageUtil = require('jest-message-util');
var _print = require('./print');
var _utils = require('./utils');
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* 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/ban-types-eventually */
const DID_NOT_THROW = 'Received function did not throw';
const getThrown = e => {
const hasMessage =
e !== null && e !== undefined && typeof e.message === 'string';
if (hasMessage && typeof e.name === 'string' && typeof e.stack === 'string') {
return {
hasMessage,
isError: true,
message: e.message,
value: e
};
}
return {
hasMessage,
isError: false,
message: hasMessage ? e.message : String(e),
value: e
};
};
const createMatcher = (matcherName, fromPromise) =>
function (received, expected) {
const options = {
isNot: this.isNot,
promise: this.promise
};
let thrown = null;
if (fromPromise && (0, _utils.isError)(received)) {
thrown = getThrown(received);
} else {
if (typeof received !== 'function') {
if (!fromPromise) {
const placeholder = expected === undefined ? '' : 'expected';
throw new Error(
(0, _jestMatcherUtils.matcherErrorMessage)(
(0, _jestMatcherUtils.matcherHint)(
matcherName,
undefined,
placeholder,
options
),
`${(0, _jestMatcherUtils.RECEIVED_COLOR)(
'received'
)} value must be a function`,
(0, _jestMatcherUtils.printWithType)(
'Received',
received,
_jestMatcherUtils.printReceived
)
)
);
}
} else {
try {
received();
} catch (e) {
thrown = getThrown(e);
}
}
}
if (expected === undefined) {
return toThrow(matcherName, options, thrown);
} else if (typeof expected === 'function') {
return toThrowExpectedClass(matcherName, options, thrown, expected);
} else if (typeof expected === 'string') {
return toThrowExpectedString(matcherName, options, thrown, expected);
} else if (expected !== null && typeof expected.test === 'function') {
return toThrowExpectedRegExp(matcherName, options, thrown, expected);
} else if (
expected !== null &&
typeof expected.asymmetricMatch === 'function'
) {
return toThrowExpectedAsymmetric(matcherName, options, thrown, expected);
} else if (expected !== null && typeof expected === 'object') {
return toThrowExpectedObject(matcherName, options, thrown, expected);
} else {
throw new Error(
(0, _jestMatcherUtils.matcherErrorMessage)(
(0, _jestMatcherUtils.matcherHint)(
matcherName,
undefined,
undefined,
options
),
`${(0, _jestMatcherUtils.EXPECTED_COLOR)(
'expected'
)} value must be a string or regular expression or class or error`,
(0, _jestMatcherUtils.printWithType)(
'Expected',
expected,
_jestMatcherUtils.printExpected
)
)
);
}
};
exports.createMatcher = createMatcher;
const matchers = {
toThrow: createMatcher('toThrow'),
toThrowError: createMatcher('toThrowError')
};
const toThrowExpectedRegExp = (matcherName, options, thrown, expected) => {
const pass = thrown !== null && expected.test(thrown.message);
const message = pass
? () =>
(0, _jestMatcherUtils.matcherHint)(
matcherName,
undefined,
undefined,
options
) +
'\n\n' +
formatExpected('Expected pattern: not ', expected) +
(thrown !== null && thrown.hasMessage
? formatReceived(
'Received message: ',
thrown,
'message',
expected
) + formatStack(thrown)
: formatReceived('Received value: ', thrown, 'value'))
: () =>
(0, _jestMatcherUtils.matcherHint)(
matcherName,
undefined,
undefined,
options
) +
'\n\n' +
formatExpected('Expected pattern: ', expected) +
(thrown === null
? '\n' + DID_NOT_THROW
: thrown.hasMessage
? formatReceived('Received message: ', thrown, 'message') +
formatStack(thrown)
: formatReceived('Received value: ', thrown, 'value'));
return {
message,
pass
};
};
const toThrowExpectedAsymmetric = (matcherName, options, thrown, expected) => {
const pass = thrown !== null && expected.asymmetricMatch(thrown.value);
const message = pass
? () =>
(0, _jestMatcherUtils.matcherHint)(
matcherName,
undefined,
undefined,
options
) +
'\n\n' +
formatExpected('Expected asymmetric matcher: not ', expected) +
'\n' +
(thrown !== null && thrown.hasMessage
? formatReceived('Received name: ', thrown, 'name') +
formatReceived('Received message: ', thrown, 'message') +
formatStack(thrown)
: formatReceived('Thrown value: ', thrown, 'value'))
: () =>
(0, _jestMatcherUtils.matcherHint)(
matcherName,
undefined,
undefined,
options
) +
'\n\n' +
formatExpected('Expected asymmetric matcher: ', expected) +
'\n' +
(thrown === null
? DID_NOT_THROW
: thrown.hasMessage
? formatReceived('Received name: ', thrown, 'name') +
formatReceived('Received message: ', thrown, 'message') +
formatStack(thrown)
: formatReceived('Thrown value: ', thrown, 'value'));
return {
message,
pass
};
};
const toThrowExpectedObject = (matcherName, options, thrown, expected) => {
const pass = thrown !== null && thrown.message === expected.message;
const message = pass
? () =>
(0, _jestMatcherUtils.matcherHint)(
matcherName,
undefined,
undefined,
options
) +
'\n\n' +
formatExpected('Expected message: not ', expected.message) +
(thrown !== null && thrown.hasMessage
? formatStack(thrown)
: formatReceived('Received value: ', thrown, 'value'))
: () =>
(0, _jestMatcherUtils.matcherHint)(
matcherName,
undefined,
undefined,
options
) +
'\n\n' +
(thrown === null
? formatExpected('Expected message: ', expected.message) +
'\n' +
DID_NOT_THROW
: thrown.hasMessage
? (0, _jestMatcherUtils.printDiffOrStringify)(
expected.message,
thrown.message,
'Expected message',
'Received message',
true
) +
'\n' +
formatStack(thrown)
: formatExpected('Expected message: ', expected.message) +
formatReceived('Received value: ', thrown, 'value'));
return {
message,
pass
};
};
const toThrowExpectedClass = (matcherName, options, thrown, expected) => {
const pass = thrown !== null && thrown.value instanceof expected;
const message = pass
? () =>
(0, _jestMatcherUtils.matcherHint)(
matcherName,
undefined,
undefined,
options
) +
'\n\n' +
(0, _print.printExpectedConstructorNameNot)(
'Expected constructor',
expected
) +
(thrown !== null &&
thrown.value != null &&
typeof thrown.value.constructor === 'function' &&
thrown.value.constructor !== expected
? (0, _print.printReceivedConstructorNameNot)(
'Received constructor',
thrown.value.constructor,
expected
)
: '') +
'\n' +
(thrown !== null && thrown.hasMessage
? formatReceived('Received message: ', thrown, 'message') +
formatStack(thrown)
: formatReceived('Received value: ', thrown, 'value'))
: () =>
(0, _jestMatcherUtils.matcherHint)(
matcherName,
undefined,
undefined,
options
) +
'\n\n' +
(0, _print.printExpectedConstructorName)(
'Expected constructor',
expected
) +
(thrown === null
? '\n' + DID_NOT_THROW
: (thrown.value != null &&
typeof thrown.value.constructor === 'function'
? (0, _print.printReceivedConstructorName)(
'Received constructor',
thrown.value.constructor
)
: '') +
'\n' +
(thrown.hasMessage
? formatReceived('Received message: ', thrown, 'message') +
formatStack(thrown)
: formatReceived('Received value: ', thrown, 'value')));
return {
message,
pass
};
};
const toThrowExpectedString = (matcherName, options, thrown, expected) => {
const pass = thrown !== null && thrown.message.includes(expected);
const message = pass
? () =>
(0, _jestMatcherUtils.matcherHint)(
matcherName,
undefined,
undefined,
options
) +
'\n\n' +
formatExpected('Expected substring: not ', expected) +
(thrown !== null && thrown.hasMessage
? formatReceived(
'Received message: ',
thrown,
'message',
expected
) + formatStack(thrown)
: formatReceived('Received value: ', thrown, 'value'))
: () =>
(0, _jestMatcherUtils.matcherHint)(
matcherName,
undefined,
undefined,
options
) +
'\n\n' +
formatExpected('Expected substring: ', expected) +
(thrown === null
? '\n' + DID_NOT_THROW
: thrown.hasMessage
? formatReceived('Received message: ', thrown, 'message') +
formatStack(thrown)
: formatReceived('Received value: ', thrown, 'value'));
return {
message,
pass
};
};
const toThrow = (matcherName, options, thrown) => {
const pass = thrown !== null;
const message = pass
? () =>
(0, _jestMatcherUtils.matcherHint)(
matcherName,
undefined,
'',
options
) +
'\n\n' +
(thrown !== null && thrown.hasMessage
? formatReceived('Error name: ', thrown, 'name') +
formatReceived('Error message: ', thrown, 'message') +
formatStack(thrown)
: formatReceived('Thrown value: ', thrown, 'value'))
: () =>
(0, _jestMatcherUtils.matcherHint)(
matcherName,
undefined,
'',
options
) +
'\n\n' +
DID_NOT_THROW;
return {
message,
pass
};
};
const formatExpected = (label, expected) =>
label + (0, _jestMatcherUtils.printExpected)(expected) + '\n';
const formatReceived = (label, thrown, key, expected) => {
if (thrown === null) {
return '';
}
if (key === 'message') {
const message = thrown.message;
if (typeof expected === 'string') {
const index = message.indexOf(expected);
if (index !== -1) {
return (
label +
(0, _print.printReceivedStringContainExpectedSubstring)(
message,
index,
expected.length
) +
'\n'
);
}
} else if (expected instanceof RegExp) {
return (
label +
(0, _print.printReceivedStringContainExpectedResult)(
message,
typeof expected.exec === 'function' ? expected.exec(message) : null
) +
'\n'
);
}
return label + (0, _jestMatcherUtils.printReceived)(message) + '\n';
}
if (key === 'name') {
return thrown.isError
? label + (0, _jestMatcherUtils.printReceived)(thrown.value.name) + '\n'
: '';
}
if (key === 'value') {
return thrown.isError
? ''
: label + (0, _jestMatcherUtils.printReceived)(thrown.value) + '\n';
}
return '';
};
const formatStack = thrown =>
thrown === null || !thrown.isError
? ''
: (0, _jestMessageUtil.formatStackTrace)(
(0, _jestMessageUtil.separateMessageFromStack)(thrown.value.stack)
.stack,
{
rootDir: process.cwd(),
testMatch: []
},
{
noStackTrace: false
}
);
var _default = matchers;
exports.default = _default;

View File

@@ -0,0 +1,327 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*/
import type { Config } from '@jest/types';
import type * as jestMatcherUtils from 'jest-matcher-utils';
import { INTERNAL_MATCHER_FLAG } from './jestMatchersObject';
export declare type SyncExpectationResult = {
pass: boolean;
message: () => string;
};
export declare type AsyncExpectationResult = Promise<SyncExpectationResult>;
export declare type ExpectationResult = SyncExpectationResult | AsyncExpectationResult;
export declare type RawMatcherFn<T extends MatcherState = MatcherState> = {
(this: T, received: any, expected: any, options?: any): ExpectationResult;
[INTERNAL_MATCHER_FLAG]?: boolean;
};
export declare type ThrowingMatcherFn = (actual: any) => void;
export declare type PromiseMatcherFn = (actual: any) => Promise<void>;
export declare type Tester = (a: any, b: any) => boolean | undefined;
export declare type MatcherState = {
assertionCalls: number;
currentTestName?: string;
dontThrow?: () => void;
error?: Error;
equals: (a: unknown, b: unknown, customTesters?: Array<Tester>, strictCheck?: boolean) => boolean;
expand?: boolean;
expectedAssertionsNumber?: number | null;
expectedAssertionsNumberError?: Error;
isExpectingAssertions?: boolean;
isExpectingAssertionsError?: Error;
isNot: boolean;
promise: string;
suppressedErrors: Array<Error>;
testPath?: Config.Path;
utils: typeof jestMatcherUtils & {
iterableEquality: Tester;
subsetEquality: Tester;
};
};
export interface AsymmetricMatcher {
asymmetricMatch(other: unknown): boolean;
toString(): string;
getExpectedType?(): string;
toAsymmetricMatcher?(): string;
}
export declare type MatchersObject<T extends MatcherState = MatcherState> = {
[id: string]: RawMatcherFn<T>;
};
export declare type ExpectedAssertionsErrors = Array<{
actual: string | number;
error: Error;
expected: string;
}>;
interface AsymmetricMatchers {
any(sample: unknown): AsymmetricMatcher;
anything(): AsymmetricMatcher;
arrayContaining(sample: Array<unknown>): AsymmetricMatcher;
closeTo(sample: number, precision?: number): AsymmetricMatcher;
objectContaining(sample: Record<string, unknown>): AsymmetricMatcher;
stringContaining(sample: string): AsymmetricMatcher;
stringMatching(sample: string | RegExp): AsymmetricMatcher;
}
export declare type Expect<State extends MatcherState = MatcherState> = {
<T = unknown>(actual: T): Matchers<void, T>;
addSnapshotSerializer(serializer: unknown): void;
assertions(numberOfAssertions: number): void;
extend<T extends MatcherState = State>(matchers: MatchersObject<T>): void;
extractExpectedAssertionsErrors: () => ExpectedAssertionsErrors;
getState(): State;
hasAssertions(): void;
setState(state: Partial<State>): void;
} & AsymmetricMatchers & {
not: Omit<AsymmetricMatchers, 'any' | 'anything'>;
};
export interface Matchers<R, T = unknown> {
/**
* Ensures the last call to a mock function was provided specific args.
*/
lastCalledWith(...expected: [unknown, ...Array<unknown>]): R;
/**
* Ensure that the last call to a mock function has returned a specified value.
*/
lastReturnedWith(expected: unknown): R;
/**
* If you know how to test something, `.not` lets you test its opposite.
*/
not: Matchers<R, T>;
/**
* Ensure that a mock function is called with specific arguments on an Nth call.
*/
nthCalledWith(nth: number, ...expected: [unknown, ...Array<unknown>]): R;
/**
* Ensure that the nth call to a mock function has returned a specified value.
*/
nthReturnedWith(nth: number, expected: unknown): R;
/**
* Use resolves to unwrap the value of a fulfilled promise so any other
* matcher can be chained. If the promise is rejected the assertion fails.
*/
resolves: Matchers<Promise<R>, T>;
/**
* Unwraps the reason of a rejected promise so any other matcher can be chained.
* If the promise is fulfilled the assertion fails.
*/
rejects: Matchers<Promise<R>, T>;
/**
* Checks that a value is what you expect. It uses `===` to check strict equality.
* Don't use `toBe` with floating-point numbers.
*/
toBe(expected: unknown): R;
/**
* Ensures that a mock function is called.
*/
toBeCalled(): R;
/**
* Ensures that a mock function is called an exact number of times.
*/
toBeCalledTimes(expected: number): R;
/**
* Ensure that a mock function is called with specific arguments.
*/
toBeCalledWith(...expected: [unknown, ...Array<unknown>]): R;
/**
* Using exact equality with floating point numbers is a bad idea.
* Rounding means that intuitive things fail.
* The default for `precision` is 2.
*/
toBeCloseTo(expected: number, precision?: number): R;
/**
* Ensure that a variable is not undefined.
*/
toBeDefined(): R;
/**
* When you don't care what a value is, you just want to
* ensure a value is false in a boolean context.
*/
toBeFalsy(): R;
/**
* For comparing floating point numbers.
*/
toBeGreaterThan(expected: number | bigint): R;
/**
* For comparing floating point numbers.
*/
toBeGreaterThanOrEqual(expected: number | bigint): R;
/**
* Ensure that an object is an instance of a class.
* This matcher uses `instanceof` underneath.
*/
toBeInstanceOf(expected: unknown): R;
/**
* For comparing floating point numbers.
*/
toBeLessThan(expected: number | bigint): R;
/**
* For comparing floating point numbers.
*/
toBeLessThanOrEqual(expected: number | bigint): R;
/**
* This is the same as `.toBe(null)` but the error messages are a bit nicer.
* So use `.toBeNull()` when you want to check that something is null.
*/
toBeNull(): R;
/**
* Use when you don't care what a value is, you just want to ensure a value
* is true in a boolean context. In JavaScript, there are six falsy values:
* `false`, `0`, `''`, `null`, `undefined`, and `NaN`. Everything else is truthy.
*/
toBeTruthy(): R;
/**
* Used to check that a variable is undefined.
*/
toBeUndefined(): R;
/**
* Used to check that a variable is NaN.
*/
toBeNaN(): R;
/**
* Used when you want to check that an item is in a list.
* For testing the items in the list, this uses `===`, a strict equality check.
*/
toContain(expected: unknown): R;
/**
* Used when you want to check that an item is in a list.
* For testing the items in the list, this matcher recursively checks the
* equality of all fields, rather than checking for object identity.
*/
toContainEqual(expected: unknown): R;
/**
* Used when you want to check that two objects have the same value.
* This matcher recursively checks the equality of all fields, rather than checking for object identity.
*/
toEqual(expected: unknown): R;
/**
* Ensures that a mock function is called.
*/
toHaveBeenCalled(): R;
/**
* Ensures that a mock function is called an exact number of times.
*/
toHaveBeenCalledTimes(expected: number): R;
/**
* Ensure that a mock function is called with specific arguments.
*/
toHaveBeenCalledWith(...expected: [unknown, ...Array<unknown>]): R;
/**
* Ensure that a mock function is called with specific arguments on an Nth call.
*/
toHaveBeenNthCalledWith(nth: number, ...expected: [unknown, ...Array<unknown>]): R;
/**
* If you have a mock function, you can use `.toHaveBeenLastCalledWith`
* to test what arguments it was last called with.
*/
toHaveBeenLastCalledWith(...expected: [unknown, ...Array<unknown>]): R;
/**
* Use to test the specific value that a mock function last returned.
* If the last call to the mock function threw an error, then this matcher will fail
* no matter what value you provided as the expected return value.
*/
toHaveLastReturnedWith(expected: unknown): R;
/**
* Used to check that an object has a `.length` property
* and it is set to a certain numeric value.
*/
toHaveLength(expected: number): R;
/**
* Use to test the specific value that a mock function returned for the nth call.
* If the nth call to the mock function threw an error, then this matcher will fail
* no matter what value you provided as the expected return value.
*/
toHaveNthReturnedWith(nth: number, expected: unknown): R;
/**
* Use to check if property at provided reference keyPath exists for an object.
* For checking deeply nested properties in an object you may use dot notation or an array containing
* the keyPath for deep references.
*
* Optionally, you can provide a value to check if it's equal to the value present at keyPath
* on the target object. This matcher uses 'deep equality' (like `toEqual()`) and recursively checks
* the equality of all fields.
*
* @example
*
* expect(houseForSale).toHaveProperty('kitchen.area', 20);
*/
toHaveProperty(expectedPath: string | Array<string>, expectedValue?: unknown): R;
/**
* Use to test that the mock function successfully returned (i.e., did not throw an error) at least one time
*/
toHaveReturned(): R;
/**
* Use to ensure that a mock function returned successfully (i.e., did not throw an error) an exact number of times.
* Any calls to the mock function that throw an error are not counted toward the number of times the function returned.
*/
toHaveReturnedTimes(expected: number): R;
/**
* Use to ensure that a mock function returned a specific value.
*/
toHaveReturnedWith(expected: unknown): R;
/**
* Check that a string matches a regular expression.
*/
toMatch(expected: string | RegExp): R;
/**
* Used to check that a JavaScript object matches a subset of the properties of an object
*/
toMatchObject(expected: Record<string, unknown> | Array<Record<string, unknown>>): R;
/**
* Ensure that a mock function has returned (as opposed to thrown) at least once.
*/
toReturn(): R;
/**
* Ensure that a mock function has returned (as opposed to thrown) a specified number of times.
*/
toReturnTimes(expected: number): R;
/**
* Ensure that a mock function has returned a specified value at least once.
*/
toReturnWith(expected: unknown): R;
/**
* Use to test that objects have the same types as well as structure.
*/
toStrictEqual(expected: unknown): R;
/**
* Used to test that a function throws when it is called.
*/
toThrow(expected?: unknown): R;
/**
* If you want to test that a specific error is thrown inside a function.
*/
toThrowError(expected?: unknown): R;
/**
* This ensures that a value matches the most recent snapshot with property matchers.
* Check out [the Snapshot Testing guide](https://jestjs.io/docs/snapshot-testing) for more information.
*/
toMatchSnapshot(hint?: string): R;
/**
* This ensures that a value matches the most recent snapshot.
* Check out [the Snapshot Testing guide](https://jestjs.io/docs/snapshot-testing) for more information.
*/
toMatchSnapshot<U extends Record<keyof T, unknown>>(propertyMatchers: Partial<U>, hint?: string): R;
/**
* This ensures that a value matches the most recent snapshot with property matchers.
* Instead of writing the snapshot value to a .snap file, it will be written into the source code automatically.
* Check out [the Snapshot Testing guide](https://jestjs.io/docs/snapshot-testing) for more information.
*/
toMatchInlineSnapshot(snapshot?: string): R;
/**
* This ensures that a value matches the most recent snapshot with property matchers.
* Instead of writing the snapshot value to a .snap file, it will be written into the source code automatically.
* Check out [the Snapshot Testing guide](https://jestjs.io/docs/snapshot-testing) for more information.
*/
toMatchInlineSnapshot<U extends Record<keyof T, unknown>>(propertyMatchers: Partial<U>, snapshot?: string): R;
/**
* Used to test that a function throws a error matching the most recent snapshot when it is called.
*/
toThrowErrorMatchingSnapshot(hint?: string): R;
/**
* Used to test that a function throws a error matching the most recent snapshot when it is called.
* Instead of writing the snapshot value to a .snap file, it will be written into the source code automatically.
*/
toThrowErrorMatchingInlineSnapshot(snapshot?: string): R;
}
export {};

View File

@@ -0,0 +1,3 @@
'use strict';
var _jestMatchersObject = require('./jestMatchersObject');

View File

@@ -0,0 +1,26 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*/
declare type GetPath = {
hasEndProp?: boolean;
lastTraversedObject: unknown;
traversedPath: Array<string>;
value?: unknown;
};
export declare const getPath: (object: Record<string, any>, propertyPath: string | Array<string>) => GetPath;
export declare const getObjectSubset: (object: any, subset: any, seenReferences?: WeakMap<object, boolean>) => any;
export declare const iterableEquality: (a: any, b: any, aStack?: Array<any>, bStack?: Array<any>) => boolean | undefined;
export declare const subsetEquality: (object: unknown, subset: unknown) => boolean | undefined;
export declare const typeEquality: (a: any, b: any) => boolean | undefined;
export declare const arrayBufferEquality: (a: unknown, b: unknown) => boolean | undefined;
export declare const sparseArrayEquality: (a: unknown, b: unknown) => boolean | undefined;
export declare const partition: <T>(items: T[], predicate: (arg: T) => boolean) => [T[], T[]];
export declare const pathAsArray: (propertyPath: string) => Array<any>;
export declare const isError: (value: unknown) => value is Error;
export declare function emptyObject(obj: unknown): boolean;
export declare const isOneline: (expected: unknown, received: unknown) => boolean;
export {};

View File

@@ -0,0 +1,458 @@
'use strict';
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 =
void 0;
var _jestGetType = require('jest-get-type');
var _jasmineUtils = require('./jasmineUtils');
var global = (function () {
if (typeof globalThis !== 'undefined') {
return globalThis;
} else if (typeof global !== 'undefined') {
return global;
} else if (typeof self !== 'undefined') {
return self;
} else if (typeof window !== 'undefined') {
return window;
} else {
return Function('return this')();
}
})();
var Symbol = global['jest-symbol-do-not-touch'] || global.Symbol;
/**
* 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)
);
};
const getPath = (object, propertyPath) => {
if (!Array.isArray(propertyPath)) {
propertyPath = pathAsArray(propertyPath);
}
if (propertyPath.length) {
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.hasEndProp =
newObject !== undefined ||
(!(0, _jestGetType.isPrimitive)(object) && prop in object);
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, 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));
}
} else if (object instanceof Date) {
return object;
} else if (isObject(object) && isObject(subset)) {
if (
(0, _jasmineUtils.equals)(object, subset, [
iterableEquality,
subsetEquality
])
) {
// Avoid unnecessary copy which might return Object instead of subclass.
return subset;
}
const trimmed = {};
seenReferences.set(object, trimmed);
Object.keys(object)
.filter(key => hasPropertyInObject(subset, key))
.forEach(key => {
trimmed[key] = seenReferences.has(object[key])
? seenReferences.get(object[key])
: getObjectSubset(object[key], subset[key], seenReferences);
});
if (Object.keys(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,
/* eslint-enable @typescript-eslint/explicit-module-boundary-types */
aStack = [],
bStack = []
) => {
if (
typeof a !== 'object' ||
typeof b !== 'object' ||
Array.isArray(a) ||
Array.isArray(b) ||
!hasIterator(a) ||
!hasIterator(b)
) {
return undefined;
}
if (a.constructor !== 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, [...aStack], [...bStack]);
if (a.size !== undefined) {
if (a.size !== b.size) {
return false;
} else if (
(0, _jasmineUtils.isA)('Set', a) ||
(0, _jasmineUtils.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, [
iterableEqualityWithStack
]);
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, _jasmineUtils.isImmutableUnorderedKeyed)(a)
) {
let allFound = true;
for (const aEntry of a) {
if (
!b.has(aEntry[0]) ||
!(0, _jasmineUtils.equals)(aEntry[1], b.get(aEntry[0]), [
iterableEqualityWithStack
])
) {
let has = false;
for (const bEntry of b) {
const matchedKey = (0, _jasmineUtils.equals)(aEntry[0], bEntry[0], [
iterableEqualityWithStack
]);
let matchedValue = false;
if (matchedKey === true) {
matchedValue = (0, _jasmineUtils.equals)(aEntry[1], bEntry[1], [
iterableEqualityWithStack
]);
}
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;
}
}
const bIterator = b[IteratorSymbol]();
for (const aValue of a) {
const nextB = bIterator.next();
if (
nextB.done ||
!(0, _jasmineUtils.equals)(aValue, nextB.value, [
iterableEqualityWithStack
])
) {
return false;
}
}
if (!bIterator.next().done) {
return false;
} // Remove the first value from the stack of traversed values.
aStack.pop();
bStack.pop();
return true;
};
exports.iterableEquality = iterableEquality;
const isObject = a => a !== null && typeof a === 'object';
const isObjectWithKeys = a =>
isObject(a) &&
!(a instanceof Error) &&
!(a instanceof Array) &&
!(a instanceof Date);
const subsetEquality = (object, subset) => {
// 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;
}
return Object.keys(subset).every(key => {
if (isObjectWithKeys(subset[key])) {
if (seenReferences.has(subset[key])) {
return (0, _jasmineUtils.equals)(object[key], subset[key], [
iterableEquality
]);
}
seenReferences.set(subset[key], true);
}
const result =
object != null &&
hasPropertyInObject(object, key) &&
(0, _jasmineUtils.equals)(object[key], subset[key], [
iterableEquality,
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;
});
};
return subsetEqualityWithContext()(object, subset);
}; // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
exports.subsetEquality = subsetEquality;
const typeEquality = (a, b) => {
if (a == null || b == null || a.constructor === b.constructor) {
return undefined;
}
return false;
};
exports.typeEquality = typeEquality;
const arrayBufferEquality = (a, b) => {
if (!(a instanceof ArrayBuffer) || !(b instanceof ArrayBuffer)) {
return undefined;
}
const dataViewA = new DataView(a);
const dataViewB = new DataView(b); // 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;
const sparseArrayEquality = (a, b) => {
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, [iterableEquality, typeEquality], true) &&
(0, _jasmineUtils.equals)(aKeys, bKeys)
);
};
exports.sparseArrayEquality = sparseArrayEquality;
const partition = (items, predicate) => {
const result = [[], []];
items.forEach(item => 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 = RegExp('[^.[\\]]+|(?=(?:\\.)(?:\\.|$))', 'g'); // Because the regex won't match a dot in the beginning of the path, if present.
if (propertyPath[0] === '.') {
properties.push('');
}
propertyPath.replace(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 : false;
}
const MULTILINE_REGEXP = /[\r\n]/;
const isOneline = (expected, received) =>
typeof expected === 'string' &&
typeof received === 'string' &&
(!MULTILINE_REGEXP.test(expected) || !MULTILINE_REGEXP.test(received));
exports.isOneline = isOneline;

View File

@@ -0,0 +1,42 @@
{
"name": "expect",
"version": "27.5.1",
"repository": {
"type": "git",
"url": "https://github.com/facebook/jest.git",
"directory": "packages/expect"
},
"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",
"./build/utils": "./build/utils.js",
"./build/matchers": "./build/matchers.js"
},
"dependencies": {
"@jest/types": "^27.5.1",
"jest-get-type": "^27.5.1",
"jest-matcher-utils": "^27.5.1",
"jest-message-util": "^27.5.1"
},
"devDependencies": {
"@jest/test-utils": "^27.5.1",
"@tsd/typescript": "~4.1.5",
"chalk": "^4.0.0",
"fast-check": "^2.0.0",
"immutable": "^4.0.0",
"tsd-lite": "^0.5.1"
},
"engines": {
"node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0"
},
"publishConfig": {
"access": "public"
},
"gitHead": "67c1aa20c5fec31366d733e901fee2b981cb1850"
}

View File

@@ -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.

View File

@@ -0,0 +1,671 @@
# jest-diff
Display differences clearly so people can review changes confidently.
The `diff` named export serializes JavaScript **values**, compares them line-by-line, and returns a string which includes comparison lines.
Two named exports compare **strings** character-by-character:
- `diffStringsUnified` returns a string.
- `diffStringsRaw` returns an array of `Diff` objects.
Three named exports compare **arrays of strings** line-by-line:
- `diffLinesUnified` and `diffLinesUnified2` return a string.
- `diffLinesRaw` returns an array of `Diff` objects.
## Installation
To add this package as a dependency of a project, run either of the following commands:
- `npm install jest-diff`
- `yarn add jest-diff`
## Usage of `diff()`
Given JavaScript **values**, `diff(a, b, options?)` does the following:
1. **serialize** the values as strings using the `pretty-format` package
2. **compare** the strings line-by-line using the `diff-sequences` package
3. **format** the changed or common lines using the `chalk` package
To use this function, write either of the following:
- `const {diff} = require('jest-diff');` in CommonJS modules
- `import {diff} from 'jest-diff';` in ECMAScript modules
### Example of `diff()`
```js
const a = ['delete', 'common', 'changed from'];
const b = ['common', 'changed to', 'insert'];
const difference = diff(a, b);
```
The returned **string** consists of:
- annotation lines: describe the two change indicators with labels, and a blank line
- comparison lines: similar to “unified” view on GitHub, but `Expected` lines are green, `Received` lines are red, and common lines are dim (by default, see Options)
```diff
- Expected
+ Received
Array [
- "delete",
"common",
- "changed from",
+ "changed to",
+ "insert",
]
```
### Edge cases of `diff()`
Here are edge cases for the return value:
- `' Comparing two different types of values. …'` if the arguments have **different types** according to the `jest-get-type` package (instances of different classes have the same `'object'` type)
- `'Compared values have no visual difference.'` if the arguments have either **referential identity** according to `Object.is` method or **same serialization** according to the `pretty-format` package
- `null` if either argument is a so-called **asymmetric matcher** in Jasmine or Jest
## Usage of diffStringsUnified
Given **strings**, `diffStringsUnified(a, b, options?)` does the following:
1. **compare** the strings character-by-character using the `diff-sequences` package
2. **clean up** small (often coincidental) common substrings, also known as chaff
3. **format** the changed or common lines using the `chalk` package
Although the function is mainly for **multiline** strings, it compares any strings.
Write either of the following:
- `const {diffStringsUnified} = require('jest-diff');` in CommonJS modules
- `import {diffStringsUnified} from 'jest-diff';` in ECMAScript modules
### Example of diffStringsUnified
```js
const a = 'common\nchanged from';
const b = 'common\nchanged to';
const difference = diffStringsUnified(a, b);
```
The returned **string** consists of:
- annotation lines: describe the two change indicators with labels, and a blank line
- comparison lines: similar to “unified” view on GitHub, and **changed substrings** have **inverse** foreground and background colors (that is, `from` has white-on-green and `to` has white-on-red, which the following example does not show)
```diff
- Expected
+ Received
common
- changed from
+ changed to
```
### Performance of diffStringsUnified
To get the benefit of **changed substrings** within the comparison lines, a character-by-character comparison has a higher computational cost (in time and space) than a line-by-line comparison.
If the input strings can have **arbitrary length**, we recommend that the calling code set a limit, beyond which splits the strings, and then calls `diffLinesUnified` instead. For example, Jest falls back to line-by-line comparison if either string has length greater than 20K characters.
## Usage of diffLinesUnified
Given **arrays of strings**, `diffLinesUnified(aLines, bLines, options?)` does the following:
1. **compare** the arrays line-by-line using the `diff-sequences` package
2. **format** the changed or common lines using the `chalk` package
You might call this function when strings have been split into lines and you do not need to see changed substrings within lines.
### Example of diffLinesUnified
```js
const aLines = ['delete', 'common', 'changed from'];
const bLines = ['common', 'changed to', 'insert'];
const difference = diffLinesUnified(aLines, bLines);
```
```diff
- Expected
+ Received
- delete
common
- changed from
+ changed to
+ insert
```
### Edge cases of diffLinesUnified or diffStringsUnified
Here are edge cases for arguments and return values:
- both `a` and `b` are empty strings: no comparison lines
- only `a` is empty string: all comparison lines have `bColor` and `bIndicator` (see Options)
- only `b` is empty string: all comparison lines have `aColor` and `aIndicator` (see Options)
- `a` and `b` are equal non-empty strings: all comparison lines have `commonColor` and `commonIndicator` (see Options)
## Usage of diffLinesUnified2
Given two **pairs** of arrays of strings, `diffLinesUnified2(aLinesDisplay, bLinesDisplay, aLinesCompare, bLinesCompare, options?)` does the following:
1. **compare** the pair of `Compare` arrays line-by-line using the `diff-sequences` package
2. **format** the corresponding lines in the pair of `Display` arrays using the `chalk` package
Jest calls this function to consider lines as common instead of changed if the only difference is indentation.
You might call this function for case insensitive or Unicode equivalence comparison of lines.
### Example of diffLinesUnified2
```js
import {format} from 'pretty-format';
const a = {
text: 'Ignore indentation in serialized object',
time: '2019-09-19T12:34:56.000Z',
type: 'CREATE_ITEM',
};
const b = {
payload: {
text: 'Ignore indentation in serialized object',
time: '2019-09-19T12:34:56.000Z',
},
type: 'CREATE_ITEM',
};
const difference = diffLinesUnified2(
// serialize with indentation to display lines
format(a).split('\n'),
format(b).split('\n'),
// serialize without indentation to compare lines
format(a, {indent: 0}).split('\n'),
format(b, {indent: 0}).split('\n'),
);
```
The `text` and `time` properties are common, because their only difference is indentation:
```diff
- Expected
+ Received
Object {
+ payload: Object {
text: 'Ignore indentation in serialized object',
time: '2019-09-19T12:34:56.000Z',
+ },
type: 'CREATE_ITEM',
}
```
The preceding example illustrates why (at least for indentation) it seems more intuitive that the function returns the common line from the `bLinesDisplay` array instead of from the `aLinesDisplay` array.
## Usage of diffStringsRaw
Given **strings** and a boolean option, `diffStringsRaw(a, b, cleanup)` does the following:
1. **compare** the strings character-by-character using the `diff-sequences` package
2. optionally **clean up** small (often coincidental) common substrings, also known as chaff
Because `diffStringsRaw` returns the difference as **data** instead of a string, you can format it as your application requires (for example, enclosed in HTML markup for browser instead of escape sequences for console).
The returned **array** describes substrings as instances of the `Diff` class, which calling code can access like array tuples:
The value at index `0` is one of the following:
| value | named export | description |
| ----: | :------------ | :-------------------- |
| `0` | `DIFF_EQUAL` | in `a` and in `b` |
| `-1` | `DIFF_DELETE` | in `a` but not in `b` |
| `1` | `DIFF_INSERT` | in `b` but not in `a` |
The value at index `1` is a substring of `a` or `b` or both.
### Example of diffStringsRaw with cleanup
```js
const diffs = diffStringsRaw('changed from', 'changed to', true);
```
| `i` | `diffs[i][0]` | `diffs[i][1]` |
| --: | ------------: | :------------ |
| `0` | `0` | `'changed '` |
| `1` | `-1` | `'from'` |
| `2` | `1` | `'to'` |
### Example of diffStringsRaw without cleanup
```js
const diffs = diffStringsRaw('changed from', 'changed to', false);
```
| `i` | `diffs[i][0]` | `diffs[i][1]` |
| --: | ------------: | :------------ |
| `0` | `0` | `'changed '` |
| `1` | `-1` | `'fr'` |
| `2` | `1` | `'t'` |
| `3` | `0` | `'o'` |
| `4` | `-1` | `'m'` |
### Advanced import for diffStringsRaw
Here are all the named imports that you might need for the `diffStringsRaw` function:
- `const {DIFF_DELETE, DIFF_EQUAL, DIFF_INSERT, Diff, diffStringsRaw} = require('jest-diff');` in CommonJS modules
- `import {DIFF_DELETE, DIFF_EQUAL, DIFF_INSERT, Diff, diffStringsRaw} from 'jest-diff';` in ECMAScript modules
To write a **formatting** function, you might need the named constants (and `Diff` in TypeScript annotations).
If you write an application-specific **cleanup** algorithm, then you might need to call the `Diff` constructor:
```js
const diffCommon = new Diff(DIFF_EQUAL, 'changed ');
const diffDelete = new Diff(DIFF_DELETE, 'from');
const diffInsert = new Diff(DIFF_INSERT, 'to');
```
## Usage of diffLinesRaw
Given **arrays of strings**, `diffLinesRaw(aLines, bLines)` does the following:
- **compare** the arrays line-by-line using the `diff-sequences` package
Because `diffLinesRaw` returns the difference as **data** instead of a string, you can format it as your application requires.
### Example of diffLinesRaw
```js
const aLines = ['delete', 'common', 'changed from'];
const bLines = ['common', 'changed to', 'insert'];
const diffs = diffLinesRaw(aLines, bLines);
```
| `i` | `diffs[i][0]` | `diffs[i][1]` |
| --: | ------------: | :--------------- |
| `0` | `-1` | `'delete'` |
| `1` | `0` | `'common'` |
| `2` | `-1` | `'changed from'` |
| `3` | `1` | `'changed to'` |
| `4` | `1` | `'insert'` |
### Edge case of diffLinesRaw
If you call `string.split('\n')` for an empty string:
- the result is `['']` an array which contains an empty string
- instead of `[]` an empty array
Depending of your application, you might call `diffLinesRaw` with either array.
### Example of split method
```js
import {diffLinesRaw} from 'jest-diff';
const a = 'non-empty string';
const b = '';
const diffs = diffLinesRaw(a.split('\n'), b.split('\n'));
```
| `i` | `diffs[i][0]` | `diffs[i][1]` |
| --: | ------------: | :------------------- |
| `0` | `-1` | `'non-empty string'` |
| `1` | `1` | `''` |
Which you might format as follows:
```diff
- Expected - 1
+ Received + 1
- non-empty string
+
```
### Example of splitLines0 function
For edge case behavior like the `diffLinesUnified` function, you might define a `splitLines0` function, which given an empty string, returns `[]` an empty array:
```js
export const splitLines0 = string =>
string.length === 0 ? [] : string.split('\n');
```
```js
import {diffLinesRaw} from 'jest-diff';
const a = '';
const b = 'line 1\nline 2\nline 3';
const diffs = diffLinesRaw(a.split('\n'), b.split('\n'));
```
| `i` | `diffs[i][0]` | `diffs[i][1]` |
| --: | ------------: | :------------ |
| `0` | `1` | `'line 1'` |
| `1` | `1` | `'line 2'` |
| `2` | `1` | `'line 3'` |
Which you might format as follows:
```diff
- Expected - 0
+ Received + 3
+ line 1
+ line 2
+ line 3
```
In contrast to the `diffLinesRaw` function, the `diffLinesUnified` and `diffLinesUnified2` functions **automatically** convert array arguments computed by string `split` method, so callers do **not** need a `splitLine0` function.
## Options
The default options are for the report when an assertion fails from the `expect` package used by Jest.
For other applications, you can provide an options object as a third argument:
- `diff(a, b, options)`
- `diffStringsUnified(a, b, options)`
- `diffLinesUnified(aLines, bLines, options)`
- `diffLinesUnified2(aLinesDisplay, bLinesDisplay, aLinesCompare, bLinesCompare, options)`
### Properties of options object
| name | default |
| :-------------------------------- | :----------------- |
| `aAnnotation` | `'Expected'` |
| `aColor` | `chalk.green` |
| `aIndicator` | `'-'` |
| `bAnnotation` | `'Received'` |
| `bColor` | `chalk.red` |
| `bIndicator` | `'+'` |
| `changeColor` | `chalk.inverse` |
| `changeLineTrailingSpaceColor` | `string => string` |
| `commonColor` | `chalk.dim` |
| `commonIndicator` | `' '` |
| `commonLineTrailingSpaceColor` | `string => string` |
| `compareKeys` | `undefined` |
| `contextLines` | `5` |
| `emptyFirstOrLastLinePlaceholder` | `''` |
| `expand` | `true` |
| `includeChangeCounts` | `false` |
| `omitAnnotationLines` | `false` |
| `patchColor` | `chalk.yellow` |
For more information about the options, see the following examples.
### Example of options for labels
If the application is code modification, you might replace the labels:
```js
const options = {
aAnnotation: 'Original',
bAnnotation: 'Modified',
};
```
```diff
- Original
+ Modified
common
- changed from
+ changed to
```
The `jest-diff` package does not assume that the 2 labels have equal length.
### Example of options for colors of changed lines
For consistency with most diff tools, you might exchange the colors:
```ts
import chalk = require('chalk');
const options = {
aColor: chalk.red,
bColor: chalk.green,
};
```
### Example of option for color of changed substrings
Although the default inverse of foreground and background colors is hard to beat for changed substrings **within lines**, especially because it highlights spaces, if you want bold font weight on yellow background color:
```ts
import chalk = require('chalk');
const options = {
changeColor: chalk.bold.bgYellowBright,
};
```
### Example of option to format trailing spaces
Because `diff()` does not display substring differences within lines, formatting can help you see when lines differ by the presence or absence of trailing spaces found by `/\s+$/` regular expression.
- If change lines have a background color, then you can see trailing spaces.
- If common lines have default dim color, then you cannot see trailing spaces. You might want yellowish background color to see them.
```js
const options = {
aColor: chalk.rgb(128, 0, 128).bgRgb(255, 215, 255), // magenta
bColor: chalk.rgb(0, 95, 0).bgRgb(215, 255, 215), // green
commonLineTrailingSpaceColor: chalk.bgYellow,
};
```
The value of a Color option is a function, which given a string, returns a string.
If you want to replace trailing spaces with middle dot characters:
```js
const replaceSpacesWithMiddleDot = string => '·'.repeat(string.length);
const options = {
changeLineTrailingSpaceColor: replaceSpacesWithMiddleDot,
commonLineTrailingSpaceColor: replaceSpacesWithMiddleDot,
};
```
If you need the TypeScript type of a Color option:
```ts
import {DiffOptionsColor} from 'jest-diff';
```
### Example of options for no colors
To store the difference in a file without escape codes for colors, provide an identity function:
```js
const noColor = string => string;
const options = {
aColor: noColor,
bColor: noColor,
changeColor: noColor,
commonColor: noColor,
patchColor: noColor,
};
```
### Example of options for indicators
For consistency with the `diff` command, you might replace the indicators:
```js
const options = {
aIndicator: '<',
bIndicator: '>',
};
```
The `jest-diff` package assumes (but does not enforce) that the 3 indicators have equal length.
### Example of options to limit common lines
By default, the output includes all common lines.
To emphasize the changes, you might limit the number of common “context” lines:
```js
const options = {
contextLines: 1,
expand: false,
};
```
A patch mark like `@@ -12,7 +12,9 @@` accounts for omitted common lines.
### Example of option for color of patch marks
If you want patch marks to have the same dim color as common lines:
```ts
import chalk = require('chalk');
const options = {
expand: false,
patchColor: chalk.dim,
};
```
### Example of option to include change counts
To display the number of changed lines at the right of annotation lines:
```js
const a = ['common', 'changed from'];
const b = ['common', 'changed to', 'insert'];
const options = {
includeChangeCounts: true,
};
const difference = diff(a, b, options);
```
```diff
- Expected - 1
+ Received + 2
Array [
"common",
- "changed from",
+ "changed to",
+ "insert",
]
```
### Example of option to omit annotation lines
To display only the comparison lines:
```js
const a = 'common\nchanged from';
const b = 'common\nchanged to';
const options = {
omitAnnotationLines: true,
};
const difference = diffStringsUnified(a, b, options);
```
```diff
common
- changed from
+ changed to
```
### Example of option for empty first or last lines
If the **first** or **last** comparison line is **empty**, because the content is empty and the indicator is a space, you might not notice it.
The replacement option is a string whose default value is `''` empty string.
Because Jest trims the report when a matcher fails, it deletes an empty last line.
Therefore, Jest uses as placeholder the downwards arrow with corner leftwards:
```js
const options = {
emptyFirstOrLastLinePlaceholder: '↵', // U+21B5
};
```
If a content line is empty, then the corresponding comparison line is automatically trimmed to remove the margin space (represented as a middle dot below) for the default indicators:
| Indicator | untrimmed | trimmed |
| ----------------: | :-------- | :------ |
| `aIndicator` | `'-·'` | `'-'` |
| `bIndicator` | `'+·'` | `'+'` |
| `commonIndicator` | `' ·'` | `''` |
### Example of option for sorting object keys
When two objects are compared their keys are printed in alphabetical order by default. If this was not the original order of the keys the diff becomes harder to read as the keys are not in their original position.
Use `compareKeys` to pass a function which will be used when sorting the object keys.
```js
const a = {c: 'c', b: 'b1', a: 'a'};
const b = {c: 'c', b: 'b2', a: 'a'};
const options = {
// The keys will be in their original order
compareKeys: () => 0,
};
const difference = diff(a, b, options);
```
```diff
- Expected
+ Received
Object {
"c": "c",
- "b": "b1",
+ "b": "b2",
"a": "a",
}
```
Depending on the implementation of `compareKeys` any sort order can be used.
```js
const a = {c: 'c', b: 'b1', a: 'a'};
const b = {c: 'c', b: 'b2', a: 'a'};
const options = {
// The keys will be in reverse order
compareKeys: (a, b) => (a > b ? -1 : 1),
};
const difference = diff(a, b, options);
```
```diff
- Expected
+ Received
Object {
"a": "a",
- "b": "b1",
+ "b": "b2",
"c": "c",
}
```

View File

@@ -0,0 +1,57 @@
/**
* Diff Match and Patch
* Copyright 2018 The diff-match-patch Authors.
* https://github.com/google/diff-match-patch
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @fileoverview Computes the difference between two texts to create a patch.
* Applies the patch onto another text, allowing for errors.
* @author fraser@google.com (Neil Fraser)
*/
/**
* CHANGES by pedrottimark to diff_match_patch_uncompressed.ts file:
*
* 1. Delete anything not needed to use diff_cleanupSemantic method
* 2. Convert from prototype properties to var declarations
* 3. Convert Diff to class from constructor and prototype
* 4. Add type annotations for arguments and return values
* 5. Add exports
*/
/**
* The data structure representing a diff is an array of tuples:
* [[DIFF_DELETE, 'Hello'], [DIFF_INSERT, 'Goodbye'], [DIFF_EQUAL, ' world.']]
* which means: delete 'Hello', add 'Goodbye' and keep ' world.'
*/
declare var DIFF_DELETE: number;
declare var DIFF_INSERT: number;
declare var DIFF_EQUAL: number;
/**
* Class representing one diff tuple.
* Attempts to look like a two-element array (which is what this used to be).
* @param {number} op Operation, one of: DIFF_DELETE, DIFF_INSERT, DIFF_EQUAL.
* @param {string} text Text to be deleted, inserted, or retained.
* @constructor
*/
declare class Diff {
0: number;
1: string;
constructor(op: number, text: string);
}
/**
* Reduce the number of edits by eliminating semantically trivial equalities.
* @param {!Array.<!diff_match_patch.Diff>} diffs Array of diff tuples.
*/
declare var diff_cleanupSemantic: (diffs: Array<Diff>) => void;
export { Diff, DIFF_EQUAL, DIFF_DELETE, DIFF_INSERT, diff_cleanupSemantic as cleanupSemantic, };

View File

@@ -0,0 +1,655 @@
'use strict';
Object.defineProperty(exports, '__esModule', {
value: true
});
exports.cleanupSemantic =
exports.Diff =
exports.DIFF_INSERT =
exports.DIFF_EQUAL =
exports.DIFF_DELETE =
void 0;
function _defineProperty(obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
}
/**
* Diff Match and Patch
* Copyright 2018 The diff-match-patch Authors.
* https://github.com/google/diff-match-patch
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @fileoverview Computes the difference between two texts to create a patch.
* Applies the patch onto another text, allowing for errors.
* @author fraser@google.com (Neil Fraser)
*/
/**
* CHANGES by pedrottimark to diff_match_patch_uncompressed.ts file:
*
* 1. Delete anything not needed to use diff_cleanupSemantic method
* 2. Convert from prototype properties to var declarations
* 3. Convert Diff to class from constructor and prototype
* 4. Add type annotations for arguments and return values
* 5. Add exports
*/
/**
* The data structure representing a diff is an array of tuples:
* [[DIFF_DELETE, 'Hello'], [DIFF_INSERT, 'Goodbye'], [DIFF_EQUAL, ' world.']]
* which means: delete 'Hello', add 'Goodbye' and keep ' world.'
*/
var DIFF_DELETE = -1;
exports.DIFF_DELETE = DIFF_DELETE;
var DIFF_INSERT = 1;
exports.DIFF_INSERT = DIFF_INSERT;
var DIFF_EQUAL = 0;
/**
* Class representing one diff tuple.
* Attempts to look like a two-element array (which is what this used to be).
* @param {number} op Operation, one of: DIFF_DELETE, DIFF_INSERT, DIFF_EQUAL.
* @param {string} text Text to be deleted, inserted, or retained.
* @constructor
*/
exports.DIFF_EQUAL = DIFF_EQUAL;
class Diff {
constructor(op, text) {
_defineProperty(this, 0, void 0);
_defineProperty(this, 1, void 0);
this[0] = op;
this[1] = text;
}
}
/**
* Determine the common prefix of two strings.
* @param {string} text1 First string.
* @param {string} text2 Second string.
* @return {number} The number of characters common to the start of each
* string.
*/
exports.Diff = Diff;
var diff_commonPrefix = function (text1, text2) {
// Quick check for common null cases.
if (!text1 || !text2 || text1.charAt(0) != text2.charAt(0)) {
return 0;
} // Binary search.
// Performance analysis: https://neil.fraser.name/news/2007/10/09/
var pointermin = 0;
var pointermax = Math.min(text1.length, text2.length);
var pointermid = pointermax;
var pointerstart = 0;
while (pointermin < pointermid) {
if (
text1.substring(pointerstart, pointermid) ==
text2.substring(pointerstart, pointermid)
) {
pointermin = pointermid;
pointerstart = pointermin;
} else {
pointermax = pointermid;
}
pointermid = Math.floor((pointermax - pointermin) / 2 + pointermin);
}
return pointermid;
};
/**
* Determine the common suffix of two strings.
* @param {string} text1 First string.
* @param {string} text2 Second string.
* @return {number} The number of characters common to the end of each string.
*/
var diff_commonSuffix = function (text1, text2) {
// Quick check for common null cases.
if (
!text1 ||
!text2 ||
text1.charAt(text1.length - 1) != text2.charAt(text2.length - 1)
) {
return 0;
} // Binary search.
// Performance analysis: https://neil.fraser.name/news/2007/10/09/
var pointermin = 0;
var pointermax = Math.min(text1.length, text2.length);
var pointermid = pointermax;
var pointerend = 0;
while (pointermin < pointermid) {
if (
text1.substring(text1.length - pointermid, text1.length - pointerend) ==
text2.substring(text2.length - pointermid, text2.length - pointerend)
) {
pointermin = pointermid;
pointerend = pointermin;
} else {
pointermax = pointermid;
}
pointermid = Math.floor((pointermax - pointermin) / 2 + pointermin);
}
return pointermid;
};
/**
* Determine if the suffix of one string is the prefix of another.
* @param {string} text1 First string.
* @param {string} text2 Second string.
* @return {number} The number of characters common to the end of the first
* string and the start of the second string.
* @private
*/
var diff_commonOverlap_ = function (text1, text2) {
// Cache the text lengths to prevent multiple calls.
var text1_length = text1.length;
var text2_length = text2.length; // Eliminate the null case.
if (text1_length == 0 || text2_length == 0) {
return 0;
} // Truncate the longer string.
if (text1_length > text2_length) {
text1 = text1.substring(text1_length - text2_length);
} else if (text1_length < text2_length) {
text2 = text2.substring(0, text1_length);
}
var text_length = Math.min(text1_length, text2_length); // Quick check for the worst case.
if (text1 == text2) {
return text_length;
} // Start by looking for a single character match
// and increase length until no match is found.
// Performance analysis: https://neil.fraser.name/news/2010/11/04/
var best = 0;
var length = 1;
while (true) {
var pattern = text1.substring(text_length - length);
var found = text2.indexOf(pattern);
if (found == -1) {
return best;
}
length += found;
if (
found == 0 ||
text1.substring(text_length - length) == text2.substring(0, length)
) {
best = length;
length++;
}
}
};
/**
* Reduce the number of edits by eliminating semantically trivial equalities.
* @param {!Array.<!diff_match_patch.Diff>} diffs Array of diff tuples.
*/
var diff_cleanupSemantic = function (diffs) {
var changes = false;
var equalities = []; // Stack of indices where equalities are found.
var equalitiesLength = 0; // Keeping our own length var is faster in JS.
/** @type {?string} */
var lastEquality = null; // Always equal to diffs[equalities[equalitiesLength - 1]][1]
var pointer = 0; // Index of current position.
// Number of characters that changed prior to the equality.
var length_insertions1 = 0;
var length_deletions1 = 0; // Number of characters that changed after the equality.
var length_insertions2 = 0;
var length_deletions2 = 0;
while (pointer < diffs.length) {
if (diffs[pointer][0] == DIFF_EQUAL) {
// Equality found.
equalities[equalitiesLength++] = pointer;
length_insertions1 = length_insertions2;
length_deletions1 = length_deletions2;
length_insertions2 = 0;
length_deletions2 = 0;
lastEquality = diffs[pointer][1];
} else {
// An insertion or deletion.
if (diffs[pointer][0] == DIFF_INSERT) {
length_insertions2 += diffs[pointer][1].length;
} else {
length_deletions2 += diffs[pointer][1].length;
} // Eliminate an equality that is smaller or equal to the edits on both
// sides of it.
if (
lastEquality &&
lastEquality.length <=
Math.max(length_insertions1, length_deletions1) &&
lastEquality.length <= Math.max(length_insertions2, length_deletions2)
) {
// Duplicate record.
diffs.splice(
equalities[equalitiesLength - 1],
0,
new Diff(DIFF_DELETE, lastEquality)
); // Change second copy to insert.
diffs[equalities[equalitiesLength - 1] + 1][0] = DIFF_INSERT; // Throw away the equality we just deleted.
equalitiesLength--; // Throw away the previous equality (it needs to be reevaluated).
equalitiesLength--;
pointer = equalitiesLength > 0 ? equalities[equalitiesLength - 1] : -1;
length_insertions1 = 0; // Reset the counters.
length_deletions1 = 0;
length_insertions2 = 0;
length_deletions2 = 0;
lastEquality = null;
changes = true;
}
}
pointer++;
} // Normalize the diff.
if (changes) {
diff_cleanupMerge(diffs);
}
diff_cleanupSemanticLossless(diffs); // Find any overlaps between deletions and insertions.
// e.g: <del>abcxxx</del><ins>xxxdef</ins>
// -> <del>abc</del>xxx<ins>def</ins>
// e.g: <del>xxxabc</del><ins>defxxx</ins>
// -> <ins>def</ins>xxx<del>abc</del>
// Only extract an overlap if it is as big as the edit ahead or behind it.
pointer = 1;
while (pointer < diffs.length) {
if (
diffs[pointer - 1][0] == DIFF_DELETE &&
diffs[pointer][0] == DIFF_INSERT
) {
var deletion = diffs[pointer - 1][1];
var insertion = diffs[pointer][1];
var overlap_length1 = diff_commonOverlap_(deletion, insertion);
var overlap_length2 = diff_commonOverlap_(insertion, deletion);
if (overlap_length1 >= overlap_length2) {
if (
overlap_length1 >= deletion.length / 2 ||
overlap_length1 >= insertion.length / 2
) {
// Overlap found. Insert an equality and trim the surrounding edits.
diffs.splice(
pointer,
0,
new Diff(DIFF_EQUAL, insertion.substring(0, overlap_length1))
);
diffs[pointer - 1][1] = deletion.substring(
0,
deletion.length - overlap_length1
);
diffs[pointer + 1][1] = insertion.substring(overlap_length1);
pointer++;
}
} else {
if (
overlap_length2 >= deletion.length / 2 ||
overlap_length2 >= insertion.length / 2
) {
// Reverse overlap found.
// Insert an equality and swap and trim the surrounding edits.
diffs.splice(
pointer,
0,
new Diff(DIFF_EQUAL, deletion.substring(0, overlap_length2))
);
diffs[pointer - 1][0] = DIFF_INSERT;
diffs[pointer - 1][1] = insertion.substring(
0,
insertion.length - overlap_length2
);
diffs[pointer + 1][0] = DIFF_DELETE;
diffs[pointer + 1][1] = deletion.substring(overlap_length2);
pointer++;
}
}
pointer++;
}
pointer++;
}
};
/**
* Look for single edits surrounded on both sides by equalities
* which can be shifted sideways to align the edit to a word boundary.
* e.g: The c<ins>at c</ins>ame. -> The <ins>cat </ins>came.
* @param {!Array.<!diff_match_patch.Diff>} diffs Array of diff tuples.
*/
exports.cleanupSemantic = diff_cleanupSemantic;
var diff_cleanupSemanticLossless = function (diffs) {
/**
* Given two strings, compute a score representing whether the internal
* boundary falls on logical boundaries.
* Scores range from 6 (best) to 0 (worst).
* Closure, but does not reference any external variables.
* @param {string} one First string.
* @param {string} two Second string.
* @return {number} The score.
* @private
*/
function diff_cleanupSemanticScore_(one, two) {
if (!one || !two) {
// Edges are the best.
return 6;
} // Each port of this function behaves slightly differently due to
// subtle differences in each language's definition of things like
// 'whitespace'. Since this function's purpose is largely cosmetic,
// the choice has been made to use each language's native features
// rather than force total conformity.
var char1 = one.charAt(one.length - 1);
var char2 = two.charAt(0);
var nonAlphaNumeric1 = char1.match(nonAlphaNumericRegex_);
var nonAlphaNumeric2 = char2.match(nonAlphaNumericRegex_);
var whitespace1 = nonAlphaNumeric1 && char1.match(whitespaceRegex_);
var whitespace2 = nonAlphaNumeric2 && char2.match(whitespaceRegex_);
var lineBreak1 = whitespace1 && char1.match(linebreakRegex_);
var lineBreak2 = whitespace2 && char2.match(linebreakRegex_);
var blankLine1 = lineBreak1 && one.match(blanklineEndRegex_);
var blankLine2 = lineBreak2 && two.match(blanklineStartRegex_);
if (blankLine1 || blankLine2) {
// Five points for blank lines.
return 5;
} else if (lineBreak1 || lineBreak2) {
// Four points for line breaks.
return 4;
} else if (nonAlphaNumeric1 && !whitespace1 && whitespace2) {
// Three points for end of sentences.
return 3;
} else if (whitespace1 || whitespace2) {
// Two points for whitespace.
return 2;
} else if (nonAlphaNumeric1 || nonAlphaNumeric2) {
// One point for non-alphanumeric.
return 1;
}
return 0;
}
var pointer = 1; // Intentionally ignore the first and last element (don't need checking).
while (pointer < diffs.length - 1) {
if (
diffs[pointer - 1][0] == DIFF_EQUAL &&
diffs[pointer + 1][0] == DIFF_EQUAL
) {
// This is a single edit surrounded by equalities.
var equality1 = diffs[pointer - 1][1];
var edit = diffs[pointer][1];
var equality2 = diffs[pointer + 1][1]; // First, shift the edit as far left as possible.
var commonOffset = diff_commonSuffix(equality1, edit);
if (commonOffset) {
var commonString = edit.substring(edit.length - commonOffset);
equality1 = equality1.substring(0, equality1.length - commonOffset);
edit = commonString + edit.substring(0, edit.length - commonOffset);
equality2 = commonString + equality2;
} // Second, step character by character right, looking for the best fit.
var bestEquality1 = equality1;
var bestEdit = edit;
var bestEquality2 = equality2;
var bestScore =
diff_cleanupSemanticScore_(equality1, edit) +
diff_cleanupSemanticScore_(edit, equality2);
while (edit.charAt(0) === equality2.charAt(0)) {
equality1 += edit.charAt(0);
edit = edit.substring(1) + equality2.charAt(0);
equality2 = equality2.substring(1);
var score =
diff_cleanupSemanticScore_(equality1, edit) +
diff_cleanupSemanticScore_(edit, equality2); // The >= encourages trailing rather than leading whitespace on edits.
if (score >= bestScore) {
bestScore = score;
bestEquality1 = equality1;
bestEdit = edit;
bestEquality2 = equality2;
}
}
if (diffs[pointer - 1][1] != bestEquality1) {
// We have an improvement, save it back to the diff.
if (bestEquality1) {
diffs[pointer - 1][1] = bestEquality1;
} else {
diffs.splice(pointer - 1, 1);
pointer--;
}
diffs[pointer][1] = bestEdit;
if (bestEquality2) {
diffs[pointer + 1][1] = bestEquality2;
} else {
diffs.splice(pointer + 1, 1);
pointer--;
}
}
}
pointer++;
}
}; // Define some regex patterns for matching boundaries.
var nonAlphaNumericRegex_ = /[^a-zA-Z0-9]/;
var whitespaceRegex_ = /\s/;
var linebreakRegex_ = /[\r\n]/;
var blanklineEndRegex_ = /\n\r?\n$/;
var blanklineStartRegex_ = /^\r?\n\r?\n/;
/**
* Reorder and merge like edit sections. Merge equalities.
* Any edit section can move as long as it doesn't cross an equality.
* @param {!Array.<!diff_match_patch.Diff>} diffs Array of diff tuples.
*/
var diff_cleanupMerge = function (diffs) {
// Add a dummy entry at the end.
diffs.push(new Diff(DIFF_EQUAL, ''));
var pointer = 0;
var count_delete = 0;
var count_insert = 0;
var text_delete = '';
var text_insert = '';
var commonlength;
while (pointer < diffs.length) {
switch (diffs[pointer][0]) {
case DIFF_INSERT:
count_insert++;
text_insert += diffs[pointer][1];
pointer++;
break;
case DIFF_DELETE:
count_delete++;
text_delete += diffs[pointer][1];
pointer++;
break;
case DIFF_EQUAL:
// Upon reaching an equality, check for prior redundancies.
if (count_delete + count_insert > 1) {
if (count_delete !== 0 && count_insert !== 0) {
// Factor out any common prefixies.
commonlength = diff_commonPrefix(text_insert, text_delete);
if (commonlength !== 0) {
if (
pointer - count_delete - count_insert > 0 &&
diffs[pointer - count_delete - count_insert - 1][0] ==
DIFF_EQUAL
) {
diffs[pointer - count_delete - count_insert - 1][1] +=
text_insert.substring(0, commonlength);
} else {
diffs.splice(
0,
0,
new Diff(DIFF_EQUAL, text_insert.substring(0, commonlength))
);
pointer++;
}
text_insert = text_insert.substring(commonlength);
text_delete = text_delete.substring(commonlength);
} // Factor out any common suffixies.
commonlength = diff_commonSuffix(text_insert, text_delete);
if (commonlength !== 0) {
diffs[pointer][1] =
text_insert.substring(text_insert.length - commonlength) +
diffs[pointer][1];
text_insert = text_insert.substring(
0,
text_insert.length - commonlength
);
text_delete = text_delete.substring(
0,
text_delete.length - commonlength
);
}
} // Delete the offending records and add the merged ones.
pointer -= count_delete + count_insert;
diffs.splice(pointer, count_delete + count_insert);
if (text_delete.length) {
diffs.splice(pointer, 0, new Diff(DIFF_DELETE, text_delete));
pointer++;
}
if (text_insert.length) {
diffs.splice(pointer, 0, new Diff(DIFF_INSERT, text_insert));
pointer++;
}
pointer++;
} else if (pointer !== 0 && diffs[pointer - 1][0] == DIFF_EQUAL) {
// Merge this equality with the previous one.
diffs[pointer - 1][1] += diffs[pointer][1];
diffs.splice(pointer, 1);
} else {
pointer++;
}
count_insert = 0;
count_delete = 0;
text_delete = '';
text_insert = '';
break;
}
}
if (diffs[diffs.length - 1][1] === '') {
diffs.pop(); // Remove the dummy entry at the end.
} // Second pass: look for single edits surrounded on both sides by equalities
// which can be shifted sideways to eliminate an equality.
// e.g: A<ins>BA</ins>C -> <ins>AB</ins>AC
var changes = false;
pointer = 1; // Intentionally ignore the first and last element (don't need checking).
while (pointer < diffs.length - 1) {
if (
diffs[pointer - 1][0] == DIFF_EQUAL &&
diffs[pointer + 1][0] == DIFF_EQUAL
) {
// This is a single edit surrounded by equalities.
if (
diffs[pointer][1].substring(
diffs[pointer][1].length - diffs[pointer - 1][1].length
) == diffs[pointer - 1][1]
) {
// Shift the edit over the previous equality.
diffs[pointer][1] =
diffs[pointer - 1][1] +
diffs[pointer][1].substring(
0,
diffs[pointer][1].length - diffs[pointer - 1][1].length
);
diffs[pointer + 1][1] = diffs[pointer - 1][1] + diffs[pointer + 1][1];
diffs.splice(pointer - 1, 1);
changes = true;
} else if (
diffs[pointer][1].substring(0, diffs[pointer + 1][1].length) ==
diffs[pointer + 1][1]
) {
// Shift the edit over the next equality.
diffs[pointer - 1][1] += diffs[pointer + 1][1];
diffs[pointer][1] =
diffs[pointer][1].substring(diffs[pointer + 1][1].length) +
diffs[pointer + 1][1];
diffs.splice(pointer + 1, 1);
changes = true;
}
}
pointer++;
} // If shifts were made, the diff needs reordering and another shift sweep.
if (changes) {
diff_cleanupMerge(diffs);
}
};

View File

@@ -0,0 +1,8 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* 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 NO_DIFF_MESSAGE = "Compared values have no visual difference.";
export declare const SIMILAR_MESSAGE: string;

View File

@@ -0,0 +1,19 @@
'use strict';
Object.defineProperty(exports, '__esModule', {
value: true
});
exports.SIMILAR_MESSAGE = exports.NO_DIFF_MESSAGE = void 0;
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
const NO_DIFF_MESSAGE = 'Compared values have no visual difference.';
exports.NO_DIFF_MESSAGE = NO_DIFF_MESSAGE;
const SIMILAR_MESSAGE =
'Compared values serialize to the same structure.\n' +
'Printing internal object structure without calling `toJSON` instead.';
exports.SIMILAR_MESSAGE = SIMILAR_MESSAGE;

View File

@@ -0,0 +1,12 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import { Diff } from './cleanupSemantic';
import type { DiffOptions, DiffOptionsNormalized } from './types';
export declare const printDiffLines: (diffs: Array<Diff>, options: DiffOptionsNormalized) => string;
export declare const diffLinesUnified: (aLines: Array<string>, bLines: Array<string>, options?: DiffOptions | undefined) => string;
export declare const diffLinesUnified2: (aLinesDisplay: Array<string>, bLinesDisplay: Array<string>, aLinesCompare: Array<string>, bLinesCompare: Array<string>, options?: DiffOptions | undefined) => string;
export declare const diffLinesRaw: (aLines: Array<string>, bLines: Array<string>) => Array<Diff>;

View File

@@ -0,0 +1,220 @@
'use strict';
Object.defineProperty(exports, '__esModule', {
value: true
});
exports.printDiffLines =
exports.diffLinesUnified2 =
exports.diffLinesUnified =
exports.diffLinesRaw =
void 0;
var _diffSequences = _interopRequireDefault(require('diff-sequences'));
var _cleanupSemantic = require('./cleanupSemantic');
var _joinAlignedDiffs = require('./joinAlignedDiffs');
var _normalizeDiffOptions = require('./normalizeDiffOptions');
function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : {default: obj};
}
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
const isEmptyString = lines => lines.length === 1 && lines[0].length === 0;
const countChanges = diffs => {
let a = 0;
let b = 0;
diffs.forEach(diff => {
switch (diff[0]) {
case _cleanupSemantic.DIFF_DELETE:
a += 1;
break;
case _cleanupSemantic.DIFF_INSERT:
b += 1;
break;
}
});
return {
a,
b
};
};
const printAnnotation = (
{
aAnnotation,
aColor,
aIndicator,
bAnnotation,
bColor,
bIndicator,
includeChangeCounts,
omitAnnotationLines
},
changeCounts
) => {
if (omitAnnotationLines) {
return '';
}
let aRest = '';
let bRest = '';
if (includeChangeCounts) {
const aCount = String(changeCounts.a);
const bCount = String(changeCounts.b); // Padding right aligns the ends of the annotations.
const baAnnotationLengthDiff = bAnnotation.length - aAnnotation.length;
const aAnnotationPadding = ' '.repeat(Math.max(0, baAnnotationLengthDiff));
const bAnnotationPadding = ' '.repeat(Math.max(0, -baAnnotationLengthDiff)); // Padding left aligns the ends of the counts.
const baCountLengthDiff = bCount.length - aCount.length;
const aCountPadding = ' '.repeat(Math.max(0, baCountLengthDiff));
const bCountPadding = ' '.repeat(Math.max(0, -baCountLengthDiff));
aRest =
aAnnotationPadding + ' ' + aIndicator + ' ' + aCountPadding + aCount;
bRest =
bAnnotationPadding + ' ' + bIndicator + ' ' + bCountPadding + bCount;
}
return (
aColor(aIndicator + ' ' + aAnnotation + aRest) +
'\n' +
bColor(bIndicator + ' ' + bAnnotation + bRest) +
'\n\n'
);
};
const printDiffLines = (diffs, options) =>
printAnnotation(options, countChanges(diffs)) +
(options.expand
? (0, _joinAlignedDiffs.joinAlignedDiffsExpand)(diffs, options)
: (0, _joinAlignedDiffs.joinAlignedDiffsNoExpand)(diffs, options)); // Compare two arrays of strings line-by-line. Format as comparison lines.
exports.printDiffLines = printDiffLines;
const diffLinesUnified = (aLines, bLines, options) =>
printDiffLines(
diffLinesRaw(
isEmptyString(aLines) ? [] : aLines,
isEmptyString(bLines) ? [] : bLines
),
(0, _normalizeDiffOptions.normalizeDiffOptions)(options)
); // Given two pairs of arrays of strings:
// Compare the pair of comparison arrays line-by-line.
// Format the corresponding lines in the pair of displayable arrays.
exports.diffLinesUnified = diffLinesUnified;
const diffLinesUnified2 = (
aLinesDisplay,
bLinesDisplay,
aLinesCompare,
bLinesCompare,
options
) => {
if (isEmptyString(aLinesDisplay) && isEmptyString(aLinesCompare)) {
aLinesDisplay = [];
aLinesCompare = [];
}
if (isEmptyString(bLinesDisplay) && isEmptyString(bLinesCompare)) {
bLinesDisplay = [];
bLinesCompare = [];
}
if (
aLinesDisplay.length !== aLinesCompare.length ||
bLinesDisplay.length !== bLinesCompare.length
) {
// Fall back to diff of display lines.
return diffLinesUnified(aLinesDisplay, bLinesDisplay, options);
}
const diffs = diffLinesRaw(aLinesCompare, bLinesCompare); // Replace comparison lines with displayable lines.
let aIndex = 0;
let bIndex = 0;
diffs.forEach(diff => {
switch (diff[0]) {
case _cleanupSemantic.DIFF_DELETE:
diff[1] = aLinesDisplay[aIndex];
aIndex += 1;
break;
case _cleanupSemantic.DIFF_INSERT:
diff[1] = bLinesDisplay[bIndex];
bIndex += 1;
break;
default:
diff[1] = bLinesDisplay[bIndex];
aIndex += 1;
bIndex += 1;
}
});
return printDiffLines(
diffs,
(0, _normalizeDiffOptions.normalizeDiffOptions)(options)
);
}; // Compare two arrays of strings line-by-line.
exports.diffLinesUnified2 = diffLinesUnified2;
const diffLinesRaw = (aLines, bLines) => {
const aLength = aLines.length;
const bLength = bLines.length;
const isCommon = (aIndex, bIndex) => aLines[aIndex] === bLines[bIndex];
const diffs = [];
let aIndex = 0;
let bIndex = 0;
const foundSubsequence = (nCommon, aCommon, bCommon) => {
for (; aIndex !== aCommon; aIndex += 1) {
diffs.push(
new _cleanupSemantic.Diff(_cleanupSemantic.DIFF_DELETE, aLines[aIndex])
);
}
for (; bIndex !== bCommon; bIndex += 1) {
diffs.push(
new _cleanupSemantic.Diff(_cleanupSemantic.DIFF_INSERT, bLines[bIndex])
);
}
for (; nCommon !== 0; nCommon -= 1, aIndex += 1, bIndex += 1) {
diffs.push(
new _cleanupSemantic.Diff(_cleanupSemantic.DIFF_EQUAL, bLines[bIndex])
);
}
};
(0, _diffSequences.default)(aLength, bLength, isCommon, foundSubsequence); // After the last common subsequence, push remaining change items.
for (; aIndex !== aLength; aIndex += 1) {
diffs.push(
new _cleanupSemantic.Diff(_cleanupSemantic.DIFF_DELETE, aLines[aIndex])
);
}
for (; bIndex !== bLength; bIndex += 1) {
diffs.push(
new _cleanupSemantic.Diff(_cleanupSemantic.DIFF_INSERT, bLines[bIndex])
);
}
return diffs;
};
exports.diffLinesRaw = diffLinesRaw;

View File

@@ -0,0 +1,9 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import { Diff } from './cleanupSemantic';
declare const diffStrings: (a: string, b: string) => Array<Diff>;
export default diffStrings;

View File

@@ -0,0 +1,78 @@
'use strict';
Object.defineProperty(exports, '__esModule', {
value: true
});
exports.default = void 0;
var _diffSequences = _interopRequireDefault(require('diff-sequences'));
var _cleanupSemantic = require('./cleanupSemantic');
function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : {default: obj};
}
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
const diffStrings = (a, b) => {
const isCommon = (aIndex, bIndex) => a[aIndex] === b[bIndex];
let aIndex = 0;
let bIndex = 0;
const diffs = [];
const foundSubsequence = (nCommon, aCommon, bCommon) => {
if (aIndex !== aCommon) {
diffs.push(
new _cleanupSemantic.Diff(
_cleanupSemantic.DIFF_DELETE,
a.slice(aIndex, aCommon)
)
);
}
if (bIndex !== bCommon) {
diffs.push(
new _cleanupSemantic.Diff(
_cleanupSemantic.DIFF_INSERT,
b.slice(bIndex, bCommon)
)
);
}
aIndex = aCommon + nCommon; // number of characters compared in a
bIndex = bCommon + nCommon; // number of characters compared in b
diffs.push(
new _cleanupSemantic.Diff(
_cleanupSemantic.DIFF_EQUAL,
b.slice(bCommon, bIndex)
)
);
};
(0, _diffSequences.default)(a.length, b.length, isCommon, foundSubsequence); // After the last common subsequence, push remaining change items.
if (aIndex !== a.length) {
diffs.push(
new _cleanupSemantic.Diff(_cleanupSemantic.DIFF_DELETE, a.slice(aIndex))
);
}
if (bIndex !== b.length) {
diffs.push(
new _cleanupSemantic.Diff(_cleanupSemantic.DIFF_INSERT, b.slice(bIndex))
);
}
return diffs;
};
var _default = diffStrings;
exports.default = _default;

View File

@@ -0,0 +1,10 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import { Diff } from './cleanupSemantic';
import type { DiffOptionsColor } from './types';
declare const getAlignedDiffs: (diffs: Array<Diff>, changeColor: DiffOptionsColor) => Array<Diff>;
export default getAlignedDiffs;

View File

@@ -0,0 +1,244 @@
'use strict';
Object.defineProperty(exports, '__esModule', {
value: true
});
exports.default = void 0;
var _cleanupSemantic = require('./cleanupSemantic');
function _defineProperty(obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
}
// Given change op and array of diffs, return concatenated string:
// * include common strings
// * include change strings which have argument op with changeColor
// * exclude change strings which have opposite op
const concatenateRelevantDiffs = (op, diffs, changeColor) =>
diffs.reduce(
(reduced, diff) =>
reduced +
(diff[0] === _cleanupSemantic.DIFF_EQUAL
? diff[1]
: diff[0] === op && diff[1].length !== 0 // empty if change is newline
? changeColor(diff[1])
: ''),
''
); // Encapsulate change lines until either a common newline or the end.
class ChangeBuffer {
// incomplete line
// complete lines
constructor(op, changeColor) {
_defineProperty(this, 'op', void 0);
_defineProperty(this, 'line', void 0);
_defineProperty(this, 'lines', void 0);
_defineProperty(this, 'changeColor', void 0);
this.op = op;
this.line = [];
this.lines = [];
this.changeColor = changeColor;
}
pushSubstring(substring) {
this.pushDiff(new _cleanupSemantic.Diff(this.op, substring));
}
pushLine() {
// Assume call only if line has at least one diff,
// therefore an empty line must have a diff which has an empty string.
// If line has multiple diffs, then assume it has a common diff,
// therefore change diffs have change color;
// otherwise then it has line color only.
this.lines.push(
this.line.length !== 1
? new _cleanupSemantic.Diff(
this.op,
concatenateRelevantDiffs(this.op, this.line, this.changeColor)
)
: this.line[0][0] === this.op
? this.line[0] // can use instance
: new _cleanupSemantic.Diff(this.op, this.line[0][1]) // was common diff
);
this.line.length = 0;
}
isLineEmpty() {
return this.line.length === 0;
} // Minor input to buffer.
pushDiff(diff) {
this.line.push(diff);
} // Main input to buffer.
align(diff) {
const string = diff[1];
if (string.includes('\n')) {
const substrings = string.split('\n');
const iLast = substrings.length - 1;
substrings.forEach((substring, i) => {
if (i < iLast) {
// The first substring completes the current change line.
// A middle substring is a change line.
this.pushSubstring(substring);
this.pushLine();
} else if (substring.length !== 0) {
// The last substring starts a change line, if it is not empty.
// Important: This non-empty condition also automatically omits
// the newline appended to the end of expected and received strings.
this.pushSubstring(substring);
}
});
} else {
// Append non-multiline string to current change line.
this.pushDiff(diff);
}
} // Output from buffer.
moveLinesTo(lines) {
if (!this.isLineEmpty()) {
this.pushLine();
}
lines.push(...this.lines);
this.lines.length = 0;
}
} // Encapsulate common and change lines.
class CommonBuffer {
constructor(deleteBuffer, insertBuffer) {
_defineProperty(this, 'deleteBuffer', void 0);
_defineProperty(this, 'insertBuffer', void 0);
_defineProperty(this, 'lines', void 0);
this.deleteBuffer = deleteBuffer;
this.insertBuffer = insertBuffer;
this.lines = [];
}
pushDiffCommonLine(diff) {
this.lines.push(diff);
}
pushDiffChangeLines(diff) {
const isDiffEmpty = diff[1].length === 0; // An empty diff string is redundant, unless a change line is empty.
if (!isDiffEmpty || this.deleteBuffer.isLineEmpty()) {
this.deleteBuffer.pushDiff(diff);
}
if (!isDiffEmpty || this.insertBuffer.isLineEmpty()) {
this.insertBuffer.pushDiff(diff);
}
}
flushChangeLines() {
this.deleteBuffer.moveLinesTo(this.lines);
this.insertBuffer.moveLinesTo(this.lines);
} // Input to buffer.
align(diff) {
const op = diff[0];
const string = diff[1];
if (string.includes('\n')) {
const substrings = string.split('\n');
const iLast = substrings.length - 1;
substrings.forEach((substring, i) => {
if (i === 0) {
const subdiff = new _cleanupSemantic.Diff(op, substring);
if (
this.deleteBuffer.isLineEmpty() &&
this.insertBuffer.isLineEmpty()
) {
// If both current change lines are empty,
// then the first substring is a common line.
this.flushChangeLines();
this.pushDiffCommonLine(subdiff);
} else {
// If either current change line is non-empty,
// then the first substring completes the change lines.
this.pushDiffChangeLines(subdiff);
this.flushChangeLines();
}
} else if (i < iLast) {
// A middle substring is a common line.
this.pushDiffCommonLine(new _cleanupSemantic.Diff(op, substring));
} else if (substring.length !== 0) {
// The last substring starts a change line, if it is not empty.
// Important: This non-empty condition also automatically omits
// the newline appended to the end of expected and received strings.
this.pushDiffChangeLines(new _cleanupSemantic.Diff(op, substring));
}
});
} else {
// Append non-multiline string to current change lines.
// Important: It cannot be at the end following empty change lines,
// because newline appended to the end of expected and received strings.
this.pushDiffChangeLines(diff);
}
} // Output from buffer.
getLines() {
this.flushChangeLines();
return this.lines;
}
} // Given diffs from expected and received strings,
// return new array of diffs split or joined into lines.
//
// To correctly align a change line at the end, the algorithm:
// * assumes that a newline was appended to the strings
// * omits the last newline from the output array
//
// Assume the function is not called:
// * if either expected or received is empty string
// * if neither expected nor received is multiline string
const getAlignedDiffs = (diffs, changeColor) => {
const deleteBuffer = new ChangeBuffer(
_cleanupSemantic.DIFF_DELETE,
changeColor
);
const insertBuffer = new ChangeBuffer(
_cleanupSemantic.DIFF_INSERT,
changeColor
);
const commonBuffer = new CommonBuffer(deleteBuffer, insertBuffer);
diffs.forEach(diff => {
switch (diff[0]) {
case _cleanupSemantic.DIFF_DELETE:
deleteBuffer.align(diff);
break;
case _cleanupSemantic.DIFF_INSERT:
insertBuffer.align(diff);
break;
default:
commonBuffer.align(diff);
}
});
return commonBuffer.getLines();
};
var _default = getAlignedDiffs;
exports.default = _default;

View File

@@ -0,0 +1,15 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import { DIFF_DELETE, DIFF_EQUAL, DIFF_INSERT, Diff } from './cleanupSemantic';
import { diffLinesRaw, diffLinesUnified, diffLinesUnified2 } from './diffLines';
import { diffStringsRaw, diffStringsUnified } from './printDiffs';
import type { DiffOptions } from './types';
export type { DiffOptions, DiffOptionsColor } from './types';
export { diffLinesRaw, diffLinesUnified, diffLinesUnified2 };
export { diffStringsRaw, diffStringsUnified };
export { DIFF_DELETE, DIFF_EQUAL, DIFF_INSERT, Diff };
export declare function diff(a: any, b: any, options?: DiffOptions): string | null;

View File

@@ -0,0 +1,267 @@
'use strict';
Object.defineProperty(exports, '__esModule', {
value: true
});
Object.defineProperty(exports, 'DIFF_DELETE', {
enumerable: true,
get: function () {
return _cleanupSemantic.DIFF_DELETE;
}
});
Object.defineProperty(exports, 'DIFF_EQUAL', {
enumerable: true,
get: function () {
return _cleanupSemantic.DIFF_EQUAL;
}
});
Object.defineProperty(exports, 'DIFF_INSERT', {
enumerable: true,
get: function () {
return _cleanupSemantic.DIFF_INSERT;
}
});
Object.defineProperty(exports, 'Diff', {
enumerable: true,
get: function () {
return _cleanupSemantic.Diff;
}
});
exports.diff = diff;
Object.defineProperty(exports, 'diffLinesRaw', {
enumerable: true,
get: function () {
return _diffLines.diffLinesRaw;
}
});
Object.defineProperty(exports, 'diffLinesUnified', {
enumerable: true,
get: function () {
return _diffLines.diffLinesUnified;
}
});
Object.defineProperty(exports, 'diffLinesUnified2', {
enumerable: true,
get: function () {
return _diffLines.diffLinesUnified2;
}
});
Object.defineProperty(exports, 'diffStringsRaw', {
enumerable: true,
get: function () {
return _printDiffs.diffStringsRaw;
}
});
Object.defineProperty(exports, 'diffStringsUnified', {
enumerable: true,
get: function () {
return _printDiffs.diffStringsUnified;
}
});
var _chalk = _interopRequireDefault(require('chalk'));
var _jestGetType = require('jest-get-type');
var _prettyFormat = require('pretty-format');
var _cleanupSemantic = require('./cleanupSemantic');
var _constants = require('./constants');
var _diffLines = require('./diffLines');
var _normalizeDiffOptions = require('./normalizeDiffOptions');
var _printDiffs = require('./printDiffs');
function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : {default: obj};
}
var global = (function () {
if (typeof globalThis !== 'undefined') {
return globalThis;
} else if (typeof global !== 'undefined') {
return global;
} else if (typeof self !== 'undefined') {
return self;
} else if (typeof window !== 'undefined') {
return window;
} else {
return Function('return this')();
}
})();
var Symbol = global['jest-symbol-do-not-touch'] || global.Symbol;
const getCommonMessage = (message, options) => {
const {commonColor} = (0, _normalizeDiffOptions.normalizeDiffOptions)(
options
);
return commonColor(message);
};
const {
AsymmetricMatcher,
DOMCollection,
DOMElement,
Immutable,
ReactElement,
ReactTestComponent
} = _prettyFormat.plugins;
const PLUGINS = [
ReactTestComponent,
ReactElement,
DOMElement,
DOMCollection,
Immutable,
AsymmetricMatcher
];
const FORMAT_OPTIONS = {
plugins: PLUGINS
};
const FALLBACK_FORMAT_OPTIONS = {
callToJSON: false,
maxDepth: 10,
plugins: PLUGINS
}; // Generate a string that will highlight the difference between two values
// with green and red. (similar to how github does code diffing)
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
function diff(a, b, options) {
if (Object.is(a, b)) {
return getCommonMessage(_constants.NO_DIFF_MESSAGE, options);
}
const aType = (0, _jestGetType.getType)(a);
let expectedType = aType;
let omitDifference = false;
if (aType === 'object' && typeof a.asymmetricMatch === 'function') {
if (a.$$typeof !== Symbol.for('jest.asymmetricMatcher')) {
// Do not know expected type of user-defined asymmetric matcher.
return null;
}
if (typeof a.getExpectedType !== 'function') {
// For example, expect.anything() matches either null or undefined
return null;
}
expectedType = a.getExpectedType(); // Primitive types boolean and number omit difference below.
// For example, omit difference for expect.stringMatching(regexp)
omitDifference = expectedType === 'string';
}
if (expectedType !== (0, _jestGetType.getType)(b)) {
return (
' Comparing two different types of values.' +
` Expected ${_chalk.default.green(expectedType)} but ` +
`received ${_chalk.default.red((0, _jestGetType.getType)(b))}.`
);
}
if (omitDifference) {
return null;
}
switch (aType) {
case 'string':
return (0, _diffLines.diffLinesUnified)(
a.split('\n'),
b.split('\n'),
options
);
case 'boolean':
case 'number':
return comparePrimitive(a, b, options);
case 'map':
return compareObjects(sortMap(a), sortMap(b), options);
case 'set':
return compareObjects(sortSet(a), sortSet(b), options);
default:
return compareObjects(a, b, options);
}
}
function comparePrimitive(a, b, options) {
const aFormat = (0, _prettyFormat.format)(a, FORMAT_OPTIONS);
const bFormat = (0, _prettyFormat.format)(b, FORMAT_OPTIONS);
return aFormat === bFormat
? getCommonMessage(_constants.NO_DIFF_MESSAGE, options)
: (0, _diffLines.diffLinesUnified)(
aFormat.split('\n'),
bFormat.split('\n'),
options
);
}
function sortMap(map) {
return new Map(Array.from(map.entries()).sort());
}
function sortSet(set) {
return new Set(Array.from(set.values()).sort());
}
function compareObjects(a, b, options) {
let difference;
let hasThrown = false;
try {
const formatOptions = getFormatOptions(FORMAT_OPTIONS, options);
difference = getObjectsDifference(a, b, formatOptions, options);
} catch {
hasThrown = true;
}
const noDiffMessage = getCommonMessage(_constants.NO_DIFF_MESSAGE, options); // If the comparison yields no results, compare again but this time
// without calling `toJSON`. It's also possible that toJSON might throw.
if (difference === undefined || difference === noDiffMessage) {
const formatOptions = getFormatOptions(FALLBACK_FORMAT_OPTIONS, options);
difference = getObjectsDifference(a, b, formatOptions, options);
if (difference !== noDiffMessage && !hasThrown) {
difference =
getCommonMessage(_constants.SIMILAR_MESSAGE, options) +
'\n\n' +
difference;
}
}
return difference;
}
function getFormatOptions(formatOptions, options) {
const {compareKeys} = (0, _normalizeDiffOptions.normalizeDiffOptions)(
options
);
return {...formatOptions, compareKeys};
}
function getObjectsDifference(a, b, formatOptions, options) {
const formatOptionsZeroIndent = {...formatOptions, indent: 0};
const aCompare = (0, _prettyFormat.format)(a, formatOptionsZeroIndent);
const bCompare = (0, _prettyFormat.format)(b, formatOptionsZeroIndent);
if (aCompare === bCompare) {
return getCommonMessage(_constants.NO_DIFF_MESSAGE, options);
} else {
const aDisplay = (0, _prettyFormat.format)(a, formatOptions);
const bDisplay = (0, _prettyFormat.format)(b, formatOptions);
return (0, _diffLines.diffLinesUnified2)(
aDisplay.split('\n'),
bDisplay.split('\n'),
aCompare.split('\n'),
bCompare.split('\n'),
options
);
}
}

View File

@@ -0,0 +1,10 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import { Diff } from './cleanupSemantic';
import type { DiffOptionsNormalized } from './types';
export declare const joinAlignedDiffsNoExpand: (diffs: Array<Diff>, options: DiffOptionsNormalized) => string;
export declare const joinAlignedDiffsExpand: (diffs: Array<Diff>, options: DiffOptionsNormalized) => string;

View File

@@ -0,0 +1,303 @@
'use strict';
Object.defineProperty(exports, '__esModule', {
value: true
});
exports.joinAlignedDiffsNoExpand = exports.joinAlignedDiffsExpand = void 0;
var _cleanupSemantic = require('./cleanupSemantic');
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
const formatTrailingSpaces = (line, trailingSpaceFormatter) =>
line.replace(/\s+$/, match => trailingSpaceFormatter(match));
const printDiffLine = (
line,
isFirstOrLast,
color,
indicator,
trailingSpaceFormatter,
emptyFirstOrLastLinePlaceholder
) =>
line.length !== 0
? color(
indicator + ' ' + formatTrailingSpaces(line, trailingSpaceFormatter)
)
: indicator !== ' '
? color(indicator)
: isFirstOrLast && emptyFirstOrLastLinePlaceholder.length !== 0
? color(indicator + ' ' + emptyFirstOrLastLinePlaceholder)
: '';
const printDeleteLine = (
line,
isFirstOrLast,
{
aColor,
aIndicator,
changeLineTrailingSpaceColor,
emptyFirstOrLastLinePlaceholder
}
) =>
printDiffLine(
line,
isFirstOrLast,
aColor,
aIndicator,
changeLineTrailingSpaceColor,
emptyFirstOrLastLinePlaceholder
);
const printInsertLine = (
line,
isFirstOrLast,
{
bColor,
bIndicator,
changeLineTrailingSpaceColor,
emptyFirstOrLastLinePlaceholder
}
) =>
printDiffLine(
line,
isFirstOrLast,
bColor,
bIndicator,
changeLineTrailingSpaceColor,
emptyFirstOrLastLinePlaceholder
);
const printCommonLine = (
line,
isFirstOrLast,
{
commonColor,
commonIndicator,
commonLineTrailingSpaceColor,
emptyFirstOrLastLinePlaceholder
}
) =>
printDiffLine(
line,
isFirstOrLast,
commonColor,
commonIndicator,
commonLineTrailingSpaceColor,
emptyFirstOrLastLinePlaceholder
); // In GNU diff format, indexes are one-based instead of zero-based.
const createPatchMark = (aStart, aEnd, bStart, bEnd, {patchColor}) =>
patchColor(
`@@ -${aStart + 1},${aEnd - aStart} +${bStart + 1},${bEnd - bStart} @@`
); // jest --no-expand
//
// Given array of aligned strings with inverse highlight formatting,
// return joined lines with diff formatting (and patch marks, if needed).
const joinAlignedDiffsNoExpand = (diffs, options) => {
const iLength = diffs.length;
const nContextLines = options.contextLines;
const nContextLines2 = nContextLines + nContextLines; // First pass: count output lines and see if it has patches.
let jLength = iLength;
let hasExcessAtStartOrEnd = false;
let nExcessesBetweenChanges = 0;
let i = 0;
while (i !== iLength) {
const iStart = i;
while (i !== iLength && diffs[i][0] === _cleanupSemantic.DIFF_EQUAL) {
i += 1;
}
if (iStart !== i) {
if (iStart === 0) {
// at start
if (i > nContextLines) {
jLength -= i - nContextLines; // subtract excess common lines
hasExcessAtStartOrEnd = true;
}
} else if (i === iLength) {
// at end
const n = i - iStart;
if (n > nContextLines) {
jLength -= n - nContextLines; // subtract excess common lines
hasExcessAtStartOrEnd = true;
}
} else {
// between changes
const n = i - iStart;
if (n > nContextLines2) {
jLength -= n - nContextLines2; // subtract excess common lines
nExcessesBetweenChanges += 1;
}
}
}
while (i !== iLength && diffs[i][0] !== _cleanupSemantic.DIFF_EQUAL) {
i += 1;
}
}
const hasPatch = nExcessesBetweenChanges !== 0 || hasExcessAtStartOrEnd;
if (nExcessesBetweenChanges !== 0) {
jLength += nExcessesBetweenChanges + 1; // add patch lines
} else if (hasExcessAtStartOrEnd) {
jLength += 1; // add patch line
}
const jLast = jLength - 1;
const lines = [];
let jPatchMark = 0; // index of placeholder line for current patch mark
if (hasPatch) {
lines.push(''); // placeholder line for first patch mark
} // Indexes of expected or received lines in current patch:
let aStart = 0;
let bStart = 0;
let aEnd = 0;
let bEnd = 0;
const pushCommonLine = line => {
const j = lines.length;
lines.push(printCommonLine(line, j === 0 || j === jLast, options));
aEnd += 1;
bEnd += 1;
};
const pushDeleteLine = line => {
const j = lines.length;
lines.push(printDeleteLine(line, j === 0 || j === jLast, options));
aEnd += 1;
};
const pushInsertLine = line => {
const j = lines.length;
lines.push(printInsertLine(line, j === 0 || j === jLast, options));
bEnd += 1;
}; // Second pass: push lines with diff formatting (and patch marks, if needed).
i = 0;
while (i !== iLength) {
let iStart = i;
while (i !== iLength && diffs[i][0] === _cleanupSemantic.DIFF_EQUAL) {
i += 1;
}
if (iStart !== i) {
if (iStart === 0) {
// at beginning
if (i > nContextLines) {
iStart = i - nContextLines;
aStart = iStart;
bStart = iStart;
aEnd = aStart;
bEnd = bStart;
}
for (let iCommon = iStart; iCommon !== i; iCommon += 1) {
pushCommonLine(diffs[iCommon][1]);
}
} else if (i === iLength) {
// at end
const iEnd = i - iStart > nContextLines ? iStart + nContextLines : i;
for (let iCommon = iStart; iCommon !== iEnd; iCommon += 1) {
pushCommonLine(diffs[iCommon][1]);
}
} else {
// between changes
const nCommon = i - iStart;
if (nCommon > nContextLines2) {
const iEnd = iStart + nContextLines;
for (let iCommon = iStart; iCommon !== iEnd; iCommon += 1) {
pushCommonLine(diffs[iCommon][1]);
}
lines[jPatchMark] = createPatchMark(
aStart,
aEnd,
bStart,
bEnd,
options
);
jPatchMark = lines.length;
lines.push(''); // placeholder line for next patch mark
const nOmit = nCommon - nContextLines2;
aStart = aEnd + nOmit;
bStart = bEnd + nOmit;
aEnd = aStart;
bEnd = bStart;
for (let iCommon = i - nContextLines; iCommon !== i; iCommon += 1) {
pushCommonLine(diffs[iCommon][1]);
}
} else {
for (let iCommon = iStart; iCommon !== i; iCommon += 1) {
pushCommonLine(diffs[iCommon][1]);
}
}
}
}
while (i !== iLength && diffs[i][0] === _cleanupSemantic.DIFF_DELETE) {
pushDeleteLine(diffs[i][1]);
i += 1;
}
while (i !== iLength && diffs[i][0] === _cleanupSemantic.DIFF_INSERT) {
pushInsertLine(diffs[i][1]);
i += 1;
}
}
if (hasPatch) {
lines[jPatchMark] = createPatchMark(aStart, aEnd, bStart, bEnd, options);
}
return lines.join('\n');
}; // jest --expand
//
// Given array of aligned strings with inverse highlight formatting,
// return joined lines with diff formatting.
exports.joinAlignedDiffsNoExpand = joinAlignedDiffsNoExpand;
const joinAlignedDiffsExpand = (diffs, options) =>
diffs
.map((diff, i, diffs) => {
const line = diff[1];
const isFirstOrLast = i === 0 || i === diffs.length - 1;
switch (diff[0]) {
case _cleanupSemantic.DIFF_DELETE:
return printDeleteLine(line, isFirstOrLast, options);
case _cleanupSemantic.DIFF_INSERT:
return printInsertLine(line, isFirstOrLast, options);
default:
return printCommonLine(line, isFirstOrLast, options);
}
})
.join('\n');
exports.joinAlignedDiffsExpand = joinAlignedDiffsExpand;

View File

@@ -0,0 +1,9 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import type { DiffOptions, DiffOptionsNormalized } from './types';
export declare const noColor: (string: string) => string;
export declare const normalizeDiffOptions: (options?: DiffOptions) => DiffOptionsNormalized;

View File

@@ -0,0 +1,64 @@
'use strict';
Object.defineProperty(exports, '__esModule', {
value: true
});
exports.normalizeDiffOptions = exports.noColor = void 0;
var _chalk = _interopRequireDefault(require('chalk'));
function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : {default: obj};
}
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
const noColor = string => string;
exports.noColor = noColor;
const DIFF_CONTEXT_DEFAULT = 5;
const OPTIONS_DEFAULT = {
aAnnotation: 'Expected',
aColor: _chalk.default.green,
aIndicator: '-',
bAnnotation: 'Received',
bColor: _chalk.default.red,
bIndicator: '+',
changeColor: _chalk.default.inverse,
changeLineTrailingSpaceColor: noColor,
commonColor: _chalk.default.dim,
commonIndicator: ' ',
commonLineTrailingSpaceColor: noColor,
compareKeys: undefined,
contextLines: DIFF_CONTEXT_DEFAULT,
emptyFirstOrLastLinePlaceholder: '',
expand: true,
includeChangeCounts: false,
omitAnnotationLines: false,
patchColor: _chalk.default.yellow
};
const getCompareKeys = compareKeys =>
compareKeys && typeof compareKeys === 'function'
? compareKeys
: OPTIONS_DEFAULT.compareKeys;
const getContextLines = contextLines =>
typeof contextLines === 'number' &&
Number.isSafeInteger(contextLines) &&
contextLines >= 0
? contextLines
: DIFF_CONTEXT_DEFAULT; // Pure function returns options with all properties.
const normalizeDiffOptions = (options = {}) => ({
...OPTIONS_DEFAULT,
...options,
compareKeys: getCompareKeys(options.compareKeys),
contextLines: getContextLines(options.contextLines)
});
exports.normalizeDiffOptions = normalizeDiffOptions;

Some files were not shown because too many files have changed in this diff Show More