Skip to content

Commit

Permalink
feat(learn): add section for dynamically generating test cases (nodej…
Browse files Browse the repository at this point in the history
…s#7387)

* feat(learn): add section for dynamically generating test cases

* fixup!: adjust for prettier mangling

* fixup!: simple & advanced examples

* fixup!: re-organise examples
  • Loading branch information
JakobJingleheimer authored Feb 2, 2025
1 parent 317dce6 commit 837a461
Showing 1 changed file with 112 additions and 0 deletions.
112 changes: 112 additions & 0 deletions apps/site/pages/en/learn/test-runner/using-test-runner.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,118 @@ Then for each setup, create a dedicated `setup` file (ensuring the base `setup.m

Each example below was taken from real-world projects; they may not be appropriate/applicable to yours, but each demonstrate general concepts that are broadly applicable.

## Dynamically generating test cases

Some times, you may want to dynamically generate test-cases. For instance, you want to test the same thing across a bunch of files. This is possible, albeit slightly arcane. You must use `test` (you cannot use `describe`) + `testContext.test`:

### Simple example

```js displayName="23.8.0 and later"
import assert from 'node:assert/strict';
import { test } from 'node:test';

import { detectOsInUserAgent } from '';

const userAgents = [
{ ua: /**/, os: 'WIN' },
//
];

test('Detect OS via user-agent', { concurrency: true }, t => {
for (const { os, ua } from userAgents) {
t.test(ua, () => assert.equal(detectOsInUserAgent(ua), os));
}
});
```

```js displayName="prior to 23.8.0"
import assert from 'node:assert/strict';
import { test } from 'node:test';

import { detectOsInUserAgent } from '';

const userAgents = [
{ ua: '', os: 'WIN' },
//
];

test('Detect OS via user-agent', { concurrency: true }, async t => {
const cases = userAgents.map(({ os, ua }) => {
t.test(ua, () => assert.equal(detectOsInUserAgent(ua), os));
});

await Promise.allSettled(cases);
});
```

### Advanced example

```js displayName="23.8.0 and later"
import assert from 'node:assert/strict';
import { test } from 'node:test';

import { getWorkspacePJSONs } from './getWorkspacePJSONs.mjs';

const requiredKeywords = ['node.js', 'sliced bread'];

test('Check package.jsons', { concurrency: true }, async t => {
const pjsons = await getWorkspacePJSONs();

for (const pjson of pjsons) {
// ⚠️ `t.test`, NOT `test`
t.test(`Ensure fields are properly set: ${pjson.name}`, () => {
assert.partialDeepStrictEqual(pjson.keywords, requiredKeywords);
});
}
});
```

```js displayName="prior to 23.8.0"
import assert from 'node:assert/strict';
import { test } from 'node:test';

import { getWorkspacePJSONs } from './getWorkspacePJSONs.mjs';

const requiredKeywords = ['node.js', 'sliced bread'];

test('Check package.jsons', { concurrency: true }, async t => {
const pjsons = await getWorkspacePJSONs();

const cases = pjsons.map(pjson =>
// ⚠️ `t.test`, NOT `test`
t.test(`Ensure fields are properly set: ${pjson.name}`, () => {
assert.partialDeepStrictEqual(pjson.keywords, requiredKeywords);
})
);

// Allow the cases to run concurrently.
await Promise.allSettled(cases);
});
```

```js displayName="./getWorkspacePJSONs.mjs"
import { globSync } from 'node:fs';
import { fileURLToPath } from 'node:url';

// Note: This would be better implemented as an async generator, leveraging fs.glob (instead of fs.globSync);
// however, generators and especially async generators are much less understood,
// so this simplified example is provided for easier understanding.

/**
* Get all the package.json files, by default 1-level deep within ./workspaces/
*/
export function getWorkspacePJSONs(path = './workspaces/*/package.json') {
return Promise.all(
globSync(
// ⚠️ Passing a file URL string, like from import.meta.resolve, causes glob* to fail silently
fileURLToPath(import.meta.resolve(path))
).map(path => import(path, { with: { type: 'json' } }))
);
}
```
> **Note**: Prior to version 23.8.0, the setup is quite different because `testContext.test` was not automatically awaited.
## ServiceWorker tests
[`ServiceWorkerGlobalScope`](https://developer.mozilla.org/docs/Web/API/ServiceWorkerGlobalScope) contains very specific APIs that don't exist in other environments, and some of its APIs are seemingly similar to others (ex `fetch`) but have augmented behaviour. You do not want these to spill into unrelated tests.
Expand Down

0 comments on commit 837a461

Please sign in to comment.