Skip to content

Commit cb2e4fd

Browse files
authored
fix: make test runner work even if there is no AbortSignal support (#36)
Fixes a breaking change for Node.js v14.x that was introduced in 3.2.0. Fixes: #35
1 parent f9c40b5 commit cb2e4fd

File tree

5 files changed

+52
-11
lines changed

5 files changed

+52
-11
lines changed

.github/workflows/ci.yml

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,14 @@ jobs:
99
strategy:
1010
matrix:
1111
node: ['14', '16', '18']
12-
include:
13-
- node: '14'
14-
env: --experimental-abortcontroller --no-warnings
1512
steps:
1613
- uses: actions/checkout@v3
1714
- uses: actions/setup-node@v3
1815
with:
1916
node-version: ${{ matrix.node }}
2017
- run: npm ci
2118
- run: npm test
19+
- name: Run test with experimental flag
20+
run: npm test
2221
env:
23-
NODE_OPTIONS: ${{ matrix.env }}
22+
NODE_OPTIONS: --experimental-abortcontroller --no-warnings

README.md

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,10 @@ Minimal dependencies, with full test suite.
1111
Differences from the core implementation:
1212

1313
- Doesn't hide its own stack frames.
14-
- Requires `--experimental-abortcontroller` CLI flag to work on Node.js v14.x.
14+
- Some features require the use of `--experimental-abortcontroller` CLI flag to
15+
work on Node.js v14.x. It's recommended to pass
16+
`NODE_OPTIONS='--experimental-abortcontroller --no-warnings'` in your env if
17+
you are testing on v14.x.
1518

1619
## Docs
1720

@@ -339,7 +342,7 @@ internally.
339342
- `only` {boolean} If truthy, and the test context is configured to run
340343
`only` tests, then this test will be run. Otherwise, the test is skipped.
341344
**Default:** `false`.
342-
* `signal` {AbortSignal} Allows aborting an in-progress test.
345+
- `signal` {AbortSignal} Allows aborting an in-progress test.
343346
- `skip` {boolean|string} If truthy, the test is skipped. If a string is
344347
provided, that string is displayed in the test results as the reason for
345348
skipping the test. **Default:** `false`.
@@ -625,6 +628,11 @@ no-op.
625628

626629
* [`AbortSignal`][] Can be used to abort test subtasks when the test has been aborted.
627630

631+
> **Warning**
632+
> On Node.js v14.x, this feature won't be available unless you pass the
633+
> `--experimental-abortcontroller` CLI flag or added an external global polyfill
634+
> for `AbortController`.
635+
628636
```js
629637
test('top level test', async (t) => {
630638
await fetch('some/uri', { signal: t.signal });
@@ -694,6 +702,12 @@ The name of the suite.
694702

695703
* [`AbortSignal`][] Can be used to abort test subtasks when the test has been aborted.
696704

705+
> **Warning**
706+
> On Node.js v14.x, this feature won't be available unless you pass the
707+
> `--experimental-abortcontroller` CLI flag or added an external global polyfill
708+
> for `AbortController`.
709+
710+
697711
[`AbortSignal`]: https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal
698712
[TAP]: https://testanything.org/
699713
[`SuiteContext`]: #class-suitecontext

lib/internal/abort_controller.js

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,30 @@
11
'use strict'
22

3-
module.exports = {
4-
AbortController,
5-
AbortSignal
3+
if (typeof AbortController === 'undefined') {
4+
// Node.js AbortController implementation is behind a CLI flag.
5+
// This is a minimal mock to make the code work if the native
6+
// implementation in not available.
7+
module.exports = {
8+
AbortController: class AbortController {
9+
#eventListeners = new Set()
10+
signal = {
11+
aborted: false,
12+
addEventListener: (_, listener) => {
13+
this.#eventListeners.add(listener)
14+
},
15+
removeEventListener: (_, listener) => {
16+
this.#eventListeners.delete(listener)
17+
}
18+
}
19+
20+
abort () {
21+
this.signal.aborted = true
22+
this.#eventListeners.forEach(listener => listener())
23+
}
24+
}
25+
}
26+
} else {
27+
module.exports = {
28+
AbortController
29+
}
630
}

test/common/index.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ function expectsError (validator, exact) {
102102
}, exact)
103103
}
104104

105-
if (typeof AbortSignal.timeout !== 'function') {
105+
if (typeof AbortSignal !== 'undefined' && typeof AbortSignal.timeout !== 'function') {
106106
// `AbortSignal.timeout` is not available on Node.js 14.x, we need to polyfill
107107
// it because some tests are using it. End-users don't need to it.
108108

@@ -121,7 +121,7 @@ if (typeof AbortSignal.timeout !== 'function') {
121121
}
122122
}
123123

124-
if (process.version.startsWith('v14.') || process.version.startsWith('v16.')) {
124+
if (typeof AbortSignal !== 'undefined' && (process.version.startsWith('v14.') || process.version.startsWith('v16.'))) {
125125
// Implementation of AbortSignal and AbortController differ slightly with the
126126
// v18.x one, creating some difference on the TAP output which makes the tests
127127
// fail. We are overriding the built-ins to make the test pass, however that's

test/message.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,10 @@ const main = async () => {
8484
for await (const dirent of dir) {
8585
const ext = extname(dirent.name)
8686
if (ext === '.js' || ext === '.mjs') {
87+
if (typeof AbortSignal === 'undefined' && dirent.name.startsWith('test_runner_abort')) {
88+
console.log('no AbortSignal support, skipping', dirent.name)
89+
continue
90+
}
8791
const filePath = join(MESSAGE_FOLDER, dirent.name)
8892
const expected = filePath.replace(/\.m?js$/, '.out')
8993
const testFile = await fs.open(filePath)

0 commit comments

Comments
 (0)