test: improve common.expectsError

The output is now improved by showing most properties all at once.
Besides that this adds a warning to use `assert.throws` instead
due to a better output.

PR-URL: https://github.com/nodejs/node/pull/19797
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
This commit is contained in:
Ruben Bridgewater 2018-04-04 17:03:58 +02:00
parent c1078c4a3b
commit f85d5996db
No known key found for this signature in database
GPG Key ID: F07496B3EB3C1762
3 changed files with 55 additions and 30 deletions

View File

@ -690,6 +690,15 @@ Object.defineProperty(exports, 'hasSmallICU', {
}
});
class Comparison {
constructor(obj, keys) {
for (const key of keys) {
if (key in obj)
this[key] = obj[key];
}
}
}
// Useful for testing expected internal/error objects
exports.expectsError = function expectsError(fn, settings, exact) {
if (typeof fn !== 'function') {
@ -697,45 +706,63 @@ exports.expectsError = function expectsError(fn, settings, exact) {
settings = fn;
fn = undefined;
}
function innerFn(error) {
const descriptor = Object.getOwnPropertyDescriptor(error, 'message');
assert.strictEqual(descriptor.enumerable,
false, 'The error message should be non-enumerable');
let innerSettings = settings;
if ('type' in settings) {
const type = settings.type;
if (type !== Error && !Error.isPrototypeOf(type)) {
throw new TypeError('`settings.type` must inherit from `Error`');
}
assert(error instanceof type,
`${error.name} is not instance of ${type.name}`);
let typeName = error.constructor.name;
if (typeName === 'NodeError' && type.name !== 'NodeError') {
typeName = Object.getPrototypeOf(error.constructor).name;
let constructor = error.constructor;
if (constructor.name === 'NodeError' && type.name !== 'NodeError') {
constructor = Object.getPrototypeOf(error.constructor);
}
assert.strictEqual(typeName, type.name);
// Add the `type` to the error to properly compare and visualize it.
if (!('type' in error))
error.type = constructor;
}
if ('info' in settings) {
assert.deepStrictEqual(error.info, settings.info);
}
if ('message' in settings) {
const message = settings.message;
if (typeof message === 'string') {
assert.strictEqual(error.message, message);
} else {
assert(message.test(error.message),
`${error.message} does not match ${message}`);
}
if ('message' in settings &&
typeof settings.message === 'object' &&
settings.message.test(error.message)) {
// Make a copy so we are able to modify the settings.
innerSettings = Object.create(
settings, Object.getOwnPropertyDescriptors(settings));
// Visualize the message as identical in case of other errors.
innerSettings.message = error.message;
}
// Check all error properties.
const keys = Object.keys(settings);
for (const key of keys) {
if (key === 'message' || key === 'type' || key === 'info')
continue;
const actual = error[key];
const expected = settings[key];
assert.strictEqual(actual, expected,
`${key}: expected ${expected}, not ${actual}`);
if (!util.isDeepStrictEqual(error[key], innerSettings[key])) {
// Create placeholder objects to create a nice output.
const a = new Comparison(error, keys);
const b = new Comparison(innerSettings, keys);
const tmpLimit = Error.stackTraceLimit;
Error.stackTraceLimit = 0;
const err = new assert.AssertionError({
actual: a,
expected: b,
operator: 'strictEqual',
stackStartFn: assert.throws
});
Error.stackTraceLimit = tmpLimit;
throw new assert.AssertionError({
actual: error,
expected: settings,
operator: 'common.expectsError',
message: err.message
});
}
}
return true;
}

View File

@ -6,7 +6,7 @@
const tmp = global.console;
global.console = 42;
const common = require('../common');
require('../common');
const assert = require('assert');
// Originally the console had a getter. Test twice to verify it had no side
@ -14,11 +14,9 @@ const assert = require('assert');
assert.strictEqual(global.console, 42);
assert.strictEqual(global.console, 42);
common.expectsError(
assert.throws(
() => console.log('foo'),
{
type: TypeError
}
{ name: 'TypeError' }
);
global.console = 1;

View File

@ -77,7 +77,7 @@ common.expectsError(() => {
}, { code: 'TEST_ERROR_1', type: RangeError });
}, {
code: 'ERR_ASSERTION',
message: /^.+ is not instance of \S/
message: /- type: \[Function: TypeError]\n\+ type: \[Function: RangeError]/
});
common.expectsError(() => {
@ -89,7 +89,7 @@ common.expectsError(() => {
}, {
code: 'ERR_ASSERTION',
type: assert.AssertionError,
message: /.+ does not match \S/
message: /- message: 'Error for testing purposes: a'\n\+ message: \/\^Error/
});
// Test ERR_INVALID_FD_TYPE