138 lines
4.7 KiB
TypeScript
138 lines
4.7 KiB
TypeScript
|
import { TimeoutError } from 'src/common/errors';
|
||
|
import CancelablePromise from 'cancelable-promise';
|
||
|
import pTimeout from 'src/common/utils/p-timeout';
|
||
|
import delay from 'delay';
|
||
|
import fn = jest.fn;
|
||
|
|
||
|
describe('p-timeout tests', () => {
|
||
|
const expected = Symbol('expected');
|
||
|
const expectedError = new Error('expectedError');
|
||
|
|
||
|
const smallTimeout = 50;
|
||
|
const bigTimeout = 200;
|
||
|
|
||
|
test('Resolves before timeout', async () => {
|
||
|
const result = await pTimeout(
|
||
|
delay(smallTimeout).then(() => expected),
|
||
|
bigTimeout
|
||
|
);
|
||
|
expect(result).toBe(expected);
|
||
|
});
|
||
|
|
||
|
test('Resolves after timeout', async () => {
|
||
|
await expect(pTimeout(delay(bigTimeout), smallTimeout)).rejects.toThrow(
|
||
|
new TimeoutError(`Promise timed out after ${smallTimeout} milliseconds`)
|
||
|
);
|
||
|
});
|
||
|
|
||
|
test('Throws when milliseconds is negative number', async () => {
|
||
|
const milliseconds = -1;
|
||
|
await expect(pTimeout(delay(smallTimeout), milliseconds)).rejects.toThrow(
|
||
|
`Expected \`milliseconds\` to be a positive number, got \`${milliseconds}\``
|
||
|
);
|
||
|
});
|
||
|
|
||
|
test('Throws when milliseconds is NaN', async () => {
|
||
|
const milliseconds = NaN;
|
||
|
await expect(pTimeout(delay(smallTimeout), milliseconds)).rejects.toThrow(
|
||
|
`Expected \`milliseconds\` to be a positive number, got \`${milliseconds}\``
|
||
|
);
|
||
|
});
|
||
|
|
||
|
test('Handles milliseconds being `Infinity`', async () => {
|
||
|
const result = await pTimeout(
|
||
|
delay(smallTimeout).then(() => expected),
|
||
|
+Infinity
|
||
|
);
|
||
|
expect(result).toBe(expected);
|
||
|
});
|
||
|
|
||
|
test('Rejects after timeout', async () => {
|
||
|
await expect(
|
||
|
pTimeout(
|
||
|
delay(bigTimeout).then(() => expected),
|
||
|
smallTimeout
|
||
|
)
|
||
|
).rejects.toThrow(new TimeoutError(`Promise timed out after ${smallTimeout} milliseconds`));
|
||
|
});
|
||
|
|
||
|
test('Rejects before timeout if specified promise rejects', async () => {
|
||
|
await expect(
|
||
|
pTimeout(
|
||
|
delay(smallTimeout).then(() => Promise.reject(expectedError)),
|
||
|
bigTimeout
|
||
|
)
|
||
|
).rejects.toThrow(expectedError);
|
||
|
});
|
||
|
|
||
|
test('Fallback argument', async () => {
|
||
|
await expect(pTimeout(delay(bigTimeout), smallTimeout, 'error message')).rejects.toThrow(
|
||
|
'error message'
|
||
|
);
|
||
|
await expect(
|
||
|
pTimeout(delay(bigTimeout), smallTimeout, new RangeError('error message'))
|
||
|
).rejects.toThrow(new RangeError('error message'));
|
||
|
await expect(
|
||
|
pTimeout(delay(bigTimeout), smallTimeout, () => Promise.reject(expectedError))
|
||
|
).rejects.toThrow(expectedError);
|
||
|
await expect(
|
||
|
pTimeout(delay(bigTimeout), smallTimeout, () => {
|
||
|
throw new RangeError('error message');
|
||
|
})
|
||
|
).rejects.toThrow(new RangeError('error message'));
|
||
|
});
|
||
|
|
||
|
test('Calls `.cancel()` on promise when it exists', async () => {
|
||
|
const callSpy = fn();
|
||
|
|
||
|
const promise = new CancelablePromise<void>(async (resolve, _, onCancel) => {
|
||
|
onCancel(() => {
|
||
|
callSpy();
|
||
|
});
|
||
|
|
||
|
await delay(bigTimeout);
|
||
|
resolve();
|
||
|
});
|
||
|
|
||
|
await expect(pTimeout(promise, smallTimeout)).rejects.toThrow(
|
||
|
new TimeoutError(`Promise timed out after ${smallTimeout} milliseconds`)
|
||
|
);
|
||
|
expect(promise.isCanceled).toBeTruthy();
|
||
|
expect(callSpy.mock.calls.length).toBe(1);
|
||
|
});
|
||
|
|
||
|
test('Accepts `customTimers` option', async () => {
|
||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||
|
const setTimeoutSpy = fn((_: number | undefined) => {});
|
||
|
const clearTimeoutSpy = fn();
|
||
|
|
||
|
await pTimeout(delay(smallTimeout), bigTimeout, undefined, {
|
||
|
customTimers: {
|
||
|
setTimeout: function (handler: () => void, timeout?: number) {
|
||
|
setTimeoutSpy(timeout);
|
||
|
return setTimeout(handler as unknown as () => void, timeout || 1000);
|
||
|
} as typeof setTimeout,
|
||
|
clearTimeout(timeoutId) {
|
||
|
clearTimeoutSpy();
|
||
|
return clearTimeout(timeoutId);
|
||
|
}
|
||
|
}
|
||
|
});
|
||
|
|
||
|
expect(setTimeoutSpy.mock.calls.length).toBe(1);
|
||
|
expect(setTimeoutSpy.mock.calls[0]).toEqual([bigTimeout]);
|
||
|
expect(clearTimeoutSpy.mock.calls.length).toBe(1);
|
||
|
});
|
||
|
|
||
|
test('`.clear()` method', async () => {
|
||
|
const promise = pTimeout(
|
||
|
delay(bigTimeout).then(() => expected),
|
||
|
smallTimeout
|
||
|
);
|
||
|
promise.clear();
|
||
|
|
||
|
const result = await promise;
|
||
|
expect(result).toBe(expected);
|
||
|
});
|
||
|
});
|