Files
clean-architecture-frontend…/tests/unit/query-cache.test.js
T

56 lines
2.0 KiB
JavaScript

import { QueryClient } from "@tanstack/react-query";
import { describe, expect, it, vi } from "vitest";
import {
createQueryCacheAdapter,
createQueryClient,
} from "../../src/adapters/query-cache/tanstack-query-cache.js";
import { queryKeys } from "../../src/contracts/query-keys.js";
describe("query key registry", () => {
it("canonicalizes filter order into the same stable key", () => {
expect(queryKeys.resource.list({ page: 1, status: "open" })).toEqual(
queryKeys.resource.list({ status: "open", page: 1 }),
);
});
it("contains no raw URL or token material", () => {
expect(JSON.stringify(queryKeys.resource.detail("resource-1"))).toBe(
'["resource",1,"detail","resource-1"]',
);
});
});
describe("TanStack QueryCachePort adapter", () => {
it("reads, writes, and invalidates only the declared namespace", async () => {
const client = createQueryClient();
const adapter = createQueryCacheAdapter(client);
const listKey = queryKeys.resource.list({ page: 1 });
const otherKey = ["other", 1];
expect(adapter.write(listKey, [{ id: "resource-1" }])).toEqual({ ok: true });
expect(adapter.write(otherKey, "preserved")).toEqual({ ok: true });
expect(adapter.read(listKey)).toMatchObject({
ok: true,
value: [{ id: "resource-1" }],
});
await adapter.invalidate(queryKeys.resource.all());
expect(client.getQueryState(listKey)?.isInvalidated).toBe(true);
expect(client.getQueryState(otherKey)?.isInvalidated).toBe(false);
});
it("normalizes adapter exceptions without raw key data", async () => {
const client = new QueryClient();
vi.spyOn(client, "invalidateQueries").mockRejectedValue(new Error("secret-key"));
const adapter = createQueryCacheAdapter(client);
const result = await adapter.invalidate(["resource", "sensitive-filter"]);
expect(result).toMatchObject({
ok: false,
error: { kind: "QUERY_CACHE_FAILURE" },
});
expect(JSON.stringify(result)).not.toContain("sensitive-filter");
});
});