From 16b35857105d21aa871179774d98e72bd1f809dd Mon Sep 17 00:00:00 2001 From: Jason O'Neill Date: Tue, 5 Apr 2022 01:42:33 -0700 Subject: [PATCH 1/3] advance timers option --- src/keyboard/keyboardAction.ts | 6 +++--- src/options.ts | 8 ++++++++ src/pointer/pointerAction.ts | 2 +- src/utils/misc/wait.ts | 12 ++++++++++-- tests/utils/misc/wait.ts | 9 +++++++++ 5 files changed, 31 insertions(+), 6 deletions(-) create mode 100644 tests/utils/misc/wait.ts diff --git a/src/keyboard/keyboardAction.ts b/src/keyboard/keyboardAction.ts index 2a0f444e..f1abb7a1 100644 --- a/src/keyboard/keyboardAction.ts +++ b/src/keyboard/keyboardAction.ts @@ -23,7 +23,7 @@ export async function keyboardAction( await keyboardKeyAction(config, actions[i]) if (typeof config.delay === 'number' && i < actions.length - 1) { - await wait(config.delay) + await wait(config.delay, config.advanceTimers) } } } @@ -32,7 +32,7 @@ async function keyboardKeyAction( config: Config, {keyDef, releasePrevious, releaseSelf, repeat}: KeyboardAction, ) { - const {document, keyboardState, delay} = config + const {document, keyboardState, delay, advanceTimers} = config const getCurrentElement = () => getActive(document) // Release the key automatically if it was pressed before. @@ -51,7 +51,7 @@ async function keyboardKeyAction( } if (typeof delay === 'number' && i < repeat) { - await wait(delay) + await wait(delay, advanceTimers) } } diff --git a/src/options.ts b/src/options.ts index 8d91e879..6848c856 100644 --- a/src/options.ts +++ b/src/options.ts @@ -120,6 +120,13 @@ export interface Options { * Defaults to `true` when calling the APIs per `setup`. */ writeToClipboard?: boolean + + /** + * A function to be called internally to advance your fake timers (if applicable) + * + * @example jest.advanceTimersByTime + */ + advanceTimers?: (delay: number) => void } /** @@ -137,6 +144,7 @@ export const defaultOptionsDirect: Required = { skipClick: false, skipHover: false, writeToClipboard: false, + advanceTimers: () => void 0, } /** diff --git a/src/pointer/pointerAction.ts b/src/pointer/pointerAction.ts index d5323c2e..3a36234b 100644 --- a/src/pointer/pointerAction.ts +++ b/src/pointer/pointerAction.ts @@ -39,7 +39,7 @@ export async function pointerAction(config: Config, actions: PointerAction[]) { if (typeof config.delay === 'number') { if (i < actions.length - 1) { - await wait(config.delay) + await wait(config.delay, config.advanceTimers) } } } diff --git a/src/utils/misc/wait.ts b/src/utils/misc/wait.ts index 69ad59b5..03bcbace 100644 --- a/src/utils/misc/wait.ts +++ b/src/utils/misc/wait.ts @@ -1,3 +1,11 @@ -export function wait(time?: number) { - return new Promise(resolve => setTimeout(() => resolve(), time)) +import type {Options} from '../../options' + +export function wait( + time: number, + advanceTimers: Exclude, +) { + return new Promise(resolve => { + setTimeout(() => resolve(), time) + advanceTimers(time) + }) } diff --git a/tests/utils/misc/wait.ts b/tests/utils/misc/wait.ts new file mode 100644 index 00000000..3f88f9ce --- /dev/null +++ b/tests/utils/misc/wait.ts @@ -0,0 +1,9 @@ +import {wait} from '#src/utils/misc/wait' + +test('advances timers when set', async () => { + jest.useFakeTimers() + jest.setTimeout(50) + // If this wasn't advancing fake timers, we'd timeout and fail the test + await wait(10000, jest.advanceTimersByTime) + jest.useRealTimers() +}) From a54dc2ce407337fea67db6eb7e10f5c6307b8115 Mon Sep 17 00:00:00 2001 From: Jason O'Neill Date: Tue, 5 Apr 2022 11:35:41 -0700 Subject: [PATCH 2/3] refactor wait to accept config object --- src/keyboard/keyboardAction.ts | 10 +++++----- src/pointer/pointerAction.ts | 6 ++---- src/utils/misc/wait.ts | 15 ++++++++------- 3 files changed, 15 insertions(+), 16 deletions(-) diff --git a/src/keyboard/keyboardAction.ts b/src/keyboard/keyboardAction.ts index f1abb7a1..d4887978 100644 --- a/src/keyboard/keyboardAction.ts +++ b/src/keyboard/keyboardAction.ts @@ -22,8 +22,8 @@ export async function keyboardAction( for (let i = 0; i < actions.length; i++) { await keyboardKeyAction(config, actions[i]) - if (typeof config.delay === 'number' && i < actions.length - 1) { - await wait(config.delay, config.advanceTimers) + if (i < actions.length - 1) { + await wait(config) } } } @@ -32,7 +32,7 @@ async function keyboardKeyAction( config: Config, {keyDef, releasePrevious, releaseSelf, repeat}: KeyboardAction, ) { - const {document, keyboardState, delay, advanceTimers} = config + const {document, keyboardState} = config const getCurrentElement = () => getActive(document) // Release the key automatically if it was pressed before. @@ -50,8 +50,8 @@ async function keyboardKeyAction( await keypress(keyDef, getCurrentElement, config) } - if (typeof delay === 'number' && i < repeat) { - await wait(delay, advanceTimers) + if (i < repeat) { + await wait(config) } } diff --git a/src/pointer/pointerAction.ts b/src/pointer/pointerAction.ts index 3a36234b..7ca73410 100644 --- a/src/pointer/pointerAction.ts +++ b/src/pointer/pointerAction.ts @@ -37,10 +37,8 @@ export async function pointerAction(config: Config, actions: PointerAction[]) { ? pointerPress(config, {...action, target, coords}) : pointerMove(config, {...action, target, coords})) - if (typeof config.delay === 'number') { - if (i < actions.length - 1) { - await wait(config.delay, config.advanceTimers) - } + if (i < actions.length - 1) { + await wait(config) } } diff --git a/src/utils/misc/wait.ts b/src/utils/misc/wait.ts index 03bcbace..21dab023 100644 --- a/src/utils/misc/wait.ts +++ b/src/utils/misc/wait.ts @@ -1,11 +1,12 @@ -import type {Options} from '../../options' +import {Config} from '../../setup' -export function wait( - time: number, - advanceTimers: Exclude, -) { +export function wait(config: Config) { + const delay = config.delay + if (typeof delay !== 'number') { + return + } return new Promise(resolve => { - setTimeout(() => resolve(), time) - advanceTimers(time) + setTimeout(() => resolve(), delay) + config.advanceTimers(delay) }) } From 0ac4ef6878620bc4c5175e5940645ebe6996d5ee Mon Sep 17 00:00:00 2001 From: Jason O'Neill Date: Wed, 6 Apr 2022 21:22:27 -0700 Subject: [PATCH 3/3] support advanceTimers returning a promise --- src/options.ts | 4 ++-- src/utils/misc/wait.ts | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/options.ts b/src/options.ts index 6848c856..1e970b0c 100644 --- a/src/options.ts +++ b/src/options.ts @@ -126,7 +126,7 @@ export interface Options { * * @example jest.advanceTimersByTime */ - advanceTimers?: (delay: number) => void + advanceTimers?: ((delay: number) => Promise) | ((delay: number) => void) } /** @@ -144,7 +144,7 @@ export const defaultOptionsDirect: Required = { skipClick: false, skipHover: false, writeToClipboard: false, - advanceTimers: () => void 0, + advanceTimers: () => Promise.resolve(), } /** diff --git a/src/utils/misc/wait.ts b/src/utils/misc/wait.ts index 21dab023..aac99961 100644 --- a/src/utils/misc/wait.ts +++ b/src/utils/misc/wait.ts @@ -5,8 +5,8 @@ export function wait(config: Config) { if (typeof delay !== 'number') { return } - return new Promise(resolve => { - setTimeout(() => resolve(), delay) - config.advanceTimers(delay) - }) + return Promise.all([ + new Promise(resolve => setTimeout(() => resolve(), delay)), + config.advanceTimers(delay), + ]) }