From 2d93630304aa88dcefad756fd6ed9cccca696f29 Mon Sep 17 00:00:00 2001 From: Robin Kehl Date: Wed, 8 Jan 2025 15:53:06 +0100 Subject: [PATCH 1/4] test: add failing test to debug #3665 --- packages/shared/watchDebounced/index.test.ts | 27 ++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/packages/shared/watchDebounced/index.test.ts b/packages/shared/watchDebounced/index.test.ts index b8317662fe5..9790aa41d92 100644 --- a/packages/shared/watchDebounced/index.test.ts +++ b/packages/shared/watchDebounced/index.test.ts @@ -44,4 +44,31 @@ describe('watchDebounced', () => { expect(cb).toHaveBeenCalledTimes(2) expect(cb).toHaveBeenCalledWith(4, 2, expect.anything()) }) + + it.todo('should work with constant changes over multiple maxWaits', async () => { + vi.useFakeTimers() + const num = ref(0) + const cb = vi.fn() + + const constantUpdateOverTime = async (ms: number) => { + for (let i = 0; i < ms; i++) { + num.value += 1 + await vi.advanceTimersByTimeAsync(1) + } + } + watchDebounced(num, cb, { debounce: 10, maxWait: 50 }) + expect(cb).toHaveBeenCalledTimes(0) + await constantUpdateOverTime(49) + expect(cb).toHaveBeenCalledTimes(0) + await constantUpdateOverTime(1) + expect(cb).toHaveBeenCalledTimes(1) + await constantUpdateOverTime(50) + expect(cb).toHaveBeenCalledTimes(2) + await constantUpdateOverTime(50) + + expect(cb).toHaveBeenCalledTimes(3) + expect(cb.mock.calls[0][0]).toBe(50) // or 51 + expect(cb.mock.calls[1][0]).toBe(100) // or 101 + expect(cb.mock.calls[2][0]).toBe(150) // or 151 + }) }) From 033b405b40942341d97068201a26aefcc1519655 Mon Sep 17 00:00:00 2001 From: OrbisK <37191683+OrbisK@users.noreply.github.com> Date: Sat, 11 Jan 2025 09:47:16 +0000 Subject: [PATCH 2/4] test: add `fails` variant --- packages/shared/watchDebounced/index.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/shared/watchDebounced/index.test.ts b/packages/shared/watchDebounced/index.test.ts index 9790aa41d92..7357f3fabcc 100644 --- a/packages/shared/watchDebounced/index.test.ts +++ b/packages/shared/watchDebounced/index.test.ts @@ -45,7 +45,7 @@ describe('watchDebounced', () => { expect(cb).toHaveBeenCalledWith(4, 2, expect.anything()) }) - it.todo('should work with constant changes over multiple maxWaits', async () => { + it.fails('should work with constant changes over multiple maxWaits', async () => { vi.useFakeTimers() const num = ref(0) const cb = vi.fn() From a46e71ecd9e6309de569e0b5adf6fe5b947f7469 Mon Sep 17 00:00:00 2001 From: James Garbutt <43081j@users.noreply.github.com> Date: Wed, 15 Jan 2025 19:44:07 +0000 Subject: [PATCH 3/4] fix(watchDebounced): always pass last value to invokers --- packages/shared/utils/filters.ts | 5 ++++- packages/shared/watchDebounced/index.test.ts | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/shared/utils/filters.ts b/packages/shared/utils/filters.ts index 1644b315e29..052f43b37b3 100644 --- a/packages/shared/utils/filters.ts +++ b/packages/shared/utils/filters.ts @@ -73,6 +73,8 @@ export function debounceFilter(ms: MaybeRefOrGetter, options: DebounceFi lastRejector = noop } + let lastInvoker: () => void + const filter: EventFilter = (invoke) => { const duration = toValue(ms) const maxDuration = toValue(options.maxWait) @@ -90,13 +92,14 @@ export function debounceFilter(ms: MaybeRefOrGetter, options: DebounceFi return new Promise((resolve, reject) => { lastRejector = options.rejectOnCancel ? reject : resolve + lastInvoker = invoke // Create the maxTimer. Clears the regular timer on invoke if (maxDuration && !maxTimer) { maxTimer = setTimeout(() => { if (timer) _clearTimeout(timer) maxTimer = null - resolve(invoke()) + resolve(lastInvoker()) }, maxDuration) } diff --git a/packages/shared/watchDebounced/index.test.ts b/packages/shared/watchDebounced/index.test.ts index 7357f3fabcc..fb2eca6d58d 100644 --- a/packages/shared/watchDebounced/index.test.ts +++ b/packages/shared/watchDebounced/index.test.ts @@ -42,10 +42,10 @@ describe('watchDebounced', () => { num.value = 5 await vi.advanceTimersByTimeAsync(75) expect(cb).toHaveBeenCalledTimes(2) - expect(cb).toHaveBeenCalledWith(4, 2, expect.anything()) + expect(cb).toHaveBeenCalledWith(5, 4, expect.anything()) }) - it.fails('should work with constant changes over multiple maxWaits', async () => { + it('should work with constant changes over multiple maxWaits', async () => { vi.useFakeTimers() const num = ref(0) const cb = vi.fn() From 5c6773f01e9c0516aeb4ceb3d417f84b22a00266 Mon Sep 17 00:00:00 2001 From: James Garbutt <43081j@users.noreply.github.com> Date: Thu, 16 Jan 2025 10:09:29 +0000 Subject: [PATCH 4/4] test(watchDebounced): remove leftover expect comments Co-authored-by: Robin <37191683+OrbisK@users.noreply.github.com> --- packages/shared/watchDebounced/index.test.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/shared/watchDebounced/index.test.ts b/packages/shared/watchDebounced/index.test.ts index fb2eca6d58d..9b40160bf62 100644 --- a/packages/shared/watchDebounced/index.test.ts +++ b/packages/shared/watchDebounced/index.test.ts @@ -67,8 +67,8 @@ describe('watchDebounced', () => { await constantUpdateOverTime(50) expect(cb).toHaveBeenCalledTimes(3) - expect(cb.mock.calls[0][0]).toBe(50) // or 51 - expect(cb.mock.calls[1][0]).toBe(100) // or 101 - expect(cb.mock.calls[2][0]).toBe(150) // or 151 + expect(cb.mock.calls[0][0]).toBe(50) + expect(cb.mock.calls[1][0]).toBe(100) + expect(cb.mock.calls[2][0]).toBe(150) }) })