mirror of
https://github.com/nodejs/node.git
synced 2025-08-15 05:38:47 +02:00
lib: restructure assert to become a class
PR-URL: https://github.com/nodejs/node/pull/58253 Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de> Reviewed-By: Michaël Zasso <targos@protonmail.com> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
This commit is contained in:
parent
3090def635
commit
4f5d11e6fb
15 changed files with 823 additions and 49 deletions
|
@ -149,6 +149,8 @@ added: v0.1.21
|
|||
* `operator` {string} The `operator` property on the error instance.
|
||||
* `stackStartFn` {Function} If provided, the generated stack trace omits
|
||||
frames before this function.
|
||||
* `diff` {string} If set to `'full'`, shows the full diff in assertion errors. Defaults to `'simple'`.
|
||||
Accepted values: `'simple'`, `'full'`.
|
||||
|
||||
A subclass of {Error} that indicates the failure of an assertion.
|
||||
|
||||
|
@ -215,6 +217,51 @@ try {
|
|||
}
|
||||
```
|
||||
|
||||
## Class: `assert.Assert`
|
||||
|
||||
<!-- YAML
|
||||
added: REPLACEME
|
||||
-->
|
||||
|
||||
The `Assert` class allows creating independent assertion instances with custom options.
|
||||
|
||||
### `new assert.Assert([options])`
|
||||
|
||||
* `options` {Object}
|
||||
* `diff` {string} If set to `'full'`, shows the full diff in assertion errors. Defaults to `'simple'`.
|
||||
Accepted values: `'simple'`, `'full'`.
|
||||
* `strict` {boolean} If set to `true`, non-strict methods behave like their
|
||||
corresponding strict methods. Defaults to `true`.
|
||||
|
||||
Creates a new assertion instance. The `diff` option controls the verbosity of diffs in assertion error messages.
|
||||
|
||||
```js
|
||||
const { Assert } = require('node:assert');
|
||||
const assertInstance = new Assert({ diff: 'full' });
|
||||
assertInstance.deepStrictEqual({ a: 1 }, { a: 2 });
|
||||
// Shows a full diff in the error message.
|
||||
```
|
||||
|
||||
**Important**: When destructuring assertion methods from an `Assert` instance,
|
||||
the methods lose their connection to the instance's configuration options (such as `diff` and `strict` settings).
|
||||
The destructured methods will fall back to default behavior instead.
|
||||
|
||||
```js
|
||||
const myAssert = new Assert({ diff: 'full' });
|
||||
|
||||
// This works as expected - uses 'full' diff
|
||||
myAssert.strictEqual({ a: 1 }, { b: { c: 1 } });
|
||||
|
||||
// This loses the 'full' diff setting - falls back to default 'simple' diff
|
||||
const { strictEqual } = myAssert;
|
||||
strictEqual({ a: 1 }, { b: { c: 1 } });
|
||||
```
|
||||
|
||||
When destructured, methods lose access to the instance's `this` context and revert to default assertion behavior
|
||||
(diff: 'simple', non-strict mode).
|
||||
To maintain custom options when using destructured methods, avoid
|
||||
destructuring and call methods directly on the instance.
|
||||
|
||||
## `assert(value[, message])`
|
||||
|
||||
<!-- YAML
|
||||
|
|
153
lib/assert.js
153
lib/assert.js
|
@ -21,6 +21,7 @@
|
|||
'use strict';
|
||||
|
||||
const {
|
||||
ArrayPrototypeForEach,
|
||||
ArrayPrototypeIndexOf,
|
||||
ArrayPrototypeJoin,
|
||||
ArrayPrototypePush,
|
||||
|
@ -28,6 +29,7 @@ const {
|
|||
Error,
|
||||
NumberIsNaN,
|
||||
ObjectAssign,
|
||||
ObjectDefineProperty,
|
||||
ObjectIs,
|
||||
ObjectKeys,
|
||||
ObjectPrototypeIsPrototypeOf,
|
||||
|
@ -37,11 +39,13 @@ const {
|
|||
StringPrototypeIndexOf,
|
||||
StringPrototypeSlice,
|
||||
StringPrototypeSplit,
|
||||
Symbol,
|
||||
} = primordials;
|
||||
|
||||
const {
|
||||
codes: {
|
||||
ERR_AMBIGUOUS_ARGUMENT,
|
||||
ERR_CONSTRUCT_CALL_REQUIRED,
|
||||
ERR_INVALID_ARG_TYPE,
|
||||
ERR_INVALID_ARG_VALUE,
|
||||
ERR_INVALID_RETURN_VALUE,
|
||||
|
@ -54,13 +58,16 @@ const {
|
|||
isPromise,
|
||||
isRegExp,
|
||||
} = require('internal/util/types');
|
||||
const { isError } = require('internal/util');
|
||||
const { isError, setOwnProperty } = require('internal/util');
|
||||
const { innerOk } = require('internal/assert/utils');
|
||||
|
||||
const {
|
||||
validateFunction,
|
||||
validateOneOf,
|
||||
} = require('internal/validators');
|
||||
|
||||
const kOptions = Symbol('options');
|
||||
|
||||
let isDeepEqual;
|
||||
let isDeepStrictEqual;
|
||||
let isPartialStrictEqual;
|
||||
|
@ -80,12 +87,60 @@ const assert = module.exports = ok;
|
|||
|
||||
const NO_EXCEPTION_SENTINEL = {};
|
||||
|
||||
/**
|
||||
* Assert options.
|
||||
* @typedef {object} AssertOptions
|
||||
* @property {'full'|'simple'} [diff='simple'] - If set to 'full', shows the full diff in assertion errors.
|
||||
* @property {boolean} [strict=true] - If set to true, non-strict methods behave like their corresponding
|
||||
* strict methods.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @class Assert
|
||||
* @param {AssertOptions} [options] - Optional configuration for assertions.
|
||||
* @throws {ERR_CONSTRUCT_CALL_REQUIRED} If not called with `new`.
|
||||
*/
|
||||
function Assert(options) {
|
||||
if (!new.target) {
|
||||
throw new ERR_CONSTRUCT_CALL_REQUIRED('Assert');
|
||||
}
|
||||
|
||||
options = ObjectAssign({ __proto__: null, strict: true }, options);
|
||||
|
||||
const allowedDiffs = ['simple', 'full'];
|
||||
if (options.diff !== undefined) {
|
||||
validateOneOf(options.diff, 'options.diff', allowedDiffs);
|
||||
}
|
||||
|
||||
this.AssertionError = AssertionError;
|
||||
ObjectDefineProperty(this, kOptions, {
|
||||
__proto__: null,
|
||||
value: options,
|
||||
enumerable: false,
|
||||
configurable: false,
|
||||
writable: false,
|
||||
});
|
||||
|
||||
if (options.strict) {
|
||||
this.equal = this.strictEqual;
|
||||
this.deepEqual = this.deepStrictEqual;
|
||||
this.notEqual = this.notStrictEqual;
|
||||
this.notDeepEqual = this.notDeepStrictEqual;
|
||||
}
|
||||
}
|
||||
|
||||
// All of the following functions must throw an AssertionError
|
||||
// when a corresponding condition is not met, with a message that
|
||||
// may be undefined if not provided. All assertion methods provide
|
||||
// both the actual and expected values to the assertion error for
|
||||
// display purposes.
|
||||
|
||||
// DESTRUCTURING WARNING: All Assert.prototype methods use optional chaining
|
||||
// (this?.[kOptions]) to safely access instance configuration. When methods are
|
||||
// destructured from an Assert instance (e.g., const {strictEqual} = myAssert),
|
||||
// they lose their `this` context and will use default behavior instead of the
|
||||
// instance's custom options.
|
||||
|
||||
function innerFail(obj) {
|
||||
if (obj.message instanceof Error) throw obj.message;
|
||||
|
||||
|
@ -96,7 +151,7 @@ function innerFail(obj) {
|
|||
* Throws an AssertionError with the given message.
|
||||
* @param {any | Error} [message]
|
||||
*/
|
||||
function fail(message) {
|
||||
Assert.prototype.fail = function fail(message) {
|
||||
if (isError(message)) throw message;
|
||||
|
||||
let internalMessage = false;
|
||||
|
@ -105,19 +160,22 @@ function fail(message) {
|
|||
internalMessage = true;
|
||||
}
|
||||
|
||||
// IMPORTANT: When adding new references to `this`, ensure they use optional chaining
|
||||
// (this?.[kOptions]?.diff) to handle cases where the method is destructured from an
|
||||
// Assert instance and loses its context. Destructured methods will fall back
|
||||
// to default behavior when `this` is undefined.
|
||||
const errArgs = {
|
||||
operator: 'fail',
|
||||
stackStartFn: fail,
|
||||
message,
|
||||
diff: this?.[kOptions]?.diff,
|
||||
};
|
||||
const err = new AssertionError(errArgs);
|
||||
if (internalMessage) {
|
||||
err.generatedMessage = true;
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
|
||||
assert.fail = fail;
|
||||
};
|
||||
|
||||
// The AssertionError is defined in internal/error.
|
||||
assert.AssertionError = AssertionError;
|
||||
|
@ -131,7 +189,17 @@ assert.AssertionError = AssertionError;
|
|||
function ok(...args) {
|
||||
innerOk(ok, args.length, ...args);
|
||||
}
|
||||
assert.ok = ok;
|
||||
|
||||
/**
|
||||
* Pure assertion tests whether a value is truthy, as determined
|
||||
* by !!value.
|
||||
* Duplicated as the other `ok` function is supercharged and exposed as default export.
|
||||
* @param {...any} args
|
||||
* @returns {void}
|
||||
*/
|
||||
Assert.prototype.ok = function ok(...args) {
|
||||
innerOk(ok, args.length, ...args);
|
||||
};
|
||||
|
||||
/**
|
||||
* The equality assertion tests shallow, coercive equality with ==.
|
||||
|
@ -140,8 +208,7 @@ assert.ok = ok;
|
|||
* @param {string | Error} [message]
|
||||
* @returns {void}
|
||||
*/
|
||||
/* eslint-disable no-restricted-properties */
|
||||
assert.equal = function equal(actual, expected, message) {
|
||||
Assert.prototype.equal = function equal(actual, expected, message) {
|
||||
if (arguments.length < 2) {
|
||||
throw new ERR_MISSING_ARGS('actual', 'expected');
|
||||
}
|
||||
|
@ -153,6 +220,7 @@ assert.equal = function equal(actual, expected, message) {
|
|||
message,
|
||||
operator: '==',
|
||||
stackStartFn: equal,
|
||||
diff: this?.[kOptions]?.diff,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
@ -165,7 +233,7 @@ assert.equal = function equal(actual, expected, message) {
|
|||
* @param {string | Error} [message]
|
||||
* @returns {void}
|
||||
*/
|
||||
assert.notEqual = function notEqual(actual, expected, message) {
|
||||
Assert.prototype.notEqual = function notEqual(actual, expected, message) {
|
||||
if (arguments.length < 2) {
|
||||
throw new ERR_MISSING_ARGS('actual', 'expected');
|
||||
}
|
||||
|
@ -177,6 +245,7 @@ assert.notEqual = function notEqual(actual, expected, message) {
|
|||
message,
|
||||
operator: '!=',
|
||||
stackStartFn: notEqual,
|
||||
diff: this?.[kOptions]?.diff,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
@ -188,7 +257,7 @@ assert.notEqual = function notEqual(actual, expected, message) {
|
|||
* @param {string | Error} [message]
|
||||
* @returns {void}
|
||||
*/
|
||||
assert.deepEqual = function deepEqual(actual, expected, message) {
|
||||
Assert.prototype.deepEqual = function deepEqual(actual, expected, message) {
|
||||
if (arguments.length < 2) {
|
||||
throw new ERR_MISSING_ARGS('actual', 'expected');
|
||||
}
|
||||
|
@ -200,6 +269,7 @@ assert.deepEqual = function deepEqual(actual, expected, message) {
|
|||
message,
|
||||
operator: 'deepEqual',
|
||||
stackStartFn: deepEqual,
|
||||
diff: this?.[kOptions]?.diff,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
@ -211,7 +281,7 @@ assert.deepEqual = function deepEqual(actual, expected, message) {
|
|||
* @param {string | Error} [message]
|
||||
* @returns {void}
|
||||
*/
|
||||
assert.notDeepEqual = function notDeepEqual(actual, expected, message) {
|
||||
Assert.prototype.notDeepEqual = function notDeepEqual(actual, expected, message) {
|
||||
if (arguments.length < 2) {
|
||||
throw new ERR_MISSING_ARGS('actual', 'expected');
|
||||
}
|
||||
|
@ -223,10 +293,10 @@ assert.notDeepEqual = function notDeepEqual(actual, expected, message) {
|
|||
message,
|
||||
operator: 'notDeepEqual',
|
||||
stackStartFn: notDeepEqual,
|
||||
diff: this?.[kOptions]?.diff,
|
||||
});
|
||||
}
|
||||
};
|
||||
/* eslint-enable */
|
||||
|
||||
/**
|
||||
* The deep strict equivalence assertion tests a deep strict equality
|
||||
|
@ -236,7 +306,7 @@ assert.notDeepEqual = function notDeepEqual(actual, expected, message) {
|
|||
* @param {string | Error} [message]
|
||||
* @returns {void}
|
||||
*/
|
||||
assert.deepStrictEqual = function deepStrictEqual(actual, expected, message) {
|
||||
Assert.prototype.deepStrictEqual = function deepStrictEqual(actual, expected, message) {
|
||||
if (arguments.length < 2) {
|
||||
throw new ERR_MISSING_ARGS('actual', 'expected');
|
||||
}
|
||||
|
@ -248,6 +318,7 @@ assert.deepStrictEqual = function deepStrictEqual(actual, expected, message) {
|
|||
message,
|
||||
operator: 'deepStrictEqual',
|
||||
stackStartFn: deepStrictEqual,
|
||||
diff: this?.[kOptions]?.diff,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
@ -260,7 +331,7 @@ assert.deepStrictEqual = function deepStrictEqual(actual, expected, message) {
|
|||
* @param {string | Error} [message]
|
||||
* @returns {void}
|
||||
*/
|
||||
assert.notDeepStrictEqual = notDeepStrictEqual;
|
||||
Assert.prototype.notDeepStrictEqual = notDeepStrictEqual;
|
||||
function notDeepStrictEqual(actual, expected, message) {
|
||||
if (arguments.length < 2) {
|
||||
throw new ERR_MISSING_ARGS('actual', 'expected');
|
||||
|
@ -273,6 +344,7 @@ function notDeepStrictEqual(actual, expected, message) {
|
|||
message,
|
||||
operator: 'notDeepStrictEqual',
|
||||
stackStartFn: notDeepStrictEqual,
|
||||
diff: this?.[kOptions]?.diff,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -284,7 +356,7 @@ function notDeepStrictEqual(actual, expected, message) {
|
|||
* @param {string | Error} [message]
|
||||
* @returns {void}
|
||||
*/
|
||||
assert.strictEqual = function strictEqual(actual, expected, message) {
|
||||
Assert.prototype.strictEqual = function strictEqual(actual, expected, message) {
|
||||
if (arguments.length < 2) {
|
||||
throw new ERR_MISSING_ARGS('actual', 'expected');
|
||||
}
|
||||
|
@ -295,6 +367,7 @@ assert.strictEqual = function strictEqual(actual, expected, message) {
|
|||
message,
|
||||
operator: 'strictEqual',
|
||||
stackStartFn: strictEqual,
|
||||
diff: this?.[kOptions]?.diff,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
@ -306,7 +379,7 @@ assert.strictEqual = function strictEqual(actual, expected, message) {
|
|||
* @param {string | Error} [message]
|
||||
* @returns {void}
|
||||
*/
|
||||
assert.notStrictEqual = function notStrictEqual(actual, expected, message) {
|
||||
Assert.prototype.notStrictEqual = function notStrictEqual(actual, expected, message) {
|
||||
if (arguments.length < 2) {
|
||||
throw new ERR_MISSING_ARGS('actual', 'expected');
|
||||
}
|
||||
|
@ -317,6 +390,7 @@ assert.notStrictEqual = function notStrictEqual(actual, expected, message) {
|
|||
message,
|
||||
operator: 'notStrictEqual',
|
||||
stackStartFn: notStrictEqual,
|
||||
diff: this?.[kOptions]?.diff,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
@ -328,7 +402,7 @@ assert.notStrictEqual = function notStrictEqual(actual, expected, message) {
|
|||
* @param {string | Error} [message]
|
||||
* @returns {void}
|
||||
*/
|
||||
assert.partialDeepStrictEqual = function partialDeepStrictEqual(
|
||||
Assert.prototype.partialDeepStrictEqual = function partialDeepStrictEqual(
|
||||
actual,
|
||||
expected,
|
||||
message,
|
||||
|
@ -344,6 +418,7 @@ assert.partialDeepStrictEqual = function partialDeepStrictEqual(
|
|||
message,
|
||||
operator: 'partialDeepStrictEqual',
|
||||
stackStartFn: partialDeepStrictEqual,
|
||||
diff: this?.[kOptions]?.diff,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
@ -377,6 +452,7 @@ function compareExceptionKey(actual, expected, key, message, keys, fn) {
|
|||
expected: b,
|
||||
operator: 'deepStrictEqual',
|
||||
stackStartFn: fn,
|
||||
diff: this?.[kOptions]?.diff,
|
||||
});
|
||||
err.actual = actual;
|
||||
err.expected = expected;
|
||||
|
@ -389,6 +465,7 @@ function compareExceptionKey(actual, expected, key, message, keys, fn) {
|
|||
message,
|
||||
operator: fn.name,
|
||||
stackStartFn: fn,
|
||||
diff: this?.[kOptions]?.diff,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -418,6 +495,7 @@ function expectedException(actual, expected, message, fn) {
|
|||
message,
|
||||
operator: 'deepStrictEqual',
|
||||
stackStartFn: fn,
|
||||
diff: this?.[kOptions]?.diff,
|
||||
});
|
||||
err.operator = fn.name;
|
||||
throw err;
|
||||
|
@ -493,6 +571,7 @@ function expectedException(actual, expected, message, fn) {
|
|||
message,
|
||||
operator: fn.name,
|
||||
stackStartFn: fn,
|
||||
diff: this?.[kOptions]?.diff,
|
||||
});
|
||||
err.generatedMessage = generatedMessage;
|
||||
throw err;
|
||||
|
@ -580,20 +659,21 @@ function expectsError(stackStartFn, actual, error, message) {
|
|||
details += ` (${error.name})`;
|
||||
}
|
||||
details += message ? `: ${message}` : '.';
|
||||
const fnType = stackStartFn === assert.rejects ? 'rejection' : 'exception';
|
||||
const fnType = stackStartFn === Assert.prototype.rejects ? 'rejection' : 'exception';
|
||||
innerFail({
|
||||
actual: undefined,
|
||||
expected: error,
|
||||
operator: stackStartFn.name,
|
||||
message: `Missing expected ${fnType}${details}`,
|
||||
stackStartFn,
|
||||
diff: this?.[kOptions]?.diff,
|
||||
});
|
||||
}
|
||||
|
||||
if (!error)
|
||||
return;
|
||||
|
||||
expectedException(actual, error, message, stackStartFn);
|
||||
expectedException.call(this, actual, error, message, stackStartFn);
|
||||
}
|
||||
|
||||
function hasMatchingError(actual, expected) {
|
||||
|
@ -627,7 +707,7 @@ function expectsNoError(stackStartFn, actual, error, message) {
|
|||
|
||||
if (!error || hasMatchingError(actual, error)) {
|
||||
const details = message ? `: ${message}` : '.';
|
||||
const fnType = stackStartFn === assert.doesNotReject ?
|
||||
const fnType = stackStartFn === Assert.prototype.doesNotReject ?
|
||||
'rejection' : 'exception';
|
||||
innerFail({
|
||||
actual,
|
||||
|
@ -636,6 +716,7 @@ function expectsNoError(stackStartFn, actual, error, message) {
|
|||
message: `Got unwanted ${fnType}${details}\n` +
|
||||
`Actual message: "${actual?.message}"`,
|
||||
stackStartFn,
|
||||
diff: this?.[kOptions]?.diff,
|
||||
});
|
||||
}
|
||||
throw actual;
|
||||
|
@ -647,7 +728,7 @@ function expectsNoError(stackStartFn, actual, error, message) {
|
|||
* @param {...any} [args]
|
||||
* @returns {void}
|
||||
*/
|
||||
assert.throws = function throws(promiseFn, ...args) {
|
||||
Assert.prototype.throws = function throws(promiseFn, ...args) {
|
||||
expectsError(throws, getActual(promiseFn), ...args);
|
||||
};
|
||||
|
||||
|
@ -657,7 +738,7 @@ assert.throws = function throws(promiseFn, ...args) {
|
|||
* @param {...any} [args]
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
assert.rejects = async function rejects(promiseFn, ...args) {
|
||||
Assert.prototype.rejects = async function rejects(promiseFn, ...args) {
|
||||
expectsError(rejects, await waitForActual(promiseFn), ...args);
|
||||
};
|
||||
|
||||
|
@ -667,7 +748,7 @@ assert.rejects = async function rejects(promiseFn, ...args) {
|
|||
* @param {...any} [args]
|
||||
* @returns {void}
|
||||
*/
|
||||
assert.doesNotThrow = function doesNotThrow(fn, ...args) {
|
||||
Assert.prototype.doesNotThrow = function doesNotThrow(fn, ...args) {
|
||||
expectsNoError(doesNotThrow, getActual(fn), ...args);
|
||||
};
|
||||
|
||||
|
@ -677,7 +758,7 @@ assert.doesNotThrow = function doesNotThrow(fn, ...args) {
|
|||
* @param {...any} [args]
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
assert.doesNotReject = async function doesNotReject(fn, ...args) {
|
||||
Assert.prototype.doesNotReject = async function doesNotReject(fn, ...args) {
|
||||
expectsNoError(doesNotReject, await waitForActual(fn), ...args);
|
||||
};
|
||||
|
||||
|
@ -686,7 +767,7 @@ assert.doesNotReject = async function doesNotReject(fn, ...args) {
|
|||
* @param {any} err
|
||||
* @returns {void}
|
||||
*/
|
||||
assert.ifError = function ifError(err) {
|
||||
Assert.prototype.ifError = function ifError(err) {
|
||||
if (err !== null && err !== undefined) {
|
||||
let message = 'ifError got unwanted exception: ';
|
||||
if (typeof err === 'object' && typeof err.message === 'string') {
|
||||
|
@ -705,6 +786,7 @@ assert.ifError = function ifError(err) {
|
|||
operator: 'ifError',
|
||||
message,
|
||||
stackStartFn: ifError,
|
||||
diff: this?.[kOptions]?.diff,
|
||||
});
|
||||
|
||||
// Make sure we actually have a stack trace!
|
||||
|
@ -747,7 +829,7 @@ function internalMatch(string, regexp, message, fn) {
|
|||
'regexp', 'RegExp', regexp,
|
||||
);
|
||||
}
|
||||
const match = fn === assert.match;
|
||||
const match = fn === Assert.prototype.match;
|
||||
if (typeof string !== 'string' ||
|
||||
RegExpPrototypeExec(regexp, string) !== null !== match) {
|
||||
if (message instanceof Error) {
|
||||
|
@ -770,6 +852,7 @@ function internalMatch(string, regexp, message, fn) {
|
|||
message,
|
||||
operator: fn.name,
|
||||
stackStartFn: fn,
|
||||
diff: this?.[kOptions]?.diff,
|
||||
});
|
||||
err.generatedMessage = generatedMessage;
|
||||
throw err;
|
||||
|
@ -783,7 +866,7 @@ function internalMatch(string, regexp, message, fn) {
|
|||
* @param {string | Error} [message]
|
||||
* @returns {void}
|
||||
*/
|
||||
assert.match = function match(string, regexp, message) {
|
||||
Assert.prototype.match = function match(string, regexp, message) {
|
||||
internalMatch(string, regexp, message, match);
|
||||
};
|
||||
|
||||
|
@ -794,7 +877,7 @@ assert.match = function match(string, regexp, message) {
|
|||
* @param {string | Error} [message]
|
||||
* @returns {void}
|
||||
*/
|
||||
assert.doesNotMatch = function doesNotMatch(string, regexp, message) {
|
||||
Assert.prototype.doesNotMatch = function doesNotMatch(string, regexp, message) {
|
||||
internalMatch(string, regexp, message, doesNotMatch);
|
||||
};
|
||||
|
||||
|
@ -807,6 +890,17 @@ function strict(...args) {
|
|||
innerOk(strict, args.length, ...args);
|
||||
}
|
||||
|
||||
// TODO(aduh95): take `ok` from `Assert.prototype` instead of a self-ref in a next major.
|
||||
assert.ok = assert;
|
||||
ArrayPrototypeForEach([
|
||||
'fail', 'equal', 'notEqual', 'deepEqual', 'notDeepEqual',
|
||||
'deepStrictEqual', 'notDeepStrictEqual', 'strictEqual',
|
||||
'notStrictEqual', 'partialDeepStrictEqual', 'match', 'doesNotMatch',
|
||||
'throws', 'rejects', 'doesNotThrow', 'doesNotReject', 'ifError',
|
||||
], (name) => {
|
||||
setOwnProperty(assert, name, Assert.prototype[name]);
|
||||
});
|
||||
|
||||
assert.strict = ObjectAssign(strict, assert, {
|
||||
equal: assert.strictEqual,
|
||||
deepEqual: assert.deepStrictEqual,
|
||||
|
@ -814,4 +908,7 @@ assert.strict = ObjectAssign(strict, assert, {
|
|||
notDeepEqual: assert.notDeepStrictEqual,
|
||||
});
|
||||
|
||||
assert.strict.Assert = Assert;
|
||||
assert.strict.strict = assert.strict;
|
||||
|
||||
assert.Assert = Assert;
|
||||
|
|
|
@ -178,7 +178,7 @@ function isSimpleDiff(actual, inspectedActual, expected, inspectedExpected) {
|
|||
return typeof actual !== 'object' || actual === null || typeof expected !== 'object' || expected === null;
|
||||
}
|
||||
|
||||
function createErrDiff(actual, expected, operator, customMessage) {
|
||||
function createErrDiff(actual, expected, operator, customMessage, diffType = 'simple') {
|
||||
operator = checkOperator(actual, expected, operator);
|
||||
|
||||
let skipped = false;
|
||||
|
@ -202,7 +202,7 @@ function createErrDiff(actual, expected, operator, customMessage) {
|
|||
} else if (inspectedActual === inspectedExpected) {
|
||||
// Handles the case where the objects are structurally the same but different references
|
||||
operator = 'notIdentical';
|
||||
if (inspectedSplitActual.length > 50) {
|
||||
if (inspectedSplitActual.length > 50 && diffType !== 'full') {
|
||||
message = `${ArrayPrototypeJoin(ArrayPrototypeSlice(inspectedSplitActual, 0, 50), '\n')}\n...}`;
|
||||
skipped = true;
|
||||
} else {
|
||||
|
@ -252,6 +252,7 @@ class AssertionError extends Error {
|
|||
details,
|
||||
// Compatibility with older versions.
|
||||
stackStartFunction,
|
||||
diff = 'simple',
|
||||
} = options;
|
||||
let {
|
||||
actual,
|
||||
|
@ -263,7 +264,7 @@ class AssertionError extends Error {
|
|||
|
||||
if (message != null) {
|
||||
if (kMethodsWithCustomMessageDiff.includes(operator)) {
|
||||
super(createErrDiff(actual, expected, operator, message));
|
||||
super(createErrDiff(actual, expected, operator, message, diff));
|
||||
} else {
|
||||
super(String(message));
|
||||
}
|
||||
|
@ -283,7 +284,7 @@ class AssertionError extends Error {
|
|||
}
|
||||
|
||||
if (kMethodsWithCustomMessageDiff.includes(operator)) {
|
||||
super(createErrDiff(actual, expected, operator, message));
|
||||
super(createErrDiff(actual, expected, operator, message, diff));
|
||||
} else if (operator === 'notDeepStrictEqual' ||
|
||||
operator === 'notStrictEqual') {
|
||||
// In case the objects are equal but the operator requires unequal, show
|
||||
|
@ -300,8 +301,7 @@ class AssertionError extends Error {
|
|||
}
|
||||
|
||||
// Only remove lines in case it makes sense to collapse those.
|
||||
// TODO: Accept env to always show the full error.
|
||||
if (res.length > 50) {
|
||||
if (res.length > 50 && diff !== 'full') {
|
||||
res[46] = `${colors.blue}...${colors.white}`;
|
||||
while (res.length > 47) {
|
||||
ArrayPrototypePop(res);
|
||||
|
@ -320,15 +320,15 @@ class AssertionError extends Error {
|
|||
const knownOperator = kReadableOperator[operator];
|
||||
if (operator === 'notDeepEqual' && res === other) {
|
||||
res = `${knownOperator}\n\n${res}`;
|
||||
if (res.length > 1024) {
|
||||
if (res.length > 1024 && diff !== 'full') {
|
||||
res = `${StringPrototypeSlice(res, 0, 1021)}...`;
|
||||
}
|
||||
super(res);
|
||||
} else {
|
||||
if (res.length > kMaxLongStringLength) {
|
||||
if (res.length > kMaxLongStringLength && diff !== 'full') {
|
||||
res = `${StringPrototypeSlice(res, 0, 509)}...`;
|
||||
}
|
||||
if (other.length > kMaxLongStringLength) {
|
||||
if (other.length > kMaxLongStringLength && diff !== 'full') {
|
||||
other = `${StringPrototypeSlice(other, 0, 509)}...`;
|
||||
}
|
||||
if (operator === 'deepEqual') {
|
||||
|
@ -378,6 +378,7 @@ class AssertionError extends Error {
|
|||
this.stack; // eslint-disable-line no-unused-expressions
|
||||
// Reset the name.
|
||||
this.name = 'AssertionError';
|
||||
this.diff = diff;
|
||||
}
|
||||
|
||||
toString() {
|
||||
|
|
|
@ -1161,6 +1161,7 @@ E('ERR_CHILD_PROCESS_STDIO_MAXBUFFER', '%s maxBuffer length exceeded',
|
|||
RangeError);
|
||||
E('ERR_CONSOLE_WRITABLE_STREAM',
|
||||
'Console expects a writable stream instance for %s', TypeError);
|
||||
E('ERR_CONSTRUCT_CALL_REQUIRED', 'Class constructor %s cannot be invoked without `new`', TypeError);
|
||||
E('ERR_CONTEXT_NOT_INITIALIZED', 'context used is not initialized', Error);
|
||||
E('ERR_CRYPTO_CUSTOM_ENGINE_NOT_SUPPORTED',
|
||||
'Custom engines not supported by this OpenSSL', Error);
|
||||
|
|
3
test/fixtures/errors/error_exit.snapshot
vendored
3
test/fixtures/errors/error_exit.snapshot
vendored
|
@ -12,7 +12,8 @@ AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
|
|||
code: 'ERR_ASSERTION',
|
||||
actual: 1,
|
||||
expected: 2,
|
||||
operator: 'strictEqual'
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
Node.js *
|
||||
|
|
|
@ -19,7 +19,8 @@ AssertionError [ERR_ASSERTION]: ifError got unwanted exception: test error
|
|||
at a (*if-error-has-good-stack.js:*:*)
|
||||
at Object.<anonymous> (*if-error-has-good-stack.js:*:*),
|
||||
expected: null,
|
||||
operator: 'ifError'
|
||||
operator: 'ifError',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
Node.js *
|
||||
|
|
|
@ -21,5 +21,6 @@
|
|||
code: [32m'ERR_ASSERTION'[39m,
|
||||
actual: [32m'!Hello World'[39m,
|
||||
expected: [32m'Hello World!'[39m,
|
||||
operator: [32m'strictEqual'[39m
|
||||
operator: [32m'strictEqual'[39m,
|
||||
diff: [32m'simple'[39m
|
||||
}
|
||||
|
|
|
@ -66,7 +66,8 @@ Failed tests:
|
|||
code: 'ERR_ASSERTION',
|
||||
actual: true,
|
||||
expected: false,
|
||||
operator: 'strictEqual'
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
✖ reject fail (*ms)
|
||||
Error: rejected from reject fail
|
||||
|
@ -215,7 +216,8 @@ Failed tests:
|
|||
code: 'ERR_ASSERTION',
|
||||
actual: [Object],
|
||||
expected: [Object],
|
||||
operator: 'deepEqual'
|
||||
operator: 'deepEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
✖ invalid subtest fail (*ms)
|
||||
'test could not be started because its parent finished'
|
||||
|
|
|
@ -124,7 +124,8 @@ true !== false
|
|||
code: 'ERR_ASSERTION',
|
||||
actual: true,
|
||||
expected: false,
|
||||
operator: 'strictEqual'
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
}
|
||||
</failure>
|
||||
|
@ -491,7 +492,8 @@ should loosely deep-equal
|
|||
code: 'ERR_ASSERTION',
|
||||
actual: [Object],
|
||||
expected: [Object],
|
||||
operator: 'deepEqual'
|
||||
operator: 'deepEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
}
|
||||
</failure>
|
||||
|
|
|
@ -171,7 +171,8 @@
|
|||
code: 'ERR_ASSERTION',
|
||||
actual: true,
|
||||
expected: false,
|
||||
operator: 'strictEqual'
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
*
|
||||
|
@ -356,7 +357,8 @@
|
|||
code: 'ERR_ASSERTION',
|
||||
actual: [Object],
|
||||
expected: [Object],
|
||||
operator: 'deepEqual'
|
||||
operator: 'deepEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
*
|
||||
|
|
|
@ -174,7 +174,8 @@
|
|||
code: 'ERR_ASSERTION',
|
||||
actual: true,
|
||||
expected: false,
|
||||
operator: 'strictEqual'
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
*
|
||||
|
@ -359,7 +360,8 @@
|
|||
code: 'ERR_ASSERTION',
|
||||
actual: { foo: 1, bar: 1, boo: [ 1 ], baz: { date: 1970-01-01T00:00:00.000Z, null: null, number: 1, string: 'Hello', undefined: undefined } },
|
||||
expected: { boo: [ 1 ], baz: { date: 1970-01-01T00:00:00.000Z, null: null, number: 1, string: 'Hello', undefined: undefined }, circular: <ref *1> { bar: 2, c: [Circular *1] } },
|
||||
operator: 'deepEqual'
|
||||
operator: 'deepEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
*
|
||||
|
|
|
@ -9,6 +9,7 @@ AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal:
|
|||
- Comparison {
|
||||
- bar: true
|
||||
- }
|
||||
|
||||
at Object.<anonymous> (*assert_throws_stack.js:*:*)
|
||||
at *
|
||||
at *
|
||||
|
@ -32,7 +33,8 @@ AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal:
|
|||
at *
|
||||
at *,
|
||||
expected: { bar: true },
|
||||
operator: 'throws'
|
||||
operator: 'throws',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
Node.js *
|
||||
|
|
133
test/parallel/test-assert-class-destructuring.js
Normal file
133
test/parallel/test-assert-class-destructuring.js
Normal file
|
@ -0,0 +1,133 @@
|
|||
'use strict';
|
||||
|
||||
require('../common');
|
||||
const assert = require('assert');
|
||||
const { Assert } = require('assert');
|
||||
const { test } = require('node:test');
|
||||
|
||||
// Disable colored output to prevent color codes from breaking assertion
|
||||
// message comparisons. This should only be an issue when process.stdout
|
||||
// is a TTY.
|
||||
if (process.stdout.isTTY) {
|
||||
process.env.NODE_DISABLE_COLORS = '1';
|
||||
}
|
||||
|
||||
test('Assert class destructuring behavior - diff option', () => {
|
||||
const assertInstanceFull = new Assert({ diff: 'full' });
|
||||
const assertInstanceSimple = new Assert({ diff: 'simple' });
|
||||
|
||||
assertInstanceFull.throws(
|
||||
() => assertInstanceFull.strictEqual({ a: 1 }, { a: 2 }),
|
||||
(err) => {
|
||||
assert.strictEqual(err.diff, 'full');
|
||||
return true;
|
||||
}
|
||||
);
|
||||
|
||||
assertInstanceSimple.throws(
|
||||
() => assertInstanceSimple.strictEqual({ a: 1 }, { a: 2 }),
|
||||
(err) => {
|
||||
assert.strictEqual(err.diff, 'simple');
|
||||
return true;
|
||||
}
|
||||
);
|
||||
|
||||
const { strictEqual: strictEqualSimple } = assertInstanceSimple;
|
||||
const { strictEqual: strictEqualFull } = assertInstanceFull;
|
||||
const { deepStrictEqual: deepStrictEqualFull } = assertInstanceFull;
|
||||
const { equal: equalFull } = assertInstanceFull;
|
||||
|
||||
assert.throws(
|
||||
() => strictEqualSimple({ a: 1 }, { a: 2 }),
|
||||
(err) => {
|
||||
assert.strictEqual(err.diff, 'simple');
|
||||
return true;
|
||||
}
|
||||
);
|
||||
|
||||
assert.throws(
|
||||
() => strictEqualFull({ a: 1 }, { a: 2 }),
|
||||
(err) => {
|
||||
assert.strictEqual(err.diff, 'simple');
|
||||
return true;
|
||||
}
|
||||
);
|
||||
|
||||
assert.throws(
|
||||
() => deepStrictEqualFull({ a: 1 }, { a: 2 }),
|
||||
(err) => {
|
||||
assert.strictEqual(err.diff, 'simple');
|
||||
return true;
|
||||
}
|
||||
);
|
||||
|
||||
assert.throws(
|
||||
() => equalFull({ a: 1 }, { a: 2 }),
|
||||
(err) => {
|
||||
assert.strictEqual(err.diff, 'simple');
|
||||
return true;
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
test('Assert class destructuring behavior - strict option', () => {
|
||||
const assertInstanceNonStrict = new Assert({ strict: false });
|
||||
const assertInstanceStrict = new Assert({ strict: true });
|
||||
|
||||
assertInstanceNonStrict.equal(2, '2');
|
||||
|
||||
assert.throws(
|
||||
() => assertInstanceStrict.equal(2, '2'),
|
||||
assert.AssertionError
|
||||
);
|
||||
|
||||
const { equal: equalNonStrict } = assertInstanceNonStrict;
|
||||
const { equal: equalStrict } = assertInstanceStrict;
|
||||
|
||||
equalNonStrict(2, '2');
|
||||
assert.throws(
|
||||
() => equalStrict(2, '2'),
|
||||
assert.AssertionError
|
||||
);
|
||||
});
|
||||
|
||||
test('Assert class destructuring behavior - comprehensive methods', () => {
|
||||
const myAssert = new Assert({ diff: 'full', strict: false });
|
||||
|
||||
const {
|
||||
fail,
|
||||
equal,
|
||||
strictEqual,
|
||||
deepStrictEqual,
|
||||
throws,
|
||||
match,
|
||||
doesNotMatch
|
||||
} = myAssert;
|
||||
|
||||
assert.throws(() => fail('test message'), (err) => {
|
||||
assert.strictEqual(err.diff, 'simple');
|
||||
assert.strictEqual(err.message, 'test message');
|
||||
return true;
|
||||
});
|
||||
|
||||
assert.throws(() => equal({ a: 1 }, { a: 2 }), (err) => {
|
||||
assert.strictEqual(err.diff, 'simple');
|
||||
return true;
|
||||
});
|
||||
|
||||
assert.throws(() => strictEqual({ a: 1 }, { a: 2 }), (err) => {
|
||||
assert.strictEqual(err.diff, 'simple');
|
||||
return true;
|
||||
});
|
||||
|
||||
assert.throws(() => deepStrictEqual({ a: 1 }, { a: 2 }), (err) => {
|
||||
assert.strictEqual(err.diff, 'simple');
|
||||
return true;
|
||||
});
|
||||
|
||||
throws(() => { throw new Error('test'); }, Error);
|
||||
|
||||
match('hello world', /world/);
|
||||
|
||||
doesNotMatch('hello world', /xyz/);
|
||||
});
|
480
test/parallel/test-assert-class.js
Normal file
480
test/parallel/test-assert-class.js
Normal file
|
@ -0,0 +1,480 @@
|
|||
'use strict';
|
||||
|
||||
require('../common');
|
||||
const assert = require('assert');
|
||||
const { Assert } = require('assert');
|
||||
const { inspect } = require('util');
|
||||
const { test } = require('node:test');
|
||||
|
||||
// Disable colored output to prevent color codes from breaking assertion
|
||||
// message comparisons. This should only be an issue when process.stdout
|
||||
// is a TTY.
|
||||
if (process.stdout.isTTY) {
|
||||
process.env.NODE_DISABLE_COLORS = '1';
|
||||
}
|
||||
|
||||
test('Assert constructor requires new', () => {
|
||||
assert.throws(() => Assert(), {
|
||||
code: 'ERR_CONSTRUCT_CALL_REQUIRED',
|
||||
name: 'TypeError',
|
||||
});
|
||||
});
|
||||
|
||||
test('Assert class non strict', () => {
|
||||
const assertInstance = new Assert({ diff: undefined, strict: false });
|
||||
|
||||
assertInstance.ok(
|
||||
assert.AssertionError.prototype instanceof Error,
|
||||
'assert.AssertionError instanceof Error'
|
||||
);
|
||||
assert.strictEqual(typeof assertInstance.ok, 'function');
|
||||
assert.strictEqual(assertInstance.ok.strictEqual, undefined);
|
||||
assert.strictEqual(typeof assertInstance.strictEqual, 'function');
|
||||
assertInstance.ok(true);
|
||||
assertInstance.throws(
|
||||
() => {
|
||||
assertInstance.fail();
|
||||
},
|
||||
{
|
||||
code: 'ERR_ASSERTION',
|
||||
name: 'AssertionError',
|
||||
message: 'Failed',
|
||||
operator: 'fail',
|
||||
actual: undefined,
|
||||
expected: undefined,
|
||||
generatedMessage: true,
|
||||
stack: /Failed/,
|
||||
}
|
||||
);
|
||||
assertInstance.equal(undefined, undefined);
|
||||
assertInstance.equal(null, undefined);
|
||||
assertInstance.equal(2, '2');
|
||||
assertInstance.notEqual(true, false);
|
||||
assertInstance.throws(() => assertInstance.deepEqual(/a/), {
|
||||
code: 'ERR_MISSING_ARGS',
|
||||
});
|
||||
assertInstance.throws(() => assertInstance.notDeepEqual('test'), {
|
||||
code: 'ERR_MISSING_ARGS',
|
||||
});
|
||||
assertInstance.notStrictEqual(2, '2');
|
||||
assertInstance.throws(
|
||||
() => assertInstance.strictEqual(2, '2'),
|
||||
assertInstance.AssertionError,
|
||||
"strictEqual(2, '2')"
|
||||
);
|
||||
assertInstance.throws(
|
||||
() => {
|
||||
assertInstance.partialDeepStrictEqual(
|
||||
{ a: true },
|
||||
{ a: false },
|
||||
'custom message'
|
||||
);
|
||||
},
|
||||
{
|
||||
code: 'ERR_ASSERTION',
|
||||
name: 'AssertionError',
|
||||
message:
|
||||
'custom message\n+ actual - expected\n\n {\n+ a: true\n- a: false\n }\n',
|
||||
}
|
||||
);
|
||||
assertInstance.throws(() => assertInstance.match(/abc/, 'string'), {
|
||||
code: 'ERR_INVALID_ARG_TYPE',
|
||||
message:
|
||||
'The "regexp" argument must be an instance of RegExp. ' +
|
||||
"Received type string ('string')",
|
||||
});
|
||||
assertInstance.throws(() => assertInstance.doesNotMatch(/abc/, 'string'), {
|
||||
code: 'ERR_INVALID_ARG_TYPE',
|
||||
message:
|
||||
'The "regexp" argument must be an instance of RegExp. ' +
|
||||
"Received type string ('string')",
|
||||
});
|
||||
|
||||
/* eslint-disable no-restricted-syntax */
|
||||
{
|
||||
function thrower(errorConstructor) {
|
||||
throw new errorConstructor({});
|
||||
}
|
||||
|
||||
let threw = false;
|
||||
try {
|
||||
assertInstance.doesNotThrow(
|
||||
() => thrower(TypeError),
|
||||
assertInstance.AssertionError
|
||||
);
|
||||
} catch (e) {
|
||||
threw = true;
|
||||
assertInstance.ok(e instanceof TypeError);
|
||||
}
|
||||
assertInstance.ok(
|
||||
threw,
|
||||
'assertInstance.doesNotThrow with an explicit error is eating extra errors'
|
||||
);
|
||||
}
|
||||
{
|
||||
let threw = false;
|
||||
const rangeError = new RangeError('my range');
|
||||
|
||||
try {
|
||||
assertInstance.doesNotThrow(
|
||||
() => {
|
||||
throw new TypeError('wrong type');
|
||||
},
|
||||
TypeError,
|
||||
rangeError
|
||||
);
|
||||
} catch (e) {
|
||||
threw = true;
|
||||
assertInstance.ok(e.message.includes(rangeError.message));
|
||||
assertInstance.ok(e instanceof assertInstance.AssertionError);
|
||||
assertInstance.ok(!e.stack.includes('doesNotThrow'), e);
|
||||
}
|
||||
assertInstance.ok(threw);
|
||||
}
|
||||
/* eslint-enable no-restricted-syntax */
|
||||
});
|
||||
|
||||
test('Assert class strict', () => {
|
||||
const assertInstance = new Assert();
|
||||
|
||||
assertInstance.equal(assertInstance.equal, assertInstance.strictEqual);
|
||||
assertInstance.equal(
|
||||
assertInstance.deepEqual,
|
||||
assertInstance.deepStrictEqual
|
||||
);
|
||||
assertInstance.equal(assertInstance.notEqual, assertInstance.notStrictEqual);
|
||||
assertInstance.equal(
|
||||
assertInstance.notDeepEqual,
|
||||
assertInstance.notDeepStrictEqual
|
||||
);
|
||||
});
|
||||
|
||||
test('Assert class with invalid diff option', () => {
|
||||
assert.throws(() => new Assert({ diff: 'invalid' }), {
|
||||
code: 'ERR_INVALID_ARG_VALUE',
|
||||
name: 'TypeError',
|
||||
message: "The property 'options.diff' must be one of: 'simple', 'full'. Received 'invalid'",
|
||||
});
|
||||
});
|
||||
|
||||
const longLinesOfAs = 'A\n'.repeat(100);
|
||||
const longLinesOFBs = 'B\n'.repeat(100);
|
||||
const truncatedAs = 'A\\n'.repeat(10) + '...';
|
||||
const truncatedBs = 'B\\n'.repeat(10) + '...';
|
||||
|
||||
const longStringOfAs = 'A'.repeat(10_000);
|
||||
const longStringOfBs = 'B'.repeat(10_000);
|
||||
|
||||
const longLinesOfAsWithEllipsis = longStringOfAs.substring(0, 9_488) + '...';
|
||||
const longLinesOFBsWithEllipsis = longStringOfBs.substring(0, 9_488) + '...';
|
||||
test('Assert class non strict with full diff', () => {
|
||||
const assertInstance = new Assert({ diff: 'full', strict: false });
|
||||
|
||||
// long strings
|
||||
{
|
||||
assertInstance.throws(
|
||||
() => {
|
||||
assertInstance.strictEqual(longStringOfAs, longStringOfBs);
|
||||
},
|
||||
(err) => {
|
||||
assertInstance.strictEqual(err.code, 'ERR_ASSERTION');
|
||||
assertInstance.strictEqual(err.operator, 'strictEqual');
|
||||
assertInstance.strictEqual(err.diff, 'full');
|
||||
assertInstance.strictEqual(err.actual, longStringOfAs);
|
||||
assertInstance.strictEqual(err.expected, longStringOfBs);
|
||||
|
||||
assertInstance.strictEqual(
|
||||
err.message,
|
||||
`Expected values to be strictly equal:\n+ actual - expected\n\n` +
|
||||
`+ '${longStringOfAs}'\n- '${longStringOfBs}'\n`
|
||||
);
|
||||
assertInstance.ok(
|
||||
inspect(err).includes(`actual: '${longLinesOfAsWithEllipsis}'`)
|
||||
);
|
||||
assertInstance.ok(
|
||||
inspect(err).includes(`expected: '${longLinesOFBsWithEllipsis}'`)
|
||||
);
|
||||
return true;
|
||||
}
|
||||
);
|
||||
|
||||
assertInstance.throws(
|
||||
() => {
|
||||
assertInstance.notStrictEqual(longStringOfAs, longStringOfAs);
|
||||
},
|
||||
(err) => {
|
||||
assertInstance.strictEqual(err.code, 'ERR_ASSERTION');
|
||||
assertInstance.strictEqual(err.operator, 'notStrictEqual');
|
||||
assertInstance.strictEqual(err.diff, 'full');
|
||||
assertInstance.strictEqual(err.actual, longStringOfAs);
|
||||
assertInstance.strictEqual(err.expected, longStringOfAs);
|
||||
|
||||
assertInstance.strictEqual(
|
||||
err.message,
|
||||
`Expected "actual" to be strictly unequal to:\n\n` +
|
||||
`'${longStringOfAs}'`
|
||||
);
|
||||
assertInstance.ok(
|
||||
inspect(err).includes(`actual: '${longLinesOfAsWithEllipsis}'`)
|
||||
);
|
||||
assertInstance.ok(
|
||||
inspect(err).includes(`expected: '${longLinesOfAsWithEllipsis}'`)
|
||||
);
|
||||
return true;
|
||||
}
|
||||
);
|
||||
|
||||
assertInstance.throws(
|
||||
() => {
|
||||
assertInstance.deepEqual(longStringOfAs, longStringOfBs);
|
||||
},
|
||||
(err) => {
|
||||
assertInstance.strictEqual(err.code, 'ERR_ASSERTION');
|
||||
assertInstance.strictEqual(err.operator, 'deepEqual');
|
||||
assertInstance.strictEqual(err.diff, 'full');
|
||||
assertInstance.strictEqual(err.actual, longStringOfAs);
|
||||
assertInstance.strictEqual(err.expected, longStringOfBs);
|
||||
|
||||
assertInstance.strictEqual(
|
||||
err.message,
|
||||
`Expected values to be loosely deep-equal:\n\n` +
|
||||
`'${longStringOfAs}'\n\nshould loosely deep-equal\n\n'${longStringOfBs}'`
|
||||
);
|
||||
assertInstance.ok(
|
||||
inspect(err).includes(`actual: '${longLinesOfAsWithEllipsis}'`)
|
||||
);
|
||||
assertInstance.ok(
|
||||
inspect(err).includes(`expected: '${longLinesOFBsWithEllipsis}'`)
|
||||
);
|
||||
return true;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// long lines
|
||||
{
|
||||
assertInstance.throws(
|
||||
() => {
|
||||
assertInstance.strictEqual(longLinesOfAs, longLinesOFBs);
|
||||
},
|
||||
(err) => {
|
||||
assertInstance.strictEqual(err.code, 'ERR_ASSERTION');
|
||||
assertInstance.strictEqual(err.operator, 'strictEqual');
|
||||
assertInstance.strictEqual(err.diff, 'full');
|
||||
assertInstance.strictEqual(err.actual, longLinesOfAs);
|
||||
assertInstance.strictEqual(err.expected, longLinesOFBs);
|
||||
|
||||
assertInstance.strictEqual(err.message.split('\n').length, 204);
|
||||
assertInstance.strictEqual(err.actual.split('\n').length, 101);
|
||||
assertInstance.ok(
|
||||
err.message.includes('Expected values to be strictly equal')
|
||||
);
|
||||
assertInstance.ok(inspect(err).includes(`actual: '${truncatedAs}`));
|
||||
assertInstance.ok(inspect(err).includes(`expected: '${truncatedBs}`));
|
||||
return true;
|
||||
}
|
||||
);
|
||||
|
||||
assertInstance.throws(
|
||||
() => {
|
||||
assertInstance.notStrictEqual(longLinesOfAs, longLinesOfAs);
|
||||
},
|
||||
(err) => {
|
||||
assertInstance.strictEqual(err.code, 'ERR_ASSERTION');
|
||||
assertInstance.strictEqual(err.operator, 'notStrictEqual');
|
||||
assertInstance.strictEqual(err.diff, 'full');
|
||||
assertInstance.strictEqual(err.actual, longLinesOfAs);
|
||||
assertInstance.strictEqual(err.expected, longLinesOfAs);
|
||||
|
||||
assertInstance.strictEqual(err.message.split('\n').length, 103);
|
||||
assertInstance.strictEqual(err.actual.split('\n').length, 101);
|
||||
assertInstance.ok(
|
||||
err.message.includes(`Expected "actual" to be strictly unequal to:`)
|
||||
);
|
||||
assertInstance.ok(inspect(err).includes(`actual: '${truncatedAs}`));
|
||||
assertInstance.ok(inspect(err).includes(`expected: '${truncatedAs}`));
|
||||
return true;
|
||||
}
|
||||
);
|
||||
|
||||
assertInstance.throws(
|
||||
() => {
|
||||
assertInstance.deepEqual(longLinesOfAs, longLinesOFBs);
|
||||
},
|
||||
(err) => {
|
||||
assertInstance.strictEqual(err.code, 'ERR_ASSERTION');
|
||||
assertInstance.strictEqual(err.operator, 'deepEqual');
|
||||
assertInstance.strictEqual(err.diff, 'full');
|
||||
assertInstance.strictEqual(err.actual, longLinesOfAs);
|
||||
assertInstance.strictEqual(err.expected, longLinesOFBs);
|
||||
|
||||
assertInstance.strictEqual(err.message.split('\n').length, 205);
|
||||
assertInstance.strictEqual(err.actual.split('\n').length, 101);
|
||||
assertInstance.ok(
|
||||
err.message.includes(`Expected values to be loosely deep-equal:`)
|
||||
);
|
||||
assertInstance.ok(inspect(err).includes(`actual: '${truncatedAs}`));
|
||||
assertInstance.ok(inspect(err).includes(`expected: '${truncatedBs}`));
|
||||
return true;
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
test('Assert class non strict with simple diff', () => {
|
||||
const assertInstance = new Assert({ diff: 'simple', strict: false });
|
||||
|
||||
// long strings
|
||||
{
|
||||
assertInstance.throws(
|
||||
() => {
|
||||
assertInstance.strictEqual(longStringOfAs, longStringOfBs);
|
||||
},
|
||||
(err) => {
|
||||
assertInstance.strictEqual(err.code, 'ERR_ASSERTION');
|
||||
assertInstance.strictEqual(err.operator, 'strictEqual');
|
||||
assertInstance.strictEqual(err.diff, 'simple');
|
||||
assertInstance.strictEqual(err.actual, longStringOfAs);
|
||||
assertInstance.strictEqual(err.expected, longStringOfBs);
|
||||
|
||||
assertInstance.strictEqual(
|
||||
err.message,
|
||||
`Expected values to be strictly equal:\n+ actual - expected\n\n` +
|
||||
`+ '${longStringOfAs}'\n- '${longStringOfBs}'\n`
|
||||
);
|
||||
assertInstance.ok(
|
||||
inspect(err).includes(`actual: '${longLinesOfAsWithEllipsis}'`)
|
||||
);
|
||||
assertInstance.ok(
|
||||
inspect(err).includes(`expected: '${longLinesOFBsWithEllipsis}'`)
|
||||
);
|
||||
return true;
|
||||
}
|
||||
);
|
||||
|
||||
assertInstance.throws(
|
||||
() => {
|
||||
assertInstance.notStrictEqual(longStringOfAs, longStringOfAs);
|
||||
},
|
||||
(err) => {
|
||||
assertInstance.strictEqual(err.code, 'ERR_ASSERTION');
|
||||
assertInstance.strictEqual(err.operator, 'notStrictEqual');
|
||||
assertInstance.strictEqual(err.diff, 'simple');
|
||||
assertInstance.strictEqual(err.actual, longStringOfAs);
|
||||
assertInstance.strictEqual(err.expected, longStringOfAs);
|
||||
|
||||
assertInstance.strictEqual(
|
||||
err.message,
|
||||
`Expected "actual" to be strictly unequal to:\n\n` +
|
||||
`'${longStringOfAs}'`
|
||||
);
|
||||
assertInstance.ok(
|
||||
inspect(err).includes(`actual: '${longLinesOfAsWithEllipsis}'`)
|
||||
);
|
||||
assertInstance.ok(
|
||||
inspect(err).includes(`expected: '${longLinesOfAsWithEllipsis}'`)
|
||||
);
|
||||
return true;
|
||||
}
|
||||
);
|
||||
|
||||
assertInstance.throws(
|
||||
() => {
|
||||
assertInstance.deepEqual(longStringOfAs, longStringOfBs);
|
||||
},
|
||||
(err) => {
|
||||
assertInstance.strictEqual(err.code, 'ERR_ASSERTION');
|
||||
assertInstance.strictEqual(err.operator, 'deepEqual');
|
||||
assertInstance.strictEqual(err.diff, 'simple');
|
||||
assertInstance.strictEqual(err.actual, longStringOfAs);
|
||||
assertInstance.strictEqual(err.expected, longStringOfBs);
|
||||
|
||||
assertInstance.strictEqual(
|
||||
err.message,
|
||||
`Expected values to be loosely deep-equal:\n\n` +
|
||||
`'${
|
||||
longStringOfAs.substring(0, 508) + '...'
|
||||
}\n\nshould loosely deep-equal\n\n'${
|
||||
longStringOfBs.substring(0, 508) + '...'
|
||||
}`
|
||||
);
|
||||
assertInstance.ok(
|
||||
inspect(err).includes(`actual: '${longLinesOfAsWithEllipsis}'`)
|
||||
);
|
||||
assertInstance.ok(
|
||||
inspect(err).includes(`expected: '${longLinesOFBsWithEllipsis}'`)
|
||||
);
|
||||
return true;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// long lines
|
||||
{
|
||||
assertInstance.throws(
|
||||
() => {
|
||||
assertInstance.strictEqual(longLinesOfAs, longLinesOFBs);
|
||||
},
|
||||
(err) => {
|
||||
assertInstance.strictEqual(err.code, 'ERR_ASSERTION');
|
||||
assertInstance.strictEqual(err.operator, 'strictEqual');
|
||||
assertInstance.strictEqual(err.diff, 'simple');
|
||||
assertInstance.strictEqual(err.actual, longLinesOfAs);
|
||||
assertInstance.strictEqual(err.expected, longLinesOFBs);
|
||||
assertInstance.strictEqual(err.message.split('\n').length, 204);
|
||||
assertInstance.strictEqual(err.actual.split('\n').length, 101);
|
||||
|
||||
assertInstance.ok(
|
||||
err.message.includes('Expected values to be strictly equal')
|
||||
);
|
||||
assertInstance.ok(inspect(err).includes(`actual: '${truncatedAs}`));
|
||||
assertInstance.ok(inspect(err).includes(`expected: '${truncatedBs}`));
|
||||
return true;
|
||||
}
|
||||
);
|
||||
|
||||
assertInstance.throws(
|
||||
() => {
|
||||
assertInstance.notStrictEqual(longLinesOfAs, longLinesOfAs);
|
||||
},
|
||||
(err) => {
|
||||
assertInstance.strictEqual(err.code, 'ERR_ASSERTION');
|
||||
assertInstance.strictEqual(err.operator, 'notStrictEqual');
|
||||
assertInstance.strictEqual(err.diff, 'simple');
|
||||
assertInstance.strictEqual(err.actual, longLinesOfAs);
|
||||
assertInstance.strictEqual(err.expected, longLinesOfAs);
|
||||
|
||||
assertInstance.strictEqual(err.message.split('\n').length, 50);
|
||||
assertInstance.strictEqual(err.actual.split('\n').length, 101);
|
||||
assertInstance.ok(
|
||||
err.message.includes(`Expected "actual" to be strictly unequal to:`)
|
||||
);
|
||||
assertInstance.ok(inspect(err).includes(`actual: '${truncatedAs}`));
|
||||
assertInstance.ok(inspect(err).includes(`expected: '${truncatedAs}`));
|
||||
return true;
|
||||
}
|
||||
);
|
||||
|
||||
assertInstance.throws(
|
||||
() => {
|
||||
assertInstance.deepEqual(longLinesOfAs, longLinesOFBs);
|
||||
},
|
||||
(err) => {
|
||||
assertInstance.strictEqual(err.code, 'ERR_ASSERTION');
|
||||
assertInstance.strictEqual(err.operator, 'deepEqual');
|
||||
assertInstance.strictEqual(err.diff, 'simple');
|
||||
assertInstance.strictEqual(err.actual, longLinesOfAs);
|
||||
assertInstance.strictEqual(err.expected, longLinesOFBs);
|
||||
|
||||
assertInstance.strictEqual(err.message.split('\n').length, 109);
|
||||
assertInstance.strictEqual(err.actual.split('\n').length, 101);
|
||||
assertInstance.ok(
|
||||
err.message.includes(`Expected values to be loosely deep-equal:`)
|
||||
);
|
||||
assertInstance.ok(inspect(err).includes(`actual: '${truncatedAs}`));
|
||||
assertInstance.ok(inspect(err).includes(`expected: '${truncatedBs}`));
|
||||
return true;
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
|
@ -7,6 +7,8 @@ test('expected methods are on t.assert', (t) => {
|
|||
const uncopiedKeys = [
|
||||
'AssertionError',
|
||||
'strict',
|
||||
'Assert',
|
||||
'options',
|
||||
];
|
||||
const assertKeys = Object.keys(assert).filter((key) => !uncopiedKeys.includes(key));
|
||||
const expectedKeys = ['snapshot', 'fileSnapshot'].concat(assertKeys).sort();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue