|
1 | 1 | import "fake-indexeddb/auto"; |
2 | 2 | import { describe, it, expect, vi, beforeEach, afterEach } from "vitest"; |
3 | | -import { createRoot } from "solid-js"; |
| 3 | +import { createRoot, createSignal } from "solid-js"; |
4 | 4 | import { createPollCoordinator, disableNotifGate, resetPollState, type DashboardData } from "../../src/app/services/poll"; |
5 | 5 |
|
6 | 6 | // Mock pushError so we can spy on it |
@@ -280,40 +280,35 @@ describe("createPollCoordinator", () => { |
280 | 280 | }); |
281 | 281 |
|
282 | 282 | it("config change (interval change) restarts the interval", async () => { |
| 283 | + const randomSpy = vi.spyOn(Math, "random").mockReturnValue(0.5); // jitter = 0 |
283 | 284 | const fetchAll = makeFetchAll(); |
284 | | - let intervalSec = 300; |
285 | 285 |
|
286 | 286 | await createRoot(async (dispose) => { |
287 | | - // Use a signal-based getter to simulate reactive config |
288 | | - const [getInterval, setGetInterval] = (() => { |
289 | | - let fn = () => intervalSec; |
290 | | - return [ |
291 | | - () => fn(), |
292 | | - (newFn: () => number) => { |
293 | | - fn = newFn; |
294 | | - }, |
295 | | - ] as const; |
296 | | - })(); |
297 | | - |
298 | | - createPollCoordinator(getInterval, fetchAll); |
| 287 | + const [interval, setInterval] = createSignal(300); |
| 288 | + |
| 289 | + createPollCoordinator(interval, fetchAll); |
299 | 290 | await Promise.resolve(); // initial fetch |
300 | 291 |
|
301 | | - // Simulate config change to shorter interval by providing a new accessor |
302 | | - // In practice SolidJS createEffect re-runs when reactive dependencies change. |
303 | | - // Here we verify that calling with interval=60 fires within 90s. |
304 | | - intervalSec = 60; |
305 | | - void setGetInterval; // suppress unused warning |
| 292 | + const callsAfterInit = fetchAll.mock.calls.length; |
306 | 293 |
|
| 294 | + // At 300s interval, 90s should NOT fire |
307 | 295 | vi.advanceTimersByTime(90_000); |
308 | 296 | await Promise.resolve(); |
| 297 | + expect(fetchAll.mock.calls.length).toBe(callsAfterInit); |
| 298 | + |
| 299 | + // Change interval to 60s — createEffect re-fires, timer restarts |
| 300 | + setInterval(60); |
| 301 | + await Promise.resolve(); // let effect run |
| 302 | + |
| 303 | + // Advance 61s — new 60s interval should fire |
| 304 | + vi.advanceTimersByTime(61_000); |
| 305 | + await Promise.resolve(); |
| 306 | + expect(fetchAll.mock.calls.length).toBeGreaterThan(callsAfterInit); |
309 | 307 |
|
310 | | - // At 300s interval, 90s would not fire. But with 60s interval restart, |
311 | | - // it should fire at least once more. Since the internal createEffect |
312 | | - // is not re-triggered (intervalSec is not a signal), we only verify |
313 | | - // that the original timer was set and would eventually fire. |
314 | | - // The key test is just that manualRefresh + timer work correctly. |
315 | 308 | dispose(); |
316 | 309 | }); |
| 310 | + |
| 311 | + randomSpy.mockRestore(); |
317 | 312 | }); |
318 | 313 |
|
319 | 314 | it("interval=0 disables auto-refresh (no setInterval)", async () => { |
|
0 commit comments