Skip to content

Commit fedf68e

Browse files
committed
test(infra): legacy-test-runner supports this.skip() and Promise-returning tests
Two improvements to scripts/legacy-test-runner.js needed for the new runtime-conditional GHSA tests: 1. `this.skip()` — Mocha exposes runtime-conditional skipping via the test context. The runner now provides a `skip()` method that throws a sentinel value, recognised by `testCompleted` and reported as pending (not failed). 2. Async tests without a `done` callback. Previously the runner only handled `done`-style async (length > 0) and assumed length-0 tests were sync. Promise-returning length-0 tests (`async function () {}`) detached and any rejection became `UnhandledPromiseRejection`. Now the sync path detects a thenable return and routes the resolution / rejection through `testCompleted`.
1 parent 69fe949 commit fedf68e

1 file changed

Lines changed: 37 additions & 8 deletions

File tree

scripts/legacy-test-runner.js

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,10 @@ function next() {
122122
}
123123

124124
const testCompleted = error => {
125-
if (error) {
125+
if (error === SKIP_SENTINEL) {
126+
console.log(' - ' + currentTest.name);
127+
counterPending++;
128+
} else if (error) {
126129
console.log(' ✘ ' + currentTest.name);
127130
hasError = true;
128131
counterFailed++;
@@ -136,10 +139,17 @@ function next() {
136139

137140
// Mocha exposes `this.timeout(ms)` inside it() callbacks too. Provide a
138141
// stub so tests don't blow up; we don't enforce real timeouts here.
142+
// Mocha exposes `this.skip()` inside it() callbacks for runtime-conditional
143+
// skipping. Throw a sentinel that we recognize as "skip" rather than a
144+
// real failure.
145+
const SKIP_SENTINEL = {};
139146
const ctx = {
140147
timeout(ms) {
141148
currentTest.timeoutMs = ms;
142149
},
150+
skip() {
151+
throw SKIP_SENTINEL;
152+
},
143153
};
144154
try {
145155
if (currentGroup.beforeEach) {
@@ -148,7 +158,7 @@ function next() {
148158
}
149159
}
150160
if (currentTest.fn.length) {
151-
// Async test
161+
// Async test (done-callback style)
152162
currentTest.fn.call(ctx, error => {
153163
if (!error && currentGroup.afterEach) {
154164
try {
@@ -162,14 +172,33 @@ function next() {
162172
testCompleted(error);
163173
});
164174
} else {
165-
// Sync test
166-
currentTest.fn.call(ctx);
167-
if (currentGroup.afterEach) {
168-
for (let i = 0; i < currentGroup.afterEach.length; i++) {
169-
currentGroup.afterEach[i].call(ctx);
175+
// Sync test or Promise-returning async test
176+
const ret = currentTest.fn.call(ctx);
177+
if (ret && typeof ret.then === 'function') {
178+
// Promise-returning test (e.g. async function ()).
179+
ret.then(
180+
() => {
181+
if (currentGroup.afterEach) {
182+
try {
183+
for (let i = 0; i < currentGroup.afterEach.length; i++) {
184+
currentGroup.afterEach[i].call(ctx);
185+
}
186+
} catch (e) {
187+
return testCompleted(e);
188+
}
189+
}
190+
testCompleted();
191+
},
192+
err => testCompleted(err),
193+
);
194+
} else {
195+
if (currentGroup.afterEach) {
196+
for (let i = 0; i < currentGroup.afterEach.length; i++) {
197+
currentGroup.afterEach[i].call(ctx);
198+
}
170199
}
200+
testCompleted();
171201
}
172-
testCompleted();
173202
}
174203
} catch (error) {
175204
testCompleted(error);

0 commit comments

Comments
 (0)