408 lines
11 KiB
JavaScript
408 lines
11 KiB
JavaScript
|
'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;
|