Skip to content

Commit 3ac1e2b

Browse files
committed
wip
1 parent 420926e commit 3ac1e2b

File tree

10 files changed

+132
-129
lines changed

10 files changed

+132
-129
lines changed

lib/internal/main/test_runner.js

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,8 @@ if (isUsingInspector()) {
2222
inspectPort = process.debugPort;
2323
}
2424

25-
const tapStream = run({ concurrency, inspectPort, watch: getOptionValue('--watch') });
26-
const reporters = setupTestReporters(tapStream);
27-
reporters.pipe(process.stdout);
28-
tapStream.once('test:fail', () => {
25+
const reporterStream = run({ concurrency, inspectPort, watch: getOptionValue('--watch') });
26+
reporterStream.once('test:fail', () => {
2927
process.exitCode = kGenericUserError;
3028
});
29+
setupTestReporters(reporterStream);

lib/internal/test_runner/harness.js

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ function setup(root) {
110110
}
111111

112112
root.startTime = hrtime();
113-
root.reporter.version();
113+
root.reporter.start();
114114

115115
wasRootSetup.add(root);
116116
return root;
@@ -120,11 +120,10 @@ let globalRoot;
120120
function getGlobalRoot() {
121121
if (!globalRoot) {
122122
globalRoot = createTestTree();
123-
const reporter = setupTestReporters(globalRoot.reporter);
124-
reporter.pipe(process.stdout);
125-
reporter.once('test:fail', () => {
123+
globalRoot.reporter.once('test:fail', () => {
126124
process.exitCode = kGenericUserError;
127125
});
126+
setupTestReporters(globalRoot.reporter);
128127
}
129128
return globalRoot;
130129
}

lib/internal/test_runner/reporter_stream.js

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@ class ReporterStream extends Readable {
1919
this.#canPush = true;
2020

2121
while (this.#buffer.length > 0) {
22-
const chunk = ArrayPrototypeShift(this.#buffer);
22+
const obj = ArrayPrototypeShift(this.#buffer);
2323

24-
if (!this.#tryPush(chunk)) {
24+
if (!this.#tryPush(obj)) {
2525
return;
2626
}
2727
}
@@ -35,8 +35,8 @@ class ReporterStream extends Readable {
3535
this.#emit('test:pass', { __proto__: null, name, nesting, testNumber, details, ...directive });
3636
}
3737

38-
plan() {
39-
// NOT IMPLEMENTED
38+
plan(nesting, count, explanation) {
39+
this.#emit('test:plan', { __proto__: null, nesting, count, explanation });
4040
}
4141

4242
getSkip(reason) {
@@ -48,15 +48,15 @@ class ReporterStream extends Readable {
4848
}
4949

5050
subtest(nesting, name) {
51-
this.#emit('test:subtest', { nesting, name });
51+
this.#emit('test:subtest', { __proto__: null, nesting, name });
5252
}
5353

5454
diagnostic(nesting, message) {
55-
this.#emit('test:diagnostic', { nesting, message });
55+
this.#emit('test:diagnostic', { __proto__: null, nesting, message });
5656
}
5757

58-
version() {
59-
// NOT IMPLEMENTED
58+
start() {
59+
this.#emit('test:start', { __proto__: null });
6060
}
6161

6262
#emit(type, data) {

lib/internal/test_runner/runner.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ const { kEmptyObject } = require('internal/util');
3737
const { createTestTree } = require('internal/test_runner/harness');
3838
const { kSubtestsFailed, Test } = require('internal/test_runner/test');
3939
const { TapParser } = require('internal/test_runner/tap_parser');
40-
const { kDefaultIndent } = require('internal/test_runner/tap_stream');
4140
const { TokenKind } = require('internal/test_runner/tap_lexer');
4241

4342
const {
@@ -130,6 +129,8 @@ function getRunArgs({ path, inspectPort }) {
130129
return argv;
131130
}
132131

132+
const kDefaultIndent = ' '; // 4 spaces
133+
133134
class FileTest extends Test {
134135
#buffer = [];
135136
#handleReportItem({ kind, node, nesting = 0 }) {

lib/internal/test_runner/test.js

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ const {
77
ArrayPrototypeSlice,
88
ArrayPrototypeSome,
99
ArrayPrototypeUnshift,
10-
Boolean,
1110
FunctionPrototype,
1211
MathMax,
1312
Number,
@@ -34,7 +33,6 @@ const {
3433
} = require('internal/errors');
3534
const { getOptionValue } = require('internal/options');
3635
const { MockTracker } = require('internal/test_runner/mock');
37-
const { TapStream } = require('internal/test_runner/tap_stream');
3836
const { ReporterStream } = require('internal/test_runner/reporter_stream');
3937
const {
4038
convertStringToRegExp,
@@ -67,7 +65,6 @@ const kHookFailure = 'hookFailed';
6765
const kDefaultTimeout = null;
6866
const noop = FunctionPrototype;
6967
const isTestRunner = getOptionValue('--test');
70-
const hasReporters = Boolean(getOptionValue('--test-reporter'));
7168
const testOnlyFlag = !isTestRunner && getOptionValue('--test-only');
7269
const testNamePatternFlag = isTestRunner ? null :
7370
getOptionValue('--test-name-pattern');
@@ -191,7 +188,7 @@ class Test extends AsyncResource {
191188
this.concurrency = 1;
192189
this.nesting = 0;
193190
this.only = testOnlyFlag;
194-
this.reporter = hasReporters ? new ReporterStream() : new TapStream();
191+
this.reporter = new ReporterStream();
195192
this.runOnlySubtests = this.only;
196193
this.testNumber = 0;
197194
this.timeout = kDefaultTimeout;

lib/internal/test_runner/utils.js

Lines changed: 55 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
11
'use strict';
2-
const { RegExp, RegExpPrototypeExec } = primordials;
2+
const { ObjectGetOwnPropertyDescriptor, RegExp, RegExpPrototypeExec, SafeMap } = primordials;
33
const { basename } = require('path');
4+
const { createWriteStream } = require('fs');
45
const { createDeferredPromise } = require('internal/util');
56
const { getOptionValue } = require('internal/options');
7+
const specReporter = require('test/reporter/spec');
8+
const dotReporter = require('test/reporter/dot');
9+
const tapReporter = require('test/reporter/tap');
10+
611
const {
712
codes: {
813
ERR_INVALID_ARG_VALUE,
@@ -11,7 +16,6 @@ const {
1116
kIsNodeError,
1217
} = require('internal/errors');
1318
const { compose } = require('stream');
14-
const { Module } = require('internal/modules/cjs/loader');
1519

1620
const kMultipleCallbackInvocations = 'multipleCallbackInvocations';
1721
const kRegExpPattern = /^\/(.*)\/([a-z]*)$/;
@@ -77,14 +81,56 @@ function convertStringToRegExp(str, name) {
7781
}
7882
}
7983

80-
let _module;
81-
function setupTestReporters(reporter) {
82-
if (getOptionValue('--test-reporter')) {
83-
_module ??= new Module('node:test');
84-
const reporters = _module.require(getOptionValue('--test-reporter'));
85-
return compose(reporter, reporters);
84+
const kBuiltinDestinations = new SafeMap([
85+
['stdout', process.stdout],
86+
['stderr', process.stderr],
87+
]);
88+
89+
const kBuiltinReporters = new SafeMap([
90+
['spec', specReporter],
91+
['dot', dotReporter],
92+
['tap', tapReporter],
93+
]);
94+
95+
const kDefaultReporter = 'tap';
96+
const kDefaltDestination = 'stdout';
97+
98+
function getReportersMap(reporters, destinations) {
99+
const result = [];
100+
reporters.forEach((name, i) => {
101+
const destination = kBuiltinDestinations.get(destinations[i]) ?? createWriteStream(destinations[i]);
102+
let reporter = kBuiltinReporters.get(name) ?? require(name);
103+
104+
if (ObjectGetOwnPropertyDescriptor(reporter.prototype, 'constructor')) {
105+
reporter = new reporter();
106+
}
107+
108+
result.push({ reporter, destination });
109+
});
110+
return result;
111+
}
112+
113+
114+
function setupTestReporters(reporterStream) {
115+
const destinations = getOptionValue('--test-reporter-destination');
116+
const reporters = getOptionValue('--test-reporter');
117+
118+
if (reporters.length === 0 && destinations.length === 0) {
119+
reporters.push(kDefaultReporter);
120+
}
121+
122+
if (reporters.length === 1 && destinations.length === 0) {
123+
destinations.push(kDefaltDestination);
124+
}
125+
126+
if (destinations.length !== reporters.length) {
127+
throw new ERR_INVALID_ARG_VALUE('The number of reporters and destinations must match');
128+
}
129+
130+
const reportersMap = getReportersMap(reporters, destinations);
131+
for (const { reporter, destination } of reportersMap) {
132+
compose(reporterStream, reporter).pipe(destination);
86133
}
87-
return reporter;
88134
}
89135

90136
module.exports = {

lib/test/reporter/spec.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,4 +65,4 @@ class SpecReporter extends Transform {
6565
}
6666
}
6767

68-
module.exports = new SpecReporter();
68+
module.exports = SpecReporter;

0 commit comments

Comments
 (0)