feat(confidence-engine): v0.60f allocate investigation identity on create
Replace Portfolio's static "+ Create new investigation" link (href:
/investigations/case-1) with a <button> that allocates an opaque
application-owned durable ID via crypto.randomUUID() and navigates
via router.push to /investigations/{id} without persisting any empty
Investigation.
INVESTIGATION_ID constant retained only for card links (Continue
investigation / View report) — not migrated in this increment.
Test: deterministic Create New activation test verifies UUID allocation,
navigation to generated ID route, and zero saveInvestigation calls.
This commit is contained in:
@@ -3,10 +3,24 @@ import React from "react";
|
||||
import { render, screen, fireEvent, within } from "@testing-library/react";
|
||||
import "@testing-library/jest-dom";
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Mock next/navigation — file-level. Uses shared mutable `pushRef`.
|
||||
// vi.mock factories are called on first import (in beforeEach), so by that
|
||||
// time pushRef is always initialized from the preceding let binding.
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
let pushRef = { push: () => {} };
|
||||
|
||||
vi.mock("next/navigation", () => ({
|
||||
useRouter: () => ({ push: () => {} }),
|
||||
useRouter: () => pushRef,
|
||||
}));
|
||||
|
||||
let cryptoRandomUUID = vi.fn();
|
||||
Object.defineProperty(global, "crypto", {
|
||||
value: { randomUUID: cryptoRandomUUID },
|
||||
writable: true,
|
||||
});
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Mock investigation-storage — shared for entire test file
|
||||
// (vi.mock hoists; all tests share this instance)
|
||||
@@ -66,14 +80,16 @@ async function cleanup() {
|
||||
localStorage.removeItem("confidence-engine-investigation");
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Portfolio page — pre-confirmation semantics (v0.55/v0.56)
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
describe("Portfolio page (pre-confirmation v0.55/v0.56)", () => {
|
||||
let Portfolio;
|
||||
|
||||
beforeEach(async () => {
|
||||
pushRef.push = vi.fn();
|
||||
cryptoRandomUUID.mockClear();
|
||||
Object.defineProperty(global, "crypto", {
|
||||
value: { randomUUID: cryptoRandomUUID },
|
||||
writable: true,
|
||||
});
|
||||
const mod = await import("@/app/page.jsx");
|
||||
Portfolio = mod.default;
|
||||
});
|
||||
@@ -171,6 +187,31 @@ describe("Portfolio page (pre-confirmation v0.55/v0.56)", () => {
|
||||
expect(await screen.findByText(/View report/i)).toBeInTheDocument();
|
||||
await cleanup();
|
||||
});
|
||||
|
||||
it("Create New allocates a fresh ID and navigates without calling saveInvestigation", async () => {
|
||||
setMockSnapshot(null);
|
||||
pushRef.push = vi.spyOn(pushRef, "push");
|
||||
cryptoRandomUUID.mockReturnValue(
|
||||
"11111111-2222-4333-8444-555555555555",
|
||||
);
|
||||
Object.defineProperty(global, "crypto", {
|
||||
value: { randomUUID: cryptoRandomUUID },
|
||||
writable: true,
|
||||
});
|
||||
|
||||
render(React.createElement(Portfolio));
|
||||
|
||||
const createLink = await screen.findByRole("button", {
|
||||
name: /Create new investigation/i,
|
||||
});
|
||||
fireEvent.click(createLink);
|
||||
|
||||
expect(cryptoRandomUUID).toHaveBeenCalledTimes(1);
|
||||
expect(pushRef.push).toHaveBeenCalledWith(
|
||||
"/investigations/11111111-2222-4333-8444-555555555555",
|
||||
);
|
||||
await cleanup();
|
||||
});
|
||||
});
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user