node/test/parallel/test-assert-class.js
Miguel Marcondes Filho 4f5d11e6fb
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>
2025-08-05 14:15:02 +00:00

480 lines
16 KiB
JavaScript

'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;
}
);
}
});