// TRACES: UR-034 | DR-038 | UT-207 import { describe, it, expect, vi, beforeEach, afterEach } from "vitest"; import { createRotationTimer } from "./heroRotation"; describe("hero banner rotation timer", () => { beforeEach(() => vi.useFakeTimers()); afterEach(() => vi.useRealTimers()); it("advances once per interval while running", () => { const onElapse = vi.fn(); const timer = createRotationTimer(6000, onElapse); timer.restart(); vi.advanceTimersByTime(6000); expect(onElapse).toHaveBeenCalledTimes(1); vi.advanceTimersByTime(6000); expect(onElapse).toHaveBeenCalledTimes(2); timer.stop(); }); it("does nothing until started", () => { const onElapse = vi.fn(); createRotationTimer(6000, onElapse); vi.advanceTimersByTime(60_000); expect(onElapse).not.toHaveBeenCalled(); }); // The bug: a manual swipe/click left the interval running, so the banner // rotated again almost immediately instead of waiting a full interval. it("restarts the countdown from now, not from the last auto-advance", () => { const onElapse = vi.fn(); const timer = createRotationTimer(6000, onElapse); timer.restart(); // 5.5s in the user swipes — the timer must restart from that moment. vi.advanceTimersByTime(5500); timer.restart(); // The remaining 500ms of the old countdown must NOT fire. vi.advanceTimersByTime(500); expect(onElapse).not.toHaveBeenCalled(); // A full interval after the swipe, it advances. vi.advanceTimersByTime(5500); expect(onElapse).toHaveBeenCalledTimes(1); timer.stop(); }); it("does not stack timers when restarted repeatedly", () => { const onElapse = vi.fn(); const timer = createRotationTimer(1000, onElapse); timer.restart(); timer.restart(); timer.restart(); vi.advanceTimersByTime(1000); expect(onElapse).toHaveBeenCalledTimes(1); timer.stop(); }); it("stops firing after stop()", () => { const onElapse = vi.fn(); const timer = createRotationTimer(1000, onElapse); timer.restart(); timer.stop(); vi.advanceTimersByTime(10_000); expect(onElapse).not.toHaveBeenCalled(); }); it("reports whether it is running", () => { const timer = createRotationTimer(1000, () => {}); expect(timer.isRunning()).toBe(false); timer.restart(); expect(timer.isRunning()).toBe(true); timer.stop(); expect(timer.isRunning()).toBe(false); }); });