Skip to content

Commit 19bed42

Browse files
committed
Create a process-exit message for process.exit()
1 parent ae53bfc commit 19bed42

File tree

7 files changed

+40
-2
lines changed

7 files changed

+40
-2
lines changed

lib/reporters/default.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ export default class Reporter {
111111

112112
this.failures = [];
113113
this.internalErrors = [];
114+
this.interrupts = [];
114115
this.knownFailures = [];
115116
this.lineNumberErrors = [];
116117
this.sharedWorkerErrors = [];
@@ -193,6 +194,7 @@ export default class Reporter {
193194
}
194195

195196
case 'interrupt': {
197+
this.interrupts.push(event);
196198
this.lineWriter.writeLine(colors.error(`\n${figures.cross} Exiting due to SIGINT`));
197199
this.lineWriter.writeLine('');
198200
this.writePendingTests(event);
@@ -233,6 +235,23 @@ export default class Reporter {
233235
break;
234236
}
235237

238+
case 'process-exit': {
239+
this.interrupts.push(event);
240+
241+
if (event.testFile) {
242+
this.write(colors.error(`${figures.cross} Exiting due to process.exit() when running ${this.relativeFile(event.testFile)}`));
243+
} else {
244+
this.write(colors.error(`${figures.cross} Exiting due to process.exit()`));
245+
}
246+
247+
this.lineWriter.writeLine(colors.stack(event.err.summary));
248+
this.lineWriter.writeLine(colors.errorStack(event.err.stack));
249+
this.lineWriter.writeLine();
250+
this.lineWriter.writeLine();
251+
252+
break;
253+
}
254+
236255
case 'hook-finished': {
237256
if (event.logs.length > 0) {
238257
this.lineWriter.writeLine(` ${this.prefixTitle(event.testFile, event.title)}`);

lib/reporters/tap.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,9 @@ export default class TapReporter {
158158
this.filesWithMissingAvaImports.add(evt.testFile);
159159
this.writeCrash(evt, `No tests found in ${this.relativeFile(evt.testFile)}, make sure to import "ava" at the top of your test file`);
160160
break;
161+
case 'process-exit':
162+
this.writeCrash(evt);
163+
break;
161164
case 'selected-test':
162165
if (evt.skip) {
163166
this.writeTest(evt, {passed: true, todo: false, skip: true});

lib/run-status.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ export default class RunStatus extends Emittery {
6262
worker.onStateChange(data => this.emitStateChange(data));
6363
}
6464

65+
// eslint-disable-next-line complexity
6566
emitStateChange(event) {
6667
const {stats} = this;
6768
const fileStats = stats.byFile.get(event.testFile);
@@ -134,6 +135,10 @@ export default class RunStatus extends Emittery {
134135
event.pendingTests = this.pendingTests;
135136
this.pendingTests = new Map();
136137
break;
138+
case 'process-exit':
139+
event.pendingTests = this.pendingTests;
140+
this.pendingTests = new Map();
141+
break;
137142
case 'uncaught-exception':
138143
stats.uncaughtExceptions++;
139144
fileStats.uncaughtExceptions++;
@@ -175,6 +180,7 @@ export default class RunStatus extends Emittery {
175180
|| this.stats.failedHooks > 0
176181
|| this.stats.failedTests > 0
177182
|| this.stats.failedWorkers > 0
183+
|| this.stats.remainingTests > 0
178184
|| this.stats.sharedWorkerErrors > 0
179185
|| this.stats.timeouts > 0
180186
|| this.stats.uncaughtExceptions > 0

lib/watcher.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,7 @@ export default class Watcher {
294294
switch (evt.type) {
295295
case 'hook-failed':
296296
case 'internal-error':
297+
case 'process-exit':
297298
case 'test-failed':
298299
case 'uncaught-exception':
299300
case 'unhandled-rejection':

lib/worker/base.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ async function exit(code, forceSync = false) {
3737

3838
process.exit = new Proxy(realExit, {
3939
apply(fn, receiver, args) {
40-
channel.send({type: 'internal-error', err: serializeError('Forced exit error', false, new Error('Unexpected process.exit()'), runner?.file)});
40+
channel.send({type: 'process-exit', err: serializeError('Forced exit error', false, new Error('Unexpected process.exit()'), runner?.file)});
4141

4242
// Make sure to extract the code only from `args` rather than e.g. `Array.prototype`.
4343
// This level of paranoia is usually unwarranted, but we're dealing with test code

test/helpers/exec.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ export const fixture = async (args, options = {}) => {
7070
failed: [],
7171
failedHooks: [],
7272
internalErrors: [],
73+
interrupts: [],
7374
passed: [],
7475
selectedTestCount: 0,
7576
sharedWorkerErrors: [],
@@ -102,6 +103,14 @@ export const fixture = async (args, options = {}) => {
102103
break;
103104
}
104105

106+
case 'process-exit': {
107+
const {testFile} = statusEvent;
108+
const statObject = {file: normalizePath(workingDir, testFile)};
109+
errors.set(statObject, statusEvent.err);
110+
stats.interrupts.push(statObject);
111+
break;
112+
}
113+
105114
case 'selected-test': {
106115
stats.selectedTestCount++;
107116
if (statusEvent.skip) {

test/test-process-exit/test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,6 @@ test('process.exit is intercepted', async t => {
88
t.like(result, {timedOut: false, isCanceled: false, killed: false});
99
t.is(result.stats.selectedTestCount, 3);
1010
t.is(result.stats.passed.length, 2);
11-
const error = result.stats.getError(result.stats.internalErrors[0]);
11+
const error = result.stats.getError(result.stats.interrupts[0]);
1212
t.is(error.message, 'Unexpected process.exit()');
1313
});

0 commit comments

Comments
 (0)