Added logging, changed some directory structure

This commit is contained in:
2018-01-13 21:33:40 -05:00
parent f079a5f067
commit 8e72ffb917
73656 changed files with 35284 additions and 53718 deletions

View File

@@ -0,0 +1,240 @@
'use strict'; /**
* Copyright (c) 2014, Facebook, Inc. All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
*
*/var _require =
require('./jasmine-utils');const equals = _require.equals,fnNameFor = _require.fnNameFor,hasProperty = _require.hasProperty,isA = _require.isA,isUndefined = _require.isUndefined;
class AsymmetricMatcher {
constructor() {
this.$$typeof = Symbol.for('jest.asymmetricMatcher');
}}
class Any extends AsymmetricMatcher {
constructor(sample) {
super();
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.');
}
this.sample = 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 == Object) {
return typeof other == 'object';
}
if (this.sample == Boolean) {
return typeof other == 'boolean';
}
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 fnNameFor(this.sample);
}
toAsymmetricMatcher() {
return 'Any<' + fnNameFor(this.sample) + '>';
}}
class Anything extends AsymmetricMatcher {
asymmetricMatch(other) {
return !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) {
super();
this.sample = sample;
}
asymmetricMatch(other) {
if (!Array.isArray(this.sample)) {
throw new Error(
"You must provide an array to ArrayContaining, not '" +
typeof this.sample +
"'.");
}
return (
this.sample.length === 0 ||
Array.isArray(other) &&
this.sample.every(item => other.some(another => equals(item, another))));
}
toString() {
return 'ArrayContaining';
}
getExpectedType() {
return 'array';
}}
class ObjectContaining extends AsymmetricMatcher {
constructor(sample) {
super();
this.sample = sample;
}
asymmetricMatch(other) {
if (typeof this.sample !== 'object') {
throw new Error(
"You must provide an object to ObjectContaining, not '" +
typeof this.sample +
"'.");
}
for (const property in this.sample) {
if (
!hasProperty(other, property) ||
!equals(this.sample[property], other[property]))
{
return false;
}
}
return true;
}
toString() {
return 'ObjectContaining';
}
getExpectedType() {
return 'object';
}}
class StringContaining extends AsymmetricMatcher {
constructor(sample) {
super();
if (!isA('String', sample)) {
throw new Error('Expected is not a string');
}
this.sample = sample;
}
asymmetricMatch(other) {
return other.includes(this.sample);
}
toString() {
return 'StringContaining';
}
getExpectedType() {
return 'string';
}}
class StringMatching extends AsymmetricMatcher {
constructor(sample) {
super();
if (!isA('String', sample) && !isA('RegExp', sample)) {
throw new Error('Expected is not a String or a RegExp');
}
this.sample = new RegExp(sample);
}
asymmetricMatch(other) {
return this.sample.test(other);
}
toString() {
return 'StringMatching';
}
getExpectedType() {
return 'string';
}}
module.exports = {
any: expectedObject => new Any(expectedObject),
anything: () => new Anything(),
arrayContaining: sample => new ArrayContaining(sample),
objectContaining: sample => new ObjectContaining(sample),
stringContaining: expected => new StringContaining(expected),
stringMatching: expected => new StringMatching(expected) };

View File

