Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: improve common.expectsError #19797

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 50 additions & 20 deletions test/common/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -690,52 +690,82 @@ 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') {
exact = settings;
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);
}
if ('info' in settings) {
assert.deepStrictEqual(error.info, settings.info);
// Add the `type` to the error to properly compare and visualize it.
if (!('type' in error))
error.type = constructor;
}
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') {
if (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,
errorDiff: 2
});
Error.stackTraceLimit = tmpLimit;

throw new assert.AssertionError({
actual: error,
expected: settings,
operator: 'common.expectsError',
message: err.message
});
}

}
return true;
}
Expand Down
8 changes: 3 additions & 5 deletions test/parallel/test-console-assign-undefined.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,17 @@
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
// effect.
assert.strictEqual(global.console, 42);
assert.strictEqual(global.console, 42);

common.expectsError(
assert.throws(
() => console.log('foo'),
{
type: TypeError
}
{ name: 'TypeError' }
);

global.console = 1;
Expand Down
2 changes: 1 addition & 1 deletion test/parallel/test-internal-errors.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down