feat(maestro): offer structured spawn view
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
// @vitest-environment happy-dom
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
import { createSpawnForm, type SpawnFormHandle } from "./spawnForm.js";
|
||||
|
||||
function stubApi(): RequestInit[] {
|
||||
const sessionRequests: RequestInit[] = [];
|
||||
vi.stubGlobal(
|
||||
"fetch",
|
||||
vi.fn(async (input: RequestInfo | URL, init?: RequestInit) => {
|
||||
const url = String(input);
|
||||
if (url.includes("/api/sessions") && init?.method === "POST") {
|
||||
sessionRequests.push(init);
|
||||
return new Response(JSON.stringify({ id: "s1", command: "claude", cwd: "/srv/work" }), {
|
||||
status: 200,
|
||||
});
|
||||
}
|
||||
if (url.includes("/api/info")) {
|
||||
return new Response(
|
||||
JSON.stringify({ hostname: "h", version: "0", home_dir: "/home/user" }),
|
||||
{ status: 200 },
|
||||
);
|
||||
}
|
||||
if (url.includes("/api/names")) {
|
||||
return new Response(JSON.stringify({ names: ["amber-fox"] }), { status: 200 });
|
||||
}
|
||||
return new Response(JSON.stringify([]), { status: 200 });
|
||||
}),
|
||||
);
|
||||
return sessionRequests;
|
||||
}
|
||||
|
||||
describe("spawn form structured view", () => {
|
||||
let handle: SpawnFormHandle | null = null;
|
||||
|
||||
async function drain(): Promise<void> {
|
||||
for (let i = 0; i < 20; i++) await Promise.resolve();
|
||||
}
|
||||
|
||||
afterEach(async () => {
|
||||
handle?.destroy();
|
||||
handle = null;
|
||||
await drain();
|
||||
vi.unstubAllGlobals();
|
||||
});
|
||||
|
||||
it("is default-off and shown only for the resolved Claude Code command", async () => {
|
||||
stubApi();
|
||||
handle = createSpawnForm({ onSuccess() {} });
|
||||
document.body.appendChild(handle.el);
|
||||
await drain();
|
||||
|
||||
const wrap = handle.el.querySelector<HTMLElement>(".structured-view")!;
|
||||
const checkbox = wrap.querySelector<HTMLInputElement>("input")!;
|
||||
const disclosure = handle.el.querySelector<HTMLElement>(".wt-collapsible")!;
|
||||
expect(disclosure.hidden).toBe(true);
|
||||
handle.el.querySelector<HTMLButtonElement>(".wt-toggle")!.click();
|
||||
expect(disclosure.hidden).toBe(false);
|
||||
expect(wrap.hidden).toBe(false);
|
||||
expect(checkbox.checked).toBe(false);
|
||||
|
||||
handle.el.querySelector<HTMLButtonElement>('[data-id="opencode"]')!.click();
|
||||
expect(wrap.hidden).toBe(true);
|
||||
|
||||
handle.el.querySelector<HTMLButtonElement>('[data-id="claude"]')!.click();
|
||||
expect(wrap.hidden).toBe(false);
|
||||
});
|
||||
|
||||
it("clears a checked value when the command changes away from Claude Code", async () => {
|
||||
stubApi();
|
||||
handle = createSpawnForm({ onSuccess() {} });
|
||||
document.body.appendChild(handle.el);
|
||||
await drain();
|
||||
|
||||
const checkbox = handle.el.querySelector<HTMLInputElement>("input[name=structured_view]")!;
|
||||
checkbox.click();
|
||||
expect(checkbox.checked).toBe(true);
|
||||
|
||||
const custom = handle.el.querySelector<HTMLButtonElement>('[data-id="custom"]')!;
|
||||
custom.click();
|
||||
const command = handle.el.querySelector<HTMLInputElement>(".cmd-raw")!;
|
||||
command.value = "opencode";
|
||||
command.dispatchEvent(new Event("input"));
|
||||
|
||||
expect(checkbox.closest<HTMLElement>(".structured-view")!.hidden).toBe(true);
|
||||
expect(checkbox.checked).toBe(false);
|
||||
});
|
||||
|
||||
it("emits Structured in the submitted request when selected", async () => {
|
||||
const requests = stubApi();
|
||||
handle = createSpawnForm({
|
||||
seed: { cwd: "/srv/work", cwdRawVisible: true, worktreeEnabled: false },
|
||||
onSuccess() {},
|
||||
});
|
||||
document.body.appendChild(handle.el);
|
||||
await drain();
|
||||
|
||||
handle.el.querySelector<HTMLInputElement>("input[name=structured_view]")!.click();
|
||||
handle.el.requestSubmit();
|
||||
await drain();
|
||||
|
||||
expect(requests).toHaveLength(1);
|
||||
expect(JSON.parse(String(requests[0].body))).toMatchObject({
|
||||
command: "claude",
|
||||
view: "Structured",
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user