feat: hand capabilities into draft authoring

This commit is contained in:
lda
2026-08-09 08:47:03 +07:00 Verified
parent ef773dedb3
commit ee0b77125d
9 changed files with 718 additions and 19 deletions
@@ -1,7 +1,14 @@
import { cleanup, render, screen } from "@testing-library/react";
import { MemoryRouter } from "react-router-dom";
import userEvent from "@testing-library/user-event";
import { MemoryRouter, Route, Routes, useLocation } from "react-router-dom";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import type { DraftWorkspace } from "../domain/draft-workspace-models.js";
import { initialState } from "../../app/state.js";
import { useConsoleWorkspace } from "../context.js";
import {
createDraftAuthoringClient,
type DraftAuthoringClient,
} from "../domain/draft-authoring-client.js";
import type { DraftWorkspaceController } from "./useDraftWorkspace.js";
import { useDraftWorkspace } from "./useDraftWorkspace.js";
import { DraftIndexRoute } from "./DraftIndexRoute.js";
@@ -10,7 +17,17 @@ vi.mock("./useDraftWorkspace.js", () => ({
useDraftWorkspace: vi.fn(),
}));
vi.mock("../context.js", () => ({
useConsoleWorkspace: vi.fn(),
}));
vi.mock("../domain/draft-authoring-client.js", () => ({
createDraftAuthoringClient: vi.fn(),
}));
const mockedUseDraftWorkspace = vi.mocked(useDraftWorkspace);
const mockedUseConsoleWorkspace = vi.mocked(useConsoleWorkspace);
const mockedCreateDraftAuthoringClient = vi.mocked(createDraftAuthoringClient);
const workspace = (
workspaceId: string,
@@ -45,9 +62,33 @@ const controller = (
...overrides,
});
beforeEach(() => mockedUseDraftWorkspace.mockReturnValue(controller()));
const authoringClient: DraftAuthoringClient = {
createEmpty: vi.fn(),
createFromCapability: vi.fn(),
addCapabilityStep: vi.fn(),
updateCapabilityStep: vi.fn(),
setRoute: vi.fn(),
validate: vi.fn(),
};
beforeEach(() => {
mockedUseDraftWorkspace.mockReturnValue(controller());
mockedUseConsoleWorkspace.mockReturnValue({
connection: initialState(),
connectedTarget: "http://workflow.test/rpc",
recordEvidence: vi.fn(),
readExecutor: null,
writeExecutor: { run: vi.fn() },
});
mockedCreateDraftAuthoringClient.mockReturnValue(authoringClient);
});
afterEach(() => cleanup());
const DraftDestination = () => {
const location = useLocation();
return <p>Draft destination: {location.pathname}{location.search}</p>;
};
describe("DraftIndexRoute", () => {
it("shows the draft heading and a row link owned by each workspace id", () => {
mockedUseDraftWorkspace.mockReturnValue(
@@ -103,4 +144,31 @@ describe("DraftIndexRoute", () => {
expect(screen.getByText(message)).toBeInTheDocument();
});
it("creates a draft from the index and routes by the canonical workspace id", async () => {
const user = userEvent.setup();
const created = workspace("canonical-draft-id", { title: "Created draft" });
vi.mocked(authoringClient.createEmpty).mockResolvedValue(created);
render(
<MemoryRouter initialEntries={["/console/drafts"]}>
<Routes>
<Route path="/console/drafts" element={<DraftIndexRoute />} />
<Route path="/console/drafts/:workspaceId" element={<DraftDestination />} />
</Routes>
</MemoryRouter>,
);
await user.click(screen.getByRole("button", { name: "New draft" }));
await user.type(screen.getByRole("textbox", { name: "Workspace id" }), "requested-draft");
await user.type(screen.getByRole("textbox", { name: "Draft name" }), "report-workflow");
await user.type(screen.getByRole("textbox", { name: "Title" }), "Created draft");
await user.click(screen.getByRole("button", { name: "Create draft" }));
expect(authoringClient.createEmpty).toHaveBeenCalledWith({
workspaceId: "requested-draft",
name: "report-workflow",
title: "Created draft",
});
expect(await screen.findByText("Draft destination: /console/drafts/canonical-draft-id")).toBeInTheDocument();
});
});