Files
PaperClipAI/tests/runner-e2e/chat-stories.test.ts
T
2026-09-21 14:17:25 -05:00

52 lines
3.5 KiB
TypeScript

import { describe, expect, it } from "vitest";
import { assertInterruptedChat } from "./chat-stories.js";
import { runnerMatrix } from "./catalog.js";
import { buildRunnerE2EProcessEnvironment } from "./harness-env.js";
const run = { id: "run", companyId: "company", agentId: "agent", status: "succeeded", runtimeMode: "native", contextSnapshot: { issueId: "chat" } };
const valid = {
first: "Read the brief", followup: "Change the launch day", reference: "BRIEF123", marker: "UPDATED123", issueId: "chat",
boundaryRun: { ...run, status: "running" }, activeAtFollowup: { ...run, status: "running" },
comments: [{ id: "first", body: "Read the brief" }, { id: "followup", body: "Change the launch day" },
{ id: "answer", authorAgentId: "agent", body: "BRIEF123 UPDATED123" }],
runs: [run], revisedPlan: JSON.stringify({ launchDay: "Friday", reference: "BRIEF123", revision: "UPDATED123" }),
};
describe("active chat follow-up oracle", () => {
it("accepts either steering or one queued successor, with the saved correction", () => {
expect(() => assertInterruptedChat(valid)).not.toThrow();
expect(() => assertInterruptedChat({ ...valid, runs: [run, { ...run, id: "successor" }] })).not.toThrow();
});
it("rejects follow-ups sent after the active boundary", () => {
expect(() => assertInterruptedChat({ ...valid, boundaryRun: run })).toThrow();
expect(() => assertInterruptedChat({ ...valid, activeAtFollowup: run })).toThrow();
expect(() => assertInterruptedChat({ ...valid, activeAtFollowup: { ...valid.activeAtFollowup, id: "other" } })).toThrow();
});
it("rejects lost or duplicated input, missing file evidence, and stale plans", () => {
expect(() => assertInterruptedChat({ ...valid, comments: valid.comments.filter(c => c.id !== "followup") })).toThrow();
expect(() => assertInterruptedChat({ ...valid, comments: [...valid.comments, { id: "duplicate", body: valid.followup }] })).toThrow();
expect(() => assertInterruptedChat({ ...valid, comments: [...valid.comments.slice(0, 2), { id: "answer", authorAgentId: "agent", body: "UPDATED123" }] })).toThrow();
expect(() => assertInterruptedChat({ ...valid, revisedPlan: valid.revisedPlan.replace("Friday", "Monday") })).toThrow();
expect(() => assertInterruptedChat({ ...valid, revisedPlan: "The updated plan is saved." })).toThrow();
});
it("rejects failed, unfinished, duplicated, or unrelated execution", () => {
for (const status of ["running", "queued", "failed", "cancelled"])
expect(() => assertInterruptedChat({ ...valid, runs: [{ ...run, status }] })).toThrow();
expect(() => assertInterruptedChat({ ...valid, runs: [] })).toThrow();
expect(() => assertInterruptedChat({ ...valid, runs: [run, run, run] })).toThrow();
expect(() => assertInterruptedChat({ ...valid, runs: [run, run] })).toThrow();
expect(() => assertInterruptedChat({ ...valid, runs: [{ ...run, id: "other" }] })).toThrow();
expect(() => assertInterruptedChat({ ...valid, runs: [{ ...run, contextSnapshot: { issueId: "other" } }] })).toThrow();
});
it("keeps setup and interruption stories native, local, opt-in, and outside API-tool overrides", () => {
const cells = runnerMatrix.filter(cell => cell.suite.id === "agent-chat-stories");
expect(cells).toHaveLength(6);
for (const cell of cells) {
expect(cell.suite.manualOnly).toBe(true);
expect(cell.profile.generation).toBe("native");
expect(cell.environment.id).toBe("local");
expect(buildRunnerE2EProcessEnvironment({}, [cell]).PAPERCLIP_RUNNER_API_TOOLS_ENABLED).toBeUndefined();
}
});
});