You're Invited:Meet the Socket Team at BlackHat and DEF CON in Las Vegas, Aug 7-8.RSVP
Socket
Socket
Sign inDemoInstall

@vitest/expect

Package Overview
Dependencies
Maintainers
4
Versions
86
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 2.0.0-beta.10 to 2.0.0-beta.11

1134

dist/index.js

@@ -11,3 +11,5 @@ import { getType, getColors, stringify, isObject, assertTypes } from '@vitest/utils';

const GLOBAL_EXPECT = Symbol.for("expect-global");
const ASYMMETRIC_MATCHERS_OBJECT = Symbol.for("asymmetric-matchers-object");
const ASYMMETRIC_MATCHERS_OBJECT = Symbol.for(
"asymmetric-matchers-object"
);

@@ -87,10 +89,13 @@ if (!Object.prototype.hasOwnProperty.call(globalThis, MATCHERS_OBJECT)) {

hint += DIM_COLOR(`${dimString}(`) + expectedColor(expected);
if (secondArgument)
if (secondArgument) {
hint += DIM_COLOR(", ") + secondArgumentColor(secondArgument);
}
dimString = ")";
}
if (comment !== "")
if (comment !== "") {
dimString += ` // ${comment}`;
if (dimString !== "")
}
if (dimString !== "") {
hint += DIM_COLOR(dimString);
}
return hint;

@@ -138,13 +143,18 @@ }

function hasAsymmetric(obj, seen = /* @__PURE__ */ new Set()) {
if (seen.has(obj))
if (seen.has(obj)) {
return false;
}
seen.add(obj);
if (isAsymmetric(obj))
if (isAsymmetric(obj)) {
return true;
if (Array.isArray(obj))
}
if (Array.isArray(obj)) {
return obj.some((i) => hasAsymmetric(i, seen));
if (obj instanceof Set)
}
if (obj instanceof Set) {
return Array.from(obj).some((i) => hasAsymmetric(i, seen));
if (isObject(obj))
}
if (isObject(obj)) {
return Object.values(obj).some((v) => hasAsymmetric(v, seen));
}
return false;

@@ -155,8 +165,11 @@ }

const asymmetricB = isAsymmetric(b);
if (asymmetricA && asymmetricB)
if (asymmetricA && asymmetricB) {
return void 0;
if (asymmetricA)
}
if (asymmetricA) {
return a.asymmetricMatch(b);
if (asymmetricB)
}
if (asymmetricB) {
return b.asymmetricMatch(a);
}
}

