mirror of
https://github.com/nodejs/node.git
synced 2026-11-09 15:11:11 -05:00
Add a log(message[, data]) method to TestContext and SuiteContext that emits a new test:log event. Unlike test:diagnostic, which is buffered so it is emitted in the order tests are defined, test:log is emitted immediately, in the order tests execute, including under process isolation where it bypasses the per-file declaration order buffer. This gives reporters that render the test tree unbuffered a live, attributed logging channel that captured stdout cannot provide under concurrency. The event carries the message, an optional opaque structured payload that the runner passes through untouched, and the emitting test's name, testId, parentId, nesting, and location. Built-in reporters render it the same way they render test:diagnostic. Signed-off-by: Moses Atlow <moshe@atlow.co.il> PR-URL: https://github.com/nodejs/node/pull/64389 Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: Chemi Atlow <chemi@atlow.co.il>
72 lines
2.2 KiB
JavaScript
72 lines
2.2 KiB
JavaScript
// Flags: --no-warnings
|
|
|
|
import '../common/index.mjs';
|
|
import * as fixtures from '../common/fixtures.mjs';
|
|
import assert from 'node:assert';
|
|
import { test, run } from 'node:test';
|
|
|
|
const files = [
|
|
fixtures.path('test-runner', 'execution-ordered-bypass', 'slow.mjs'),
|
|
fixtures.path('test-runner', 'execution-ordered-bypass', 'fast-fail.mjs'),
|
|
];
|
|
|
|
test('execution-ordered events bypass FileTest declaration-order buffer', async () => {
|
|
// Concurrency must be a number so the runner does not collapse it to 1 on
|
|
// single-core CI runners (where `concurrency: true` resolves to
|
|
// `availableParallelism() - 1`). Without two slots the runner spawns the
|
|
// files sequentially and fast-fail never starts while slow is sleeping.
|
|
const stream = run({
|
|
files,
|
|
isolation: 'process',
|
|
concurrency: 2,
|
|
});
|
|
|
|
const events = [];
|
|
|
|
stream.on('test:complete', (data) => {
|
|
if (data.name === 'slow' || data.name === 'fast-fail') {
|
|
events.push(`complete:${data.name}`);
|
|
}
|
|
});
|
|
|
|
stream.on('test:fail', (data) => {
|
|
if (data.name === 'fast-fail') {
|
|
events.push(`fail:${data.name}`);
|
|
}
|
|
});
|
|
|
|
stream.on('test:log', (data) => {
|
|
events.push(`log:${data.message}`);
|
|
});
|
|
|
|
// eslint-disable-next-line no-unused-vars
|
|
for await (const _ of stream);
|
|
|
|
const completeFast = events.indexOf('complete:fast-fail');
|
|
const completeSlow = events.indexOf('complete:slow');
|
|
const failFast = events.indexOf('fail:fast-fail');
|
|
|
|
assert.notStrictEqual(completeFast, -1);
|
|
assert.notStrictEqual(completeSlow, -1);
|
|
assert.notStrictEqual(failFast, -1);
|
|
|
|
assert.ok(
|
|
completeFast < completeSlow,
|
|
`test:complete for fast-fail should arrive before slow; events=${events.join(', ')}`,
|
|
);
|
|
|
|
// test:fail is declaration-ordered, so the bypass must not affect it.
|
|
assert.ok(
|
|
failFast > completeSlow,
|
|
`test:fail for fast-fail should arrive after test:complete for slow; events=${events.join(', ')}`,
|
|
);
|
|
|
|
// test:log is execution-ordered, so it must bypass the buffer too.
|
|
const logFast = events.indexOf('log:live');
|
|
assert.notStrictEqual(logFast, -1);
|
|
assert.ok(
|
|
logFast < completeSlow,
|
|
`test:log for fast-fail should arrive before slow's test:complete; events=${events.join(', ')}`,
|
|
);
|
|
});
|