1
0
Fork 0
mirror of https://github.com/actions/setup-python.git synced 2024-09-20 00:56:43 +00:00
setup-python/node_modules/jest-snapshot/build/index.js
Danny McCormick 39c08a0eaa Initial pass
2019-06-26 21:12:00 -04:00

518 lines
13 KiB
JavaScript

'use strict';
var _fs = _interopRequireDefault(require('fs'));
var _jestDiff = _interopRequireDefault(require('jest-diff'));
var _jestMatcherUtils = require('jest-matcher-utils');
var _snapshot_resolver = require('./snapshot_resolver');
var _State = _interopRequireDefault(require('./State'));
var _plugins = require('./plugins');
var utils = _interopRequireWildcard(require('./utils'));
function _interopRequireWildcard(obj) {
if (obj && obj.__esModule) {
return obj;
} else {
var newObj = {};
if (obj != null) {
for (var key in obj) {
if (Object.prototype.hasOwnProperty.call(obj, key)) {
var desc =
Object.defineProperty && Object.getOwnPropertyDescriptor
? Object.getOwnPropertyDescriptor(obj, key)
: {};
if (desc.get || desc.set) {
Object.defineProperty(newObj, key, desc);
} else {
newObj[key] = obj[key];
}
}
}
}
newObj.default = obj;
return newObj;
}
}
function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : {default: obj};
}
var Symbol = global['jest-symbol-do-not-touch'] || global.Symbol;
var Symbol = global['jest-symbol-do-not-touch'] || global.Symbol;
var jestExistsFile =
global[Symbol.for('jest-native-exists-file')] || _fs.default.existsSync;
const DID_NOT_THROW = 'Received function did not throw'; // same as toThrow
const NOT_SNAPSHOT_MATCHERS = `.${(0, _jestMatcherUtils.BOLD_WEIGHT)(
'not'
)} cannot be used with snapshot matchers`;
const HINT_ARG = (0, _jestMatcherUtils.BOLD_WEIGHT)('hint');
const INLINE_SNAPSHOT_ARG = 'snapshot';
const PROPERTY_MATCHERS_ARG = 'properties';
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 printName = (concatenatedBlockNames = '', hint = '', count) => {
const hasNames = concatenatedBlockNames.length !== 0;
const hasHint = hint.length !== 0;
return (
'`' +
(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].substr(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) => {
const pattern = '\\.' + _snapshot_resolver.EXTENSION + '$';
const files = hasteFS.matchFiles(pattern);
const filesRemoved = files.reduce((acc, snapshotFile) => {
if (!fileExists(snapshotResolver.resolveTestPath(snapshotFile), hasteFS)) {
if (update === 'all') {
_fs.default.unlinkSync(snapshotFile);
}
return acc + 1;
}
return acc;
}, 0);
return {
filesRemoved
};
};
const toMatchSnapshot = function toMatchSnapshot(
received,
propertyMatchers,
hint
) {
const matcherName = 'toMatchSnapshot';
let expectedArgument = '';
let secondArgument = '';
if (typeof propertyMatchers === 'object' && propertyMatchers !== null) {
expectedArgument = PROPERTY_MATCHERS_ARG;
if (typeof hint === 'string' && hint.length !== 0) {
secondArgument = HINT_ARG;
}
} else if (
typeof propertyMatchers === 'string' &&
propertyMatchers.length !== 0
) {
expectedArgument = HINT_ARG;
}
const options = {
isNot: this.isNot,
promise: this.promise,
secondArgument
};
if (arguments.length === 3 && !propertyMatchers) {
throw new Error(
'Property matchers must be an object.\n\nTo provide a snapshot test name without property matchers, use: toMatchSnapshot("name")'
);
}
return _toMatchSnapshot({
context: this,
expectedArgument,
hint,
matcherName,
options,
propertyMatchers,
received
});
};
const toMatchInlineSnapshot = function toMatchInlineSnapshot(
received,
propertyMatchersOrInlineSnapshot,
inlineSnapshot
) {
const matcherName = 'toMatchInlineSnapshot';
let expectedArgument = '';
let secondArgument = '';
if (typeof propertyMatchersOrInlineSnapshot === 'string') {
expectedArgument = INLINE_SNAPSHOT_ARG;
} else if (
typeof propertyMatchersOrInlineSnapshot === 'object' &&
propertyMatchersOrInlineSnapshot !== null
) {
expectedArgument = PROPERTY_MATCHERS_ARG;
if (typeof inlineSnapshot === 'string') {
secondArgument = INLINE_SNAPSHOT_ARG;
}
}
const options = {
isNot: this.isNot,
promise: this.promise,
secondArgument
};
let propertyMatchers;
if (typeof propertyMatchersOrInlineSnapshot === 'string') {
inlineSnapshot = propertyMatchersOrInlineSnapshot;
} else {
propertyMatchers = propertyMatchersOrInlineSnapshot;
}
return _toMatchSnapshot({
context: this,
expectedArgument,
inlineSnapshot: stripAddedIndentation(inlineSnapshot || ''),
matcherName,
options,
propertyMatchers,
received
});
};
const _toMatchSnapshot = ({
context,
expectedArgument,
hint,
inlineSnapshot,
matcherName,
options,
propertyMatchers,
received
}) => {
context.dontThrow && context.dontThrow();
hint = typeof propertyMatchers === 'string' ? propertyMatchers : hint;
const currentTestName = context.currentTestName,
isNot = context.isNot,
snapshotState = context.snapshotState;
if (isNot) {
throw new Error(
(0, _jestMatcherUtils.matcherHint)(
matcherName,
undefined,
expectedArgument,
options
) +
'\n\n' +
NOT_SNAPSHOT_MATCHERS
);
}
if (!snapshotState) {
throw new Error(
(0, _jestMatcherUtils.matcherHint)(
matcherName,
undefined,
expectedArgument,
options
) + '\n\nsnapshot state must be initialized'
);
}
const fullTestName =
currentTestName && hint
? `${currentTestName}: ${hint}`
: currentTestName || ''; // future BREAKING change: || hint
if (typeof propertyMatchers === 'object') {
if (propertyMatchers === null) {
throw new Error(`Property matchers must be an object.`);
}
const propertyPass = context.equals(received, propertyMatchers, [
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 report = () =>
`Snapshot name: ${printName(currentTestName, hint, count)}\n` +
'\n' +
`Expected properties: ${context.utils.printExpected(
propertyMatchers
)}\n` +
`Received value: ${context.utils.printReceived(received)}`;
return {
message: () =>
(0, _jestMatcherUtils.matcherHint)(
matcherName,
undefined,
expectedArgument,
options
) +
'\n\n' +
report(),
name: matcherName,
pass: false,
report
};
} else {
received = utils.deepMerge(received, propertyMatchers);
}
}
const result = snapshotState.match({
error: context.error,
inlineSnapshot,
received,
testName: fullTestName
});
const count = result.count,
pass = result.pass;
let actual = result.actual,
expected = result.expected;
let report;
if (pass) {
return {
message: () => '',
pass: true
};
} else if (!expected) {
report = () =>
`New snapshot was ${(0, _jestMatcherUtils.RECEIVED_COLOR)(
'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` +
`${(0, _jestMatcherUtils.RECEIVED_COLOR)('Received value')} ` +
`${actual}`;
} else {
expected = (expected || '').trim();
actual = (actual || '').trim();
const diffMessage = (0, _jestDiff.default)(expected, actual, {
aAnnotation: 'Snapshot',
bAnnotation: 'Received',
expand: snapshotState.expand
});
report = () =>
`Snapshot name: ${printName(currentTestName, hint, count)}\n\n` +
(diffMessage ||
(0, _jestMatcherUtils.EXPECTED_COLOR)('- ' + (expected || '')) +
'\n' +
(0, _jestMatcherUtils.RECEIVED_COLOR)('+ ' + actual));
} // 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: () =>
(0, _jestMatcherUtils.matcherHint)(
matcherName,
undefined,
expectedArgument,
options
) +
'\n\n' +
report(),
name: matcherName,
pass: false,
report
};
};
const toThrowErrorMatchingSnapshot = function toThrowErrorMatchingSnapshot(
received,
hint, // because error TS1016 for hint?: string
fromPromise
) {
const matcherName = 'toThrowErrorMatchingSnapshot';
const expectedArgument =
typeof hint === 'string' && hint.length !== 0 ? HINT_ARG : '';
const options = {
isNot: this.isNot,
promise: this.promise,
secondArgument: ''
};
return _toThrowErrorMatchingSnapshot(
{
context: this,
expectedArgument,
hint,
matcherName,
options,
received
},
fromPromise
);
};
const toThrowErrorMatchingInlineSnapshot = function toThrowErrorMatchingInlineSnapshot(
received,
inlineSnapshot,
fromPromise
) {
const matcherName = 'toThrowErrorMatchingInlineSnapshot';
const expectedArgument =
typeof inlineSnapshot === 'string' ? INLINE_SNAPSHOT_ARG : '';
const options = {
isNot: this.isNot,
promise: this.promise,
secondArgument: ''
};
return _toThrowErrorMatchingSnapshot(
{
context: this,
expectedArgument,
inlineSnapshot: inlineSnapshot || '',
matcherName,
options,
received
},
fromPromise
);
};
const _toThrowErrorMatchingSnapshot = (
{
context,
expectedArgument,
inlineSnapshot,
matcherName,
options,
received,
hint
},
fromPromise
) => {
context.dontThrow && context.dontThrow();
const isNot = context.isNot;
if (isNot) {
throw new Error(
(0, _jestMatcherUtils.matcherHint)(
matcherName,
undefined,
expectedArgument,
options
) +
'\n\n' +
NOT_SNAPSHOT_MATCHERS
);
}
let error;
if (fromPromise) {
error = received;
} else {
try {
received();
} catch (e) {
error = e;
}
}
if (error === undefined) {
throw new Error(
(0, _jestMatcherUtils.matcherHint)(
matcherName,
undefined,
expectedArgument,
options
) +
'\n\n' +
DID_NOT_THROW
);
}
return _toMatchSnapshot({
context,
expectedArgument,
hint,
inlineSnapshot,
matcherName,
options,
received: error.message
});
};
const JestSnapshot = {
EXTENSION: _snapshot_resolver.EXTENSION,
SnapshotState: _State.default,
addSerializer: _plugins.addSerializer,
buildSnapshotResolver: _snapshot_resolver.buildSnapshotResolver,
cleanup,
getSerializers: _plugins.getSerializers,
isSnapshotPath: _snapshot_resolver.isSnapshotPath,
toMatchInlineSnapshot,
toMatchSnapshot,
toThrowErrorMatchingInlineSnapshot,
toThrowErrorMatchingSnapshot,
utils
};
/* eslint-disable-next-line no-redeclare */
module.exports = JestSnapshot;