@@ -0,0 +1,290 @@
'use strict';function _asyncToGenerator(fn) {return function () {var gen = fn.apply(this, arguments);return new Promise(function (resolve, reject) {function step(key, arg) {try {var info = gen[key](arg);var value = info.value;} catch (error) {reject(error);return;}if (info.done) {resolve(value);} else {return Promise.resolve(value).then(function (value) {step("next", value);}, function (err) {step("throw", err);});}}return step("next");});};}
const utils = require('jest-matcher-utils'); /**
* Copyright (c) 2014, Facebook, Inc. All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
*
*/const matchers = require('./matchers');const spyMatchers = require('./spyMatchers');const toThrowMatchers = require('./toThrowMatchers');var _require = require('./jasmine-utils');const equals = _require.equals;var _require2 =
require('./asymmetric-matchers');const any = _require2.any,anything = _require2.anything,arrayContaining = _require2.arrayContaining,objectContaining = _require2.objectContaining,stringContaining = _require2.stringContaining,stringMatching = _require2.stringMatching;
const GLOBAL_STATE = Symbol.for('$$jest-matchers-object');
class JestAssertionError extends Error {}
const isPromise = obj => {
return (
!!obj && (
typeof obj === 'object' || typeof obj === 'function') &&
typeof obj.then === 'function');
};
if (!global[GLOBAL_STATE]) {
Object.defineProperty(global, GLOBAL_STATE, {
value: {
matchers: Object.create(null),
state: {
assertionCalls: 0,
expectedAssertionsNumber: null,
isExpectingAssertions: false,
suppressedErrors: [] } } });
}
const expect = actual => {
const allMatchers = global[GLOBAL_STATE].matchers;
const expectation = {
not: {},
rejects: { not: {} },
resolves: { not: {} } };
Object.keys(allMatchers).forEach(name => {
expectation[name] = makeThrowingMatcher(allMatchers[name], false, actual);
expectation.not[name] = makeThrowingMatcher(
allMatchers[name],
true,
actual);
expectation.resolves[name] = makeResolveMatcher(
name,
allMatchers[name],
false,
actual);
expectation.resolves.not[name] = makeResolveMatcher(
name,
allMatchers[name],
true,
actual);
expectation.rejects[name] = makeRejectMatcher(
name,
allMatchers[name],
false,
actual);
expectation.rejects.not[name] = makeRejectMatcher(
name,
allMatchers[name],
true,
actual);
});
return expectation;
};
const getMessage = message => {
// for performance reasons some of the messages are evaluated
// lazily
if (typeof message === 'function') {
message = message();
}
if (!message) {
message = utils.RECEIVED_COLOR(
'No message was specified for this matcher.');
}
return message;
};
const makeResolveMatcher = (
matcherName,
matcher,
isNot,
actual) => _asyncToGenerator(
function* () {for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {args[_key] = arguments[_key];}
const matcherStatement = `.resolves.${isNot ? 'not.' : ''}${matcherName}`;
if (!isPromise(actual)) {
throw new JestAssertionError(
utils.matcherHint(matcherStatement, 'received', '') +
'\n\n' +
`${utils.RECEIVED_COLOR('received')} value must be a Promise.\n` +
utils.printWithType('Received', actual, utils.printReceived));
}
let result;
try {
result = yield actual;
} catch (e) {
throw new JestAssertionError(
utils.matcherHint(matcherStatement, 'received', '') +
'\n\n' +
`Expected ${utils.RECEIVED_COLOR('received')} Promise to resolve, ` +
'instead it rejected to value\n' +
` ${utils.printReceived(e)}`);
}
return makeThrowingMatcher(matcher, isNot, result).apply(null, args);
});
const makeRejectMatcher = (
matcherName,
matcher,
isNot,
actual) => _asyncToGenerator(
function* () {for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {args[_key2] = arguments[_key2];}
const matcherStatement = `.rejects.${isNot ? 'not.' : ''}${matcherName}`;
if (!isPromise(actual)) {
throw new JestAssertionError(
utils.matcherHint(matcherStatement, 'received', '') +
'\n\n' +
`${utils.RECEIVED_COLOR('received')} value must be a Promise.\n` +
utils.printWithType('Received', actual, utils.printReceived));
}
let result;
try {
result = yield actual;
} catch (e) {
return makeThrowingMatcher(matcher, isNot, e).apply(null, args);
}
throw new JestAssertionError(
utils.matcherHint(matcherStatement, 'received', '') +
'\n\n' +
`Expected ${utils.RECEIVED_COLOR('received')} Promise to reject, ` +
'instead it resolved to value\n' +
` ${utils.printReceived(result)}`);
});
const makeThrowingMatcher = (
matcher,
isNot,
actual) =>
{
return function throwingMatcher() {
let throws = true;
const matcherContext = Object.assign(
// 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 },
global[GLOBAL_STATE].state,
{
equals,
isNot,
utils });
let result;
try {for (var _len3 = arguments.length, args = Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {args[_key3] = arguments[_key3];}
result = matcher.apply(matcherContext, [actual].concat(args));
} catch (error) {
// Remove this and deeper functions from the stack trace frame.
Error.captureStackTrace(error, throwingMatcher);
throw error;
}
_validateResult(result);
global[GLOBAL_STATE].state.assertionCalls++;
if (result.pass && isNot || !result.pass && !isNot) {
// XOR
const message = getMessage(result.message);
const error = new JestAssertionError(message);
// 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;
// Remove this function from the stack trace frame.
Error.captureStackTrace(error, throwingMatcher);
if (throws) {
throw error;
} else {
global[GLOBAL_STATE].state.suppressedErrors.push(error);
}
}
};
};
expect.extend = matchers => {
Object.assign(global[GLOBAL_STATE].matchers, matchers);
};
expect.anything = anything;
expect.any = any;
expect.objectContaining = objectContaining;
expect.arrayContaining = arrayContaining;
expect.stringContaining = stringContaining;
expect.stringMatching = 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' +
`'${utils.stringify(result)}' was returned`);
}
};
// add default jest matchers
expect.extend(matchers);
expect.extend(spyMatchers);
expect.extend(toThrowMatchers);
expect.addSnapshotSerializer = () => void 0;
expect.assertions = expected => {
global[GLOBAL_STATE].state.expectedAssertionsNumber = expected;
};
expect.hasAssertions = expected => {
utils.ensureNoExpected(expected, '.hasAssertions');
global[GLOBAL_STATE].state.isExpectingAssertions = true;
};
expect.setState = state => {
Object.assign(global[GLOBAL_STATE].state, state);
};
expect.getState = () => global[GLOBAL_STATE].state;
module.exports = expect;

View File

