91 lines
2.7 KiB
TypeScript
91 lines
2.7 KiB
TypeScript
import { QueryClient } from "@tanstack/react-query";
|
|
import { describe, expect, it } from "vitest";
|
|
|
|
import { createOptimisticLayerRuntime } from "../../src/presentation/adapters/query/optimistic-layer-runtime.ts";
|
|
import { createRuntimeIdentityRegistry } from "../../src/contracts/query-keys.ts";
|
|
|
|
function scope() {
|
|
let current = true;
|
|
const lifetime = new AbortController();
|
|
return {
|
|
snapshot: {
|
|
generation: 1,
|
|
fingerprint: "scope-token-00000001",
|
|
identities: createRuntimeIdentityRegistry({
|
|
tokenFactory: () => crypto.randomUUID(),
|
|
}),
|
|
signal: lifetime.signal,
|
|
isCurrent: () => current,
|
|
},
|
|
expire: () => {
|
|
current = false;
|
|
lifetime.abort();
|
|
},
|
|
};
|
|
}
|
|
|
|
describe("revision-safe optimistic layer runtime", () => {
|
|
it("removes only the failed layer when commands settle out of order", () => {
|
|
const client = new QueryClient();
|
|
const key = ["query", "resources"];
|
|
client.setQueryData(key, ["base"]);
|
|
const selectedScope = scope();
|
|
const runtime = createOptimisticLayerRuntime(client);
|
|
const append = (previous: unknown, input: string) => [
|
|
...(previous as string[]),
|
|
input,
|
|
];
|
|
const first = runtime.begin(
|
|
key,
|
|
"first",
|
|
append,
|
|
selectedScope.snapshot,
|
|
);
|
|
const second = runtime.begin(
|
|
key,
|
|
"second",
|
|
append,
|
|
selectedScope.snapshot,
|
|
);
|
|
expect(client.getQueryData(key)).toEqual(["base", "first", "second"]);
|
|
|
|
second?.commit();
|
|
first?.rollback();
|
|
expect(client.getQueryData(key)).toEqual(["base", "second"]);
|
|
});
|
|
|
|
it("reapplies pending layers over an authoritative external cache update", () => {
|
|
const client = new QueryClient();
|
|
const key = ["query", "resources"];
|
|
client.setQueryData(key, ["base"]);
|
|
const selectedScope = scope();
|
|
const runtime = createOptimisticLayerRuntime(client);
|
|
runtime.begin(
|
|
key,
|
|
"pending",
|
|
(previous, input) => [...(previous as string[]), input],
|
|
selectedScope.snapshot,
|
|
);
|
|
|
|
client.setQueryData(key, ["server"]);
|
|
expect(client.getQueryData(key)).toEqual(["server", "pending"]);
|
|
});
|
|
|
|
it("removes scoped data instead of restoring it after scope expiry", () => {
|
|
const client = new QueryClient();
|
|
const key = ["query", "resources"];
|
|
client.setQueryData(key, ["base"]);
|
|
const selectedScope = scope();
|
|
const runtime = createOptimisticLayerRuntime(client);
|
|
const layer = runtime.begin(
|
|
key,
|
|
"pending",
|
|
(previous, input) => [...(previous as string[]), input],
|
|
selectedScope.snapshot,
|
|
);
|
|
selectedScope.expire();
|
|
layer?.rollback();
|
|
expect(client.getQueryData(key)).toBeUndefined();
|
|
});
|
|
});
|