| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192 |
- import type { Page, Route } from "@playwright/test"
- const emptyList = new Set([
- "/skill",
- "/command",
- "/lsp",
- "/formatter",
- "/permission",
- "/question",
- "/vcs/status",
- "/vcs/diff",
- ])
- const emptyObject = new Set(["/global/config", "/config", "/provider/auth", "/mcp", "/session/status"])
- export interface MockServerConfig {
- provider: unknown
- directory: string
- project: unknown
- sessions: ({ id: string } & Record<string, unknown>)[]
- pageMessages: (sessionId: string, limit: number, before?: string) => { items: unknown[]; cursor?: string }
- events?: () => unknown[]
- }
- export async function mockOpenCodeServer(page: Page, config: MockServerConfig) {
- const staticRoutes: Record<string, unknown> = {
- "/provider": config.provider,
- "/path": {
- state: config.directory,
- config: config.directory,
- worktree: config.directory,
- directory: config.directory,
- home: "C:/OpenCode",
- },
- "/project": [config.project],
- "/project/current": config.project,
- "/agent": [{ name: "build", mode: "primary" }],
- "/vcs": { branch: "main", default_branch: "main" },
- "/session": config.sessions,
- }
- await page.route("**/*", async (route) => {
- const url = new URL(route.request().url())
- const targetPort = process.env.PLAYWRIGHT_SERVER_PORT ?? "4096"
- if (url.port !== targetPort) return route.fallback()
- const path = url.pathname
- if (path === "/global/event" || path === "/event") return sse(route, config.events?.())
- if (path === "/global/health") return json(route, { healthy: true })
- if (emptyObject.has(path)) return json(route, {})
- if (emptyList.has(path)) return json(route, [])
- if (path in staticRoutes) return json(route, staticRoutes[path])
- const sessionMatch = path.match(/^\/session\/([^/]+)$/)
- if (sessionMatch) {
- const session = config.sessions.find((s) => s.id === sessionMatch[1])
- return json(route, session ?? {})
- }
- if (/^\/session\/[^/]+\/(children|todo|diff)$/.test(path)) return json(route, [])
- const messagesMatch = path.match(/^\/session\/([^/]+)\/message$/)
- if (messagesMatch) {
- const limit = Number(url.searchParams.get("limit") ?? 80)
- const before = url.searchParams.get("before") ?? undefined
- const pageData = config.pageMessages(messagesMatch[1], limit, before)
- return json(route, pageData.items, pageData.cursor ? { "x-next-cursor": pageData.cursor } : undefined)
- }
- return json(route, {})
- })
- }
- function json(route: Route, body: unknown, headers?: Record<string, string>) {
- return route.fulfill({
- status: 200,
- contentType: "application/json",
- headers: {
- "access-control-allow-origin": "*",
- "access-control-expose-headers": "x-next-cursor",
- ...headers,
- },
- body: JSON.stringify(body ?? null),
- })
- }
- function sse(route: Route, events?: unknown[]) {
- return route.fulfill({
- status: 200,
- contentType: "text/event-stream",
- body: events?.map((event) => `data: ${JSON.stringify(event)}\n\n`).join("") || ": ok\n\n",
- })
- }
|