GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — test_runner: add context.log() and test:log event · nodejs/node@bb51f2c

File tree

Expand file treeCollapse file tree
Open diff view settings
Filter options
  • doc/api
    • test.md
  • lib/internal/test_runner
    • reporter
      • junit.js
      • spec.js
      • tap.js
      • utils.js
    • runner.js
    • test.js
    • tests_stream.js
  • test
    • fixtures/test-runner
      • execution-ordered-bypass
        • fast-fail.mjs
      • log-events
        • basic.mjs
    • parallel
      • test-runner-execution-ordered-bypass.mjs
      • test-runner-log.mjs
Expand file treeCollapse file tree
Open diff view settings
Collapse file

‎doc/api/test.md‎

Copy file name to clipboardExpand all lines: doc/api/test.md
+81Lines changed: 81 additions & 0 deletions
  • Display the source diff
  • Display the rich diff
Original file line numberDiff line numberDiff line change
@@ -3476,6 +3476,10 @@ ordered events, emitted immediately as the tests execute.
34763476
| [`'test:fail'`][] | [`'test:complete'`][] (`details.passed` is `false`) |
34773477
| [`'test:plan'`][] | |
34783478
| [`'test:diagnostic'`][] | |
3479+
| | [`'test:log'`][] |
3480+
3481+
[`'test:log'`][] is deliberately execution ordered only: it is the live
3482+
counterpart of [`'test:diagnostic'`][]'s buffered reporting.
34793483

34803484
File scoped and global events are always emitted immediately, in execution
34813485
order.
@@ -3743,6 +3747,38 @@ When using process isolation (the default), the test name will be the file path
37433747
since the parent runner only knows about file-level tests. When using
37443748
`--test-isolation=none`, the actual test name is shown.
37453749

3750+
### Event: `'test:log'`
3751+
3752+
<!-- YAML
3753+
added: REPLACEME
3754+
-->
3755+
3756+
* `data` {Object}
3757+
* `column` {number|undefined} The column number where the test is defined, or
3758+
`undefined` if the test was run through the REPL.
3759+
* `data` {any} The structured payload passed to [`context.log`][], or
3760+
`undefined` if none was provided. The test runner does not interpret this
3761+
value.
3762+
* `entryFile` {string|undefined} The path of the test file that was
3763+
executed as the entry point of the child process that emitted this event.
3764+
Only present when tests run with process isolation. May differ from
3765+
`file` when the test is defined in a module imported by the entry file.
3766+
* `file` {string|undefined} The path of the test file,
3767+
`undefined` if test was run through the REPL.
3768+
* `line` {number|undefined} The line number where the test is defined, or
3769+
`undefined` if the test was run through the REPL.
3770+
* `message` {string} The log message.
3771+
* `name` {string} The test name.
3772+
* `nesting` {number} The nesting level of the test.
3773+
* `parentId` {number|undefined} The `testId` of the enclosing test, or
3774+
`undefined` for top-level tests.
3775+
* `testId` {number} A numeric identifier for the test instance that emitted
3776+
the log message.
3777+
3778+
Emitted when [`context.log`][] is called. Unlike [`'test:diagnostic'`][],
3779+
this event is emitted immediately, in the order that the tests execute,
3780+
making it suitable for reporters that render test output unbuffered.
3781+
37463782
### Event: `'test:pass'`
37473783

37483784
* `data` {Object}
@@ -4266,6 +4302,29 @@ test('top level test', (t) => {
42664302
});
42674303
```
42684304

4305+
### `context.log(message[, data])`
4306+
4307+
<!-- YAML
4308+
added: REPLACEME
4309+
-->
4310+
4311+
* `message` {string} Message to be reported.
4312+
* `data` {any} Optional structured payload attached to the message. The test
4313+
runner passes it through untouched. When tests run with process isolation,
4314+
this value must be compatible with the [HTML structured clone algorithm][].
4315+
4316+
This function is used to write a log message to the output. Unlike
4317+
[`context.diagnostic`][], the resulting [`'test:log'`][] event is emitted
4318+
immediately, in the order that the tests execute, rather than being buffered
4319+
until the test reports its results. This function does not return a value.
4320+
4321+
```js
4322+
test('top level test', (t) => {
4323+
t.log('fetched user', { userId: 42 });
4324+
t.log('retrying flaky endpoint', { attempt: 3 });
4325+
});
4326+
```
4327+
42694328
### `context.filePath`
42704329

42714330
<!-- YAML
@@ -4747,6 +4806,26 @@ test.describe('my suite', (suite) => {
47474806
});
47484807
```
47494808

