Files
HiveGrid-Wireframes/hivegrid-cloud/apps/web/app/utils/db/tenant-cache.server.test.ts
T

68 lines
2.4 KiB
TypeScript

import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
vi.mock("~/utils/cache.server", () => {
const map = new Map<string, unknown>();
return {
cache: map,
cachified: vi.fn(),
clearCacheKey: vi.fn((key: string) => map.delete(key)),
clearCacheKeyPrefix: vi.fn((prefix: string) => {
for (const k of map.keys()) if (k.startsWith(prefix)) map.delete(k);
}),
__test_map: map,
};
});
vi.mock("~/shared-store.server", async () => {
const { MemoryAdapter, createSharedStore } = await import("@toolctrl/shared-store");
const adapter = new MemoryAdapter();
const store = createSharedStore({ namespace: "web-test", adapter });
return {
getSharedStore: () => store,
__setSharedStoreFactoryForTests: vi.fn(),
__resetSharedStoreForTests: vi.fn(),
};
});
import {
publishTenantInvalidation,
subscribeTenantCache,
__resetTenantCacheForTests,
} from "./tenant-cache.server";
import * as cacheServer from "~/utils/cache.server";
beforeEach(() => {
__resetTenantCacheForTests();
(cacheServer as unknown as { __test_map: Map<string, unknown> }).__test_map.clear();
vi.mocked(cacheServer.clearCacheKey).mockClear();
vi.mocked(cacheServer.clearCacheKeyPrefix).mockClear();
delete process.env.CACHE_INVALIDATION_ENABLED;
});
afterEach(() => {
__resetTenantCacheForTests();
});
describe("tenant cache (two-tier)", () => {
it("publishTenantInvalidation clears local cachified keys for tenant id", async () => {
await publishTenantInvalidation("tenant-7");
expect(vi.mocked(cacheServer.clearCacheKey)).toHaveBeenCalledWith("tenant:tenant-7");
expect(vi.mocked(cacheServer.clearCacheKey)).toHaveBeenCalledWith("tenantSimple:tenant-7");
expect(vi.mocked(cacheServer.clearCacheKey)).toHaveBeenCalledWith("tenantIdOrSlug:tenant-7");
});
it("remote invalidation purges all 3 cachified prefixes for the affected tenant", async () => {
await subscribeTenantCache();
await publishTenantInvalidation("tenant-9");
await new Promise((r) => setTimeout(r, 10));
// local + remote both fire clearCacheKey — assert tenant-9 keys were dropped
expect(vi.mocked(cacheServer.clearCacheKey).mock.calls.filter((c) => c[0] === "tenant:tenant-9").length).toBeGreaterThanOrEqual(1);
});
it("subscribeTenantCache is idempotent", async () => {
const a = await subscribeTenantCache();
const b = await subscribeTenantCache();
expect(a).toBe(b);
});
});