Skip to content

Commit 4b87bc6

Browse files
committed
CLI: Fix TAP compliance for test plan when using QUnit.test.only()
Cherry-picked from 2fcafa4 (3.0.0-dev). > We correctly prevent registration, counting, and execution of non-only > tests after the first QUnit.test.only call. And we correctly undo > the execution and registration of any QUnit.test calls before the > first QUnit.test.only call. > But, we did not clear the test *count*. This left the test count > emitted in `runEnd` event, and thus in the "1..X" test plan printed > by the TAP reporter, inaccurate. This has implications for TAP-based > test runners (such as QTap) as those rely on this being accurate to > declare a run as finished, stop waiting for results, and stop the > browser process.
1 parent 2753920 commit 4b87bc6

File tree

6 files changed

+47
-8
lines changed

6 files changed

+47
-8
lines changed

src/module.js

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,41 @@ function processModule (name, options, scope, modifiers = {}) {
135135
}
136136
}
137137

138+
/**
139+
* Clear the SuiteReport tree of all tests and leave only current module as child suite
140+
*
141+
* This should be called before defining the first module.only() or test.only()
142+
* because otherwise:
143+
* - `runEnd.testCounts` is too high.
144+
* - UI (HtmlReporter) and TAP (TapReporter) display totals too high.
145+
* - Test runners like QTap might timeout because the TAP plan
146+
* would be printed as "1..9" even if only 2 tests are run,
147+
* which means tap-finished will wait for 3-9.
148+
*/
149+
export function clearSuiteReports (currentModule) {
150+
let childSuite = null;
151+
let suiteReport = currentModule.suiteReport;
152+
while (suiteReport) {
153+
suiteReport.tests.length = 0;
154+
const i = suiteReport.childSuites.indexOf(childSuite);
155+
if (i === -1) {
156+
suiteReport.childSuites.length = 0;
157+
} else {
158+
// Reduce in-place to just currentModule.suiteReport or its intermediary
159+
suiteReport.childSuites.splice(0, i);
160+
suiteReport.childSuites.splice(1);
161+
}
162+
163+
if (suiteReport === runSuite) {
164+
suiteReport = null;
165+
} else {
166+
childSuite = suiteReport;
167+
currentModule = currentModule.parentModule;
168+
suiteReport = (currentModule && currentModule.suiteReport) || runSuite;
169+
}
170+
}
171+
}
172+
138173
let focused = false; // indicates that the "only" filter was used
139174

140175
export function module (name, options, scope) {
@@ -149,6 +184,7 @@ module.only = function (...args) {
149184
// delete any and all previously registered modules and tests.
150185
config.modules.length = 0;
151186
config.queue.length = 0;
187+
clearSuiteReports(config.currentModule);
152188

153189
// Ignore any tests declared after this block within the same
154190
// module parent. https://github.com/qunitjs/qunit/issues/1645

src/test.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { globalThis, setTimeout, clearTimeout, StringMap } from './globals';
22
import { emit } from './events';
33
import Assert from './assert';
44
import Logger from './logger';
5+
import { clearSuiteReports } from './module';
56
import Promise from './promise';
67

78
import config from './core/config';
@@ -979,6 +980,8 @@ function addOnlyTest (settings) {
979980
}
980981
if (!focused) {
981982
config.queue.length = 0;
983+
clearSuiteReports(config.currentModule);
984+
982985
focused = true;
983986
}
984987

test/cli/fixtures/only-module-flat.tap.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ not ok 1 module B > test B # TODO
1212
...
1313
ok 2 module B > test C # SKIP
1414
ok 3 module B > test D
15-
1..4
16-
# pass 2
15+
1..3
16+
# pass 1
1717
# skip 1
1818
# todo 1
1919
# fail 0

test/cli/fixtures/only-module-then-test.tap.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33

44
TAP version 13
55
ok 1 module A > module B > test B
6-
1..2
7-
# pass 2
6+
1..1
7+
# pass 1
88
# skip 0
99
# todo 0
1010
# fail 0

test/cli/fixtures/only-module.tap.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ ok 3 module B > Only this module should run > normal test
1616
ok 4 module D > test D
1717
ok 5 module E > module F > test F
1818
ok 6 module E > test E
19-
1..8
20-
# pass 6
19+
1..6
20+
# pass 4
2121
# skip 1
2222
# todo 1
2323
# fail 0

test/cli/fixtures/only-test.tap.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
TAP version 13
55
ok 1 run this test
66
ok 2 all tests with only run
7-
1..3
8-
# pass 3
7+
1..2
8+
# pass 2
99
# skip 0
1010
# todo 0
1111
# fail 0

0 commit comments

Comments
 (0)