110 lines
5.0 KiB
JavaScript
110 lines
5.0 KiB
JavaScript
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
|
|
const mockGetAuthenticatedUser = vi.fn();
|
|
const mockCreateServerSupabaseClient = vi.fn();
|
|
|
|
vi.mock("@/lib/supabase/server.js", () => ({
|
|
getAuthenticatedUser: () => mockGetAuthenticatedUser(),
|
|
createServerSupabaseClient: () => mockCreateServerSupabaseClient(),
|
|
}));
|
|
|
|
function makeClient(result) {
|
|
const query = {
|
|
from: vi.fn(() => query),
|
|
upsert: vi.fn(() => query),
|
|
select: vi.fn(() => query),
|
|
eq: vi.fn(() => query),
|
|
maybeSingle: vi.fn(() => Promise.resolve(result)),
|
|
single: vi.fn(() => Promise.resolve(result)),
|
|
order: vi.fn(() => Promise.resolve(result)),
|
|
};
|
|
return { client: { schema: vi.fn(() => query) }, query };
|
|
}
|
|
|
|
describe("server investigation persistence", () => {
|
|
beforeEach(() => vi.clearAllMocks());
|
|
|
|
it("rejects unauthenticated persistence access", async () => {
|
|
mockGetAuthenticatedUser.mockResolvedValue(null);
|
|
const { saveInvestigation } = await import("@/lib/storage/server-investigation-persistence.js");
|
|
|
|
await expect(saveInvestigation({ id: "investigation-1" })).resolves.toBeNull();
|
|
expect(mockCreateServerSupabaseClient).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it("saves an unchanged snapshot with user identity derived on the server", async () => {
|
|
const snapshot = { id: "investigation-1", scenario: "A situation", user_id: "untrusted" };
|
|
const { client, query } = makeClient({ data: { snapshot }, error: null });
|
|
mockGetAuthenticatedUser.mockResolvedValue({ id: "trusted-user" });
|
|
mockCreateServerSupabaseClient.mockReturnValue(client);
|
|
const { saveInvestigation } = await import("@/lib/storage/server-investigation-persistence.js");
|
|
|
|
await expect(saveInvestigation(snapshot)).resolves.toBe(snapshot);
|
|
expect(client.schema).toHaveBeenCalledWith("confidence_engine");
|
|
expect(query.from).toHaveBeenCalledWith("investigations");
|
|
expect(query.upsert).toHaveBeenCalledWith(
|
|
{ id: "investigation-1", user_id: "trusted-user", snapshot },
|
|
{ onConflict: "id" },
|
|
);
|
|
});
|
|
|
|
it("loads the RLS-scoped stored snapshot", async () => {
|
|
const snapshot = { id: "investigation-1", findings: [] };
|
|
const { client, query } = makeClient({ data: { snapshot }, error: null });
|
|
mockGetAuthenticatedUser.mockResolvedValue({ id: "trusted-user" });
|
|
mockCreateServerSupabaseClient.mockReturnValue(client);
|
|
const { loadInvestigation } = await import("@/lib/storage/server-investigation-persistence.js");
|
|
|
|
await expect(loadInvestigation("investigation-1")).resolves.toBe(snapshot);
|
|
expect(client.schema).toHaveBeenCalledWith("confidence_engine");
|
|
expect(query.eq).toHaveBeenCalledWith("id", "investigation-1");
|
|
});
|
|
|
|
it("lists only RLS-visible persistence records", async () => {
|
|
const snapshot = {
|
|
scenario: "A situation",
|
|
updatedAt: "2026-09-08T00:30:00Z",
|
|
investigationRevision: 3,
|
|
investigationReport: { generatedFromRevision: 2 },
|
|
};
|
|
const { client, query } = makeClient({
|
|
data: [{ id: "investigation-1", snapshot, created_at: "2026-09-08T00:00:00Z", updated_at: "2026-09-08T01:00:00Z" }],
|
|
error: null,
|
|
});
|
|
mockGetAuthenticatedUser.mockResolvedValue({ id: "trusted-user" });
|
|
mockCreateServerSupabaseClient.mockReturnValue(client);
|
|
const { listInvestigations } = await import("@/lib/storage/server-investigation-persistence.js");
|
|
|
|
await expect(listInvestigations()).resolves.toEqual([{
|
|
id: "investigation-1",
|
|
scenario: "A situation",
|
|
updatedAt: "2026-09-08T00:30:00Z",
|
|
investigationRevision: 3,
|
|
reportExists: true,
|
|
reportGeneratedFromRevision: 2,
|
|
}]);
|
|
expect(client.schema).toHaveBeenCalledWith("confidence_engine");
|
|
expect(query.select).toHaveBeenCalledWith("id, snapshot, created_at, updated_at");
|
|
expect(query.order).toHaveBeenCalledWith("updated_at", { ascending: false });
|
|
});
|
|
|
|
it("restarts an owned snapshot through the server path using the established transformation", async () => {
|
|
const snapshot = {
|
|
id: "investigation-1", scenario: "A situation", situationGraph: {}, selectedQuestion: "Question",
|
|
summary: "Summary", focusedContributions: [{}], findings: [{}], investigationReport: {}, investigationRevision: 4,
|
|
};
|
|
const { client, query } = makeClient({ data: { snapshot }, error: null });
|
|
mockGetAuthenticatedUser.mockResolvedValue({ id: "trusted-user" });
|
|
mockCreateServerSupabaseClient.mockReturnValue(client);
|
|
const { restartInvestigation } = await import("@/lib/storage/server-investigation-persistence.js");
|
|
|
|
await restartInvestigation("investigation-1");
|
|
|
|
expect(query.upsert).toHaveBeenCalledWith(expect.objectContaining({
|
|
id: "investigation-1", user_id: "trusted-user", snapshot: expect.objectContaining({
|
|
id: "investigation-1", scenario: "A situation", situationGraph: null, selectedQuestion: null,
|
|
summary: null, focusedContributions: [], findings: [], investigationReport: null, investigationRevision: 0,
|
|
}),
|
|
}), { onConflict: "id" });
|
|
});
|
|
}); |