From 8846459558e2ef6b5c5e15bd39de51c33b00b057 Mon Sep 17 00:00:00 2001 From: Shinigami92 Date: Mon, 14 Jul 2025 21:05:36 +0200 Subject: [PATCH] test: useIntervalFn --- .../src/useIntervalFn/index.solid.spec.ts | 47 ++++++++++ .../unuse/src/useIntervalFn/index.spec.ts | 87 ++++++++++++++++++- .../unuse/src/useIntervalFn/index.vue.spec.ts | 87 ++++++++++++++++++- 3 files changed, 219 insertions(+), 2 deletions(-) create mode 100644 packages/unuse/src/useIntervalFn/index.solid.spec.ts diff --git a/packages/unuse/src/useIntervalFn/index.solid.spec.ts b/packages/unuse/src/useIntervalFn/index.solid.spec.ts new file mode 100644 index 0000000..073724d --- /dev/null +++ b/packages/unuse/src/useIntervalFn/index.solid.spec.ts @@ -0,0 +1,47 @@ +import type { Accessor } from 'solid-js'; +import { beforeEach, expect, it, vi } from 'vitest'; +import { useIntervalFn } from '.'; +import { describeSolid } from '../_testUtils/solid'; + +describeSolid('useIntervalFn', () => { + let callback = vi.fn(); + vi.useFakeTimers(); + + beforeEach(() => { + callback = vi.fn(); + }); + + it('pause in callback', async () => { + const pausable = useIntervalFn( + () => { + callback(); + pausable.pause(); + }, + 50, + { immediateCallback: true, immediate: false } + ); + + pausable.resume(); + expect(pausable.isActive).toSatisfy((value) => typeof value === 'function'); + expect((pausable.isActive as Accessor)()).toBeFalsy(); + expect(callback).toHaveBeenCalledTimes(1); + + await vi.advanceTimersByTimeAsync(60); + expect(callback).toHaveBeenCalledTimes(1); + + pausable.resume(); + expect((pausable.isActive as Accessor)()).toBeFalsy(); + expect(callback).toHaveBeenCalledTimes(2); + + await vi.advanceTimersByTimeAsync(60); + expect(callback).toHaveBeenCalledTimes(2); + }); + + it('cant work when interval is negative', async () => { + const { isActive } = useIntervalFn(callback, -1); + + expect((isActive as Accessor)()).toBeFalsy(); + await vi.advanceTimersByTimeAsync(60); + expect(callback).toHaveBeenCalledTimes(0); + }); +}); diff --git a/packages/unuse/src/useIntervalFn/index.spec.ts b/packages/unuse/src/useIntervalFn/index.spec.ts index 15b134c..287f9ee 100644 --- a/packages/unuse/src/useIntervalFn/index.spec.ts +++ b/packages/unuse/src/useIntervalFn/index.spec.ts @@ -1,8 +1,93 @@ -import { describe, expect, it } from 'vitest'; +// @vitest-environment happy-dom + +import type { UnComputed } from 'unuse-reactivity'; +import { isUnComputed, unSignal } from 'unuse-reactivity'; +import { beforeEach, describe, expect, it, vi } from 'vitest'; +import type { Pausable } from '.'; import { useIntervalFn } from '.'; describe('useIntervalFn', () => { it('should be defined', () => { expect(useIntervalFn).toBeTypeOf('function'); }); + + let callback = vi.fn(); + vi.useFakeTimers(); + + beforeEach(() => { + callback = vi.fn(); + }); + + async function exec({ isActive, pause, resume }: Pausable) { + expect(isActive).toSatisfy(isUnComputed); + expect((isActive as unknown as UnComputed).get()).toBeTruthy(); + expect(callback).toHaveBeenCalledTimes(0); + + await vi.advanceTimersByTimeAsync(60); + expect(callback).toHaveBeenCalledTimes(1); + + pause(); + expect((isActive as unknown as UnComputed).get()).toBeFalsy(); + + await vi.advanceTimersByTimeAsync(60); + expect(callback).toHaveBeenCalledTimes(1); + + resume(); + expect((isActive as unknown as UnComputed).get()).toBeTruthy(); + + await vi.advanceTimersByTimeAsync(60); + expect(callback).toHaveBeenCalledTimes(2); + } + + it('basic pause/resume', async () => { + await exec(useIntervalFn(callback, 50)); + + callback = vi.fn(); + + const interval = unSignal(50); + await exec(useIntervalFn(callback, interval)); + + callback.mockClear(); + interval.set(20); + await vi.advanceTimersByTimeAsync(30); + expect(callback).toHaveBeenCalledTimes(1); + }); + + it('pause in callback', async () => { + const pausable = useIntervalFn( + () => { + callback(); + pausable.pause(); + }, + 50, + { immediateCallback: true, immediate: false } + ); + + pausable.resume(); + expect(pausable.isActive).toSatisfy(isUnComputed); + expect( + (pausable.isActive as unknown as UnComputed).get() + ).toBeFalsy(); + expect(callback).toHaveBeenCalledTimes(1); + + await vi.advanceTimersByTimeAsync(60); + expect(callback).toHaveBeenCalledTimes(1); + + pausable.resume(); + expect( + (pausable.isActive as unknown as UnComputed).get() + ).toBeFalsy(); + expect(callback).toHaveBeenCalledTimes(2); + + await vi.advanceTimersByTimeAsync(60); + expect(callback).toHaveBeenCalledTimes(2); + }); + + it('cant work when interval is negative', async () => { + const { isActive } = useIntervalFn(callback, -1); + + expect((isActive as unknown as UnComputed).get()).toBeFalsy(); + await vi.advanceTimersByTimeAsync(60); + expect(callback).toHaveBeenCalledTimes(0); + }); }); diff --git a/packages/unuse/src/useIntervalFn/index.vue.spec.ts b/packages/unuse/src/useIntervalFn/index.vue.spec.ts index 875e71a..e1c1eb9 100644 --- a/packages/unuse/src/useIntervalFn/index.vue.spec.ts +++ b/packages/unuse/src/useIntervalFn/index.vue.spec.ts @@ -2,7 +2,7 @@ import { beforeEach, expect, it, vi } from 'vitest'; import type { Ref } from 'vue'; -import { isRef, shallowRef } from 'vue'; +import { effectScope, isRef, nextTick, shallowRef } from 'vue'; import type { Pausable } from '.'; import { useIntervalFn } from '.'; import { describeVue } from '../_testUtils/vue'; @@ -36,6 +36,28 @@ describeVue('useIntervalFn', () => { expect(callback).toHaveBeenCalledTimes(2); } + async function execImmediateCallback({ isActive, pause, resume }: Pausable) { + expect(isActive).toSatisfy(isRef); + expect((isActive as unknown as Ref).value).toBeTruthy(); + expect(callback).toHaveBeenCalledTimes(1); + + await vi.advanceTimersByTimeAsync(60); + expect(callback).toHaveBeenCalledTimes(2); + + pause(); + expect((isActive as unknown as Ref).value).toBeFalsy(); + + await vi.advanceTimersByTimeAsync(60); + expect(callback).toHaveBeenCalledTimes(2); + + resume(); + expect((isActive as unknown as Ref).value).toBeTruthy(); + expect(callback).toHaveBeenCalledTimes(3); + + await vi.advanceTimersByTimeAsync(60); + expect(callback).toHaveBeenCalledTimes(4); + } + it('basic pause/resume', async () => { await exec(useIntervalFn(callback, 50)); @@ -49,4 +71,67 @@ describeVue('useIntervalFn', () => { await vi.advanceTimersByTimeAsync(30); expect(callback).toHaveBeenCalledTimes(1); }); + + it('pause/resume with immediateCallback', async () => { + await execImmediateCallback( + useIntervalFn(callback, 50, { immediateCallback: true }) + ); + + callback = vi.fn(); + + const interval = shallowRef(50); + await execImmediateCallback( + useIntervalFn(callback, interval, { immediateCallback: true }) + ); + + callback.mockClear(); + interval.value = 20; + await nextTick(); + expect(callback).toHaveBeenCalledTimes(1); + }); + + it('pause/resume in scope', async () => { + const scope = effectScope(); + await scope.run(async () => { + await exec(useIntervalFn(callback, 50)); + }); + callback.mockClear(); + scope.stop(); + await vi.advanceTimersByTimeAsync(60); + expect(callback).toHaveBeenCalledTimes(0); + }); + + it('pause in callback', async () => { + const pausable = useIntervalFn( + () => { + callback(); + pausable.pause(); + }, + 50, + { immediateCallback: true, immediate: false } + ); + + pausable.resume(); + expect(pausable.isActive).toSatisfy(isRef); + expect((pausable.isActive as unknown as Ref).value).toBeFalsy(); + expect(callback).toHaveBeenCalledTimes(1); + + await vi.advanceTimersByTimeAsync(60); + expect(callback).toHaveBeenCalledTimes(1); + + pausable.resume(); + expect((pausable.isActive as unknown as Ref).value).toBeFalsy(); + expect(callback).toHaveBeenCalledTimes(2); + + await vi.advanceTimersByTimeAsync(60); + expect(callback).toHaveBeenCalledTimes(2); + }); + + it('cant work when interval is negative', async () => { + const { isActive } = useIntervalFn(callback, -1); + + expect((isActive as unknown as Ref).value).toBeFalsy(); + await vi.advanceTimersByTimeAsync(60); + expect(callback).toHaveBeenCalledTimes(0); + }); });