@@ -0,0 +1,297 @@
'use strict';
// Extracted out of jasmine 2.5.2
function equals(a, b, customTesters) {
customTesters = customTesters || [];
return eq(a, b, [], [], customTesters);
} /*
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 */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) {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;
}
// Identical objects are equal. `0 === -0`, but they aren't identical.
// See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal).
if (a === b) {
return a !== 0 || 1 / a == 1 / b;
}
// 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) {
// Strings, numbers, dates, and booleans are compared by value.
case '[object String]':
// Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
// equivalent to `new String("5")`.
return a == String(b);
case '[object Number]':
// `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for
// other numeric values.
return a != +a ? b != +b : a === 0 ? 1 / a == 1 / b : a == +b;
case '[object Date]':
case '[object Boolean]':
// Coerce dates and booleans 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.global == b.global &&
a.multiline == b.multiline &&
a.ignoreCase == b.ignoreCase);}
if (typeof a != 'object' || typeof b != 'object') {
return false;
}
var aIsDomNode = isDomNode(a);
var bIsDomNode = isDomNode(b);
if (aIsDomNode && bIsDomNode) {
// At first try to use DOM3 method isEqualNode
if (a.isEqualNode) {
return a.isEqualNode(b);
}
// IE8 doesn't support isEqualNode, try to use outerHTML && innerText
var aIsElement = a instanceof Element;
var bIsElement = b instanceof Element;
if (aIsElement && bIsElement) {
return a.outerHTML == b.outerHTML;
}
if (aIsElement || bIsElement) {
return false;
}
return a.innerText == b.innerText && a.textContent == b.textContent;
}
if (aIsDomNode || bIsDomNode) {
return false;
}
// Assume equality for cyclic structures. The algorithm for detecting cyclic
// structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
var length = aStack.length;
while (length--) {
// Linear search. Performance is inversely proportional to the number of
// unique nested structures.
if (aStack[length] == a) {
return bStack[length] == b;
}
}
// Add the first object to the stack of traversed objects.
aStack.push(a);
bStack.push(b);
var size = 0;
// Recursively compare objects and arrays.
// Compare array lengths to determine if a deep comparison is necessary.
if (className == '[object Array]') {
size = a.length;
if (size !== b.length) {
return false;
}
while (size--) {
result = eq(a[size], b[size], aStack, bStack, customTesters);
if (!result) {
return false;
}
}
} else {
} // Objects with different constructors are not equivalent, but `Object`s
// or `Array`s from different frames are.
// CUSTOM JEST CHANGE:
// TODO(cpojer): fix all tests and this and re-enable this check
/*
var aCtor = a.constructor, bCtor = b.constructor;
if (aCtor !== bCtor && !(isFunction(aCtor) && aCtor instanceof aCtor &&
isFunction(bCtor) && bCtor instanceof bCtor)) {
return false;
}
*/ // Deep compare objects.
var aKeys = keys(a, className == '[object Array]'),key;size = aKeys.length; // Ensure that both objects contain the same number of properties before comparing deep equality.
if (keys(b, className == '[object Array]').length !== size) {return false;}while (size--) {key = aKeys[size];
// Deep compare each member
result = has(b, key) && eq(a[key], b[key], aStack, bStack, customTesters);
if (!result) {
return false;
}
}
// Remove the first object from the stack of traversed objects.
aStack.pop();
bStack.pop();
return result;
}
function keys(obj, isArray) {
// CUSTOM JEST CHANGE: don't consider undefined keys.
var allKeys = function (o) {
var keys = [];
for (var key in o) {
if (has(o, key)) {
keys.push(key);
}
}
return keys;
}(obj);
if (!isArray) {
return allKeys;
}
var extraKeys = [];
if (allKeys.length === 0) {
return allKeys;
}
for (var x = 0; x < allKeys.length; x++) {
if (!allKeys[x].match(/^[0-9]+$/)) {
extraKeys.push(allKeys[x]);
}
}
return extraKeys;
}
function has(obj, key) {
// CUSTOM JEST CHANGE:
// TODO(cpojer): remove the `obj[key] !== undefined` check.
return (
Object.prototype.hasOwnProperty.call(obj, key) && obj[key] !== undefined);
}
function isA(typeName, value) {
return Object.prototype.toString.apply(value) === '[object ' + typeName + ']';
}
function isDomNode(obj) {
return obj.nodeType > 0;
}
function fnNameFor(func) {
if (func.name) {
return func.name;
}
const matches = func.toString().match(/^\s*function\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);
}
module.exports = {
equals,
fnNameFor,
hasProperty,
isA,
isUndefined };

View File

