From 67d3d5f203bcb89bc997197e3d013b4525b0b4c8 Mon Sep 17 00:00:00 2001 From: Max Schmitt Date: Mon, 26 Aug 2024 18:26:38 +0200 Subject: [PATCH] fix(clock): don't throw for |null| or |undefined| callbacks (#32309) Fixes https://github.com/microsoft/playwright/issues/32293 This aligns it how Chromium and other browsers are doing it. --- .../playwright-core/src/server/injected/clock.ts | 7 ++++++- tests/library/clock.spec.ts | 16 ++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/packages/playwright-core/src/server/injected/clock.ts b/packages/playwright-core/src/server/injected/clock.ts index 48cc9276a2..414d23b958 100644 --- a/packages/playwright-core/src/server/injected/clock.ts +++ b/packages/playwright-core/src/server/injected/clock.ts @@ -239,7 +239,12 @@ export class ClockController { addTimer(options: { func: TimerHandler, type: TimerType, delay?: number | string, args?: any[] }): number { this._replayLogOnce(); - if (options.func === undefined) + + if (options.type === TimerType.AnimationFrame && !options.func) + throw new Error('Callback must be provided to requestAnimationFrame calls'); + if (options.type === TimerType.IdleCallback && !options.func) + throw new Error('Callback must be provided to requestIdleCallback calls'); + if ([TimerType.Timeout, TimerType.Interval].includes(options.type) && !options.func && options.delay === undefined) throw new Error('Callback must be provided to timer calls'); let delay = options.delay ? +options.delay : 0; diff --git a/tests/library/clock.spec.ts b/tests/library/clock.spec.ts index 90279fd893..daad405e70 100644 --- a/tests/library/clock.spec.ts +++ b/tests/library/clock.spec.ts @@ -75,6 +75,14 @@ it.describe('setTimeout', () => { }).toThrow(); }); + it('does not throw if |undefined| or |null| is passed as a callback', async ({ clock }) => { + const timerId1 = clock.setTimeout(undefined, 10); + const timerId2 = clock.setTimeout(null, 10); + await clock.runFor(10); + expect(timerId1).toBeGreaterThan(0); + expect(timerId2).toBeGreaterThan(timerId1); + }); + it('returns numeric id or object with numeric id', async ({ clock }) => { const result = clock.setTimeout(() => { }, 10); expect(result).toEqual(expect.any(Number)); @@ -761,6 +769,14 @@ it.describe('setInterval', () => { }).toThrow(); }); + it('does not throw if |undefined| or |null| is passed as a callback', async ({ clock }) => { + const timerId1 = clock.setInterval(undefined, 10); + const timerId2 = clock.setInterval(null, 10); + await clock.runFor(10); + expect(timerId1).toBeGreaterThan(0); + expect(timerId2).toBeGreaterThan(timerId1); + }); + it('returns numeric id or object with numeric id', async ({ clock }) => { const result = clock.setInterval(() => {}, 10); expect(result).toBeGreaterThan(0);