test_runner: expose reporter for use in run api

PR-URL: https://github.com/nodejs/node/pull/47238
Fixes: https://github.com/nodejs/node/issues/47231
Reviewed-By: Moshe Atlow <moshe@atlow.co.il>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
This commit is contained in:
Chemi Atlow 2023-03-28 15:10:34 +03:00 committed by GitHub
parent 67200dca0f
commit 29d7aecf42
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 101 additions and 1 deletions

View File

@ -520,6 +520,10 @@ test('spies on an object method', (t) => {
added: added:
- v19.6.0 - v19.6.0
- v18.15.0 - v18.15.0
changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/47238
description: Reporters are now exposed at `node:test/reporters`.
--> -->
The `node:test` module supports passing [`--test-reporter`][] The `node:test` module supports passing [`--test-reporter`][]
@ -546,6 +550,16 @@ Node.js, and should not be relied on programmatically. If programmatic access
to the test runner's output is required, use the events emitted by the to the test runner's output is required, use the events emitted by the
{TestsStream}. {TestsStream}.
The reporters are available via the `node:test/reporters` module:
```mjs
import { tap, spec, dot } from 'node:test/reporters';
```
```cjs
const { tap, spec, dot } = require('node:test/reporters');
```
### Custom reporters ### Custom reporters
[`--test-reporter`][] can be used to specify a path to custom reporter. [`--test-reporter`][] can be used to specify a path to custom reporter.
@ -739,8 +753,20 @@ added:
**Default:** `undefined`. **Default:** `undefined`.
* Returns: {TestsStream} * Returns: {TestsStream}
```js ```mjs
import { tap } from 'node:test/reporters';
import process from 'node:process';
run({ files: [path.resolve('./tests/test.js')] }) run({ files: [path.resolve('./tests/test.js')] })
.compose(tap)
.pipe(process.stdout);
```
```cjs
const { tap } = require('node:test/reporters');
run({ files: [path.resolve('./tests/test.js')] })
.compose(tap)
.pipe(process.stdout); .pipe(process.stdout);
``` ```

38
lib/test/reporters.js Normal file
View File

@ -0,0 +1,38 @@
'use strict';
const { ObjectDefineProperties } = primordials;
let dot;
let spec;
let tap;
ObjectDefineProperties(module.exports, {
__proto__: null,
dot: {
__proto__: null,
configurable: true,
enumerable: true,
get() {
dot ??= require('internal/test_runner/reporter/dot');
return dot;
},
},
spec: {
__proto__: null,
configurable: true,
enumerable: true,
get() {
spec ??= require('internal/test_runner/reporter/spec');
return spec;
},
},
tap: {
__proto__: null,
configurable: true,
enumerable: true,
get() {
tap ??= require('internal/test_runner/reporter/tap');
return tap;
},
},
});

View File

@ -2,6 +2,7 @@ import * as common from '../common/index.mjs';
import * as fixtures from '../common/fixtures.mjs'; import * as fixtures from '../common/fixtures.mjs';
import { join } from 'node:path'; import { join } from 'node:path';
import { describe, it, run } from 'node:test'; import { describe, it, run } from 'node:test';
import { dot, spec, tap } from 'node:test/reporters';
import assert from 'node:assert'; import assert from 'node:assert';
const testFixtures = fixtures.path('test-runner'); const testFixtures = fixtures.path('test-runner');
@ -65,4 +66,39 @@ describe('require(\'node:test\').run', { concurrency: true }, () => {
code: 'ERR_INVALID_ARG_TYPE' code: 'ERR_INVALID_ARG_TYPE'
})); }));
}); });
it('should be piped with dot', async () => {
const result = await run({ files: [join(testFixtures, 'test/random.cjs')] }).compose(dot).toArray();
assert.deepStrictEqual(result, [
'.',
'\n',
]);
});
it('should be piped with spec', async () => {
const specReporter = new spec();
const result = await run({ files: [join(testFixtures, 'test/random.cjs')] }).compose(specReporter).toArray();
const stringResults = result.map((bfr) => bfr.toString());
assert.match(stringResults[0], /this should pass/);
assert.match(stringResults[1], /tests 1/);
assert.match(stringResults[1], /pass 1/);
});
it('should be piped with tap', async () => {
const result = await run({ files: [join(testFixtures, 'test/random.cjs')] }).compose(tap).toArray();
assert.strictEqual(result.length, 13);
assert.strictEqual(result[0], 'TAP version 13\n');
assert.strictEqual(result[1], '# Subtest: this should pass\n');
assert.strictEqual(result[2], 'ok 1 - this should pass\n');
assert.match(result[3], /duration_ms: \d+\.?\d*/);
assert.strictEqual(result[4], '1..1\n');
assert.strictEqual(result[5], '# tests 1\n');
assert.strictEqual(result[6], '# suites 0\n');
assert.strictEqual(result[7], '# pass 1\n');
assert.strictEqual(result[8], '# fail 0\n');
assert.strictEqual(result[9], '# cancelled 0\n');
assert.strictEqual(result[10], '# skipped 0\n');
assert.strictEqual(result[11], '# todo 0\n');
assert.match(result[12], /# duration_ms \d+\.?\d*/);
});
}); });