mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-07-31 04:12:10 +03:00
Fix E2E flakiness and implicit any type errors
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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 });
|
||||
|
||||
@@ -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}`);
|
||||
|
||||
@@ -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<string, unknown> | 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<string, string>;
|
||||
} = {}) {
|
||||
const requestHeaders = {
|
||||
const requestHeaders: Record<string, string> = {
|
||||
"Content-Type": "application/json",
|
||||
...headers,
|
||||
};
|
||||
|
||||
@@ -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 [];
|
||||
|
||||
|
||||
Reference in New Issue
Block a user