Skip to content

Commit

Permalink
feat: [#1470] Adds support for the static method `AbortSignal.timeout…
Browse files Browse the repository at this point in the history
…()` (#1471)

* feat: [#1470] Add AbortSignal.timeout() static method

* chore: [#1468] As we use setTimeout() from Window, we cant use the fake timers from Vitest

---------

Co-authored-by: David Ortner <david@ortner.se>
  • Loading branch information
ezzatron and capricorn86 authored Aug 28, 2024
1 parent 3e1191e commit a99364f
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 0 deletions.
1 change: 1 addition & 0 deletions packages/happy-dom/src/exception/DOMExceptionNameEnum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ enum DOMExceptionNameEnum {
invalidAccessError = 'InvalidAccessError',
unknownError = 'UnknownError',
abortError = 'AbortError',
timeoutError = 'TimeoutError',
encodingError = 'EncodingError',
uriMismatchError = 'URIMismatchError'
}
Expand Down
18 changes: 18 additions & 0 deletions packages/happy-dom/src/fetch/AbortSignal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,24 @@ export default class AbortSignal extends EventTarget {
return signal;
}

/**
* Returns an AbortSignal that will automatically abort after a specified
* time.
*
* @param [time] Time in milliseconds.
* @returns AbortSignal instance.
*/
public static timeout(time: number): AbortSignal {
const window = this[PropertySymbol.window];
const signal = new this();
window.setTimeout(() => {
signal[PropertySymbol.abort](
new window.DOMException('signal timed out', DOMExceptionNameEnum.timeoutError)
);
}, time);
return signal;
}

/**
* Takes an iterable of abort signals and returns an AbortSignal that is
* aborted when any of the input iterable abort signals are aborted.
Expand Down
15 changes: 15 additions & 0 deletions packages/happy-dom/test/fetch/AbortSignal.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { describe, it, expect, beforeEach } from 'vitest';
import * as PropertySymbol from '../../src/PropertySymbol.js';
import BrowserWindow from '../../src/window/BrowserWindow.js';
import Window from '../../src/window/Window.js';
import DOMException from '../../src/exception/DOMException.js';

describe('AbortSignal', () => {
let window: BrowserWindow;
Expand Down Expand Up @@ -50,6 +51,20 @@ describe('AbortSignal', () => {
});
});

describe('AbortSignal.timeout()', () => {
it('Returns a new instance of AbortSignal that aborts with a "TimeoutError" after a timeout.', async () => {
const signal = window.AbortSignal.timeout(10);

expect(signal.aborted).toBe(false);

await new Promise((resolve) => setTimeout(resolve, 100));

expect(signal.aborted).toBe(true);
expect(signal.reason).toBeInstanceOf(DOMException);
expect(signal.reason?.name).toBe('TimeoutError');
});
});

describe('AbortSignal.any()', () => {
it('Returns a signal that is asynchronously aborted when one of the supplied signals is asynchronously aborted.', () => {
const signal1 = new window.AbortSignal();
Expand Down

0 comments on commit a99364f

Please sign in to comment.