109 lines
3.6 KiB
TypeScript
109 lines
3.6 KiB
TypeScript
// @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",
|
|
});
|
|
});
|
|
});
|