@@ -166,21 +179,33 @@ function eq(a, b, aStack, bStack, customTesters, hasKey2) {

const asymmetricResult = asymmetricMatch(a, b);
if (asymmetricResult !== void 0)
if (asymmetricResult !== void 0) {
return asymmetricResult;
}
const testerContext = { equals };
for (let i = 0; i < customTesters.length; i++) {
const customTesterResult = customTesters[i].call(testerContext, a, b, customTesters);
if (customTesterResult !== void 0)
const customTesterResult = customTesters[i].call(
testerContext,
a,
b,
customTesters
);
if (customTesterResult !== void 0) {
return customTesterResult;
}
}
if (a instanceof Error && b instanceof Error)
if (a instanceof Error && b instanceof Error) {
return a.message === b.message;
if (typeof URL === "function" && a instanceof URL && b instanceof URL)
}
if (typeof URL === "function" && a instanceof URL && b instanceof URL) {
return a.href === b.href;
if (Object.is(a, b))
}
if (Object.is(a, b)) {
return true;
if (a === null || b === null)
}
if (a === null || b === null) {
return a === b;
}
const className = Object.prototype.toString.call(a);
if (className !== Object.prototype.toString.call(b))
if (className !== Object.prototype.toString.call(b)) {
return false;
}
switch (className) {

@@ -205,27 +230,33 @@ case "[object Boolean]":

}
if (typeof a !== "object" || typeof b !== "object")
if (typeof a !== "object" || typeof b !== "object") {
return false;
if (isDomNode(a) && isDomNode(b))
}
if (isDomNode(a) && isDomNode(b)) {
return a.isEqualNode(b);
}
let length = aStack.length;
while (length--) {
if (aStack[length] === a)
if (aStack[length] === a) {
return bStack[length] === b;
else if (bStack[length] === b)
} else if (bStack[length] === b) {
return false;
}
}
aStack.push(a);
bStack.push(b);
if (className === "[object Array]" && a.length !== b.length)
if (className === "[object Array]" && a.length !== b.length) {
return false;
}
const aKeys = keys(a, hasKey2);
let key;
let size = aKeys.length;
if (keys(b, hasKey2).length !== size)
if (keys(b, hasKey2).length !== size) {
return false;
}
while (size--) {
key = aKeys[size];
result = hasKey2(b, key) && eq(a[key], b[key], aStack, bStack, customTesters, hasKey2);
if (!result)
if (!result) {
return false;
}
}

@@ -239,4 +270,5 @@ aStack.pop();

for (const key in obj) {
if (hasKey2(obj, key))
if (hasKey2(obj, key)) {
keys2.push(key);
}
}

@@ -262,4 +294,5 @@ return keys2.concat(

function fnNameFor(func) {
if (func.name)
if (func.name) {
return func.name;
}
const matches = functionToString.call(func).match(/^(?:async)?\s*function\s*(?:\*\s*)?([\w$]+)\s*\(/);

@@ -269,13 +302,17 @@ return matches ? matches[1] : "<anonymous>";

function getPrototype(obj) {
if (Object.getPrototypeOf)
if (Object.getPrototypeOf) {
return Object.getPrototypeOf(obj);
if (obj.constructor.prototype === obj)
}
if (obj.constructor.prototype === obj) {
return null;
}
return obj.constructor.prototype;
}
function hasProperty(obj, property) {
if (!obj)
if (!obj) {
return false;
if (Object.prototype.hasOwnProperty.call(obj, property))
}
if (Object.prototype.hasOwnProperty.call(obj, property)) {
return true;
}
return hasProperty(getPrototype(obj), property);

@@ -321,8 +358,10 @@ }

}
if (a.constructor !== b.constructor)
if (a.constructor !== b.constructor) {
return false;
}
let length = aStack.length;
while (length--) {
if (aStack[length] === a)
if (aStack[length] === a) {
return bStack[length] === b;
}
}

@@ -336,9 +375,3 @@ aStack.push(a);

function iterableEqualityWithStack(a2, b2) {
return iterableEquality(
a2,
b2,
[...customTesters],
[...aStack],
[...bStack]
);
return iterableEquality(a2, b2, [...customTesters], [...aStack], [...bStack]);
}

@@ -355,4 +388,5 @@ if (a.size !== void 0) {

const isEqual = equals(aValue, bValue, filteredCustomTesters);
if (isEqual === true)
if (isEqual === true) {
has = true;
}
}

@@ -374,8 +408,18 @@ if (has === false) {

for (const bEntry of b) {
const matchedKey = equals(aEntry[0], bEntry[0], filteredCustomTesters);
const matchedKey = equals(
aEntry[0],
bEntry[0],
filteredCustomTesters
);
let matchedValue = false;
if (matchedKey === true)
matchedValue = equals(aEntry[1], bEntry[1], filteredCustomTesters);
if (matchedValue === true)
if (matchedKey === true) {
matchedValue = equals(
aEntry[1],
bEntry[1],
filteredCustomTesters
);
}
if (matchedValue === true) {
has = true;
}
}

@@ -400,9 +444,11 @@ if (has === false) {

}
if (!bIterator.next().done)
if (!bIterator.next().done) {
return false;
}
if (!isImmutableList(a) && !isImmutableOrderedKeyed(a) && !isImmutableOrderedSet(a) && !isImmutableRecord(a)) {
const aEntries = Object.entries(a);
const bEntries = Object.entries(b);
if (!equals(aEntries, bEntries))
if (!equals(aEntries, bEntries)) {
return false;
}
}

@@ -415,4 +461,5 @@ aStack.pop();

const shouldTerminate = !object || typeof object !== "object" || object === Object.prototype;
if (shouldTerminate)
if (shouldTerminate) {
return false;
}
return Object.prototype.hasOwnProperty.call(object, key) || hasPropertyInObject(Object.getPrototypeOf(object), key);

@@ -424,10 +471,14 @@ }

function subsetEquality(object, subset, customTesters = []) {
const filteredCustomTesters = customTesters.filter((t) => t !== subsetEquality);
const filteredCustomTesters = customTesters.filter(
(t) => t !== subsetEquality
);
const subsetEqualityWithContext = (seenReferences = /* @__PURE__ */ new WeakMap()) => (object2, subset2) => {
if (!isObjectWithKeys(subset2))
if (!isObjectWithKeys(subset2)) {
return void 0;
}
return Object.keys(subset2).every((key) => {
if (subset2[key] != null && typeof subset2[key] === "object") {
if (seenReferences.has(subset2[key]))
if (seenReferences.has(subset2[key])) {
return equals(object2[key], subset2[key], filteredCustomTesters);
}
seenReferences.set(subset2[key], true);

@@ -446,4 +497,5 @@ }

function typeEquality(a, b) {
if (a == null || b == null || a.constructor === b.constructor)
if (a == null || b == null || a.constructor === b.constructor) {
return void 0;
}
return false;

@@ -455,4 +507,5 @@ }

if (!(a instanceof DataView && b instanceof DataView)) {
if (!(a instanceof ArrayBuffer) || !(b instanceof ArrayBuffer))
if (!(a instanceof ArrayBuffer) || !(b instanceof ArrayBuffer)) {
return void 0;
}
try {

@@ -465,7 +518,9 @@ dataViewA = new DataView(a);

}
if (dataViewA.byteLength !== dataViewB.byteLength)
if (dataViewA.byteLength !== dataViewB.byteLength) {
return false;
}
for (let i = 0; i < dataViewA.byteLength; i++) {
if (dataViewA.getUint8(i) !== dataViewB.getUint8(i))
if (dataViewA.getUint8(i) !== dataViewB.getUint8(i)) {
return false;
}
}

@@ -475,7 +530,10 @@ return true;

function sparseArrayEquality(a, b, customTesters = []) {
if (!Array.isArray(a) || !Array.isArray(b))
if (!Array.isArray(a) || !Array.isArray(b)) {
return void 0;
}
const aKeys = Object.keys(a);
const bKeys = Object.keys(b);
const filteredCustomTesters = customTesters.filter((t) => t !== sparseArrayEquality);
const filteredCustomTesters = customTesters.filter(
(t) => t !== sparseArrayEquality
);
return equals(a, b, filteredCustomTesters, true) && equals(aKeys, bKeys);

@@ -485,3 +543,3 @@ }

const toBeMessage = `expected ${expected} to be ${actual} // Object.is equality`;
if (["toStrictEqual", "toEqual"].includes(deepEqualityName))
if (["toStrictEqual", "toEqual"].includes(deepEqualityName)) {
return `${toBeMessage}

@@ -494,2 +552,3 @@

`;
}
return toBeMessage;

@@ -534,14 +593,22 @@ }

if (hasPropertyInObject(subset2, key)) {
trimmed[key] = seenReferences.has(object2[key]) ? seenReferences.get(object2[key]) : getObjectSubsetWithContext(seenReferences)(object2[key], subset2[key]);
trimmed[key] = seenReferences.has(object2[key]) ? seenReferences.get(object2[key]) : getObjectSubsetWithContext(seenReferences)(
object2[key],
subset2[key]
);
} else {
if (!seenReferences.has(object2[key])) {
stripped += 1;
if (isObject(object2[key]))
if (isObject(object2[key])) {
stripped += getObjectKeys(object2[key]).length;
getObjectSubsetWithContext(seenReferences)(object2[key], subset2[key]);
}
getObjectSubsetWithContext(seenReferences)(
object2[key],
subset2[key]
);
}
}
}
if (getObjectKeys(trimmed).length > 0)
if (getObjectKeys(trimmed).length > 0) {
return trimmed;
}
}

@@ -579,4 +646,5 @@ return object2;

const result = stringify(this, options.depth, { min: true });
if (result.length <= options.truncate)
if (result.length <= options.truncate) {
return result;
}
return `${this.toString()}{\u2026}`;

@@ -587,4 +655,5 @@ }

constructor(sample, inverse = false) {
if (!isA("String", sample))
if (!isA("String", sample)) {
throw new Error("Expected is not a string");
}
super(sample, inverse);

@@ -619,13 +688,17 @@ }

getPrototype(obj) {
if (Object.getPrototypeOf)
if (Object.getPrototypeOf) {
return Object.getPrototypeOf(obj);
if (obj.constructor.prototype === obj)
}
if (obj.constructor.prototype === obj) {
return null;
}
return obj.constructor.prototype;
}
hasProperty(obj, property) {
if (!obj)
if (!obj) {
return false;
if (Object.prototype.hasOwnProperty.call(obj, property))
}
if (Object.prototype.hasOwnProperty.call(obj, property)) {
return true;
}
return this.hasProperty(this.getPrototype(obj), property);

@@ -642,3 +715,7 @@ }

for (const property in this.sample) {
if (!this.hasProperty(other, property) || !equals(this.sample[property], other[property], matcherContext.customTesters)) {
if (!this.hasProperty(other, property) || !equals(
this.sample[property],
other[property],
matcherContext.customTesters
)) {
result = false;

@@ -669,3 +746,5 @@ break;

const result = this.sample.length === 0 || Array.isArray(other) && this.sample.every(
(item) => other.some((another) => equals(item, another, matcherContext.customTesters))
(item) => other.some(
(another) => equals(item, another, matcherContext.customTesters)
)
);

@@ -691,4 +770,5 @@ return this.inverse ? !result : result;

fnNameFor(func) {
if (func.name)
if (func.name) {
return func.name;
}
const functionToString = Function.prototype.toString;

@@ -699,16 +779,23 @@ const matches = functionToString.call(func).match(/^(?:async)?\s*function\s*(?:\*\s*)?([\w$]+)\s*\(/);

asymmetricMatch(other) {
if (this.sample === String)
if (this.sample === String) {
return typeof other == "string" || other instanceof String;
if (this.sample === Number)
}
if (this.sample === Number) {
return typeof other == "number" || other instanceof Number;
if (this.sample === Function)
}
if (this.sample === Function) {
return typeof other == "function" || other instanceof Function;
if (this.sample === Boolean)
}
if (this.sample === Boolean) {
return typeof other == "boolean" || other instanceof Boolean;
if (this.sample === BigInt)
}
if (this.sample === BigInt) {
return typeof other == "bigint" || other instanceof BigInt;
if (this.sample === Symbol)
}
if (this.sample === Symbol) {
return typeof other == "symbol" || other instanceof Symbol;
if (this.sample === Object)
}
if (this.sample === Object) {
return typeof other == "object";
}
return other instanceof this.sample;

@@ -720,12 +807,17 @@ }

getExpectedType() {
if (this.sample === String)
if (this.sample === String) {
return "string";
if (this.sample === Number)
}
if (this.sample === Number) {
return "number";
if (this.sample === Function)
}
if (this.sample === Function) {
return "function";
if (this.sample === Object)
}
if (this.sample === Object) {
return "object";
if (this.sample === Boolean)
}
if (this.sample === Boolean) {
return "boolean";
}
return this.fnNameFor(this.sample);

@@ -739,4 +831,5 @@ }

constructor(sample, inverse = false) {
if (!isA("String", sample) && !isA("RegExp", sample))
if (!isA("String", sample) && !isA("RegExp", sample)) {
throw new Error("Expected is not a String or a RegExp");
}
super(new RegExp(sample), inverse);

@@ -758,6 +851,8 @@ }

constructor(sample, precision = 2, inverse = false) {
if (!isA("Number", sample))
if (!isA("Number", sample)) {
throw new Error("Expected is not a Number");
if (!isA("Number", precision))
}
if (!isA("Number", precision)) {
throw new Error("Precision is not a Number");
}
super(sample);

@@ -768,4 +863,5 @@ this.inverse = inverse;

asymmetricMatch(other) {
if (!isA("Number", other))
if (!isA("Number", other)) {
return false;
}
let result = false;

@@ -796,14 +892,6 @@ if (other === Number.POSITIVE_INFINITY && this.sample === Number.POSITIVE_INFINITY) {

const JestAsymmetricMatchers = (chai, utils) => {
utils.addMethod(chai.expect, "anything", () => new Anything());
utils.addMethod(chai.expect, "any", (expected) => new Any(expected));
utils.addMethod(
chai.expect,
"anything",
() => new Anything()
);
utils.addMethod(
chai.expect,
"any",
(expected) => new Any(expected)
);
utils.addMethod(
chai.expect,
"stringContaining",

@@ -845,7 +933,9 @@ (expected) => new StringContaining(expected)

const index = test.promises.indexOf(promise);
if (index !== -1)
if (index !== -1) {
test.promises.splice(index, 1);
}
});
if (!test.promises)
if (!test.promises) {
test.promises = [];
}
test.promises.push(promise);

@@ -858,7 +948,9 @@ }

var _a;
if (!utils.flag(this, "soft"))
if (!utils.flag(this, "soft")) {
return fn.apply(this, args);
}
const test = utils.flag(this, "vitest-test");
if (!test)
if (!test) {
throw new Error("expect.soft() can only be used inside a test");
}
try {

@@ -883,8 +975,13 @@ return fn.apply(this, args);

utils.addMethod(chai.Assertion.prototype, n, softWrapper);
utils.addMethod(globalThis[JEST_MATCHERS_OBJECT].matchers, n, softWrapper);
utils.addMethod(
globalThis[JEST_MATCHERS_OBJECT].matchers,
n,
softWrapper
);
};
if (Array.isArray(name))
if (Array.isArray(name)) {
name.forEach((n) => addMethod(n));
else
} else {
addMethod(name);
}
}

@@ -922,7 +1019,6 @@ ["throw", "throws", "Throw"].forEach((m) => {

const actual = utils.flag(this, "object");
const equal = equals(
actual,
expected,
[...customTesters, iterableEquality]
);
const equal = equals(actual, expected, [
...customTesters,
iterableEquality
]);
return this.assert(

@@ -978,9 +1074,9 @@ equal,

} else {
const toEqualPass = equals(
actual,
expected,
[...customTesters, iterableEquality]
);
if (toEqualPass)
const toEqualPass = equals(actual, expected, [
...customTesters,
iterableEquality
]);
if (toEqualPass) {
deepEqualityName = "toEqual";
}
}

@@ -998,20 +1094,28 @@ }

const actual = this._obj;
const pass = equals(actual, expected, [...customTesters, iterableEquality, subsetEquality]);
const pass = equals(actual, expected, [
...customTesters,
iterableEquality,
subsetEquality
]);
const isNot = utils.flag(this, "negate");
const { subset: actualSubset, stripped } = getObjectSubset(actual, expected);
const { subset: actualSubset, stripped } = getObjectSubset(
actual,
expected
);
if (pass && isNot || !pass && !isNot) {
const msg = utils.getMessage(
this,
[
pass,
"expected #{this} to match object #{exp}",
"expected #{this} to not match object #{exp}",
expected,
actualSubset,
false
]
);
const msg = utils.getMessage(this, [
pass,
"expected #{this} to match object #{exp}",
"expected #{this} to not match object #{exp}",
expected,
actualSubset,
false
]);
const message = stripped === 0 ? msg : `${msg}
(${stripped} matching ${stripped === 1 ? "property" : "properties"} omitted from actual)`;
throw new AssertionError(message, { showDiff: true, expected, actual: actualSubset });
throw new AssertionError(message, {
showDiff: true,
expected,
actual: actualSubset
});
}

@@ -1021,4 +1125,7 @@ });

const actual = this._obj;
if (typeof actual !== "string")
throw new TypeError(`.toMatch() expects to receive a string, but got ${typeof actual}`);
if (typeof actual !== "string") {
throw new TypeError(
`.toMatch() expects to receive a string, but got ${typeof actual}`
);
}
return this.assert(

@@ -1035,4 +1142,7 @@ typeof expected === "string" ? actual.includes(expected) : actual.match(expected),

if (typeof Node !== "undefined" && actual instanceof Node) {
if (!(item instanceof Node))
throw new TypeError(`toContain() expected a DOM node as the argument, but got ${typeof item}`);
if (!(item instanceof Node)) {
throw new TypeError(
`toContain() expected a DOM node as the argument, but got ${typeof item}`
);
}
return this.assert(

@@ -1067,4 +1177,5 @@ actual.contains(item),

}
if (actual != null && typeof actual !== "string")
if (actual != null && typeof actual !== "string") {
utils.flag(this, "object", Array.from(actual));
}
return this.contain(item);

@@ -1168,17 +1279,21 @@ });

utils.flag(this, "negate", false);
if (negate)
if (negate) {
return this.be.undefined;
}
return this.not.be.undefined;
});
def("toBeTypeOf", function(expected) {
const actual = typeof this._obj;
const equal = expected === actual;
return this.assert(
equal,
"expected #{this} to be type of #{exp}",
"expected #{this} not to be type of #{exp}",
expected,
actual
);
});
def(
"toBeTypeOf",
function(expected) {
const actual = typeof this._obj;
const equal = expected === actual;
return this.assert(
equal,
"expected #{this} to be type of #{exp}",
"expected #{this} not to be type of #{exp}",
expected,
actual
);
}
);
def("toBeInstanceOf", function(obj) {

@@ -1190,24 +1305,32 @@ return this.instanceOf(obj);

});
def("toHaveProperty", function(...args) {
if (Array.isArray(args[0]))
args[0] = args[0].map((key) => String(key).replace(/([.[\]])/g, "\\$1")).join(".");
const actual = this._obj;
const [propertyName, expected] = args;
const getValue = () => {
const hasOwn = Object.prototype.hasOwnProperty.call(actual, propertyName);
if (hasOwn)
return { value: actual[propertyName], exists: true };
return utils.getPathInfo(actual, propertyName);
};
const { value, exists } = getValue();
const pass = exists && (args.length === 1 || equals(expected, value, customTesters));
const valueString = args.length === 1 ? "" : ` with value ${utils.objDisplay(expected)}`;
return this.assert(
pass,
`expected #{this} to have property "${propertyName}"${valueString}`,
`expected #{this} to not have property "${propertyName}"${valueString}`,
expected,
exists ? value : void 0
);
});
def(
"toHaveProperty",
function(...args) {
if (Array.isArray(args[0])) {
args[0] = args[0].map((key) => String(key).replace(/([.[\]])/g, "\\$1")).join(".");
}
const actual = this._obj;
const [propertyName, expected] = args;
const getValue = () => {
const hasOwn = Object.prototype.hasOwnProperty.call(
actual,
propertyName
);
if (hasOwn) {
return { value: actual[propertyName], exists: true };
}
return utils.getPathInfo(actual, propertyName);
};
const { value, exists } = getValue();
const pass = exists && (args.length === 1 || equals(expected, value, customTesters));
const valueString = args.length === 1 ? "" : ` with value ${utils.objDisplay(expected)}`;
return this.assert(
pass,
`expected #{this} to have property "${propertyName}"${valueString}`,
`expected #{this} to not have property "${propertyName}"${valueString}`,
expected,
exists ? value : void 0
);
}
);
def("toBeCloseTo", function(received, precision = 2) {

@@ -1237,4 +1360,7 @@ const expected = this._obj;

const assertIsMock = (assertion) => {
if (!isMockFunction(assertion._obj))
throw new TypeError(`${utils.inspect(assertion._obj)} is not a spy or a call to a spy!`);
if (!isMockFunction(assertion._obj)) {
throw new TypeError(
`${utils.inspect(assertion._obj)} is not a spy or a call to a spy!`
);
}
};

@@ -1248,8 +1374,11 @@ const getSpy = (assertion) => {

const k = i % 100;
if (j === 1 && k !== 11)
if (j === 1 && k !== 11) {
return `${i}st`;
if (j === 2 && k !== 12)
}
if (j === 2 && k !== 12) {
return `${i}nd`;
if (j === 3 && k !== 13)
}
if (j === 3 && k !== 13) {
return `${i}rd`;
}
return `${i}th`;

@@ -1259,3 +1388,4 @@ };

if (spy.mock.calls) {
msg += c().gray(`
msg += c().gray(
`

@@ -1265,21 +1395,30 @@ Received:

${spy.mock.calls.map((callArg, i) => {
let methodCall = c().bold(` ${ordinalOf(i + 1)} ${spy.getMockName()} call:
let methodCall = c().bold(
` ${ordinalOf(i + 1)} ${spy.getMockName()} call:
`);
if (showActualCall)
methodCall += diff(showActualCall, callArg, { omitAnnotationLines: true });
else
methodCall += stringify(callArg).split("\n").map((line) => ` ${line}`).join("\n");
methodCall += "\n";
return methodCall;
}).join("\n")}`);
`
);
if (showActualCall) {
methodCall += diff(showActualCall, callArg, {
omitAnnotationLines: true
});
} else {
methodCall += stringify(callArg).split("\n").map((line) => ` ${line}`).join("\n");
}
methodCall += "\n";
return methodCall;
}).join("\n")}`
);
}
msg += c().gray(`
msg += c().gray(
`
Number of calls: ${c().bold(spy.mock.calls.length)}
`);
`
);
return msg;
};
const formatReturns = (spy, results, msg, showActualReturn) => {
msg += c().gray(`
msg += c().gray(
`

@@ -1289,16 +1428,24 @@ Received:

${results.map((callReturn, i) => {
let methodCall = c().bold(` ${ordinalOf(i + 1)} ${spy.getMockName()} call return:
let methodCall = c().bold(
` ${ordinalOf(i + 1)} ${spy.getMockName()} call return:
`);
if (showActualReturn)
methodCall += diff(showActualReturn, callReturn.value, { omitAnnotationLines: true });
else
methodCall += stringify(callReturn).split("\n").map((line) => ` ${line}`).join("\n");
methodCall += "\n";
return methodCall;
}).join("\n")}`);
msg += c().gray(`
`
);
if (showActualReturn) {
methodCall += diff(showActualReturn, callReturn.value, {
omitAnnotationLines: true
});
} else {
methodCall += stringify(callReturn).split("\n").map((line) => ` ${line}`).join("\n");
}
methodCall += "\n";
return methodCall;
}).join("\n")}`
);
msg += c().gray(
`
Number of calls: ${c().bold(spy.mock.calls.length)}
`);
`
);
return msg;

@@ -1338,16 +1485,15 @@ };

const isNot = utils.flag(this, "negate");
let msg = utils.getMessage(
this,
[
called,
`expected "${spyName}" to be called at least once`,
`expected "${spyName}" to not be called at all, but actually been called ${callCount} times`,
true,
called
]
);
if (called && isNot)
let msg = utils.getMessage(this, [
called,
`expected "${spyName}" to be called at least once`,
`expected "${spyName}" to not be called at all, but actually been called ${callCount} times`,
true,
called
]);
if (called && isNot) {
msg = formatCalls(spy, msg);
if (called && isNot || !called && !isNot)
}
if (called && isNot || !called && !isNot) {
throw new AssertionError(msg);
}
});

@@ -1357,109 +1503,125 @@ def(["toHaveBeenCalledWith", "toBeCalledWith"], function(...args) {

const spyName = spy.getMockName();
const pass = spy.mock.calls.some((callArg) => equals(callArg, args, [...customTesters, iterableEquality]));
const pass = spy.mock.calls.some(
(callArg) => equals(callArg, args, [...customTesters, iterableEquality])
);
const isNot = utils.flag(this, "negate");
const msg = utils.getMessage(
this,
[
pass,
`expected "${spyName}" to be called with arguments: #{exp}`,
`expected "${spyName}" to not be called with arguments: #{exp}`,
args
]
);
if (pass && isNot || !pass && !isNot)
const msg = utils.getMessage(this, [
pass,
`expected "${spyName}" to be called with arguments: #{exp}`,
`expected "${spyName}" to not be called with arguments: #{exp}`,
args
]);
if (pass && isNot || !pass && !isNot) {
throw new AssertionError(formatCalls(spy, msg, args));
}
});
def(["toHaveBeenNthCalledWith", "nthCalledWith"], function(times, ...args) {
const spy = getSpy(this);
const spyName = spy.getMockName();
const nthCall = spy.mock.calls[times - 1];
const callCount = spy.mock.calls.length;
const isCalled = times <= callCount;
this.assert(
equals(nthCall, args, [...customTesters, iterableEquality]),
`expected ${ordinalOf(times)} "${spyName}" call to have been called with #{exp}${isCalled ? `` : `, but called only ${callCount} times`}`,
`expected ${ordinalOf(times)} "${spyName}" call to not have been called with #{exp}`,
args,
nthCall,
isCalled
);
});
def(["toHaveBeenLastCalledWith", "lastCalledWith"], function(...args) {
const spy = getSpy(this);
const spyName = spy.getMockName();
const lastCall = spy.mock.calls[spy.mock.calls.length - 1];
this.assert(
equals(lastCall, args, [...customTesters, iterableEquality]),
`expected last "${spyName}" call to have been called with #{exp}`,
`expected last "${spyName}" call to not have been called with #{exp}`,
args,
lastCall
);
});
def(["toThrow", "toThrowError"], function(expected) {
if (typeof expected === "string" || typeof expected === "undefined" || expected instanceof RegExp)
return this.throws(expected);
const obj = this._obj;
const promise = utils.flag(this, "promise");
const isNot = utils.flag(this, "negate");
let thrown = null;
if (promise === "rejects") {
thrown = obj;
} else if (promise === "resolves" && typeof obj !== "function") {
if (!isNot) {
const message = utils.flag(this, "message") || "expected promise to throw an error, but it didn't";
const error = {
showDiff: false
};
throw new AssertionError(message, error, utils.flag(this, "ssfi"));
def(
["toHaveBeenNthCalledWith", "nthCalledWith"],
function(times, ...args) {
const spy = getSpy(this);
const spyName = spy.getMockName();
const nthCall = spy.mock.calls[times - 1];
const callCount = spy.mock.calls.length;
const isCalled = times <= callCount;
this.assert(
equals(nthCall, args, [...customTesters, iterableEquality]),
`expected ${ordinalOf(
times
)} "${spyName}" call to have been called with #{exp}${isCalled ? `` : `, but called only ${callCount} times`}`,
`expected ${ordinalOf(
times
)} "${spyName}" call to not have been called with #{exp}`,
args,
nthCall,
isCalled
);
}
);
def(
["toHaveBeenLastCalledWith", "lastCalledWith"],
function(...args) {
const spy = getSpy(this);
const spyName = spy.getMockName();
const lastCall = spy.mock.calls[spy.mock.calls.length - 1];
this.assert(
equals(lastCall, args, [...customTesters, iterableEquality]),
`expected last "${spyName}" call to have been called with #{exp}`,
`expected last "${spyName}" call to not have been called with #{exp}`,
args,
lastCall
);
}
);
def(
["toThrow", "toThrowError"],
function(expected) {
if (typeof expected === "string" || typeof expected === "undefined" || expected instanceof RegExp) {
return this.throws(expected);
}
const obj = this._obj;
const promise = utils.flag(this, "promise");
const isNot = utils.flag(this, "negate");
let thrown = null;
if (promise === "rejects") {
thrown = obj;
} else if (promise === "resolves" && typeof obj !== "function") {
if (!isNot) {
const message = utils.flag(this, "message") || "expected promise to throw an error, but it didn't";
const error = {
showDiff: false
};
throw new AssertionError(message, error, utils.flag(this, "ssfi"));
} else {
return;
}
} else {
return;
let isThrow = false;
try {
obj();
} catch (err) {
isThrow = true;
thrown = err;
}
if (!isThrow && !isNot) {
const message = utils.flag(this, "message") || "expected function to throw an error, but it didn't";
const error = {
showDiff: false
};
throw new AssertionError(message, error, utils.flag(this, "ssfi"));
}
}
} else {
let isThrow = false;
try {
obj();
} catch (err) {
isThrow = true;
thrown = err;
if (typeof expected === "function") {
const name = expected.name || expected.prototype.constructor.name;
return this.assert(
thrown && thrown instanceof expected,
`expected error to be instance of ${name}`,
`expected error not to be instance of ${name}`,
expected,
thrown
);
}
if (!isThrow && !isNot) {
const message = utils.flag(this, "message") || "expected function to throw an error, but it didn't";
const error = {
showDiff: false
};
throw new AssertionError(message, error, utils.flag(this, "ssfi"));
if (expected instanceof Error) {
return this.assert(
thrown && expected.message === thrown.message,
`expected error to have message: ${expected.message}`,
`expected error not to have message: ${expected.message}`,
expected.message,
thrown && thrown.message
);
}
}
if (typeof expected === "function") {
const name = expected.name || expected.prototype.constructor.name;
return this.assert(
thrown && thrown instanceof expected,
`expected error to be instance of ${name}`,
`expected error not to be instance of ${name}`,
expected,
thrown
if (typeof expected === "object" && "asymmetricMatch" in expected && typeof expected.asymmetricMatch === "function") {
const matcher = expected;
return this.assert(
thrown && matcher.asymmetricMatch(thrown),
"expected error to match asymmetric matcher",
"expected error not to match asymmetric matcher",
matcher,
thrown
);
}
throw new Error(
`"toThrow" expects string, RegExp, function, Error instance or asymmetric matcher, got "${typeof expected}"`
);
}
if (expected instanceof Error) {
return this.assert(
thrown && expected.message === thrown.message,
`expected error to have message: ${expected.message}`,
`expected error not to have message: ${expected.message}`,
expected.message,
thrown && thrown.message
);
}
if (typeof expected === "object" && "asymmetricMatch" in expected && typeof expected.asymmetricMatch === "function") {
const matcher = expected;
return this.assert(
thrown && matcher.asymmetricMatch(thrown),
"expected error to match asymmetric matcher",
"expected error not to match asymmetric matcher",
matcher,
thrown
);
}
throw new Error(`"toThrow" expects string, RegExp, function, Error instance or asymmetric matcher, got "${typeof expected}"`);
});
);
[

@@ -1494,3 +1656,6 @@ {

name: "toHaveResolvedTimes",
condition: (spy, times) => spy.mock.settledResults.reduce((s, { type }) => type === "fulfilled" ? ++s : s, 0) === times,
condition: (spy, times) => spy.mock.settledResults.reduce(
(s, { type }) => type === "fulfilled" ? ++s : s,
0
) === times,
action: "resolved"

@@ -1500,3 +1665,6 @@ },

name: ["toHaveReturnedTimes", "toReturnTimes"],
condition: (spy, times) => spy.mock.results.reduce((s, { type }) => type === "throw" ? s : ++s, 0) === times,
condition: (spy, times) => spy.mock.results.reduce(
(s, { type }) => type === "throw" ? s : ++s,
0
) === times,
action: "called"

@@ -1522,3 +1690,5 @@ }

name: "toHaveResolvedWith",
condition: (spy, value) => spy.mock.settledResults.some(({ type, value: result }) => type === "fulfilled" && equals(value, result)),
condition: (spy, value) => spy.mock.settledResults.some(
({ type, value: result }) => type === "fulfilled" && equals(value, result)
),
action: "resolve"

@@ -1528,3 +1698,5 @@ },

name: ["toHaveReturnedWith", "toReturnWith"],
condition: (spy, value) => spy.mock.results.some(({ type, value: result }) => type === "return" && equals(value, result)),
condition: (spy, value) => spy.mock.results.some(
({ type, value: result }) => type === "return" && equals(value, result)
),
action: "return"

@@ -1539,11 +1711,8 @@ }

const spyName = spy.getMockName();
const msg = utils.getMessage(
this,
[
pass,
`expected "${spyName}" to ${action} with: #{exp} at least once`,
`expected "${spyName}" to not ${action} with: #{exp}`,
value
]
);
const msg = utils.getMessage(this, [
pass,
`expected "${spyName}" to ${action} with: #{exp} at least once`,
`expected "${spyName}" to not ${action} with: #{exp}`,
value
]);
const results = action === "return" ? spy.mock.results : spy.mock.settledResults;

@@ -1623,80 +1792,117 @@ throw new AssertionError(formatReturns(spy, results, msg, value));

def("withContext", function(context) {
for (const key in context)
for (const key in context) {
utils.flag(this, key, context[key]);
}
return this;
});
utils.addProperty(chai.Assertion.prototype, "resolves", function __VITEST_RESOLVES__() {
const error = new Error("resolves");
utils.flag(this, "promise", "resolves");
utils.flag(this, "error", error);
const test = utils.flag(this, "vitest-test");
const obj = utils.flag(this, "object");
if (utils.flag(this, "poll"))
throw new SyntaxError(`expect.poll() is not supported in combination with .resolves`);
if (typeof (obj == null ? void 0 : obj.then) !== "function")
throw new TypeError(`You must provide a Promise to expect() when using .resolves, not '${typeof obj}'.`);
const proxy = new Proxy(this, {
get: (target, key, receiver) => {
const result = Reflect.get(target, key, receiver);
if (typeof result !== "function")
return result instanceof chai.Assertion ? proxy : result;
return async (...args) => {
const promise = obj.then(
(value) => {
utils.flag(this, "object", value);
return result.call(this, ...args);
},
(err) => {
const _error = new AssertionError(
`promise rejected "${utils.inspect(err)}" instead of resolving`,
{ showDiff: false }
);
_error.cause = err;
_error.stack = error.stack.replace(error.message, _error.message);
throw _error;
}
);
return recordAsyncExpect(test, promise);
};
utils.addProperty(
chai.Assertion.prototype,
"resolves",
function __VITEST_RESOLVES__() {
const error = new Error("resolves");
utils.flag(this, "promise", "resolves");
utils.flag(this, "error", error);
const test = utils.flag(this, "vitest-test");
const obj = utils.flag(this, "object");
if (utils.flag(this, "poll")) {
throw new SyntaxError(
`expect.poll() is not supported in combination with .resolves`
);
}
});
return proxy;
});
utils.addProperty(chai.Assertion.prototype, "rejects", function __VITEST_REJECTS__() {
const error = new Error("rejects");
utils.flag(this, "promise", "rejects");
utils.flag(this, "error", error);
const test = utils.flag(this, "vitest-test");
const obj = utils.flag(this, "object");
const wrapper = typeof obj === "function" ? obj() : obj;
if (utils.flag(this, "poll"))
throw new SyntaxError(`expect.poll() is not supported in combination with .rejects`);
if (typeof (wrapper == null ? void 0 : wrapper.then) !== "function")
throw new TypeError(`You must provide a Promise to expect() when using .rejects, not '${typeof wrapper}'.`);
const proxy = new Proxy(this, {
get: (target, key, receiver) => {
const result = Reflect.get(target, key, receiver);
if (typeof result !== "function")
return result instanceof chai.Assertion ? proxy : result;
return async (...args) => {
const promise = wrapper.then(
(value) => {
const _error = new AssertionError(
`promise resolved "${utils.inspect(value)}" instead of rejecting`,
{ showDiff: true, expected: new Error("rejected promise"), actual: value }
);
_error.stack = error.stack.replace(error.message, _error.message);
throw _error;
},
(err) => {
utils.flag(this, "object", err);
return result.call(this, ...args);
}
);
return recordAsyncExpect(test, promise);
};
if (typeof (obj == null ? void 0 : obj.then) !== "function") {
throw new TypeError(
`You must provide a Promise to expect() when using .resolves, not '${typeof obj}'.`
);
}
});
return proxy;
});
const proxy = new Proxy(this, {
get: (target, key, receiver) => {
const result = Reflect.get(target, key, receiver);
if (typeof result !== "function") {
return result instanceof chai.Assertion ? proxy : result;
}
return async (...args) => {
const promise = obj.then(
(value) => {
utils.flag(this, "object", value);
return result.call(this, ...args);
},
(err) => {
const _error = new AssertionError(
`promise rejected "${utils.inspect(
err
)}" instead of resolving`,
{ showDiff: false }
);
_error.cause = err;
_error.stack = error.stack.replace(
error.message,
_error.message
);
throw _error;
}
);
return recordAsyncExpect(test, promise);
};
}
});
return proxy;
}
);
utils.addProperty(
chai.Assertion.prototype,
"rejects",
function __VITEST_REJECTS__() {
const error = new Error("rejects");
utils.flag(this, "promise", "rejects");
utils.flag(this, "error", error);
const test = utils.flag(this, "vitest-test");
const obj = utils.flag(this, "object");
const wrapper = typeof obj === "function" ? obj() : obj;
if (utils.flag(this, "poll")) {
throw new SyntaxError(
`expect.poll() is not supported in combination with .rejects`
);
}
if (typeof (wrapper == null ? void 0 : wrapper.then) !== "function") {
throw new TypeError(
`You must provide a Promise to expect() when using .rejects, not '${typeof wrapper}'.`
);
}
const proxy = new Proxy(this, {
get: (target, key, receiver) => {
const result = Reflect.get(target, key, receiver);
if (typeof result !== "function") {
return result instanceof chai.Assertion ? proxy : result;
}
return async (...args) => {
const promise = wrapper.then(
(value) => {
const _error = new AssertionError(
`promise resolved "${utils.inspect(
value
)}" instead of rejecting`,
{
showDiff: true,
expected: new Error("rejected promise"),
actual: value
}
);
_error.stack = error.stack.replace(
error.message,
_error.message
);
throw _error;
},
(err) => {
utils.flag(this, "object", err);
return result.call(this, ...args);
}
);
return recordAsyncExpect(test, promise);
};
}
});
return proxy;
}
);
};

@@ -1742,69 +1948,89 @@

return (_, utils) => {
Object.entries(matchers).forEach(([expectAssertionName, expectAssertion]) => {
function expectWrapper(...args) {
const { state, isNot, obj } = getMatcherState(this, expect);
const result = expectAssertion.call(state, obj, ...args);
if (result && typeof result === "object" && result instanceof Promise) {
return result.then(({ pass: pass2, message: message2, actual: actual2, expected: expected2 }) => {
if (pass2 && isNot || !pass2 && !isNot)
throw new JestExtendError(message2(), actual2, expected2);
});
Object.entries(matchers).forEach(
([expectAssertionName, expectAssertion]) => {
function expectWrapper(...args) {
const { state, isNot, obj } = getMatcherState(this, expect);
const result = expectAssertion.call(state, obj, ...args);
if (result && typeof result === "object" && result instanceof Promise) {
return result.then(({ pass: pass2, message: message2, actual: actual2, expected: expected2 }) => {
if (pass2 && isNot || !pass2 && !isNot) {
throw new JestExtendError(message2(), actual2, expected2);
}
});
}
const { pass, message, actual, expected } = result;
if (pass && isNot || !pass && !isNot) {
throw new JestExtendError(message(), actual, expected);
}
}
const { pass, message, actual, expected } = result;
if (pass && isNot || !pass && !isNot)
throw new JestExtendError(message(), actual, expected);
}
const softWrapper = wrapSoft(utils, expectWrapper);
utils.addMethod(globalThis[JEST_MATCHERS_OBJECT].matchers, expectAssertionName, softWrapper);
utils.addMethod(c.Assertion.prototype, expectAssertionName, softWrapper);
class CustomMatcher extends AsymmetricMatcher {
constructor(inverse = false, ...sample) {
super(sample, inverse);
const softWrapper = wrapSoft(utils, expectWrapper);
utils.addMethod(
globalThis[JEST_MATCHERS_OBJECT].matchers,
expectAssertionName,
softWrapper
);
utils.addMethod(
c.Assertion.prototype,
expectAssertionName,
softWrapper
);
class CustomMatcher extends AsymmetricMatcher {
constructor(inverse = false, ...sample) {
super(sample, inverse);
}
asymmetricMatch(other) {
const { pass } = expectAssertion.call(
this.getMatcherContext(expect),
other,
...this.sample
);
return this.inverse ? !pass : pass;
}
toString() {
return `${this.inverse ? "not." : ""}${expectAssertionName}`;
}
getExpectedType() {
return "any";
}
toAsymmetricMatcher() {
return `${this.toString()}<${this.sample.map(String).join(", ")}>`;
}
}
asymmetricMatch(other) {
const { pass } = expectAssertion.call(
this.getMatcherContext(expect),
other,
...this.sample
);
return this.inverse ? !pass : pass;
}
toString() {
return `${this.inverse ? "not." : ""}${expectAssertionName}`;
}
getExpectedType() {
return "any";
}
toAsymmetricMatcher() {
return `${this.toString()}<${this.sample.map(String).join(", ")}>`;
}
const customMatcher = (...sample) => new CustomMatcher(false, ...sample);
Object.defineProperty(expect, expectAssertionName, {
configurable: true,
enumerable: true,
value: customMatcher,
writable: true
});
Object.defineProperty(expect.not, expectAssertionName, {
configurable: true,
enumerable: true,
value: (...sample) => new CustomMatcher(true, ...sample),
writable: true
});
Object.defineProperty(
globalThis[ASYMMETRIC_MATCHERS_OBJECT],
expectAssertionName,
{
configurable: true,
enumerable: true,
value: customMatcher,
writable: true
}
);
}
const customMatcher = (...sample) => new CustomMatcher(false, ...sample);
Object.defineProperty(expect, expectAssertionName, {
configurable: true,
enumerable: true,
value: customMatcher,
writable: true
});
Object.defineProperty(expect.not, expectAssertionName, {
configurable: true,
enumerable: true,
value: (...sample) => new CustomMatcher(true, ...sample),
writable: true
});
Object.defineProperty(globalThis[ASYMMETRIC_MATCHERS_OBJECT], expectAssertionName, {
configurable: true,
enumerable: true,
value: customMatcher,
writable: true
});
});
);
};
}
const JestExtend = (chai, utils) => {
utils.addMethod(chai.expect, "extend", (expect, expects) => {
use(JestExtendPlugin(chai, expect, expects));
});
utils.addMethod(
chai.expect,
"extend",
(expect, expects) => {
use(JestExtendPlugin(chai, expect, expects));
}
);
};
export { ASYMMETRIC_MATCHERS_OBJECT, Any, Anything, ArrayContaining, AsymmetricMatcher, GLOBAL_EXPECT, JEST_MATCHERS_OBJECT, JestAsymmetricMatchers, JestChaiExpect, JestExtend, MATCHERS_OBJECT, ObjectContaining, StringContaining, StringMatching, addCustomEqualityTesters, arrayBufferEquality, equals, fnNameFor, generateToBeMessage, getObjectKeys, getObjectSubset, getState, hasAsymmetric, hasProperty, isA, isAsymmetric, isImmutableUnorderedKeyed, isImmutableUnorderedSet, iterableEquality, pluralize, setState, sparseArrayEquality, subsetEquality, typeEquality };
{
"name": "@vitest/expect",
"type": "module",
"version": "2.0.0-beta.10",
"version": "2.0.0-beta.11",
"description": "Jest's expect matchers as a Chai plugin",

@@ -34,4 +34,4 @@ "license": "MIT",

"chai": "^5.1.1",
"@vitest/spy": "2.0.0-beta.10",
"@vitest/utils": "2.0.0-beta.10"
"@vitest/spy": "2.0.0-beta.11",
"@vitest/utils": "2.0.0-beta.11"
},

@@ -42,3 +42,3 @@ "devDependencies": {

"rollup-plugin-copy": "^3.5.0",
"@vitest/runner": "2.0.0-beta.10"
"@vitest/runner": "2.0.0-beta.11"
},

@@ -45,0 +45,0 @@ "scripts": {

@@ -9,3 +9,7 @@ # @vitest/expect

import * as chai from 'chai'
import { JestAsymmetricMatchers, JestChaiExpect, JestExtend } from '@vitest/expect'
import {
JestAsymmetricMatchers,
JestChaiExpect,
JestExtend,
} from '@vitest/expect'

@@ -12,0 +16,0 @@ // allows using expect.extend instead of chai.use to extend plugins

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc