useSubmit holds the idle, sending, done and error state and the request flow that six forms each wrote out; FormResult shows the success line and the problem panel; FormStack is the column the link, claude-login, inference and limits forms each styled by hand. The create-agent, link account, backend-env and agent-input forms use the submit flow; the link, claude-login, inference and limits forms use FormStack.
58 lines
2 KiB
JavaScript
58 lines
2 KiB
JavaScript
// The request flow every form shares: a refusal becomes a problem, a failure
|
|
// to send becomes a problem, a success parses its reply.
|
|
import assert from "node:assert/strict";
|
|
import { test } from "node:test";
|
|
import { submitOutcome } from "../src/ui/submit/submit.ts";
|
|
|
|
const problem = (status, body) =>
|
|
new Response(JSON.stringify(body), {
|
|
status,
|
|
headers: { "content-type": "application/problem+json" },
|
|
});
|
|
|
|
test("an ok reply is done, with nothing parsed by default", async () => {
|
|
const out = await submitOutcome(
|
|
async () => new Response(null, { status: 204 }),
|
|
);
|
|
assert.deepEqual(out, { status: "done", value: undefined });
|
|
});
|
|
|
|
test("an ok reply is parsed into the done value", async () => {
|
|
const out = await submitOutcome(
|
|
async () => new Response(JSON.stringify({ node_id: 7 })),
|
|
{ parse: async (r) => (await r.json()).node_id },
|
|
);
|
|
assert.deepEqual(out, { status: "done", value: 7 });
|
|
});
|
|
|
|
test("a refusal carries the server's problem", async () => {
|
|
const out = await submitOutcome(async () =>
|
|
problem(409, { title: "conflict", detail: "already linked" }),
|
|
);
|
|
assert.equal(out.status, "error");
|
|
assert.equal(out.problem.detail, "already linked");
|
|
});
|
|
|
|
test("refine can reword a refusal by status", async () => {
|
|
const out = await submitOutcome(async () => problem(404, {}), {
|
|
refine: (r, p) =>
|
|
r.status === 404 && !p.detail ? { ...p, detail: "no such agent" } : p,
|
|
});
|
|
assert.equal(out.status, "error");
|
|
assert.equal(out.problem.detail, "no such agent");
|
|
});
|
|
|
|
test("a request that throws is an error with the message", async () => {
|
|
const out = await submitOutcome(async () => {
|
|
throw new Error("offline");
|
|
});
|
|
assert.equal(out.status, "error");
|
|
assert.match(out.problem.detail, /offline/);
|
|
});
|
|
|
|
test("a parse that throws is an error, not a done", async () => {
|
|
const out = await submitOutcome(async () => new Response("not json"), {
|
|
parse: (r) => r.json(),
|
|
});
|
|
assert.equal(out.status, "error");
|
|
});
|