@@ -0,0 +1,682 @@
'use strict';
const diff = require('jest-diff'); /**
* Copyright (c) 2014, Facebook, Inc. All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
*
*/var _require = require('jest-regex-util');const escapeStrForRegex = _require.escapeStrForRegex;var _require2 =
require('jest-matcher-utils');const EXPECTED_COLOR = _require2.EXPECTED_COLOR,RECEIVED_COLOR = _require2.RECEIVED_COLOR,ensureNoExpected = _require2.ensureNoExpected,ensureNumbers = _require2.ensureNumbers,getType = _require2.getType,matcherHint = _require2.matcherHint,printReceived = _require2.printReceived,printExpected = _require2.printExpected,printWithType = _require2.printWithType;var _require3 =
require('./utils');const getObjectSubset = _require3.getObjectSubset,getPath = _require3.getPath,hasOwnProperty = _require3.hasOwnProperty;var _require4 =
require('./jasmine-utils');const equals = _require4.equals;
const IteratorSymbol = Symbol.iterator;
const hasIterator = object => !!(object != null && object[IteratorSymbol]);
const iterableEquality = (a, b) => {
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;
}
const bIterator = b[IteratorSymbol]();
for (const aValue of a) {
const nextB = bIterator.next();
if (nextB.done || !equals(aValue, nextB.value, [iterableEquality])) {
return false;
}
}
if (!bIterator.next().done) {
return false;
}
return true;
};
const isObjectWithKeys = a =>
a !== null &&
typeof a === 'object' &&
!(a instanceof Array) &&
!(a instanceof Date);
const subsetEquality = (object, subset) => {
if (!isObjectWithKeys(object) || !isObjectWithKeys(subset)) {
return undefined;
}
return Object.keys(subset).every(
key =>
hasOwnProperty(object, key) &&
equals(object[key], subset[key], [iterableEquality, subsetEquality]));
};
const matchers = {
toBe(received, expected) {
const pass = received === expected;
const message = pass ?
() =>
matcherHint('.not.toBe') +
'\n\n' +
`Expected value to not be (using ===):\n` +
` ${printExpected(expected)}\n` +
`Received:\n` +
` ${printReceived(received)}` :
() => {
const diffString = diff(expected, received, {
expand: this.expand });
return (
matcherHint('.toBe') +
'\n\n' +
`Expected value to be (using ===):\n` +
` ${printExpected(expected)}\n` +
`Received:\n` +
` ${printReceived(received)}` + (
diffString ? `\n\nDifference:\n\n${diffString}` : ''));
};
// Passing the 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: received, expected, message, name: 'toBe', pass };
},
toBeCloseTo(actual, expected) {let precision = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 2;
ensureNumbers(actual, expected, '.toBeCloseTo');
const pass = Math.abs(expected - actual) < Math.pow(10, -precision) / 2;
const message = pass ?
() =>
matcherHint('.not.toBeCloseTo', 'received', 'expected, precision') +
'\n\n' +
`Expected value not to be close to (with ${printExpected(precision)}-digit precision):\n` +
` ${printExpected(expected)}\n` +
`Received:\n` +
` ${printReceived(actual)}` :
() =>
matcherHint('.toBeCloseTo', 'received', 'expected, precision') +
'\n\n' +
`Expected value to be close to (with ${printExpected(precision)}-digit precision):\n` +
` ${printExpected(expected)}\n` +
`Received:\n` +
` ${printReceived(actual)}`;
return { message, pass };
},
toBeDefined(actual, expected) {
ensureNoExpected(expected, '.toBeDefined');
const pass = actual !== void 0;
const message = pass ?
() =>
matcherHint('.not.toBeDefined', 'received', '') +
'\n\n' +
`Expected value not to be defined, instead received\n` +
` ${printReceived(actual)}` :
() =>
matcherHint('.toBeDefined', 'received', '') +
'\n\n' +
`Expected value to be defined, instead received\n` +
` ${printReceived(actual)}`;
return { message, pass };
},
toBeFalsy(actual, expected) {
ensureNoExpected(expected, '.toBeFalsy');
const pass = !actual;
const message = pass ?
() =>
matcherHint('.not.toBeFalsy', 'received', '') +
'\n\n' +
`Expected value not to be falsy, instead received\n` +
` ${printReceived(actual)}` :
() =>
matcherHint('.toBeFalsy', 'received', '') +
'\n\n' +
`Expected value to be falsy, instead received\n` +
` ${printReceived(actual)}`;
return { message, pass };
},
toBeGreaterThan(actual, expected) {
ensureNumbers(actual, expected, '.toBeGreaterThan');
const pass = actual > expected;
const message = pass ?
() =>
matcherHint('.not.toBeGreaterThan') +
'\n\n' +
`Expected value not to be greater than:\n` +
` ${printExpected(expected)}\n` +
`Received:\n` +
` ${printReceived(actual)}` :
() =>
matcherHint('.toBeGreaterThan') +
'\n\n' +
`Expected value to be greater than:\n` +
` ${printExpected(expected)}\n` +
`Received:\n` +
` ${printReceived(actual)}`;
return { message, pass };
},
toBeGreaterThanOrEqual(actual, expected) {
ensureNumbers(actual, expected, '.toBeGreaterThanOrEqual');
const pass = actual >= expected;
const message = pass ?
() =>
matcherHint('.not.toBeGreaterThanOrEqual') +
'\n\n' +
`Expected value not to be greater than or equal:\n` +
` ${printExpected(expected)}\n` +
`Received:\n` +
` ${printReceived(actual)}` :
() =>
matcherHint('.toBeGreaterThanOrEqual') +
'\n\n' +
`Expected value to be greater than or equal:\n` +
` ${printExpected(expected)}\n` +
`Received:\n` +
` ${printReceived(actual)}`;
return { message, pass };
},
toBeInstanceOf(received, constructor) {
const constType = getType(constructor);
if (constType !== 'function') {
throw new Error(
matcherHint('[.not].toBeInstanceOf', 'value', 'constructor') +
`\n\n` +
`Expected constructor to be a function. Instead got:\n` +
` ${printExpected(constType)}`);
}
const pass = received instanceof constructor;
const message = pass ?
() =>
matcherHint('.not.toBeInstanceOf', 'value', 'constructor') +
'\n\n' +
`Expected value not to be an instance of:\n` +
` ${printExpected(constructor.name || constructor)}\n` +
`Received:\n` +
` ${printReceived(received)}\n` :
() =>
matcherHint('.toBeInstanceOf', 'value', 'constructor') +
'\n\n' +
`Expected value to be an instance of:\n` +
` ${printExpected(constructor.name || constructor)}\n` +
`Received:\n` +
` ${printReceived(received)}\n` +
`Constructor:\n` +
` ${printReceived(received.constructor && received.constructor.name)}`;
return { message, pass };
},
toBeLessThan(actual, expected) {
ensureNumbers(actual, expected, '.toBeLessThan');
const pass = actual < expected;
const message = pass ?
() =>
matcherHint('.not.toBeLessThan') +
'\n\n' +
`Expected value not to be less than:\n` +
` ${printExpected(expected)}\n` +
`Received:\n` +
` ${printReceived(actual)}` :
() =>
matcherHint('.toBeLessThan') +
'\n\n' +
`Expected value to be less than:\n` +
` ${printExpected(expected)}\n` +
`Received:\n` +
` ${printReceived(actual)}`;
return { message, pass };
},
toBeLessThanOrEqual(actual, expected) {
ensureNumbers(actual, expected, '.toBeLessThanOrEqual');
const pass = actual <= expected;
const message = pass ?
() =>
matcherHint('.not.toBeLessThanOrEqual') +
'\n\n' +
`Expected value not to be less than or equal:\n` +
` ${printExpected(expected)}\n` +
`Received:\n` +
` ${printReceived(actual)}` :
() =>
matcherHint('.toBeLessThanOrEqual') +
'\n\n' +
`Expected value to be less than or equal:\n` +
` ${printExpected(expected)}\n` +
`Received:\n` +
` ${printReceived(actual)}`;
return { message, pass };
},
toBeNaN(actual, expected) {
ensureNoExpected(expected, '.toBeNaN');
const pass = Number.isNaN(actual);
const message = pass ?
() =>
matcherHint('.not.toBeNaN', 'received', '') +
'\n\n' +
`Expected value not to be NaN, instead received\n` +
` ${printReceived(actual)}` :
() =>
matcherHint('.toBeNaN', 'received', '') +
'\n\n' +
`Expected value to be NaN, instead received\n` +
` ${printReceived(actual)}`;
return { message, pass };
},
toBeNull(actual, expected) {
ensureNoExpected(expected, '.toBeNull');
const pass = actual === null;
const message = pass ?
() =>
matcherHint('.not.toBeNull', 'received', '') +
'\n\n' +
`Expected value not to be null, instead received\n` +
` ${printReceived(actual)}` :
() =>
matcherHint('.toBeNull', 'received', '') +
'\n\n' +
`Expected value to be null, instead received\n` +
` ${printReceived(actual)}`;
return { message, pass };
},
toBeTruthy(actual, expected) {
ensureNoExpected(expected, '.toBeTruthy');
const pass = !!actual;
const message = pass ?
() =>
matcherHint('.not.toBeTruthy', 'received', '') +
'\n\n' +
`Expected value not to be truthy, instead received\n` +
` ${printReceived(actual)}` :
() =>
matcherHint('.toBeTruthy', 'received', '') +
'\n\n' +
`Expected value to be truthy, instead received\n` +
` ${printReceived(actual)}`;
return { message, pass };
},
toBeUndefined(actual, expected) {
ensureNoExpected(expected, '.toBeUndefined');
const pass = actual === void 0;
const message = pass ?
() =>
matcherHint('.not.toBeUndefined', 'received', '') +
'\n\n' +
`Expected value not to be undefined, instead received\n` +
` ${printReceived(actual)}` :
() =>
matcherHint('.toBeUndefined', 'received', '') +
'\n\n' +
`Expected value to be undefined, instead received\n` +
` ${printReceived(actual)}`;
return { message, pass };
},
toContain(collection, value) {
const collectionType = getType(collection);
let converted = null;
if (Array.isArray(collection) || typeof collection === 'string') {
// strings have `indexOf` so we don't need to convert
// arrays have `indexOf` and we don't want to make a copy
converted = collection;
} else {
try {
converted = Array.from(collection);
} catch (e) {
throw new Error(
matcherHint('[.not].toContainEqual', 'collection', 'value') +
'\n\n' +
`Expected ${RECEIVED_COLOR('collection')} to be an array-like structure.\n` +
printWithType('Received', collection, printReceived));
}
}
// At this point, we're either a string or an Array,
// which was converted from an array-like structure.
const pass = converted.indexOf(value) != -1;
const message = pass ?
() =>
matcherHint('.not.toContain', collectionType, 'value') +
'\n\n' +
`Expected ${collectionType}:\n` +
` ${printReceived(collection)}\n` +
`Not to contain value:\n` +
` ${printExpected(value)}\n` :
() =>
matcherHint('.toContain', collectionType, 'value') +
'\n\n' +
`Expected ${collectionType}:\n` +
` ${printReceived(collection)}\n` +
`To contain value:\n` +
` ${printExpected(value)}`;
return { message, pass };
},
toContainEqual(collection, value) {
const collectionType = getType(collection);
let converted = null;
if (Array.isArray(collection)) {
converted = collection;
} else {
try {
converted = Array.from(collection);
} catch (e) {
throw new Error(
matcherHint('[.not].toContainEqual', 'collection', 'value') +
'\n\n' +
`Expected ${RECEIVED_COLOR('collection')} to be an array-like structure.\n` +
printWithType('Received', collection, printReceived));
}
}
const pass =
converted.findIndex(item => equals(item, value, [iterableEquality])) !==
-1;
const message = pass ?
() =>
matcherHint('.not.toContainEqual', collectionType, 'value') +
'\n\n' +
`Expected ${collectionType}:\n` +
` ${printReceived(collection)}\n` +
`Not to contain a value equal to:\n` +
` ${printExpected(value)}\n` :
() =>
matcherHint('.toContainEqual', collectionType, 'value') +
'\n\n' +
`Expected ${collectionType}:\n` +
` ${printReceived(collection)}\n` +
`To contain a value equal to:\n` +
` ${printExpected(value)}`;
return { message, pass };
},
toEqual(received, expected) {
const pass = equals(received, expected, [iterableEquality]);
const message = pass ?
() =>
matcherHint('.not.toEqual') +
'\n\n' +
`Expected value to not equal:\n` +
` ${printExpected(expected)}\n` +
`Received:\n` +
` ${printReceived(received)}` :
() => {
const diffString = diff(expected, received, {
expand: this.expand });
return (
matcherHint('.toEqual') +
'\n\n' +
`Expected value to equal:\n` +
` ${printExpected(expected)}\n` +
`Received:\n` +
` ${printReceived(received)}` + (
diffString ? `\n\nDifference:\n\n${diffString}` : ''));
};
// Passing the 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: received, expected, message, name: 'toEqual', pass };
},
toHaveLength(received, length) {
if (
typeof received !== 'string' && (
!received || typeof received.length !== 'number'))
{
throw new Error(
matcherHint('[.not].toHaveLength', 'received', 'length') +
'\n\n' +
`Expected value to have a 'length' property that is a number. ` +
`Received:\n` +
` ${printReceived(received)}\n` + (
received ?
`received.length:\n ${printReceived(received.length)}` :
''));
}
const pass = received.length === length;
const message = pass ?
() =>
matcherHint('.not.toHaveLength', 'received', 'length') +
'\n\n' +
`Expected value to not have length:\n` +
` ${printExpected(length)}\n` +
`Received:\n` +
` ${printReceived(received)}\n` +
`received.length:\n` +
` ${printReceived(received.length)}` :
() =>
matcherHint('.toHaveLength', 'received', 'length') +
'\n\n' +
`Expected value to have length:\n` +
` ${printExpected(length)}\n` +
`Received:\n` +
` ${printReceived(received)}\n` +
`received.length:\n` +
` ${printReceived(received.length)}`;
return { message, pass };
},
toHaveProperty(object, keyPath, value) {
const valuePassed = arguments.length === 3;
if (!object && typeof object !== 'string' && typeof object !== 'number') {
throw new Error(
matcherHint('[.not].toHaveProperty', 'object', 'path', {
secondArgument: valuePassed ? 'value' : null }) +
'\n\n' +
`Expected ${RECEIVED_COLOR('object')} to be an object. Received:\n` +
` ${getType(object)}: ${printReceived(object)}`);
}
if (getType(keyPath) !== 'string') {
throw new Error(
matcherHint('[.not].toHaveProperty', 'object', 'path', {
secondArgument: valuePassed ? 'value' : null }) +
'\n\n' +
`Expected ${EXPECTED_COLOR('path')} to be a string. Received:\n` +
` ${getType(keyPath)}: ${printReceived(keyPath)}`);
}
const result = getPath(object, keyPath);const
lastTraversedObject = result.lastTraversedObject,hasEndProp = result.hasEndProp;
let diffString;
if (valuePassed && hasOwnProperty(result, 'value')) {
diffString = diff(value, result.value, {
expand: this.expand });
}
const pass = valuePassed ?
equals(result.value, value, [iterableEquality]) :
hasEndProp;
if (hasOwnProperty(result, 'value')) {
// we don't diff numbers. So instead we'll show the object that contains the resulting value.
// And to get that object we need to go up a level.
result.traversedPath.pop();
}
const traversedPath = result.traversedPath.join('.');
const message = pass ?
matcherHint('.not.toHaveProperty', 'object', 'path', {
secondArgument: valuePassed ? 'value' : null }) +
'\n\n' +
`Expected the object:\n` +
` ${printReceived(object)}\n` +
`Not to have a nested property:\n` +
` ${printExpected(keyPath)}\n` + (
valuePassed ? `With a value of:\n ${printExpected(value)}\n` : '') :
matcherHint('.toHaveProperty', 'object', 'path', {
secondArgument: valuePassed ? 'value' : null }) +
'\n\n' +
`Expected the object:\n` +
` ${printReceived(object)}\n` +
`To have a nested property:\n` +
` ${printExpected(keyPath)}\n` + (
valuePassed ? `With a value of:\n ${printExpected(value)}\n` : '') + (
traversedPath ?
`Received:\n ${RECEIVED_COLOR('object')}.${traversedPath}: ${printReceived(lastTraversedObject)}` :
'') + (
diffString ? `\nDifference:\n\n${diffString}` : '');
if (pass === undefined) {
throw new Error('pass must be initialized');
}
return { message, pass };
},
toMatch(received, expected) {
if (typeof received !== 'string') {
throw new Error(
matcherHint('[.not].toMatch', 'string', 'expected') +
'\n\n' +
`${RECEIVED_COLOR('string')} value must be a string.\n` +
printWithType('Received', received, printReceived));
}
if (!(expected instanceof RegExp) && !(typeof expected === 'string')) {
throw new Error(
matcherHint('[.not].toMatch', 'string', 'expected') +
'\n\n' +
`${EXPECTED_COLOR('expected')} value must be a string or a regular expression.\n` +
printWithType('Expected', expected, printExpected));
}
const pass = new RegExp(
typeof expected === 'string' ? escapeStrForRegex(expected) : expected).
test(received);
const message = pass ?
() =>
matcherHint('.not.toMatch') +
`\n\nExpected value not to match:\n` +
` ${printExpected(expected)}` +
`\nReceived:\n` +
` ${printReceived(received)}` :
() =>
matcherHint('.toMatch') +
`\n\nExpected value to match:\n` +
` ${printExpected(expected)}` +
`\nReceived:\n` +
` ${printReceived(received)}`;
return { message, pass };
},
toMatchObject(receivedObject, expectedObject) {
if (typeof receivedObject !== 'object' || receivedObject === null) {
throw new Error(
matcherHint('[.not].toMatchObject', 'object', 'expected') +
'\n\n' +
`${RECEIVED_COLOR('received')} value must be an object.\n` +
printWithType('Received', receivedObject, printReceived));
}
if (typeof expectedObject !== 'object' || expectedObject === null) {
throw new Error(
matcherHint('[.not].toMatchObject', 'object', 'expected') +
'\n\n' +
`${EXPECTED_COLOR('expected')} value must be an object.\n` +
printWithType('Expected', expectedObject, printExpected));
}
const pass = equals(receivedObject, expectedObject, [
iterableEquality,
subsetEquality]);
const message = pass ?
() =>
matcherHint('.not.toMatchObject') +
`\n\nExpected value not to match object:\n` +
` ${printExpected(expectedObject)}` +
`\nReceived:\n` +
` ${printReceived(receivedObject)}` :
() => {
const diffString = diff(
expectedObject,
getObjectSubset(receivedObject, expectedObject),
{
expand: this.expand });
return (
matcherHint('.toMatchObject') +
`\n\nExpected value to match object:\n` +
` ${printExpected(expectedObject)}` +
`\nReceived:\n` +
` ${printReceived(receivedObject)}` + (
diffString ? `\nDifference:\n${diffString}` : ''));
};
return { message, pass };
} };
module.exports = matchers;

