Skip to content

Commit

Permalink
fix: ensure reporter errors can propagate (#4111)
Browse files Browse the repository at this point in the history
* feat: allow reporters to error

* fix(reporter): reject handle for consistent error processing
  • Loading branch information
WilcoFiers committed Aug 3, 2023
1 parent 33b0314 commit 080cc1b
Show file tree
Hide file tree
Showing 6 changed files with 80 additions and 15 deletions.
3 changes: 2 additions & 1 deletion axe.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -371,7 +371,8 @@ declare namespace axe {
type AxeReporter<T = unknown> = (
rawResults: RawResult[],
option: RunOptions,
callback: (report: T) => void
resolve: (report: T) => void,
reject: (error: Error) => void
) => void;

interface VirtualNode {
Expand Down
4 changes: 2 additions & 2 deletions lib/core/public/finish-run.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ function getMergedFrameSpecs({
}

function createReport(results, options) {
return new Promise(resolve => {
return new Promise((resolve, reject) => {
const reporter = getReporter(options.reporter);
reporter(results, options, resolve);
reporter(results, options, resolve, reject);
});
}
27 changes: 17 additions & 10 deletions lib/core/public/run.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,23 +41,29 @@ export default function run(...args) {
axe._running = false;
teardown();
try {
callback(null, results);
resolve(results);
} catch (e) {
axe.log(e);
}
resolve(results);
};
const wrappedReject = err => {
axe._running = false;
teardown();
try {
reject(err);
} catch (e) {
axe.log(e);
}
};

if (options.performanceTimer) {
axe.utils.performanceTimer.end();
}

try {
createReport(rawResults, options, respond);
createReport(rawResults, options, respond, wrappedReject);
} catch (err) {
axe._running = false;
teardown();
callback(err);
reject(err);
wrappedReject(err);
}
}

Expand All @@ -82,14 +88,15 @@ function getPromiseHandlers(callback) {
resolve = _resolve;
});
} else {
resolve = reject = noop;
resolve = result => callback(null, result);
reject = err => callback(err);
}
return { thenable, reject, resolve };
}

function createReport(rawResults, options, respond) {
function createReport(rawResults, options, respond, reject) {
const reporter = getReporter(options.reporter);
const results = reporter(rawResults, options, respond);
const results = reporter(rawResults, options, respond, reject);
if (results !== undefined) {
respond(results);
}
Expand Down
34 changes: 34 additions & 0 deletions test/core/public/finish-run.js
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,40 @@ describe('axe.finishRun', function () {
.catch(done);
});

it('rejects with sync reporter errors', async () => {
axe.addReporter('throwing', () => {
throw new Error('Something went wrong');
});
const options = { reporter: 'throwing' };

fixture.innerHTML = '<h1>Hello world</h1>';
const partial = await axe.runPartial('#fixture', options);
try {
await axe.finishRun([partial], options);
assert.fail('Should have thrown');
} catch (err) {
assert.equal(err.message, 'Something went wrong');
}
});

it('rejects with async reporter errors', async () => {
axe.addReporter('throwing', (results, options, resolve, reject) => {
setTimeout(() => {
reject(new Error('Something went wrong'));
}, 10);
});
const options = { reporter: 'throwing' };

fixture.innerHTML = '<h1>Hello world</h1>';
const partial = await axe.runPartial('#fixture', options);
try {
await axe.finishRun([partial], options);
assert.fail('Should have thrown');
} catch (err) {
assert.equal(err.message, 'Something went wrong');
}
});

describe('frames', function () {
function createIframe(html, parent) {
return new Promise(function (resolve) {
Expand Down
22 changes: 22 additions & 0 deletions test/core/public/run.js
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,28 @@ describe('axe.run', function () {
done();
});
});

it('rejects with sync reporter errors', done => {
axe.addReporter('throwing', () => {
throw new Error('Something went wrong');
});
axe.run({ reporter: 'throwing' }, err => {
assert.equal(err.message, 'Something went wrong');
done();
});
});

it('rejects with async reporter errors', done => {
axe.addReporter('throwing', (results, options, resolve, reject) => {
setTimeout(() => {
reject(new Error('Something went wrong'));
}, 10);
});
axe.run({ reporter: 'throwing' }, err => {
assert.equal(err.message, 'Something went wrong');
done();
});
});
});

describe('promise result', function () {
Expand Down
5 changes: 3 additions & 2 deletions typings/axe-core/axe-core-tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -348,9 +348,10 @@ axe.configure({
let fooReporter = (
results: axe.RawResult[],
options: axe.RunOptions,
cb: (out: 'foo') => void
resolve: (out: 'foo') => void,
reject: (err: Error) => void
) => {
cb('foo');
reject && resolve('foo');
};

axe.addReporter<'foo'>('foo', fooReporter, true);
Expand Down

0 comments on commit 080cc1b

Please sign in to comment.