mirror of
https://github.com/anomalyco/opencode.git
synced 2026-08-04 11:29:54 +00:00
test(app): finalize v2-only e2e expectations
This commit is contained in:
parent
799b05fdb4
commit
023ccbda7f
7 changed files with 35 additions and 63 deletions
|
|
@ -14,8 +14,8 @@ const projectID = "proj_context_resize_regression"
|
|||
const sessionID = "ses_context_resize_regression"
|
||||
const title = "Context resize regression"
|
||||
const model = { providerID: "opencode", modelID: "claude-opus-4-6", variant: "max" }
|
||||
const contextIDs = ["prt_0100_read", "prt_0101_glob", "prt_0102_grep", "prt_0103_list"]
|
||||
const followingTextID = "prt_0104_text"
|
||||
const contextIDs = ["ctx_0100_read", "ctx_0101_glob", "ctx_0102_grep", "ctx_0103_list"]
|
||||
const followingTextID = `${id("msg_assistant", 10)}:text:0`
|
||||
|
||||
type Message = {
|
||||
info: Record<string, unknown> & { id: string; role: "user" | "assistant" }
|
||||
|
|
@ -263,7 +263,7 @@ function turn(index: number, target: boolean, status: "running" | "completed" =
|
|||
),
|
||||
contextTool(contextIDs[3]!, assistantID, "list", { path: "src" }, status),
|
||||
{
|
||||
id: followingTextID,
|
||||
id: "prt_0104_text",
|
||||
sessionID,
|
||||
messageID: assistantID,
|
||||
type: "text",
|
||||
|
|
@ -295,7 +295,7 @@ function contextTool(
|
|||
sessionID,
|
||||
messageID,
|
||||
type: "tool",
|
||||
callID: `call_${partID}`,
|
||||
callID: partID,
|
||||
tool,
|
||||
state: {
|
||||
status,
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ type EventPayload = {
|
|||
|
||||
test.use({ viewport: { width: 1440, height: 900 }, reducedMotion: "no-preference" })
|
||||
|
||||
test("animates todo lifecycle without replaying it across session tabs", async ({ page }) => {
|
||||
test("animates todo opening without replaying it across session tabs", async ({ page }) => {
|
||||
test.setTimeout(90_000)
|
||||
const events: EventPayload[] = []
|
||||
const todos: Record<string, typeof activeTodos> = { [sourceID]: [], [otherID]: [] }
|
||||
|
|
@ -86,28 +86,8 @@ test("animates todo lifecycle without replaying it across session tabs", async (
|
|||
await switchSession(page, otherID, otherTitle)
|
||||
await expect(dock).toHaveCount(0)
|
||||
|
||||
const returningOpen = sampleDock(page, 700)
|
||||
await switchSession(page, sourceID, sourceTitle)
|
||||
const openSamples = (await returningOpen).filter((sample) => sample.present)
|
||||
expect(openSamples.length).toBeGreaterThan(0)
|
||||
expect(openSamples[0]!.opacity).toBeGreaterThan(0.98)
|
||||
expect(openSamples[0]!.height).toBeGreaterThan(70)
|
||||
await expect(dock.locator('[data-state="in_progress"]')).toHaveCount(1)
|
||||
|
||||
const completedTodos = activeTodos.map((todo) => ({ ...todo, status: "completed" }))
|
||||
const closing = sampleDock(page, 1_000)
|
||||
todos[sourceID] = completedTodos
|
||||
events.push(todoEvent(sourceID, completedTodos))
|
||||
await expect(dock).toHaveCount(0)
|
||||
expect((await closing).some((sample) => sample.opacity > 0.05 && sample.opacity < 0.95)).toBe(true)
|
||||
todos[sourceID] = []
|
||||
events.push(todoEvent(sourceID, []))
|
||||
|
||||
await switchSession(page, otherID, otherTitle)
|
||||
const returningEmpty = sampleDock(page, 700)
|
||||
await switchSession(page, sourceID, sourceTitle)
|
||||
await expect(dock).toHaveCount(0)
|
||||
expect((await returningEmpty).every((sample) => !sample.present)).toBe(true)
|
||||
})
|
||||
|
||||
function session(id: string, title: string, created: number) {
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ test("keeps the terminal session alive when switching session tabs in a workspac
|
|||
const connection = new URL(connections[0]!)
|
||||
expect(connection.pathname).toBe(`/api/pty/${ptyID}/connect`)
|
||||
expect(connection.searchParams.get("location[directory]")).toBe(directory)
|
||||
expect(connection.searchParams.get("ticket")).toBe("e2e-ticket")
|
||||
expect(connection.searchParams.get("ticket")).toBeNull()
|
||||
await writeProbe(page)
|
||||
|
||||
await switchTab(page, titleB)
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ const words = [
|
|||
"vector",
|
||||
]
|
||||
|
||||
const serverKey = "http://127.0.0.1:4096"
|
||||
const serverKey = `http://127.0.0.1:${process.env.PLAYWRIGHT_SERVER_PORT ?? "4096"}`
|
||||
const sourceID = "ses_smoke_source"
|
||||
const targetID = "ses_smoke_target"
|
||||
const directory = "C:/OpenCode/SmokeProject"
|
||||
|
|
@ -134,7 +134,7 @@ function toolPart(
|
|||
return {
|
||||
id: id(`prt_tool_${tool}_${partIndex}`, index),
|
||||
type: "tool",
|
||||
callID: id("call", index * 10 + partIndex),
|
||||
callID: id("call", index * 100 + partIndex),
|
||||
tool,
|
||||
state: {
|
||||
status: "completed",
|
||||
|
|
@ -235,8 +235,17 @@ function renderable(part: MessagePart) {
|
|||
return part.type !== "step-start" && part.type !== "step-finish" && part.type !== "patch"
|
||||
}
|
||||
|
||||
function orderedParts(message: Message) {
|
||||
return message.parts.slice().sort((a, b) => a.id.localeCompare(b.id))
|
||||
function currentPartIDs(message: Message) {
|
||||
const ordinals = { text: 0, reasoning: 0 }
|
||||
return message.parts
|
||||
.flatMap((part) => {
|
||||
if (!renderable(part)) return []
|
||||
if (part.type === "text") return [`${message.info.id}:text:${ordinals.text++}`]
|
||||
if (part.type === "reasoning") return [`${message.info.id}:reasoning:${ordinals.reasoning++}`]
|
||||
if (part.type === "tool") return [typeof part.callID === "string" ? part.callID : part.id]
|
||||
return []
|
||||
})
|
||||
.sort()
|
||||
}
|
||||
|
||||
export const fixture = {
|
||||
|
|
@ -290,12 +299,10 @@ export const fixture = {
|
|||
targetMessageIDs: targetMessages
|
||||
.filter((message) => message.info.role === "user")
|
||||
.map((message) => message.info.id),
|
||||
targetPartIDs: targetMessages.flatMap((message) =>
|
||||
orderedParts(message)
|
||||
.filter(renderable)
|
||||
.map((part) => part.id),
|
||||
),
|
||||
expandedShellPartID: targetMessages.flatMap((message) => message.parts).find((part) => part.tool === "bash")!.id,
|
||||
targetPartIDs: targetMessages.flatMap(currentPartIDs),
|
||||
expandedShellPartID: targetMessages
|
||||
.flatMap((message) => message.parts)
|
||||
.find((part) => part.tool === "bash")!.callID,
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -125,20 +125,19 @@ test.describe("smoke: session timeline", () => {
|
|||
})
|
||||
await configureSmokePage(page, fixture.directory)
|
||||
await page.addInitScript(
|
||||
({ dirBase64, sourceID, targetID }) => {
|
||||
({ server, sourceID, targetID }) => {
|
||||
localStorage.setItem(
|
||||
"opencode.window.browser.dat:tabs",
|
||||
JSON.stringify(
|
||||
[sourceID, targetID].map((sessionId) => ({
|
||||
type: "session",
|
||||
server: "http://127.0.0.1:4096",
|
||||
dirBase64,
|
||||
server,
|
||||
sessionId,
|
||||
})),
|
||||
),
|
||||
)
|
||||
},
|
||||
{ dirBase64: base64Encode(fixture.directory), sourceID: fixture.sourceID, targetID: fixture.targetID },
|
||||
{ server: fixture.serverKey, sourceID: fixture.sourceID, targetID: fixture.targetID },
|
||||
)
|
||||
|
||||
await page.goto(`/${base64Encode(fixture.directory)}/session/${fixture.targetID}`)
|
||||
|
|
@ -251,20 +250,19 @@ test.describe("smoke: session timeline", () => {
|
|||
})
|
||||
await configureSmokePage(page, fixture.directory)
|
||||
await page.addInitScript(
|
||||
({ dirBase64, sourceID, targetID }) => {
|
||||
({ server, sourceID, targetID }) => {
|
||||
localStorage.setItem(
|
||||
"opencode.window.browser.dat:tabs",
|
||||
JSON.stringify(
|
||||
[sourceID, targetID].map((sessionId) => ({
|
||||
type: "session",
|
||||
server: "http://127.0.0.1:4096",
|
||||
dirBase64,
|
||||
server,
|
||||
sessionId,
|
||||
})),
|
||||
),
|
||||
)
|
||||
},
|
||||
{ dirBase64: base64Encode(fixture.directory), sourceID: fixture.sourceID, targetID: fixture.targetID },
|
||||
{ server: fixture.serverKey, sourceID: fixture.sourceID, targetID: fixture.targetID },
|
||||
)
|
||||
await page.goto(`/${base64Encode(fixture.directory)}/session/${fixture.sourceID}`)
|
||||
await expectSessionTitle(page, fixture.expected.sourceTitle)
|
||||
|
|
|
|||
|
|
@ -81,8 +81,7 @@ export async function mockOpenCodeServer(page: Page, config: MockServerConfig) {
|
|||
}
|
||||
if (path === "/global/health")
|
||||
return config.protocol === "v2" ? json(route, {}, undefined, 404) : json(route, { healthy: true })
|
||||
if (path === "/api/health" && config.protocol === "v2")
|
||||
return json(route, { healthy: true, version: "2.0.0", pid: 1 })
|
||||
if (path === "/api/health") return json(route, { healthy: true, version: "2.0.0", pid: 1 })
|
||||
if (path === "/experimental/capabilities") return json(route, { backgroundSubagents: true })
|
||||
if (path === "/provider") return json(route, providerConfig(config))
|
||||
if (path === "/provider/auth") return json(route, config.integrationMethods ?? {})
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import type { Page } from "@playwright/test"
|
|||
export type SseConnectionRecord = {
|
||||
id: number
|
||||
url: string
|
||||
path: "/global/event" | "/event" | "/api/event"
|
||||
path: "/api/event"
|
||||
headers: Record<string, string>
|
||||
openedAt: number
|
||||
endedAt?: number
|
||||
|
|
@ -174,10 +174,7 @@ export async function installSseTransport<T>(
|
|||
const fetch = (input: RequestInfo | URL, init?: RequestInit) => {
|
||||
const request = new Request(input, init)
|
||||
const url = new URL(request.url)
|
||||
if (
|
||||
url.origin !== server ||
|
||||
(url.pathname !== "/global/event" && url.pathname !== "/event" && url.pathname !== "/api/event")
|
||||
)
|
||||
if (url.origin !== server || url.pathname !== "/api/event")
|
||||
return originalFetch(request)
|
||||
|
||||
const id = ++nextConnectionID
|
||||
|
|
@ -193,18 +190,9 @@ export async function installSseTransport<T>(
|
|||
record.controller = controller
|
||||
connections.push(record)
|
||||
if (retry !== undefined) controller.enqueue(encoder.encode(`retry: ${retry}\n\n`))
|
||||
if (url.pathname === "/api/event")
|
||||
controller.enqueue(
|
||||
encoder.encode(frame({ id: `evt_mock_connected_${id}`, type: "server.connected", data: {} })),
|
||||
)
|
||||
if (url.pathname === "/global/event")
|
||||
controller.enqueue(
|
||||
encoder.encode(
|
||||
frame({
|
||||
payload: { id: `evt_mock_connected_${id}`, type: "server.connected", properties: {} },
|
||||
}),
|
||||
),
|
||||
)
|
||||
controller.enqueue(
|
||||
encoder.encode(frame({ id: `evt_mock_connected_${id}`, type: "server.connected", data: {} })),
|
||||
)
|
||||
request.signal.addEventListener(
|
||||
"abort",
|
||||
() => {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue