Skip to content

Commit

Permalink
Docs: Copy "Reporter API" from js-reporters CRI standard here
Browse files Browse the repository at this point in the history
With the adoption of TAP, the js-reporters project is less important
now, and is effectively done or archived. Reduce mention and reliance
on it, besides one mention on the `QUnit.on()` page about its origin.
  • Loading branch information
Krinkle committed Jul 22, 2024
1 parent 2b93753 commit deccc52
Show file tree
Hide file tree
Showing 12 changed files with 304 additions and 16 deletions.
1 change: 1 addition & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,7 @@
"rules": {
// https://github.com/eslint/eslint/issues/15732
"array-bracket-spacing": "off",
"n/handle-callback-err": "off",
"no-labels": "off",
"no-undef": "off",
"no-unused-expressions": "off",
Expand Down
58 changes: 57 additions & 1 deletion docs/api/callbacks/QUnit.on.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ version_added: "2.2.0"

Register a callback that will be invoked after the specified event is emitted.

This API is the primary interface for QUnit plugins, continuous integration support, and other reporters. It is based on the [js-reporters CRI standard](https://github.com/js-reporters/js-reporters/blob/v2.1.0/spec/cri-draft.adoc).
This API is the primary interface for QUnit reporters, plugins, and continuous integration support. It is based on the [js-reporters CRI standard](https://github.com/js-reporters/js-reporters/blob/v2.1.0/spec/cri-draft.adoc).

| type | parameter | description
|--|--|--
Expand Down Expand Up @@ -166,3 +166,59 @@ QUnit.on('error', error => {
console.error(error);
});
```

## Reporter API

The QUnit CLI accepts a [`--reporter` option](../../cli.md#--reporter) that loads a reporter from a Node module (e.g. npm package). Such module must export an `init` function, which QUnit will call and pass the `QUnit` object, which you can then use to call `QUnit.on()`. This contract is known as the *Reporter API*.

You can implement your reporter either as simply an exported function, or as a class with a static `init` method.

### Example: Reporter class

```js
class MyReporter {
static init (QUnit) {
return new MyReporter(QUnit);
}

constructor (QUnit) {
QUnit.on('error', this.onError.bind(this));
QUnit.on('testEnd', this.onTestEnd.bind(this));
QUnit.on('runEnd', this.onRunEnd.bind(this));
}

onError (error) {
}

onTestEnd (testEnd) {
}

onRunEnd (runEnd) {
}
}

// CommonJS, or ES Module
module.exports = MyReporter;
export default MyReporter;
```

### Example: Reporter function

```js
function init (QUnit) {
QUnit.on('error', onError);
QUnit.on('testEnd', onTestEnd);
QUnit.on('runEnd', onRunEnd);

function onError (error) {
}
function onTestEnd (testEnd) {
}
function onRunEnd (runEnd) {
}
}

// CommonJS, or ES Module
module.exports.init = init;
export { init };
```
10 changes: 7 additions & 3 deletions docs/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,14 +127,18 @@ Check [`QUnit.config.module`](./api/config/module.md) for more information.

### `--reporter`

By default, the TAP reporter is used.
By default, the TAP reporter is used. This allows you to pair QUnit with any [TAP-compatible reporter](https://github.com/sindresorhus/awesome-tap#reporters), by piping the output. For example:

Run `qunit --reporter <name>` to use a different reporter, where `<name>` can be the name of a built-in reporter, or an Node module that implements the [js-reporters](https://github.com/js-reporters/js-reporters) spec. The reporter will be loaded and initialised automatically.
```sh
qunit test/ | tap-min
```

To change the reporting from QUnit itself, use `qunit --reporter <name>` to set a different reporter, where `<name>` can be the name of a built-in reporter, or an Node module that implements the [QUnit Reporter API](./api/callbacks/QUnit.on.md#reporter-api). The reporter will be loaded and initialised automatically.

Built-in reporters:

* `tap`: [TAP compliant](https://testanything.org/) reporter.
* `console`: Log the JSON object for each reporter event from [`QUnit.on`](./api/callbacks/QUnit.on.md). Use this to explore or debug the reporter interface.
* `console`: Log the JSON object for each reporter event from [`QUnit.on`](./api/callbacks/QUnit.on.md). Use this to explore or debug the Reporter API.

### `--require`

Expand Down
2 changes: 1 addition & 1 deletion docs/upgrade-guide-2.x.md
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ Early alpha releases of QUnit 0.x required property assignments to register call

<p class="note" markdown="1">

See also [`QUnit.on()`](./api/callbacks/QUnit.on.md), which implements the [js-reporters spec](https://github.com/js-reporters/js-reporters) since QUnit 2.2.
See also [`QUnit.on()`](./api/callbacks/QUnit.on.md).

</p>

Expand Down
142 changes: 141 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,8 @@
"nyc": "^17.0.0",
"proxyquire": "^1.8.0",
"requirejs": "^2.3.6",
"rollup": "^4.18.0"
"rollup": "^4.18.0",
"tap-min": "^3.0.0"
},
"scripts": {
"build": "rollup -c && grunt copy:src-css",
Expand Down
4 changes: 2 additions & 2 deletions src/core/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -397,12 +397,12 @@ Test.prototype = {
}
}

// After emitting the js-reporters event we cleanup the assertion data to
// After emitting the event, we trim the assertion data to
// avoid leaking it. It is not used by the legacy testDone callbacks.
emit('testEnd', this.testReport.end(true));
this.testReport.slimAssertions();
const test = this;

const test = this;
return runLoggingCallbacks('testDone', {
name: testName,
module: moduleName,
Expand Down
47 changes: 46 additions & 1 deletion test/cli/cli-main.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

const path = require('path');

const { execute, concurrentMapKeys } = require('./helpers/execute.js');
const { execute, executeRaw, concurrentMapKeys } = require('./helpers/execute.js');
const { readFixtures } = require('./helpers/fixtures.js');

const FIXTURES_DIR = path.join(__dirname, 'fixtures');
Expand Down Expand Up @@ -146,6 +146,51 @@ ok 1 test-object > example test
# fail 0`);
});

QUnit.test.if('tap pipe [pass]', !isWindows, async assert => {
const command = 'qunit basic-one.js | ../../../node_modules/.bin/tap-min';
const execution = await executeRaw(command);
assert.equal(execution.snapshot.trim(), '1 test complete (1ms)');
});

QUnit.test.if('tap pipe [fail]', !isWindows, async assert => {
const command = 'qunit basic-fail.js | ../../../node_modules/.bin/tap-min';
const execution = await executeRaw(command);
assert.equal(execution.snapshot.trim(), `bar
\tat: undefined
\toperator: undefined
\texpected: true
\tactual: false
at /qunit/test/cli/fixtures/basic-fail.js:5:14
3 tests complete (1ms)
# exit code: 1`);
});

QUnit.test.if('tap pipe [error]', !isWindows, async assert => {
assert.timeout(10000);
const command = 'qunit syntax-error.js | ../../../node_modules/.bin/tap-min';
const execution = await executeRaw(command);
assert.equal(execution.snapshot.trim(), `global failure
\tat: undefined
\toperator: undefined
\texpected: undefined
\tactual: undefined
ReferenceError: varIsNotDefined is not defined
at /qunit/test/cli/fixtures/syntax-error.js:1:1
at internal
1 test complete (1ms)
# exit code: 1`);
});

// TODO: Workaround fact that child_process.spawn() args array is a lie on Windows.
// https://github.com/nodejs/node/issues/29532
// Can't trivially quote since that breaks Linux which would interpret quotes
Expand Down
Loading

0 comments on commit deccc52

Please sign in to comment.