feat(confidence-engine): v0.60c identity-aware investigation storage
- loadInvestigation(id) selects by durable ID when provided, null for unknown - saveInvestigation(snapshot, id) persists under provider-chosen key derived from id - clearInvestigation(id) removes specific investigation by identity when provided - localStorage representation: confidence-engine-investigation:<durable-id> - Backward-compatible singleton path preserved for existing unmigrated callers - 6 new targeted tests proving two independently addressable Investigations
This commit is contained in:
@@ -226,3 +226,110 @@ describe("investigation-storage provider", () => {
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
// ── v0.60c — identity-aware multi-investigation persistence ────────────
|
||||
|
||||
describe("investigation-storage v0.60c identity-aware", () => {
|
||||
|
||||
function newId() {
|
||||
return `inv-${Math.random().toString(36).slice(2, 9)}`;
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
globalThis.window.localStorage.clear();
|
||||
});
|
||||
|
||||
// ── A: saveInvestigation(A) persists A under A.id ───────────────
|
||||
|
||||
it("save with id persists under that id key", async () => {
|
||||
const { load, save } = await getModule();
|
||||
const idA = newId();
|
||||
const snapA = makeSnapshot({ id: idA, title: "Alpha" });
|
||||
|
||||
save(snapA, idA);
|
||||
|
||||
const loaded = load(idA);
|
||||
expect(loaded).not.toBeNull();
|
||||
expect(loaded.id).toBe(idA);
|
||||
expect(loaded.title).toBe("Alpha");
|
||||
});
|
||||
|
||||
// ── B: saveInvestigation(B) persists B independently under B.id ──
|
||||
|
||||
it("save two investigations with different ids are independent", async () => {
|
||||
const { load, save } = await getModule();
|
||||
const idA = newId();
|
||||
const idB = newId();
|
||||
const snapA = makeSnapshot({ id: idA, title: "Alpha" });
|
||||
const snapB = makeSnapshot({ id: idB, title: "Beta" });
|
||||
|
||||
save(snapA, idA);
|
||||
save(snapB, idB);
|
||||
|
||||
// A survives B save
|
||||
const loadedA = load(idA);
|
||||
expect(loadedA).not.toBeNull();
|
||||
expect(loadedA.id).toBe(idA);
|
||||
expect(loadedA.title).toBe("Alpha");
|
||||
});
|
||||
|
||||
// ── A loads by A.id ──────────────────────────────────────────────
|
||||
|
||||
it("loadInvestigation(A.id) returns A", async () => {
|
||||
const { load, save } = await getModule();
|
||||
const idA = newId();
|
||||
const snapA = makeSnapshot({ id: idA, title: "Alpha" });
|
||||
save(snapA, idA);
|
||||
|
||||
const loaded = load(idA);
|
||||
expect(loaded).not.toBeNull();
|
||||
expect(loaded.id).toBe(idA);
|
||||
expect(loaded.title).toBe("Alpha");
|
||||
});
|
||||
|
||||
// ── B loads by B.id ──────────────────────────────────────────────
|
||||
|
||||
it("loadInvestigation(B.id) returns B", async () => {
|
||||
const { load, save } = await getModule();
|
||||
const idA = newId();
|
||||
const idB = newId();
|
||||
const snapA = makeSnapshot({ id: idA, title: "Alpha" });
|
||||
const snapB = makeSnapshot({ id: idB, title: "Beta" });
|
||||
|
||||
save(snapA, idA);
|
||||
save(snapB, idB);
|
||||
|
||||
const loaded = load(idB);
|
||||
expect(loaded).not.toBeNull();
|
||||
expect(loaded.id).toBe(idB);
|
||||
expect(loaded.title).toBe("Beta");
|
||||
});
|
||||
|
||||
// ── unknown ID returns null ──────────────────────────────────────
|
||||
|
||||
it("loadInvestigation(unknownId) returns null", async () => {
|
||||
const { load } = await getModule();
|
||||
const loaded = load("non-existent-id-xyz");
|
||||
expect(loaded).toBeNull();
|
||||
});
|
||||
|
||||
// ── save does not invent or change the supplied ID ───────────────
|
||||
|
||||
it("saveInvestigation does not invent or replace the supplied id", async () => {
|
||||
const { save } = await getModule();
|
||||
const originalId = `inv-unique-77`;
|
||||
const snapA = makeSnapshot({ id: originalId, title: "Alpha" });
|
||||
|
||||
save(snapA, originalId);
|
||||
|
||||
// Verify the persisted record still carries exactly the supplied id
|
||||
// (the deep clone should not have mutated it)
|
||||
const raw = globalThis.window.localStorage.getItem(
|
||||
`confidence-engine-investigation:${originalId}`
|
||||
);
|
||||
expect(raw).not.toBeNull();
|
||||
const parsed = JSON.parse(raw);
|
||||
expect(parsed.id).toBe(originalId);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user