feat(core): add session form service (#34855)

This commit is contained in:
Aiden Cline 2026-07-02 17:15:18 -05:00 committed by GitHub
commit 7ebd344fa2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
67 changed files with 7862 additions and 5223 deletions

View file

@ -10,17 +10,21 @@ const title = "Request dock regression"
test("shows a pending question dock", async ({ page }) => {
await mockServer(page, {
questions: [
forms: [
{
id: "question-request",
id: "frm_question_request",
sessionID,
questions: [
mode: "form",
metadata: { kind: "question" },
fields: [
{
header: "Implementation",
question: "Which implementation should be used?",
key: "question_0",
type: "string",
title: "Which implementation should be used?",
description: "Implementation",
options: [
{ label: "Minimal", description: "Use the smallest correct change" },
{ label: "Extended", description: "Include additional behavior" },
{ value: "Minimal", label: "Minimal", description: "Use the smallest correct change" },
{ value: "Extended", label: "Extended", description: "Include additional behavior" },
],
},
],
@ -41,7 +45,8 @@ test("shows a pending question dock", async ({ page }) => {
const rejectRequests: string[] = []
page.on("request", (request) => {
if (request.method() !== "POST") return
if (new URL(request.url()).pathname === "/question/question-request/reject") rejectRequests.push(request.url())
if (new URL(request.url()).pathname === `/api/session/${sessionID}/form/frm_question_request/cancel`)
rejectRequests.push(request.url())
})
await question.locator('[data-component="icon-button"][data-icon="chevron-down"]').click()
@ -63,10 +68,12 @@ test("shows a pending question dock", async ({ page }) => {
await question.getByRole("radio", { name: /Minimal/ }).click()
const reply = page.waitForRequest(
(request) => request.method() === "POST" && new URL(request.url()).pathname === "/question/question-request/reply",
(request) =>
request.method() === "POST" &&
new URL(request.url()).pathname === `/api/session/${sessionID}/form/frm_question_request/reply`,
)
await question.getByRole("button", { name: "Submit" }).click()
expect((await reply).postDataJSON()).toEqual({ answers: [["Minimal"]] })
expect((await reply).postDataJSON()).toEqual({ answer: { question_0: "Minimal" } })
})
test("shows a pending permission dock", async ({ page }) => {
@ -105,6 +112,7 @@ async function mockServer(
requests: {
permissions?: unknown[] | (() => unknown[])
questions?: unknown[] | (() => unknown[])
forms?: unknown[] | (() => unknown[])
},
) {
await mockOpenCodeServer(page, {
@ -148,6 +156,7 @@ async function mockServer(
pageMessages: () => ({ items: [] }),
permissions: requests.permissions,
questions: requests.questions,
forms: requests.forms,
})
await page.addInitScript(() => {
localStorage.setItem("settings.v3", JSON.stringify({ general: { newLayoutDesigns: true } }))

View file

@ -17,6 +17,7 @@ export interface MockServerConfig {
todos?: (sessionID: string) => unknown[]
permissions?: unknown[] | (() => unknown[])
questions?: unknown[] | (() => unknown[])
forms?: unknown[] | (() => unknown[])
}
export async function mockOpenCodeServer(page: Page, config: MockServerConfig) {
@ -53,6 +54,17 @@ export async function mockOpenCodeServer(page: Page, config: MockServerConfig) {
return json(route, typeof config.permissions === "function" ? config.permissions() : (config.permissions ?? []))
if (path === "/question")
return json(route, typeof config.questions === "function" ? config.questions() : (config.questions ?? []))
if (path === "/api/form/request")
return json(route, {
location: { directory: config.directory, project: config.project },
data: typeof config.forms === "function" ? config.forms() : (config.forms ?? []),
})
if (/^\/api\/session\/[^/]+\/form$/.test(path))
return json(route, {
location: { directory: config.directory, project: config.project },
data: typeof config.forms === "function" ? config.forms() : (config.forms ?? []),
})
if (/^\/api\/session\/[^/]+\/form\/[^/]+\/(reply|cancel)$/.test(path)) return json(route, undefined, undefined, 204)
if (path === "/vcs/diff" && config.vcsDiff) return json(route, config.vcsDiff)
if (emptyObject.has(path)) return json(route, {})
if (emptyList.has(path)) return json(route, [])