Skip to content

Recognize typical assertion errors and use their formatting #3187

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

Merged
merged 13 commits into from
May 24, 2023
46 changes: 36 additions & 10 deletions lib/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,16 @@ import concordanceOptions from './concordance-options.js';
import nowAndTimers from './now-and-timers.cjs';
import parseTestArgs from './parse-test-args.js';

function isExternalAssertError(error) {
// Match errors thrown by <https://www.npmjs.com/package/expect>.
if (error.matcherResult) {
return true;
}

// Match errors thrown by <https://www.npmjs.com/package/chai> and <https://nodejs.org/api/assert.html>.
return error.hasOwnProperty('actual') && error.hasOwnProperty('expected');
}

function formatErrorValue(label, error) {
const formatted = concordance.format(error, concordanceOptions);
return {label, formatted};
Expand Down Expand Up @@ -519,11 +529,19 @@ export default class Test {

const result = this.callFn();
if (!result.ok) {
this.saveFirstError(new AssertionError({
message: 'Error thrown in test',
savedError: result.error instanceof Error && result.error,
values: [formatErrorValue('Error thrown in test:', result.error)],
}));
if (isExternalAssertError(result.error)) {
this.saveFirstError(new AssertionError({
message: 'Assertion failed',
savedError: result.error instanceof Error && result.error,
values: [{label: 'Assertion failed: ', formatted: result.error.message}]
}));
} else {
this.saveFirstError(new AssertionError({
message: 'Error thrown in test',
savedError: result.error instanceof Error && result.error,
values: [formatErrorValue('Error thrown in test:', result.error)]
}));
}

return this.finish();
}
Expand Down Expand Up @@ -564,11 +582,19 @@ export default class Test {

promise
.catch(error => {
this.saveFirstError(new AssertionError({
message: 'Rejected promise returned by test',
savedError: error instanceof Error && error,
values: [formatErrorValue('Rejected promise returned by test. Reason:', error)],
}));
if (isExternalAssertError(error)) {
this.saveFirstError(new AssertionError({
message: 'Assertion failed',
savedError: error instanceof Error && error,
values: [{label: 'Assertion failed: ', formatted: error.message}]
}));
} else {
this.saveFirstError(new AssertionError({
message: 'Rejected promise returned by test',
savedError: error instanceof Error && error,
values: [formatErrorValue('Rejected promise returned by test. Reason:', error)]
}));
}
})
.then(() => resolve(this.finish()));
});
Expand Down
7 changes: 7 additions & 0 deletions test/external-assertions/fixtures/assert-failure.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import assert from 'node:assert';

import test from 'ava';

test('test', () => {
assert(false);
});
7 changes: 7 additions & 0 deletions test/external-assertions/fixtures/expect-failure.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { expect } from 'expect';

import test from 'ava';

test('test', () => {
expect(false).toBeTruthy();
});
11 changes: 11 additions & 0 deletions test/external-assertions/fixtures/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"type": "module",
"ava": {
"files": [
"*.js"
]
},
"dependencies": {
"expect": "^29.5.0"
}
}
60 changes: 60 additions & 0 deletions test/external-assertions/snapshots/test.js.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# Snapshot report for `test/external-assertions/test.js`

The actual snapshot is saved in `test.js.snap`.

Generated by [AVA](https://avajs.dev).

## node assertion

> Snapshot 1

`␊
✘ [fail]: test Assertion failed␊
─␊
test␊
assert-failure.js:6␊
5: test('test', () => {␊
6: assert(false); ␊
7: }); ␊
Assertion failed: ␊
false == true␊
› file://assert-failure.js:6:2␊
─␊
1 test failed`

## expect error

> Snapshot 1

`␊
✘ [fail]: test Assertion failed␊
─␊
test␊
expect-failure.js:6␊
5: test('test', () => { ␊
6: expect(false).toBeTruthy();␊
7: }); ␊
Assertion failed: ␊
expect(received).toBeTruthy()␊
Received: false␊
› Received: false␊
› file://expect-failure.js:6:16␊
─␊
1 test failed`
Binary file added test/external-assertions/snapshots/test.js.snap
Binary file not shown.
13 changes: 13 additions & 0 deletions test/external-assertions/test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import test from '@ava/test';

import {fixture} from '../helpers/exec.js';

test('node assertion ', async t => {
const result = await t.throwsAsync(fixture(['assert-failure.js']));
t.snapshot(result.stdout);
});

test('expect error ', async t => {
const result = await t.throwsAsync(fixture(['expect-failure.js']));
t.snapshot(result.stdout);
});