4809+
### `context.log(message[, data])`
4810+
4811+
<!-- YAML
4812+
added: REPLACEME
4813+
-->
4814+
4815+
* `message` {string} Message to be reported.
4816+
* `data` {any} Optional structured payload attached to the message. The test
4817+
runner passes it through untouched.
4818+
4819+
Write a log message to the output. The resulting [`'test:log'`][] event is
4820+
emitted immediately, in the order that the tests execute.
4821+
4822+
```js
4823+
test.describe('my suite', (suite) => {
4824+
suite.log('Suite log message');
4825+
});
4826+
```
4827+
4828+
[HTML structured clone algorithm]: https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm
47504829
[TAP]: https://testanything.org/
47514830
[Test tags]: #test-tags
47524831
[`'test:complete'`]: #event-testcomplete
@@ -4756,6 +4835,7 @@ test.describe('my suite', (suite) => {
47564835
[`'test:enqueue'`]: #event-testenqueue
47574836
[`'test:fail'`]: #event-testfail
47584837
[`'test:interrupted'`]: #event-testinterrupted
4838+
[`'test:log'`]: #event-testlog
47594839
[`'test:pass'`]: #event-testpass
47604840
[`'test:plan'`]: #event-testplan
47614841
[`'test:start'`]: #event-teststart
@@ -4791,6 +4871,7 @@ test.describe('my suite', (suite) => {
47914871
[`TracingChannel`]: diagnostics_channel.md#class-tracingchannel
47924872
[`assert.throws`]: assert.md#assertthrowsfn-error-message
47934873
[`context.diagnostic`]: #contextdiagnosticmessage
4874+
[`context.log`]: #contextlogmessage-data
47944875
[`context.skip`]: #contextskipmessage
47954876
[`context.tags`]: #contexttags
47964877
[`context.todo`]: #contexttodomessage
Collapse file

‎lib/internal/test_runner/reporter/junit.js‎

Copy file name to clipboardExpand all lines: lib/internal/test_runner/reporter/junit.js
+2-1Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,8 @@ module.exports = async function* junitReporter(source) {
154154
}
155155
break;
156156
}
157-
case 'test:diagnostic': {
157+
case 'test:diagnostic':
158+
case 'test:log': {
158159
const parent = currentSuite?.children ?? roots;
159160
ArrayPrototypePush(parent, {
160161
__proto__: null, nesting: event.data.nesting, comment: event.data.message,
Collapse file

‎lib/internal/test_runner/reporter/spec.js‎

Copy file name to clipboardExpand all lines: lib/internal/test_runner/reporter/spec.js
+3-2Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,9 @@ class SpecReporter extends Transform {
9191
case 'test:stderr':
9292
case 'test:stdout':
9393
return data.message;
94-
case 'test:diagnostic':{
95-
const diagnosticColor = reporterColorMap[data.level] || reporterColorMap['test:diagnostic'];
94+
case 'test:diagnostic':
95+
case 'test:log': {
96+
const diagnosticColor = reporterColorMap[data.level] || reporterColorMap[type];
9697
return `${diagnosticColor}${indent(data.nesting)}${reporterUnicodeSymbolMap[type]}${data.message}${colors.white}\n`;
9798
}
9899
case 'test:coverage':
Collapse file

‎lib/internal/test_runner/reporter/tap.js‎

Copy file name to clipboardExpand all lines: lib/internal/test_runner/reporter/tap.js
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ async function * tapReporter(source) {
5656
}
5757
break;
5858
} case 'test:diagnostic':
59+
case 'test:log':
5960
yield `${indent(data.nesting)}# ${tapEscape(data.message)}\n`;
6061
break;
6162
case 'test:coverage':
Collapse file

‎lib/internal/test_runner/reporter/utils.js‎

Copy file name to clipboardExpand all lines: lib/internal/test_runner/reporter/utils.js
+4Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ const reporterUnicodeSymbolMap = {
2121
'test:fail': '\u2716 ',
2222
'test:pass': '\u2714 ',
2323
'test:diagnostic': '\u2139 ',
24+
'test:log': '\u2139 ',
2425
'test:coverage': '\u2139 ',
2526
'arrow:right': '\u25B6 ',
2627
'hyphen:minus': '\uFE63 ',
@@ -38,6 +39,9 @@ const reporterColorMap = {
3839
get 'test:diagnostic'() {
3940
return colors.blue;
4041
},
42+
get 'test:log'() {
43+
return colors.blue;
44+
},
4145
get 'info'() {
4246
return colors.blue;
4347
},
Collapse file

‎lib/internal/test_runner/runner.js‎

Copy file name to clipboardExpand all lines: lib/internal/test_runner/runner.js
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ const kCanceledTests = new SafeSet()
130130
// Execution-ordered events are forwarded immediately, bypassing the
131131
// per-file declaration-order buffer.
132132
const kExecutionOrderedEvents = new SafeSet()
133-
.add('test:enqueue').add('test:dequeue').add('test:complete');
133+
.add('test:enqueue').add('test:dequeue').add('test:complete').add('test:log');
134134

135135
let kResistStopPropagation;
136136

Collapse file

‎lib/internal/test_runner/test.js‎

Copy file name to clipboardExpand all lines: lib/internal/test_runner/test.js
+15Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ const {
8080
validateNumber,
8181
validateObject,
8282
validateOneOf,
83+
validateString,
8384
validateUint32,
8485
} = require('internal/validators');
8586
const {
@@ -315,6 +316,10 @@ class TestContext {
315316
this.#test.diagnostic(message);
316317
}
317318

319+
log(message, data) {
320+
this.#test.log(message, data);
321+
}
322+
318323
plan(count, options = kEmptyObject) {
319324
if (this.#test.plan !== null) {
320325
throw new ERR_TEST_FAILURE(
@@ -523,6 +528,10 @@ class SuiteContext {
523528
diagnostic(message) {
524529
this.#suite.diagnostic(message);
525530
}
531+
532+
log(message, data) {
533+
this.#suite.log(message, data);
534+
}
526535
}
527536

528537
function parseExpectFailure(expectFailure) {
@@ -1198,6 +1207,12 @@ class Test extends AsyncResource {
11981207
ArrayPrototypePush(this.diagnostics, message);
11991208
}
12001209

1210+
log(message, data) {
1211+
validateString(message, 'message');
1212+
this.reporter.log(this.nesting, this.loc, message, data,
1213+
this.name, this.testId, this.parent?.testId);
1214+
}
1215+
12011216
start() {
12021217
this.applyFilters();
12031218

Collapse file

‎lib/internal/test_runner/tests_stream.js‎

Copy file name to clipboardExpand all lines: lib/internal/test_runner/tests_stream.js
+13Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,19 @@ class TestsStream extends Readable {
139139
});
140140
}
141141

142+
log(nesting, loc, message, data, name, testId, parentId) {
143+
this[kEmitMessage]('test:log', {
144+
__proto__: null,
145+
name,
146+
nesting,
147+
testId,
148+
parentId,
149+
message,
150+
data,
151+
...loc,
152+
});
153+
}
154+
142155
diagnostic(nesting, loc, message, level = 'info') {
143156
this[kEmitMessage]('test:diagnostic', {
144157
__proto__: null,
Collapse file

‎test/fixtures/test-runner/execution-ordered-bypass/fast-fail.mjs‎

Copy file name to clipboard
+2-1Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { test } from 'node:test';
22
import assert from 'node:assert';
33

4-
test('fast-fail', () => {
4+
test('fast-fail', (t) => {
5+
t.log('live');
56
assert.fail('fast');
67
});
Collapse file

‎test/fixtures/test-runner/log-events/basic.mjs‎

Copy file name to clipboard
+19Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { suite, test } from 'node:test';
2+
import { setTimeout } from 'node:timers/promises';
3+
4+
suite('my suite', (s) => {
5+
s.log('suite message');
6+
test('in suite', () => {});
7+
});
8+
9+
test('parent', { concurrency: 2 }, async (t) => {
10+
await Promise.all([
11+
t.test('slow', async () => {
12+
await setTimeout(200);
13+
}),
14+
t.test('logger', (t) => {
15+
t.log('hello', { foo: 1 });
16+
t.log('warned', { level: 'warn', attempt: 2 });
17+
}),
18+
]);
19+
});

0 commit comments

Comments
0 (0)
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.