test: cover presentation route rehearsal contracts
This commit is contained in:
@@ -73,6 +73,62 @@ afterEach(() => {
|
||||
});
|
||||
|
||||
describe("PresentationRoute", () => {
|
||||
const directHashRoutes = [
|
||||
{ hash: "#scene/thesis/title", heading: "Design and Implementation of lda.chat", hasDemoChrome: false },
|
||||
{ hash: "#scene/architecture/client", heading: "Architecture Zoom", hasDemoChrome: false },
|
||||
{ hash: "#scene/authoring/diagnose", heading: "Author, Validate, Repair", hasDemoChrome: false },
|
||||
{ hash: "#scene/prepared-lifecycle/discover", heading: "Prepared Workflow Lifecycle", hasDemoChrome: true },
|
||||
{ hash: "#scene/run-from-deployment/graph", heading: "Run From Deployment", hasDemoChrome: true },
|
||||
{ hash: "#scene/typed-human-boundary/approval", heading: "Typed Human Boundary", hasDemoChrome: true },
|
||||
{ hash: "#scene/resume-output-evidence/trace", heading: "Resume, Output, Evidence", hasDemoChrome: true },
|
||||
{ hash: "#scene/evaluation/cohort", heading: "Evaluation", hasDemoChrome: false },
|
||||
{ hash: "#scene/conclusion/questions", heading: "Thesis contribution", hasDemoChrome: false },
|
||||
] as const;
|
||||
|
||||
it.each(directHashRoutes)(
|
||||
"renders $hash with heading $heading and expected demo chrome ownership",
|
||||
async ({ hash, heading, hasDemoChrome }) => {
|
||||
window.location.hash = hash;
|
||||
const { PresentationRoute } = await import("./PresentationRoute.js");
|
||||
render(<PresentationRoute />);
|
||||
|
||||
expect(await screen.findByRole("heading", { name: heading })).toBeInTheDocument();
|
||||
const demoChrome = screen.queryByTestId("presentation-demo-rail");
|
||||
expect(demoChrome !== null).toBe(hasDemoChrome);
|
||||
},
|
||||
);
|
||||
|
||||
it.each([
|
||||
"#scene/thesis/title",
|
||||
"#scene/problem/direct-actions",
|
||||
"#scene/architecture/client",
|
||||
"#scene/evaluation/cohort",
|
||||
"#scene/conclusion/questions",
|
||||
])("does not leak live target or prepared-run chrome onto %s", async (hash) => {
|
||||
window.location.hash = hash;
|
||||
const { PresentationRoute } = await import("./PresentationRoute.js");
|
||||
render(<PresentationRoute />);
|
||||
|
||||
expect(await screen.findByRole("main", { name: /lda\.chat presentation/i })).toBeInTheDocument();
|
||||
expect(screen.queryByLabelText("presentation evidence mode")).not.toBeInTheDocument();
|
||||
expect(screen.queryByRole("button", { name: "Run prepared workflow" })).not.toBeInTheDocument();
|
||||
expect(screen.queryByRole("button", { name: "Play replay walkthrough" })).not.toBeInTheDocument();
|
||||
expect(screen.queryByRole("button", { name: "Retry live service" })).not.toBeInTheDocument();
|
||||
expect(screen.queryByRole("region", { name: "prepared workflow launch" })).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("keeps prepared lifecycle chat and footer ownership without duplicating a run action", async () => {
|
||||
window.location.hash = "#scene/prepared-lifecycle/discover";
|
||||
const { PresentationRoute } = await import("./PresentationRoute.js");
|
||||
render(<PresentationRoute />);
|
||||
|
||||
expect(await screen.findByRole("complementary", { name: /prepared authoring assistant/i })).toBeInTheDocument();
|
||||
const footer = screen.getByRole("contentinfo", { name: /presentation footer/i });
|
||||
expect(within(footer).getByRole("button", { name: /run prepared workflow|play replay walkthrough/i })).toBeInTheDocument();
|
||||
expect(screen.getAllByRole("button", { name: /run prepared workflow|play replay walkthrough/i })).toHaveLength(1);
|
||||
expect(screen.queryByRole("region", { name: "prepared workflow launch" })).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("renders the presentation stage entry point", { timeout: 15000 }, async () => {
|
||||
const { PresentationRoute } = await import("./PresentationRoute.js");
|
||||
render(<PresentationRoute />);
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { mainScenes } from "./storyboard.js";
|
||||
|
||||
const expectedBeats = {
|
||||
thesis: ["title", "substrate"],
|
||||
problem: ["direct-actions", "missing-contracts"],
|
||||
positioning: ["landscape", "lda-position"],
|
||||
"planner-runtime": ["planner", "runtime", "boundary"],
|
||||
lifecycle: ["draft", "artifact", "deployment", "run"],
|
||||
architecture: ["client", "api", "runtime", "node-use"],
|
||||
authoring: ["discover", "author", "diagnose", "repair"],
|
||||
"agent-handoff": ["request"],
|
||||
"prepared-lifecycle": ["discover", "draft", "validate", "artifact", "deployment"],
|
||||
"run-from-deployment": ["input", "operation", "graph"],
|
||||
"typed-human-boundary": ["interrupt", "approval"],
|
||||
"resume-output-evidence": ["resume", "output", "trace"],
|
||||
evaluation: ["cohort", "validity", "findings"],
|
||||
conclusion: ["limits", "future", "conclusion", "questions"],
|
||||
} as const;
|
||||
|
||||
describe("presentation rehearsal storyboard", () => {
|
||||
it("keeps every scene count and canonical beat id aligned with the rehearsal", () => {
|
||||
for (const [sceneId, beatIds] of Object.entries(expectedBeats)) {
|
||||
const scene = mainScenes.find((candidate) => candidate.id === sceneId);
|
||||
expect(scene, `missing rehearsal scene ${sceneId}`).toBeDefined();
|
||||
if (!scene) continue;
|
||||
|
||||
expect(scene.beats, `scene ${sceneId} has the wrong beat count`).toHaveLength(beatIds.length);
|
||||
for (const beatId of beatIds) {
|
||||
expect(
|
||||
scene.beats.map((beat) => beat.id),
|
||||
`scene ${sceneId} is missing beat ${beatId}`,
|
||||
).toContain(beatId);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user