From 79fbe10688680ea2a293cab69e2ed0715f4d21ce Mon Sep 17 00:00:00 2001 From: Andrew Tatomyr Date: Fri, 14 Nov 2025 13:05:25 +0200 Subject: [PATCH] fix: make the once re-run on changing the key --- src/ls.test.ts | 1 - src/once.test.ts | 22 ++++++++++++---------- src/once.ts | 8 ++++---- src/purity.test.ts | 1 - src/purity.ts | 5 +++++ src/router.test.ts | 1 - test-utils.ts | 3 --- vitest.config.ts | 1 + 8 files changed, 22 insertions(+), 20 deletions(-) diff --git a/src/ls.test.ts b/src/ls.test.ts index 8611b1d..cd7a726 100644 --- a/src/ls.test.ts +++ b/src/ls.test.ts @@ -10,7 +10,6 @@ describe("ls", () => { }) afterEach(() => { - vi.restoreAllMocks() localStorage.clear() storage = null }) diff --git a/src/once.test.ts b/src/once.test.ts index 6f8cd83..fb69c6f 100644 --- a/src/once.test.ts +++ b/src/once.test.ts @@ -12,16 +12,6 @@ describe("once", () => { mockQuery = vi.fn() }) - afterEach(() => { - vi.restoreAllMocks() - }) - - it("should call the query function once", async () => { - once("123", mockQuery) - await delay() - expect(mockQuery).toHaveBeenCalledTimes(1) - }) - it("should only call the query function once with the same ID", async () => { Promise.all([ once("123", mockQuery), @@ -41,4 +31,16 @@ describe("once", () => { await delay() expect(mockQuery).toHaveBeenCalledTimes(3) }) + + it("should call the query function again if the key changes and then changes again", async () => { + once("123", mockQuery) + await delay() + expect(mockQuery).toHaveBeenCalledTimes(1) + once("234", mockQuery) + await delay() + expect(mockQuery).toHaveBeenCalledTimes(2) + once("123", mockQuery) + await delay() + expect(mockQuery).toHaveBeenCalledTimes(3) + }) }) diff --git a/src/once.ts b/src/once.ts index bf4c3e2..1e84276 100644 --- a/src/once.ts +++ b/src/once.ts @@ -1,8 +1,8 @@ export const makeOnce = () => { - const calls = new Set() - return (id: string | number, query: () => void | Promise) => { - if (!calls.has(id)) { - calls.add(id) + let latestCalledKey: string | number | undefined + return (key: string | number, query: () => void | Promise) => { + if (latestCalledKey !== key) { + latestCalledKey = key setTimeout(query) } } diff --git a/src/purity.test.ts b/src/purity.test.ts index 01a5ed8..bfbcc4f 100644 --- a/src/purity.test.ts +++ b/src/purity.test.ts @@ -17,7 +17,6 @@ describe("purity", () => { // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore app = undefined - vi.restoreAllMocks() }) describe("counter app", () => { diff --git a/src/purity.ts b/src/purity.ts index 7825100..c8c2500 100644 --- a/src/purity.ts +++ b/src/purity.ts @@ -116,6 +116,11 @@ export const init = >( * Forces html re-rendering with the current state */ function rerender() { + if (!rootComponent) { + throw new Error( + "Cannot rerender: app has not been mounted. Call mount() first." + ) + } const newNodesMap = rootComponent() console.warn("🌀") for (const [id, domNode] of domNodesMap) { diff --git a/src/router.test.ts b/src/router.test.ts index e1a1f63..1df7eb8 100644 --- a/src/router.test.ts +++ b/src/router.test.ts @@ -12,7 +12,6 @@ describe("router", () => { }) afterEach(() => { document.body.innerHTML = "" - vi.restoreAllMocks() }) it("switches between different views depending on the url state", async () => { const App = (): string => render` diff --git a/test-utils.ts b/test-utils.ts index 6922d81..402113c 100644 --- a/test-utils.ts +++ b/test-utils.ts @@ -43,9 +43,6 @@ export const setBeforeAndAfter = ({ beforeEach(() => { console.warn = vi.fn() }) - afterEach(() => { - vi.restoreAllMocks() - }) afterAll(() => { document.body.innerHTML = "" }) diff --git a/vitest.config.ts b/vitest.config.ts index 9a99d76..fa398d8 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -3,6 +3,7 @@ import {defineConfig} from "vitest/config" export default defineConfig({ test: { environment: "jsdom", + restoreMocks: true, coverage: { reporter: ["text", "json-summary", "json"], extension: [".ts"],