Files
Recordly/electron/countdownController.test.ts
webadderall f007984ebc Fix editor previews, zoom controls and recording workflow
Preserve renderer state through mute and export transitions, gate hover previews on a composed frame, and align timeline bounds with authored zoom intervals. Improve settings, cursor and webcam controls, inline recording countdown, project recovery and safe library cleanup.
2026-11-06 18:05:14 +11:00

56 lines
2.2 KiB
TypeScript

import { afterEach, beforeEach, expect, it, vi } from "vitest";
import { createCountdownController } from "./countdownController";
beforeEach(() => vi.useFakeTimers());
afterEach(() => vi.useRealTimers());
it("emits 3, 2, 1 from the main-process timer and settles without a window", async () => {
const state = vi.fn();
const controller = createCountdownController(state);
const pending = controller.start(3);
expect(state).toHaveBeenLastCalledWith(3);
await vi.advanceTimersByTimeAsync(3000);
await expect(pending).resolves.toEqual({ success: true });
expect(state.mock.calls).toEqual([[3], [2], [1], [null]]);
expect(vi.getTimerCount()).toBe(0);
});
it("cancels immediately, releases the timer and allows another start", async () => {
const state = vi.fn();
const controller = createCountdownController(state);
const pending = controller.start(3);
controller.cancel();
await expect(pending).resolves.toEqual({ success: false, cancelled: true });
expect(state).toHaveBeenLastCalledWith(null);
expect(vi.getTimerCount()).toBe(0);
const next = controller.start(1);
await vi.advanceTimersByTimeAsync(1000);
await expect(next).resolves.toEqual({ success: true });
});
it("does not let a concurrent start replace the active recording countdown", async () => {
const state = vi.fn();
const controller = createCountdownController(state);
const pending = controller.start(2);
await expect(controller.start(3)).resolves.toMatchObject({ success: false });
await vi.advanceTimersByTimeAsync(2000);
await expect(pending).resolves.toEqual({ success: true });
expect(state.mock.calls).toEqual([[2], [1], [null]]);
});
it.each([-1, Number.NaN, Number.POSITIVE_INFINITY])("rejects invalid delay %s", async (delay) => {
const state = vi.fn();
await expect(createCountdownController(state).start(delay)).resolves.toMatchObject({
success: false,
});
expect(state).not.toHaveBeenCalled();
expect(vi.getTimerCount()).toBe(0);
});
it("settles zero delay immediately without adding a timer", async () => {
const state = vi.fn();
await expect(createCountdownController(state).start(0)).resolves.toEqual({ success: true });
expect(state.mock.calls).toEqual([[null]]);
expect(vi.getTimerCount()).toBe(0);
});