View File

@@ -0,0 +1,200 @@
'use strict';
const CALL_PRINT_LIMIT = 3; /**
* Copyright (c) 2014, Facebook, Inc. All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
*
*/const LAST_CALL_PRINT_LIMIT = 1;var _require =
require('jest-matcher-utils');const ensureExpectedIsNumber = _require.ensureExpectedIsNumber,ensureNoExpected = _require.ensureNoExpected,EXPECTED_COLOR = _require.EXPECTED_COLOR,matcherHint = _require.matcherHint,pluralize = _require.pluralize,printExpected = _require.printExpected,printReceived = _require.printReceived,printWithType = _require.printWithType,RECEIVED_COLOR = _require.RECEIVED_COLOR;var _require2 =
require('./jasmine-utils');const equals = _require2.equals;
const RECEIVED_NAME = {
'mock function': 'jest.fn()',
spy: 'spy' };
const createToBeCalledMatcher = matcherName => (received, expected) => {
ensureNoExpected(expected, matcherName);
ensureMock(received, matcherName);
const receivedIsSpy = isSpy(received);
const type = receivedIsSpy ? 'spy' : 'mock function';
const count = receivedIsSpy ?
received.calls.count() :
received.mock.calls.length;
const calls = receivedIsSpy ?
received.calls.all().map(x => x.args) :
received.mock.calls;
const pass = count > 0;
const message = pass ?
() =>
matcherHint('.not' + matcherName, RECEIVED_NAME[type], '') +
'\n\n' +
`Expected ${type} not to be called ` +
formatReceivedCalls(calls, CALL_PRINT_LIMIT, { sameSentence: true }) :
() =>
matcherHint(matcherName, RECEIVED_NAME[type], '') +
'\n\n' +
`Expected ${type} to have been called.`;
return { message, pass };
};
const createToBeCalledWithMatcher = matcherName => function (
received)
{for (var _len = arguments.length, expected = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {expected[_key - 1] = arguments[_key];}
ensureMock(received, matcherName);
const receivedIsSpy = isSpy(received);
const type = receivedIsSpy ? 'spy' : 'mock function';
const calls = receivedIsSpy ?
received.calls.all().map(x => x.args) :
received.mock.calls;
const pass = calls.some(call => equals(call, expected));
const message = pass ?
() =>
matcherHint('.not' + matcherName, RECEIVED_NAME[type]) +
'\n\n' +
`Expected ${type} not to have been called with:\n` +
` ${printExpected(expected)}` :
() =>
matcherHint(matcherName, RECEIVED_NAME[type]) +
'\n\n' +
`Expected ${type} to have been called with:\n` +
` ${printExpected(expected)}\n` +
formatReceivedCalls(calls, CALL_PRINT_LIMIT);
return { message, pass };
};
const createLastCalledWithMatcher = matcherName => function (
received)
{for (var _len2 = arguments.length, expected = Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {expected[_key2 - 1] = arguments[_key2];}
ensureMock(received, matcherName);
const receivedIsSpy = isSpy(received);
const type = receivedIsSpy ? 'spy' : 'mock function';
const calls = receivedIsSpy ?
received.calls.all().map(x => x.args) :
received.mock.calls;
const pass = equals(calls[calls.length - 1], expected);
const message = pass ?
() =>
matcherHint('.not' + matcherName, RECEIVED_NAME[type]) +
'\n\n' +
`Expected ${type} to not have been last called with:\n` +
` ${printExpected(expected)}` :
() =>
matcherHint(matcherName, RECEIVED_NAME[type]) +
'\n\n' +
`Expected ${type} to have been last called with:\n` +
` ${printExpected(expected)}\n` +
formatReceivedCalls(calls, LAST_CALL_PRINT_LIMIT, { isLast: true });
return { message, pass };
};
const spyMatchers = {
lastCalledWith: createLastCalledWithMatcher('.lastCalledWith'),
toBeCalled: createToBeCalledMatcher('.toBeCalled'),
toBeCalledWith: createToBeCalledWithMatcher('.toBeCalledWith'),
toHaveBeenCalled: createToBeCalledMatcher('.toHaveBeenCalled'),
toHaveBeenCalledTimes(received, expected) {
const matcherName = '.toHaveBeenCalledTimes';
ensureExpectedIsNumber(expected, matcherName);
ensureMock(received, matcherName);
const receivedIsSpy = isSpy(received);
const type = receivedIsSpy ? 'spy' : 'mock function';
const count = receivedIsSpy ?
received.calls.count() :
received.mock.calls.length;
const pass = count === expected;
const message = pass ?
() =>
matcherHint(
'.not' + matcherName,
RECEIVED_NAME[type],
String(expected)) +
`\n\n` +
`Expected ${type} not to be called ` +
`${EXPECTED_COLOR(pluralize('time', expected))}, but it was` +
` called exactly ${RECEIVED_COLOR(pluralize('time', count))}.` :
() =>
matcherHint(matcherName, RECEIVED_NAME[type], String(expected)) +
'\n\n' +
`Expected ${type} to have been called ` +
`${EXPECTED_COLOR(pluralize('time', expected))},` +
` but it was called ${RECEIVED_COLOR(pluralize('time', count))}.`;
return { message, pass };
},
toHaveBeenCalledWith: createToBeCalledWithMatcher('.toHaveBeenCalledWith'),
toHaveBeenLastCalledWith: createLastCalledWithMatcher(
'.toHaveBeenLastCalledWith') };
const isSpy = spy => spy.calls && typeof spy.calls.count === 'function';
const ensureMock = (mockOrSpy, matcherName) => {
if (
!mockOrSpy ||
(mockOrSpy.calls === undefined || mockOrSpy.calls.all === undefined) &&
mockOrSpy._isMockFunction !== true)
{
throw new Error(
matcherHint('[.not]' + matcherName, 'jest.fn()', '') +
'\n\n' +
`${RECEIVED_COLOR('jest.fn()')} value must be a mock function ` +
`or spy.\n` +
printWithType('Received', mockOrSpy, printReceived));
}
};
const formatReceivedCalls = (calls, limit, options) => {
if (calls.length) {
const but = options && options.sameSentence ? 'but' : 'But';
const count = calls.length - limit;
const printedCalls = calls.
slice(-limit).
reverse().
map(printReceived).
join(', ');
return (
`${but} it was ${options && options.isLast ? 'last ' : ''}called ` +
`with:\n ` +
printedCalls + (
count > 0 ?
'\nand ' + RECEIVED_COLOR(pluralize('more call', count)) + '.' :
''));
} else {
return `But it was ${RECEIVED_COLOR('not called')}.`;
}
};
module.exports = spyMatchers;

View File

@@ -0,0 +1,196 @@
'use strict';var _require =
require('jest-regex-util');const escapeStrForRegex = _require.escapeStrForRegex; /**
* Copyright (c) 2014, Facebook, Inc. All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
*
*/var _require2 = require('jest-message-util');const formatStackTrace = _require2.formatStackTrace,separateMessageFromStack = _require2.separateMessageFromStack;var _require3 =
require('jest-matcher-utils');const RECEIVED_BG = _require3.RECEIVED_BG,RECEIVED_COLOR = _require3.RECEIVED_COLOR,getType = _require3.getType,highlightTrailingWhitespace = _require3.highlightTrailingWhitespace,matcherHint = _require3.matcherHint,printExpected = _require3.printExpected,printWithType = _require3.printWithType;var _require4 =
require('./jasmine-utils');const equals = _require4.equals;
const createMatcher = matcherName => (
actual,
expected) =>
{
const value = expected;
let error;
if (typeof actual !== 'function') {
throw new Error(
matcherHint(matcherName, 'function', getType(value)) +
'\n\n' +
'Received value must be a function, but instead ' +
`"${getType(actual)}" was found`);
}
try {
actual();
} catch (e) {
error = e;
}
if (typeof expected === 'string') {
expected = new RegExp(escapeStrForRegex(expected));
}
if (typeof expected === 'function') {
return toThrowMatchingError(matcherName, error, expected);
} else if (expected instanceof RegExp) {
return toThrowMatchingStringOrRegexp(matcherName, error, expected, value);
} else if (expected && typeof expected === 'object') {
return toThrowMatchingErrorInstance(matcherName, error, expected);
} else if (expected === undefined) {
const pass = error !== undefined;
return {
message: pass ?
() =>
matcherHint('.not' + matcherName, 'function', '') +
'\n\n' +
'Expected the function not to throw an error.\n' +
printActualErrorMessage(error) :
() =>
matcherHint(matcherName, 'function', getType(value)) +
'\n\n' +
'Expected the function to throw an error.\n' +
printActualErrorMessage(error),
pass };
} else {
throw new Error(
matcherHint('.not' + matcherName, 'function', getType(value)) +
'\n\n' +
'Unexpected argument passed.\nExpected: ' +
`${printExpected('string')}, ${printExpected('Error (type)')} or ${printExpected('regexp')}.\n` +
printWithType('Got', String(expected), printExpected));
}
};
const matchers = {
toThrow: createMatcher('.toThrow'),
toThrowError: createMatcher('.toThrowError') };
const toThrowMatchingStringOrRegexp = (
name,
error,
pattern,
value) =>
{
if (error && !error.message && !error.name) {
error = new Error(error);
}
const pass = !!(error && error.message.match(pattern));
const message = pass ?
() =>
matcherHint('.not' + name, 'function', getType(value)) +
'\n\n' +
`Expected the function not to throw an error matching:\n` +
` ${printExpected(value)}\n` +
printActualErrorMessage(error) :
() =>
matcherHint(name, 'function', getType(value)) +
'\n\n' +
`Expected the function to throw an error matching:\n` +
` ${printExpected(value)}\n` +
printActualErrorMessage(error);
return { message, pass };
};
const toThrowMatchingErrorInstance = (
name,
error,
expectedError) =>
{
if (error && !error.message && !error.name) {
error = new Error(error);
}
const pass = equals(error, expectedError);
const message = pass ?
() =>
matcherHint('.not' + name, 'function', 'error') +
'\n\n' +
`Expected the function not to throw an error matching:\n` +
` ${printExpected(expectedError)}\n` +
printActualErrorMessage(error) :
() =>
matcherHint(name, 'function', 'error') +
'\n\n' +
`Expected the function to throw an error matching:\n` +
` ${printExpected(expectedError)}\n` +
printActualErrorMessage(error);
return { message, pass };
};
const toThrowMatchingError = (
name,
error,
ErrorClass) =>
{
const pass = !!(error && error instanceof ErrorClass);
const message = pass ?
() =>
matcherHint('.not' + name, 'function', 'type') +
'\n\n' +
`Expected the function not to throw an error of type:\n` +
` ${printExpected(ErrorClass.name)}\n` +
printActualErrorMessage(error) :
() =>
matcherHint(name, 'function', 'type') +
'\n\n' +
`Expected the function to throw an error of type:\n` +
` ${printExpected(ErrorClass.name)}\n` +
printActualErrorMessage(error);
return { message, pass };
};
const printActualErrorMessage = error => {
if (error) {var _separateMessageFromS =
separateMessageFromStack(error.stack);const message = _separateMessageFromS.message,stack = _separateMessageFromS.stack;
return (
`Instead, it threw:\n` +
RECEIVED_COLOR(
' ' +
highlightTrailingWhitespace(message, RECEIVED_BG) +
formatStackTrace(
stack,
{
rootDir: process.cwd(),
testMatch: [] },
{
noStackTrace: false })));
}
return `But it didn't throw anything.`;
};
module.exports = matchers;

View File

@@ -0,0 +1,97 @@
'use strict';
const hasOwnProperty = (object, value) =>
Object.prototype.hasOwnProperty.call(object, value); /**
* Copyright (c) 2014, Facebook, Inc. All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
*
*/const getPath = (object, propertyPath) => {if (!Array.isArray(propertyPath)) {propertyPath = propertyPath.split('.');}
const lastProp = propertyPath.length === 1;
if (propertyPath.length) {
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 broken and we return right away.
return {
hasEndProp: false,
lastTraversedObject: object,
traversedPath: [] };
} else {
const result = getPath(newObject, propertyPath.slice(1));
result.lastTraversedObject || (result.lastTraversedObject = object);
result.traversedPath.unshift(prop);
if (propertyPath.length === 1) {
result.hasEndProp = hasOwnProperty(object, prop);
if (!result.hasEndProp) {
delete result.value;
result.traversedPath.shift();
}
}
return result;
}
} else {
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.
const getObjectSubset = (object, subset) => {
if (Array.isArray(object)) {
if (Array.isArray(subset) && subset.length === object.length) {
return subset.map((sub, i) => getObjectSubset(object[i], sub));
}
} else if (object instanceof Date) {
return object;
} else if (
typeof object === 'object' &&
object !== null &&
typeof subset === 'object' &&
subset !== null)
{
const trimmed = {};
Object.keys(subset).
filter(key => object.hasOwnProperty(key)).
forEach(
key => trimmed[key] = getObjectSubset(object[key], subset[key]));
if (Object.keys(trimmed).length > 0) {
return trimmed;
}
}
return object;
};
module.exports = {
getObjectSubset,
getPath,
hasOwnProperty };