nodejs/test/parallel/test-assert.js

1417 lines
35 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Flags: --expose-internals
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
'use strict';
const common = require('../common');
const assert = require('assert');
const { inspect } = require('util');
const { internalBinding } = require('internal/test/binding');
const a = assert;
// 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';
const strictEqualMessageStart = 'Expected values to be strictly equal:\n';
const start = 'Expected values to be strictly deep-equal:';
const actExp = '+ actual - expected';
assert.ok(a.AssertionError.prototype instanceof Error,
'a.AssertionError instanceof Error');
assert.throws(() => a(false), a.AssertionError, 'ok(false)');
assert.throws(() => a.ok(false), a.AssertionError, 'ok(false)');
// Throw message if the message is instanceof Error.
{
let threw = false;
try {
assert.ok(false, new Error('ok(false)'));
} catch (e) {
threw = true;
assert.ok(e instanceof Error);
}
assert.ok(threw, 'Error: ok(false)');
}
a(true);
a('test', 'ok(\'test\')');
a.ok(true);
a.ok('test');
assert.throws(() => a.equal(true, false),
a.AssertionError, 'equal(true, false)');
a.equal(null, null);
a.equal(undefined, undefined);
a.equal(null, undefined);
a.equal(true, true);
a.equal(2, '2');
a.notEqual(true, false);
assert.throws(() => a.notEqual(true, true),
a.AssertionError, 'notEqual(true, true)');
assert.throws(() => a.strictEqual(2, '2'),
a.AssertionError, 'strictEqual(2, \'2\')');
/* eslint-disable no-restricted-syntax */
assert.throws(() => a.strictEqual(null, undefined),
a.AssertionError, 'strictEqual(null, undefined)');
assert.throws(
() => a.notStrictEqual(2, 2),
{
message: 'Expected "actual" to be strictly unequal to: 2',
name: 'AssertionError'
}
);
assert.throws(
() => a.notStrictEqual('a '.repeat(30), 'a '.repeat(30)),
{
message: 'Expected "actual" to be strictly unequal to:\n\n' +
`'${'a '.repeat(30)}'`,
name: 'AssertionError'
}
);
assert.throws(
() => a.notEqual(1, 1),
{
message: '1 != 1',
operator: '!='
}
);
a.notStrictEqual(2, '2');
// Testing the throwing.
function thrower(errorConstructor) {
throw new errorConstructor({});
}
// The basic calls work.
assert.throws(() => thrower(a.AssertionError), a.AssertionError, 'message');
assert.throws(() => thrower(a.AssertionError), a.AssertionError);
assert.throws(() => thrower(a.AssertionError));
// If not passing an error, catch all.
assert.throws(() => thrower(TypeError));
// When passing a type, only catch errors of the appropriate type.
{
let threw = false;
try {
a.throws(() => thrower(TypeError), a.AssertionError);
} catch (e) {
threw = true;
assert.ok(e instanceof TypeError, 'type');
}
assert.ok(threw, 'a.throws with an explicit error is eating extra errors');
}
// doesNotThrow should pass through all errors.
{
let threw = false;
try {
a.doesNotThrow(() => thrower(TypeError), a.AssertionError);
} catch (e) {
threw = true;
assert.ok(e instanceof TypeError);
}
assert(threw, 'a.doesNotThrow with an explicit error is eating extra errors');
}
// Key difference is that throwing our correct error makes an assertion error.
{
let threw = false;
try {
a.doesNotThrow(() => thrower(TypeError), TypeError);
} catch (e) {
threw = true;
assert.ok(e instanceof a.AssertionError);
assert.ok(!e.stack.includes('at Function.doesNotThrow'));
}
assert.ok(threw, 'a.doesNotThrow is not catching type matching errors');
}
assert.throws(
() => a.doesNotThrow(() => thrower(Error), 'user message'),
{
name: 'AssertionError',
code: 'ERR_ASSERTION',
operator: 'doesNotThrow',
message: 'Got unwanted exception: user message\n' +
'Actual message: "[object Object]"'
}
);
assert.throws(
() => a.doesNotThrow(() => thrower(Error)),
{
code: 'ERR_ASSERTION',
message: 'Got unwanted exception.\nActual message: "[object Object]"'
}
);
assert.throws(
() => a.doesNotThrow(() => thrower(Error), /\[[a-z]{6}\s[A-z]{6}\]/g, 'user message'),
{
name: 'AssertionError',
code: 'ERR_ASSERTION',
operator: 'doesNotThrow',
message: 'Got unwanted exception: user message\n' +
'Actual message: "[object Object]"'
}
);
// Make sure that validating using constructor really works.
{
let threw = false;
try {
assert.throws(
() => {
throw ({}); // eslint-disable-line no-throw-literal
},
Array
);
} catch {
threw = true;
}
assert.ok(threw, 'wrong constructor validation');
}
// Use a RegExp to validate the error message.
{
a.throws(() => thrower(TypeError), /\[object Object\]/);
const symbol = Symbol('foo');
a.throws(() => {
throw symbol;
}, /foo/);
a.throws(() => {
a.throws(() => {
throw symbol;
}, /abc/);
}, {
message: 'The input did not match the regular expression /abc/. ' +
"Input:\n\n'Symbol(foo)'\n",
code: 'ERR_ASSERTION',
operator: 'throws',
actual: symbol,
expected: /abc/
});
}
// Use a fn to validate the error object.
a.throws(() => thrower(TypeError), (err) => {
if ((err instanceof TypeError) && /\[object Object\]/.test(err)) {
return true;
}
});
// https://github.com/nodejs/node/issues/3188
{
let threw = false;
let AnotherErrorType;
try {
const ES6Error = class extends Error {};
AnotherErrorType = class extends Error {};
assert.throws(() => { throw new AnotherErrorType('foo'); }, ES6Error);
} catch (e) {
threw = true;
assert(e instanceof AnotherErrorType,
`expected AnotherErrorType, received ${e}`);
}
assert.ok(threw);
}
// Check messages from assert.throws().
{
const noop = () => {};
assert.throws(
() => { a.throws((noop)); },
{
code: 'ERR_ASSERTION',
message: 'Missing expected exception.',
operator: 'throws',
actual: undefined,
expected: undefined
});
assert.throws(
() => { a.throws(noop, TypeError); },
{
code: 'ERR_ASSERTION',
message: 'Missing expected exception (TypeError).',
actual: undefined,
expected: TypeError
});
assert.throws(
() => { a.throws(noop, 'fhqwhgads'); },
{
code: 'ERR_ASSERTION',
message: 'Missing expected exception: fhqwhgads',
actual: undefined,
expected: undefined
});
assert.throws(
() => { a.throws(noop, TypeError, 'fhqwhgads'); },
{
code: 'ERR_ASSERTION',
message: 'Missing expected exception (TypeError): fhqwhgads',
actual: undefined,
expected: TypeError
});
let threw = false;
try {
a.throws(noop);
} catch (e) {
threw = true;
assert.ok(e instanceof a.AssertionError);
assert.ok(!e.stack.includes('at Function.throws'));
}
assert.ok(threw);
}
const circular = { y: 1 };
circular.x = circular;
function testAssertionMessage(actual, expected, msg) {
assert.throws(
() => assert.strictEqual(actual, ''),
{
generatedMessage: true,
message: msg || strictEqualMessageStart +
`+ actual - expected\n\n+ ${expected}\n- ''`
}
);
}
function testShortAssertionMessage(actual, expected) {
testAssertionMessage(actual, expected, strictEqualMessageStart +
`\n${inspect(actual)} !== ''\n`);
}
testShortAssertionMessage(null, 'null');
testShortAssertionMessage(true, 'true');
testShortAssertionMessage(false, 'false');
testShortAssertionMessage(100, '100');
testShortAssertionMessage(NaN, 'NaN');
testShortAssertionMessage(Infinity, 'Infinity');
testShortAssertionMessage('a', '"a"');
testShortAssertionMessage('foo', '\'foo\'');
testShortAssertionMessage(0, '0');
testShortAssertionMessage(Symbol(), 'Symbol()');
testShortAssertionMessage(undefined, 'undefined');
testShortAssertionMessage(-Infinity, '-Infinity');
testShortAssertionMessage(function() {}, '[Function]');
testAssertionMessage([], '[]');
testAssertionMessage(/a/, '/a/');
testAssertionMessage(/abc/gim, '/abc/gim');
testAssertionMessage({}, '{}');
testAssertionMessage([1, 2, 3], '[\n+ 1,\n+ 2,\n+ 3\n+ ]');
testAssertionMessage(function f() {}, '[Function: f]');
testAssertionMessage(circular,
'{\n+ x: [Circular],\n+ y: 1\n+ }');
testAssertionMessage({ a: undefined, b: null },
'{\n+ a: undefined,\n+ b: null\n+ }');
testAssertionMessage({ a: NaN, b: Infinity, c: -Infinity },
'{\n+ a: NaN,\n+ b: Infinity,\n+ c: -Infinity\n+ }');
// https://github.com/nodejs/node-v0.x-archive/issues/5292
assert.throws(
() => assert.strictEqual(1, 2),
{
message: `${strictEqualMessageStart}\n1 !== 2\n`,
generatedMessage: true
}
);
assert.throws(
() => assert.strictEqual(1, 2, 'oh no'),
{
message: 'oh no',
generatedMessage: false
}
);
{
let threw = false;
const rangeError = new RangeError('my range');
// Verify custom errors.
try {
assert.strictEqual(1, 2, rangeError);
} catch (e) {
assert.strictEqual(e, rangeError);
threw = true;
assert.ok(e instanceof RangeError, 'Incorrect error type thrown');
}
assert.ok(threw);
threw = false;
// Verify AssertionError is the result from doesNotThrow with custom Error.
try {
a.doesNotThrow(() => {
throw new TypeError('wrong type');
}, TypeError, rangeError);
} catch (e) {
threw = true;
assert.ok(e.message.includes(rangeError.message));
assert.ok(e instanceof assert.AssertionError);
assert.ok(!e.stack.includes('doesNotThrow'), e);
}
assert.ok(threw);
}
{
// Verify that throws() and doesNotThrow() throw on non-functions.
const testBlockTypeError = (method, fn) => {
assert.throws(
() => method(fn),
{
code: 'ERR_INVALID_ARG_TYPE',
name: 'TypeError',
message: 'The "fn" argument must be of type function.' +
common.invalidArgTypeHelper(fn)
}
);
};
testBlockTypeError(assert.throws, 'string');
testBlockTypeError(assert.doesNotThrow, 'string');
testBlockTypeError(assert.throws, 1);
testBlockTypeError(assert.doesNotThrow, 1);
testBlockTypeError(assert.throws, true);
testBlockTypeError(assert.doesNotThrow, true);
testBlockTypeError(assert.throws, false);
testBlockTypeError(assert.doesNotThrow, false);
testBlockTypeError(assert.throws, []);
testBlockTypeError(assert.doesNotThrow, []);
testBlockTypeError(assert.throws, {});
testBlockTypeError(assert.doesNotThrow, {});
testBlockTypeError(assert.throws, /foo/);
testBlockTypeError(assert.doesNotThrow, /foo/);
testBlockTypeError(assert.throws, null);
testBlockTypeError(assert.doesNotThrow, null);
testBlockTypeError(assert.throws, undefined);
testBlockTypeError(assert.doesNotThrow, undefined);
}
// https://github.com/nodejs/node/issues/3275
// eslint-disable-next-line no-throw-literal
assert.throws(() => { throw 'error'; }, (err) => err === 'error');
assert.throws(() => { throw new Error(); }, (err) => err instanceof Error);
// Long values should be truncated for display.
assert.throws(() => {
assert.strictEqual('A'.repeat(1000), '');
}, (err) => {
assert.strictEqual(err.code, 'ERR_ASSERTION');
assert.strictEqual(err.message,
`${strictEqualMessageStart}+ actual - expected\n\n` +
`+ '${'A'.repeat(1000)}'\n- ''`);
assert.strictEqual(err.actual.length, 1000);
assert.ok(inspect(err).includes(`actual: '${'A'.repeat(488)}...'`));
return true;
});
// Output that extends beyond 10 lines should also be truncated for display.
{
const multilineString = 'fhqwhgads\n'.repeat(15);
assert.throws(() => {
assert.strictEqual(multilineString, '');
}, (err) => {
assert.strictEqual(err.code, 'ERR_ASSERTION');
assert.strictEqual(err.message.split('\n').length, 19);
assert.strictEqual(err.actual.split('\n').length, 16);
assert.ok(inspect(err).includes(
"actual: 'fhqwhgads\\n' +\n" +
" 'fhqwhgads\\n' +\n".repeat(9) +
" '...'"));
return true;
});
}
{
// Bad args to AssertionError constructor should throw TypeError.
const args = [1, true, false, '', null, Infinity, Symbol('test'), undefined];
args.forEach((input) => {
assert.throws(
() => new assert.AssertionError(input),
{
code: 'ERR_INVALID_ARG_TYPE',
name: 'TypeError',
message: 'The "options" argument must be of type object.' +
common.invalidArgTypeHelper(input)
});
});
}
assert.throws(
() => assert.strictEqual(new Error('foo'), new Error('foobar')),
{
code: 'ERR_ASSERTION',
name: 'AssertionError',
message: 'Expected "actual" to be reference-equal to "expected":\n' +
'+ actual - expected\n\n' +
'+ [Error: foo]\n- [Error: foobar]'
}
);
// Test strict assert.
{
const a = require('assert');
const assert = require('assert').strict;
/* eslint-disable no-restricted-properties */
assert.throws(() => assert.equal(1, true), assert.AssertionError);
assert.notEqual(0, false);
assert.throws(() => assert.deepEqual(1, true), assert.AssertionError);
assert.notDeepEqual(0, false);
assert.equal(assert.strict, assert.strict.strict);
assert.equal(assert.equal, assert.strictEqual);
assert.equal(assert.deepEqual, assert.deepStrictEqual);
assert.equal(assert.notEqual, assert.notStrictEqual);
assert.equal(assert.notDeepEqual, assert.notDeepStrictEqual);
assert.equal(Object.keys(assert).length, Object.keys(a).length);
assert(7);
assert.throws(
() => assert(...[]),
{
message: 'No value argument passed to `assert.ok()`',
name: 'AssertionError',
generatedMessage: true
}
);
assert.throws(
() => a(),
{
message: 'No value argument passed to `assert.ok()`',
name: 'AssertionError'
}
);
// Test setting the limit to zero and that assert.strict works properly.
const tmpLimit = Error.stackTraceLimit;
Error.stackTraceLimit = 0;
assert.throws(
() => {
assert.ok(
typeof 123 === 'string'
);
},
{
code: 'ERR_ASSERTION',
constructor: assert.AssertionError,
message: 'The expression evaluated to a falsy value:\n\n ' +
"assert.ok(\n typeof 123 === 'string'\n )\n"
}
);
Error.stackTraceLimit = tmpLimit;
// Test error diffs.
let message = [
start,
`${actExp} ... Lines skipped`,
'',
' [',
' [',
' [',
' 1,',
' 2,',
'+ 3',
"- '3'",
' ]',
'...',
' 4,',
' 5',
' ]'].join('\n');
assert.throws(
() => assert.deepEqual([[[1, 2, 3]], 4, 5], [[[1, 2, '3']], 4, 5]),
{ message });
message = [
start,
`${actExp} ... Lines skipped`,
'',
' [',
' 1,',
'...',
' 1,',
' 0,',
'- 1,',
' 1,',
'...',
' 1,',
' 1',
' ]'
].join('\n');
assert.throws(
() => assert.deepEqual(
[1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1]),
{ message });
message = [
start,
`${actExp} ... Lines skipped`,
'',
' [',
' 1,',
'...',
' 1,',
' 0,',
'+ 1,',
' 1,',
' 1,',
' 1',
' ]'
].join('\n');
assert.throws(
() => assert.deepEqual(
[1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1]),
{ message });
message = [
start,
actExp,
'',
' [',
' 1,',
'+ 2,',
'- 1,',
' 1,',
' 1,',
' 0,',
'+ 1,',
' 1',
' ]'
].join('\n');
assert.throws(
() => assert.deepEqual(
[1, 2, 1, 1, 0, 1, 1],
[1, 1, 1, 1, 0, 1]),
{ message });
message = [
start,
actExp,
'',
'+ [',
'+ 1,',
'+ 2,',
'+ 1',
'+ ]',
'- undefined',
].join('\n');
assert.throws(
() => assert.deepEqual([1, 2, 1], undefined),
{ message });
message = [
start,
actExp,
'',
' [',
'+ 1,',
' 2,',
' 1',
' ]'
].join('\n');
assert.throws(
() => assert.deepEqual([1, 2, 1], [2, 1]),
{ message });
message = `${start}\n` +
`${actExp} ... Lines skipped\n` +
'\n' +
' [\n' +
'+ 1,\n'.repeat(25) +
'...\n' +
'- 2,\n'.repeat(25) +
'...';
assert.throws(
() => assert.deepEqual(Array(28).fill(1), Array(28).fill(2)),
{ message });
const obj1 = {};
const obj2 = { loop: 'forever' };
obj2[inspect.custom] = () => '{}';
// No infinite loop and no custom inspect.
assert.throws(() => assert.deepEqual(obj1, obj2), {
message: `${start}\n` +
`${actExp}\n` +
'\n' +
'+ {}\n' +
'- {\n' +
'- [Symbol(nodejs.util.inspect.custom)]: [Function],\n' +
"- loop: 'forever'\n" +
'- }'
});
// notDeepEqual tests
assert.throws(
() => assert.notDeepEqual([1], [1]),
{
message: 'Expected "actual" not to be strictly deep-equal to:\n\n' +
'[\n 1\n]\n'
}
);
message = 'Expected "actual" not to be strictly deep-equal to:' +
`\n\n[${'\n 1,'.repeat(45)}\n...\n`;
const data = Array(51).fill(1);
assert.throws(
() => assert.notDeepEqual(data, data),
{ message });
/* eslint-enable no-restricted-properties */
}
assert.throws(
() => assert.ok(null),
{
code: 'ERR_ASSERTION',
constructor: assert.AssertionError,
generatedMessage: true,
message: 'The expression evaluated to a falsy value:\n\n ' +
'assert.ok(null)\n'
}
);
assert.throws(
() => assert(typeof 123n === 'string'),
{
code: 'ERR_ASSERTION',
constructor: assert.AssertionError,
generatedMessage: true,
message: 'The expression evaluated to a falsy value:\n\n ' +
"assert(typeof 123n === 'string')\n"
}
);
assert.throws(
() => assert(false, Symbol('foo')),
{
code: 'ERR_ASSERTION',
constructor: assert.AssertionError,
generatedMessage: false,
message: 'Symbol(foo)'
}
);
{
// Test caching.
const fs = internalBinding('fs');
const tmp = fs.close;
fs.close = common.mustCall(tmp, 1);
function throwErr() {
assert(
(Buffer.from('test') instanceof Error)
);
}
assert.throws(
() => throwErr(),
{
code: 'ERR_ASSERTION',
constructor: assert.AssertionError,
message: 'The expression evaluated to a falsy value:\n\n ' +
"assert(\n (Buffer.from('test') instanceof Error)\n )\n"
}
);
assert.throws(
() => throwErr(),
{
code: 'ERR_ASSERTION',
constructor: assert.AssertionError,
message: 'The expression evaluated to a falsy value:\n\n ' +
"assert(\n (Buffer.from('test') instanceof Error)\n )\n"
}
);
fs.close = tmp;
}
assert.throws(
() => {
a(
(() => 'string')()
// eslint-disable-next-line operator-linebreak
===
123 instanceof
Buffer
);
},
{
code: 'ERR_ASSERTION',
constructor: assert.AssertionError,
message: 'The expression evaluated to a falsy value:\n\n' +
' a(\n' +
' (() => \'string\')()\n' +
' // eslint-disable-next-line operator-linebreak\n' +
' ===\n' +
' 123 instanceof\n' +
' Buffer\n' +
' )\n'
}
);
assert.throws(
() => {
a(
(() => 'string')()
// eslint-disable-next-line operator-linebreak
===
123 instanceof
Buffer
);
},
{
code: 'ERR_ASSERTION',
constructor: assert.AssertionError,
message: 'The expression evaluated to a falsy value:\n\n' +
' a(\n' +
' (() => \'string\')()\n' +
' // eslint-disable-next-line operator-linebreak\n' +
' ===\n' +
' 123 instanceof\n' +
' Buffer\n' +
' )\n'
}
);
/* eslint-disable indent */
assert.throws(() => {
a((
() => 'string')() ===
123 instanceof
Buffer
);
}, {
code: 'ERR_ASSERTION',
constructor: assert.AssertionError,
message: 'The expression evaluated to a falsy value:\n\n' +
' a((\n' +
' () => \'string\')() ===\n' +
' 123 instanceof\n' +
' Buffer\n' +
' )\n'
}
);
/* eslint-enable indent */
assert.throws(
() => {
assert(true); assert(null, undefined);
},
{
code: 'ERR_ASSERTION',
constructor: assert.AssertionError,
message: 'The expression evaluated to a falsy value:\n\n ' +
'assert(null, undefined)\n'
}
);
assert.throws(
() => {
assert
.ok(null, undefined);
},
{
code: 'ERR_ASSERTION',
constructor: assert.AssertionError,
message: 'The expression evaluated to a falsy value:\n\n ' +
'ok(null, undefined)\n'
}
);
assert.throws(
// eslint-disable-next-line dot-notation, quotes
() => assert['ok']["apply"](null, [0]),
{
code: 'ERR_ASSERTION',
constructor: assert.AssertionError,
message: 'The expression evaluated to a falsy value:\n\n ' +
'assert[\'ok\']["apply"](null, [0])\n'
}
);
assert.throws(
() => {
const wrapper = (fn, value) => fn(value);
wrapper(assert, false);
},
{
code: 'ERR_ASSERTION',
constructor: assert.AssertionError,
message: 'The expression evaluated to a falsy value:\n\n fn(value)\n'
}
);
assert.throws(
() => assert.ok.call(null, 0),
{
code: 'ERR_ASSERTION',
constructor: assert.AssertionError,
message: 'The expression evaluated to a falsy value:\n\n ' +
'assert.ok.call(null, 0)\n',
generatedMessage: true
}
);
assert.throws(
() => assert.ok.call(null, 0, 'test'),
{
code: 'ERR_ASSERTION',
constructor: assert.AssertionError,
message: 'test',
generatedMessage: false
}
);
// Works in eval.
assert.throws(
() => new Function('assert', 'assert(1 === 2);')(assert),
{
code: 'ERR_ASSERTION',
constructor: assert.AssertionError,
message: 'The expression evaluated to a falsy value:\n\n assert(1 === 2)\n'
}
);
assert.throws(
() => eval('console.log("FOO");\nassert.ok(1 === 2);'),
{
code: 'ERR_ASSERTION',
message: 'false == true'
}
);
assert.throws(
() => assert.throws(() => {}, 'Error message', 'message'),
{
code: 'ERR_INVALID_ARG_TYPE',
name: 'TypeError',
message: 'The "error" argument must be of type function or ' +
'an instance of Error, RegExp, or Object. Received type string ' +
"('Error message')"
}
);
[
1,
false,
Symbol()
].forEach((input) => {
assert.throws(
() => assert.throws(() => {}, input),
{
code: 'ERR_INVALID_ARG_TYPE',
message: 'The "error" argument must be of type function or ' +
'an instance of Error, RegExp, or Object.' +
common.invalidArgTypeHelper(input)
}
);
});
{
assert.throws(() => {
assert.ok((() => Boolean('' === false))());
}, {
message: 'The expression evaluated to a falsy value:\n\n' +
" assert.ok((() => Boolean('\\u0001' === false))())\n"
});
const errFn = () => {
const err = new TypeError('Wrong value');
err.code = 404;
throw err;
};
const errObj = {
name: 'TypeError',
message: 'Wrong value'
};
assert.throws(errFn, errObj);
errObj.code = 404;
assert.throws(errFn, errObj);
// Fail in case a expected property is undefined and not existent on the
// error.
errObj.foo = undefined;
assert.throws(
() => assert.throws(errFn, errObj),
{
code: 'ERR_ASSERTION',
name: 'AssertionError',
message: `${start}\n${actExp}\n\n` +
' Comparison {\n' +
' code: 404,\n' +
'- foo: undefined,\n' +
" message: 'Wrong value',\n" +
" name: 'TypeError'\n" +
' }'
}
);
// Show multiple wrong properties at the same time.
errObj.code = '404';
assert.throws(
() => assert.throws(errFn, errObj),
{
code: 'ERR_ASSERTION',
name: 'AssertionError',
message: `${start}\n${actExp}\n\n` +
' Comparison {\n' +
'+ code: 404,\n' +
"- code: '404',\n" +
'- foo: undefined,\n' +
" message: 'Wrong value',\n" +
" name: 'TypeError'\n" +
' }'
}
);
assert.throws(
() => assert.throws(() => { throw new Error(); }, { foo: 'bar' }, 'foobar'),
{
constructor: assert.AssertionError,
code: 'ERR_ASSERTION',
message: 'foobar'
}
);
assert.throws(
() => a.doesNotThrow(() => { throw new Error(); }, { foo: 'bar' }),
{
name: 'TypeError',
code: 'ERR_INVALID_ARG_TYPE',
message: 'The "expected" argument must be of type function or an ' +
'instance of RegExp. Received an instance of Object'
}
);
assert.throws(() => { throw new Error('e'); }, new Error('e'));
assert.throws(
() => assert.throws(() => { throw new TypeError('e'); }, new Error('e')),
{
name: 'AssertionError',
code: 'ERR_ASSERTION',
message: `${start}\n${actExp}\n\n` +
' Comparison {\n' +
" message: 'e',\n" +
"+ name: 'TypeError'\n" +
"- name: 'Error'\n" +
' }'
}
);
assert.throws(
() => assert.throws(() => { throw new Error('foo'); }, new Error('')),
{
name: 'AssertionError',
code: 'ERR_ASSERTION',
generatedMessage: true,
message: `${start}\n${actExp}\n\n` +
' Comparison {\n' +
"+ message: 'foo',\n" +
"- message: '',\n" +
" name: 'Error'\n" +
' }'
}
);
// eslint-disable-next-line no-throw-literal
assert.throws(() => { throw undefined; }, /undefined/);
assert.throws(
// eslint-disable-next-line no-throw-literal
() => a.doesNotThrow(() => { throw undefined; }),
{
name: 'AssertionError',
code: 'ERR_ASSERTION',
message: 'Got unwanted exception.\nActual message: "undefined"'
}
);
}
assert.throws(
() => assert.throws(() => { throw new Error(); }, {}),
{
message: "The argument 'error' may not be an empty object. Received {}",
code: 'ERR_INVALID_ARG_VALUE'
}
);
assert.throws(
() => a.throws(
// eslint-disable-next-line no-throw-literal
() => { throw 'foo'; },
'foo'
),
{
code: 'ERR_AMBIGUOUS_ARGUMENT',
message: 'The "error/message" argument is ambiguous. ' +
'The error "foo" is identical to the message.'
}
);
assert.throws(
() => a.throws(
() => { throw new TypeError('foo'); },
'foo'
),
{
code: 'ERR_AMBIGUOUS_ARGUMENT',
message: 'The "error/message" argument is ambiguous. ' +
'The error message "foo" is identical to the message.'
}
);
/* eslint-enable no-restricted-syntax */
// Should not throw.
// eslint-disable-next-line no-restricted-syntax, no-throw-literal
assert.throws(() => { throw null; }, 'foo');
assert.throws(
() => assert.strictEqual([], []),
{
message: 'Values have same structure but are not reference-equal:\n\n[]\n'
}
);
{
const args = (function() { return arguments; })('a');
assert.throws(
() => assert.strictEqual(args, { 0: 'a' }),
{
message: 'Expected "actual" to be reference-equal to "expected":\n' +
'+ actual - expected\n\n' +
"+ [Arguments] {\n- {\n '0': 'a'\n }"
}
);
}
assert.throws(
() => { throw new TypeError('foobar'); },
{
message: /foo/,
name: /^TypeError$/
}
);
assert.throws(
() => assert.throws(
() => { throw new TypeError('foobar'); },
{
message: /fooa/,
name: /^TypeError$/
}
),
{
message: `${start}\n${actExp}\n\n` +
' Comparison {\n' +
"+ message: 'foobar',\n" +
'- message: /fooa/,\n' +
" name: 'TypeError'\n" +
' }'
}
);
{
let actual = null;
const expected = { message: 'foo' };
assert.throws(
() => assert.throws(
() => { throw actual; },
expected
),
{
operator: 'throws',
actual,
expected,
generatedMessage: true,
message: `${start}\n${actExp}\n\n` +
'+ null\n' +
'- {\n' +
"- message: 'foo'\n" +
'- }'
}
);
actual = 'foobar';
const message = 'message';
assert.throws(
() => assert.throws(
() => { throw actual; },
{ message: 'foobar' },
message
),
{
actual,
message,
operator: 'throws',
generatedMessage: false
}
);
}
// Indicate where the strings diverge.
assert.throws(
() => assert.strictEqual('test test', 'test foobar'),
{
code: 'ERR_ASSERTION',
name: 'AssertionError',
message: strictEqualMessageStart +
'+ actual - expected\n\n' +
"+ 'test test'\n" +
"- 'test foobar'\n" +
' ^'
}
);
// Check for reference-equal objects in `notStrictEqual()`
assert.throws(
() => {
const obj = {};
assert.notStrictEqual(obj, obj);
},
{
code: 'ERR_ASSERTION',
name: 'AssertionError',
message: 'Expected "actual" not to be reference-equal to "expected": {}'
}
);
assert.throws(
() => {
const obj = { a: true };
assert.notStrictEqual(obj, obj);
},
{
code: 'ERR_ASSERTION',
name: 'AssertionError',
message: 'Expected "actual" not to be reference-equal to "expected":\n\n' +
'{\n a: true\n}\n'
}
);
{
let threw = false;
try {
assert.deepStrictEqual(Array(100).fill(1), 'foobar');
} catch (err) {
threw = true;
assert(/actual: \[Array],\n expected: 'foobar',/.test(inspect(err)));
}
assert(threw);
}
assert.throws(
() => a.equal(1),
{ code: 'ERR_MISSING_ARGS' }
);
assert.throws(
() => a.deepEqual(/a/),
{ code: 'ERR_MISSING_ARGS' }
);
assert.throws(
() => a.notEqual(null),
{ code: 'ERR_MISSING_ARGS' }
);
assert.throws(
() => a.notDeepEqual('test'),
{ code: 'ERR_MISSING_ARGS' }
);
assert.throws(
() => a.strictEqual({}),
{ code: 'ERR_MISSING_ARGS' }
);
assert.throws(
() => a.deepStrictEqual(Symbol()),
{ code: 'ERR_MISSING_ARGS' }
);
assert.throws(
() => a.notStrictEqual(5n),
{ code: 'ERR_MISSING_ARGS' }
);
assert.throws(
() => a.notDeepStrictEqual(undefined),
{ code: 'ERR_MISSING_ARGS' }
);
assert.throws(
() => a.strictEqual(),
{ code: 'ERR_MISSING_ARGS' }
);
assert.throws(
() => a.deepStrictEqual(),
{ code: 'ERR_MISSING_ARGS' }
);
// Verify that `stackStartFunction` works as alternative to `stackStartFn`.
{
(function hidden() {
const err = new assert.AssertionError({
actual: 'foo',
operator: 'strictEqual',
stackStartFunction: hidden
});
const err2 = new assert.AssertionError({
actual: 'foo',
operator: 'strictEqual',
stackStartFn: hidden
});
assert(!err.stack.includes('hidden'));
assert(!err2.stack.includes('hidden'));
})();
}
// Multiple assert.match() tests.
{
assert.throws(
() => assert.match(/abc/, 'string'),
{
code: 'ERR_INVALID_ARG_TYPE',
message: 'The "regexp" argument must be an instance of RegExp. ' +
"Received type string ('string')"
}
);
assert.throws(
() => assert.match('string', /abc/),
{
actual: 'string',
expected: /abc/,
operator: 'match',
message: 'The input did not match the regular expression /abc/. ' +
"Input:\n\n'string'\n",
generatedMessage: true
}
);
assert.throws(
() => assert.match('string', /abc/, 'foobar'),
{
actual: 'string',
expected: /abc/,
operator: 'match',
message: 'foobar',
generatedMessage: false
}
);
const errorMessage = new RangeError('foobar');
assert.throws(
() => assert.match('string', /abc/, errorMessage),
errorMessage
);
assert.throws(
() => assert.match({ abc: 123 }, /abc/),
{
actual: { abc: 123 },
expected: /abc/,
operator: 'match',
message: 'The "string" argument must be of type string. ' +
'Received type object ({ abc: 123 })',
generatedMessage: true
}
);
assert.match('I will pass', /pass$/);
}
// Multiple assert.doesNotMatch() tests.
{
assert.throws(
() => assert.doesNotMatch(/abc/, 'string'),
{
code: 'ERR_INVALID_ARG_TYPE',
message: 'The "regexp" argument must be an instance of RegExp. ' +
"Received type string ('string')"
}
);
assert.throws(
() => assert.doesNotMatch('string', /string/),
{
actual: 'string',
expected: /string/,
operator: 'doesNotMatch',
message: 'The input was expected to not match the regular expression ' +
"/string/. Input:\n\n'string'\n",
generatedMessage: true
}
);
assert.throws(
() => assert.doesNotMatch('string', /string/, 'foobar'),
{
actual: 'string',
expected: /string/,
operator: 'doesNotMatch',
message: 'foobar',
generatedMessage: false
}
);
const errorMessage = new RangeError('foobar');
assert.throws(
() => assert.doesNotMatch('string', /string/, errorMessage),
errorMessage
);
assert.throws(
() => assert.doesNotMatch({ abc: 123 }, /abc/),
{
actual: { abc: 123 },
expected: /abc/,
operator: 'doesNotMatch',
message: 'The "string" argument must be of type string. ' +
'Received type object ({ abc: 123 })',
generatedMessage: true
}
);
assert.doesNotMatch('I will pass', /different$/);
}
{
const tempColor = inspect.defaultOptions.colors;
assert.throws(() => {
inspect.defaultOptions.colors = true;
// Guarantee the position indicator is placed correctly.
assert.strictEqual(111554n, 11111115);
}, (err) => {
assert.strictEqual(inspect(err).split('\n')[5], ' ^');
inspect.defaultOptions.colors = tempColor;
return true;
});
}