diff --git a/tests/e2e/memory-settings.spec.ts b/tests/e2e/memory-settings.spec.ts index 0444b6bff7..d1059a1c22 100644 --- a/tests/e2e/memory-settings.spec.ts +++ b/tests/e2e/memory-settings.spec.ts @@ -81,7 +81,7 @@ test.describe("Memory settings", () => { deleteCalls: 0, }; - await page.route("**/api/settings", async (route) => { + await page.route(/\/api\/settings$/, async (route) => { const method = route.request().method(); if (method === "GET") { await fulfillJson(route, state.settings); @@ -101,7 +101,7 @@ test.describe("Memory settings", () => { await fulfillJson(route, { error: "Method not allowed in settings stub" }, 405); }); - await page.route("**/api/settings/memory", async (route) => { + await page.route(/\/api\/settings\/memory$/, async (route) => { const method = route.request().method(); if (method === "GET") { await fulfillJson(route, state.config); diff --git a/tests/e2e/protocol-visibility.spec.ts b/tests/e2e/protocol-visibility.spec.ts index 3a4dea2b3a..f85cb785b5 100644 --- a/tests/e2e/protocol-visibility.spec.ts +++ b/tests/e2e/protocol-visibility.spec.ts @@ -2,34 +2,24 @@ import { test, expect } from "@playwright/test"; import { gotoDashboardRoute } from "./helpers/dashboardAuth"; test.describe("Protocol visibility", () => { - test("shows MCP/A2A links inside protocols tab in endpoint page", async ({ page }) => { + test("shows MCP and A2A tabs inside the endpoint page", async ({ page }) => { await gotoDashboardRoute(page, "/dashboard/endpoint"); await page.waitForLoadState("networkidle"); - // MCP and A2A are now shown inside the "Protocols" tab — click it first - const protocolTab = page.getByRole("tab", { name: /protocols|protocolos/i }); - await expect(protocolTab).toBeVisible(); - await protocolTab.click(); + // MCP and A2A are now tabs directly in the SegmentedControl + const mcpTab = page.getByRole("tab", { name: "MCP" }); + const a2aTab = page.getByRole("tab", { name: "A2A" }); - // Links to MCP and A2A management pages appear after tab switch - await expect(page.locator('a[href="/dashboard/mcp"]').first()).toBeVisible(); - await expect(page.locator('a[href="/dashboard/a2a"]').first()).toBeVisible(); + await expect(mcpTab).toBeVisible(); + await expect(a2aTab).toBeVisible(); - const mcpLinks = await page.locator('a[href="/dashboard/mcp"]').count(); - const a2aLinks = await page.locator('a[href="/dashboard/a2a"]').count(); - expect(mcpLinks).toBeGreaterThanOrEqual(1); - expect(a2aLinks).toBeGreaterThanOrEqual(1); - }); - - test("loads MCP and A2A dashboards without runtime error page", async ({ page }) => { - await gotoDashboardRoute(page, "/dashboard/mcp"); - await page.waitForLoadState("networkidle"); - await expect(page.locator("body")).toBeVisible(); + // Verify MCP dashboard mounts + await mcpTab.click(); + // In dev/test it might just show "loading..." or the processStatus card await expect(page.locator("body")).not.toContainText(/application error|500/i); - await gotoDashboardRoute(page, "/dashboard/a2a"); - await page.waitForLoadState("networkidle"); - await expect(page.locator("body")).toBeVisible(); + // Verify A2A dashboard mounts + await a2aTab.click(); await expect(page.locator("body")).not.toContainText(/application error|500/i); }); }); diff --git a/tests/e2e/providers-bailian-coding-plan.spec.ts b/tests/e2e/providers-bailian-coding-plan.spec.ts index b9c3c88f01..1abe178c17 100644 --- a/tests/e2e/providers-bailian-coding-plan.spec.ts +++ b/tests/e2e/providers-bailian-coding-plan.spec.ts @@ -69,18 +69,13 @@ test.describe("Bailian Coding Plan Provider", () => { } const addKeyButton = page.getByRole("button", { - name: /add.*api.*key|add.*key|add.*connection|connect/i, + name: /add.*api.*key|add.*key|add.*connection|connect|adicionar.*chave/i, }); - if ( - await addKeyButton - .first() - .isVisible({ timeout: 15000 }) - .catch(() => false) - ) { - await expect(addKeyButton.first()).toBeEnabled({ timeout: 5000 }); - await addKeyButton.first().click(); - } + // Wait for the button to appear instead of immediately checking visibility + await addKeyButton.first().waitFor({ state: "visible", timeout: 15000 }); + await expect(addKeyButton.first()).toBeEnabled({ timeout: 5000 }); + await addKeyButton.first().click(); const dialog = page.getByRole("dialog").first(); await expect(dialog).toBeVisible({ timeout: 10000 }); @@ -185,18 +180,13 @@ test.describe("Bailian Coding Plan Provider", () => { } const addKeyButton = page.getByRole("button", { - name: /add.*api.*key|add.*key|add.*connection|connect/i, + name: /add.*api.*key|add.*key|add.*connection|connect|adicionar.*chave/i, }); - if ( - await addKeyButton - .first() - .isVisible({ timeout: 15000 }) - .catch(() => false) - ) { - await expect(addKeyButton.first()).toBeEnabled({ timeout: 5000 }); - await addKeyButton.first().click(); - } + // Wait for the button to appear instead of immediately checking visibility + await addKeyButton.first().waitFor({ state: "visible", timeout: 15000 }); + await expect(addKeyButton.first()).toBeEnabled({ timeout: 5000 }); + await addKeyButton.first().click(); const dialog = page.getByRole("dialog").first(); await expect(dialog).toBeVisible({ timeout: 10000 }); diff --git a/tests/integration/api-keys.test.ts b/tests/integration/api-keys.test.ts index 269bceee61..e86a03cd3b 100644 --- a/tests/integration/api-keys.test.ts +++ b/tests/integration/api-keys.test.ts @@ -38,7 +38,10 @@ async function createManagementKey() { return apiKeysDb.createApiKey("management", MACHINE_ID); } -function makeRequest(url, { method = "GET", token, body } = {}) { +function makeRequest( + url: string | URL, + { method = "GET", token, body }: { method?: string; token?: string; body?: unknown } = {} +) { const headers = new Headers(); if (token) { headers.set("authorization", `Bearer ${token}`); diff --git a/tests/integration/chat-pipeline.test.ts b/tests/integration/chat-pipeline.test.ts index cc0e446c92..bb4a7d155a 100644 --- a/tests/integration/chat-pipeline.test.ts +++ b/tests/integration/chat-pipeline.test.ts @@ -30,7 +30,7 @@ const { clearProviderFailure } = await import("../../open-sse/services/accountFa const originalFetch = globalThis.fetch; const originalRetryDelayMs = BaseExecutor.RETRY_CONFIG.delayMs; -function toPlainHeaders(headers) { +function toPlainHeaders(headers: Headers | Record | undefined | null) { if (!headers) return {}; if (headers instanceof Headers) return Object.fromEntries(headers.entries()); return Object.fromEntries( @@ -43,8 +43,13 @@ function buildRequest({ body, authKey = null, headers = {}, +}: { + url?: string; + body?: unknown; + authKey?: string | null; + headers?: Record; } = {}) { - const requestHeaders = { + const requestHeaders: Record = { "Content-Type": "application/json", ...headers, }; diff --git a/tests/integration/integration-wiring.test.ts b/tests/integration/integration-wiring.test.ts index 4fbfbdac7c..d805c5d99a 100644 --- a/tests/integration/integration-wiring.test.ts +++ b/tests/integration/integration-wiring.test.ts @@ -14,19 +14,19 @@ import { fileURLToPath } from "node:url"; const __dirname = dirname(fileURLToPath(import.meta.url)); const ROOT = join(__dirname, "..", ".."); -function readProjectFile(relPath) { +function readProjectFile(relPath: string) { const full = join(ROOT, relPath); if (!existsSync(full)) return null; return readFileSync(full, "utf8"); } -function assertFileExists(relPath) { +function assertFileExists(relPath: string) { const full = join(ROOT, relPath); assert.ok(existsSync(full), `${relPath} should exist`); return full; } -function assertRouteMethods(relPath, methods) { +function assertRouteMethods(relPath: string, methods: string[]) { const src = readProjectFile(relPath); assert.ok(src, `${relPath} should exist`); for (const method of methods) { @@ -34,7 +34,7 @@ function assertRouteMethods(relPath, methods) { } } -function listProjectFiles(relPath) { +function listProjectFiles(relPath: string): string[] { const full = join(ROOT, relPath); if (!existsSync(full)) return [];