From edc1d655587343b594d6d4604b720b7eefa367b6 Mon Sep 17 00:00:00 2001 From: Yuneng Jiang Date: Sat, 15 Aug 2026 15:34:37 -0700 Subject: [PATCH 1/2] test(e2e/ui): address the migrated dashboard controls by role, not antd classes The playground, logs drawer and AI Hub modal moved off antd, so the specs that reached for .ant-select, .ant-drawer-content, .ant-modal and .ant-radio-button-wrapper no longer match anything and time out. Address the same controls through their accessible role and name instead, which holds across the component library swap and reads closer to what a user does. --- tests/e2e/ui/helpers/playground.ts | 20 +++++++++---------- tests/e2e/ui/tests/logs/logs.spec.ts | 12 +++++------ tests/e2e/ui/tests/modelHub/modelHub.spec.ts | 2 +- .../ui/tests/playground/playground.spec.ts | 6 +++--- 4 files changed, 18 insertions(+), 22 deletions(-) diff --git a/tests/e2e/ui/helpers/playground.ts b/tests/e2e/ui/helpers/playground.ts index 39aae8398a5..866334e1c94 100644 --- a/tests/e2e/ui/helpers/playground.ts +++ b/tests/e2e/ui/helpers/playground.ts @@ -10,16 +10,15 @@ import { Page } from "../fixtures/pages"; */ export const onlyVisible = (locator: Locator): Locator => locator.filter({ visible: true }).first(); -/** The model dropdown, addressed by the placeholder it shows before selection. */ -export const modelSelect = (page: PlaywrightPage): Locator => - onlyVisible(page.locator('.ant-select:has(.ant-select-selection-placeholder:text-is("Select a Model"))')); +/** The model combobox, addressed by the placeholder its search input shows before selection. */ +export const modelSelect = (page: PlaywrightPage): Locator => onlyVisible(page.getByPlaceholder("Select a Model")); -/** Send button is icon-only (an up-arrow), so there is no accessible name. */ -export const sendButton = (page: PlaywrightPage): Locator => onlyVisible(page.locator("button:has(.anticon-arrow-up)")); +export const sendButton = (page: PlaywrightPage): Locator => + onlyVisible(page.getByRole("button", { name: "Send message" })); -/** The Virtual Key Source dropdown, addressed by its currently selected label. */ -export const keySourceSelect = (page: PlaywrightPage, current: string): Locator => - onlyVisible(page.locator(`.ant-select:has(.ant-select-selection-item[title="${current}"])`)); +/** The Virtual Key Source dropdown, addressed by the accessible name on its trigger. */ +export const keySourceSelect = (page: PlaywrightPage): Locator => + onlyVisible(page.getByLabel("Virtual Key Source")); export async function openPlayground(page: PlaywrightPage): Promise { await navigateToPage(page, Page.LlmPlayground); @@ -33,9 +32,8 @@ export async function selectModel(page: PlaywrightPage, model: string): Promise< const select = modelSelect(page); await select.click(); // Virtualized: options outside the rendered window are absent from the DOM, so search first. - await select.locator("input.ant-select-selection-search-input").fill(model); - // antd portals its dropdown to the body; options carry the value as `title`. - await onlyVisible(page.locator(`.ant-select-item-option[title="${model}"]`)).click({ timeout: 15_000 }); + await select.fill(model); + await onlyVisible(page.getByRole("option", { name: model, exact: true })).click({ timeout: 15_000 }); } export async function sendMessage(page: PlaywrightPage, message: string): Promise { diff --git a/tests/e2e/ui/tests/logs/logs.spec.ts b/tests/e2e/ui/tests/logs/logs.spec.ts index fc5cce53511..c1182a7ca5c 100644 --- a/tests/e2e/ui/tests/logs/logs.spec.ts +++ b/tests/e2e/ui/tests/logs/logs.spec.ts @@ -59,7 +59,7 @@ test.describe("Logs page", () => { // Expand: clicking the row opens the detail drawer for that request. await row.click(); - const drawer = page.locator(".ant-drawer-content").first(); + const drawer = page.getByRole("dialog").first(); await expect(drawer).toBeVisible({ timeout: 20_000 }); await expect(drawer.getByText("Request & Response")).toBeVisible({ timeout: 20_000, @@ -91,7 +91,7 @@ test.describe("Logs page", () => { const row = await openLogsForRequest(page, requestId); await row.click(); - const drawer = page.locator(".ant-drawer-content").first(); + const drawer = page.getByRole("dialog").first(); await expect(drawer).toBeVisible({ timeout: 20_000 }); // Copy request: the Input card's copy button puts the prompt on the clipboard. @@ -120,7 +120,7 @@ test.describe("Logs page", () => { const row = await openLogsForRequest(page, requestId); await row.click(); - const drawer = page.locator(".ant-drawer-content").first(); + const drawer = page.getByRole("dialog").first(); await expect(drawer.getByText("Request & Response")).toBeVisible({ timeout: 20_000, }); @@ -159,14 +159,12 @@ test.describe("Logs page", () => { const row = await openLogsForRequest(page, requestId); await row.click(); - const drawer = page.locator(".ant-drawer-content").first(); + const drawer = page.getByRole("dialog").first(); await expect(drawer.getByText("Request & Response")).toBeVisible({ timeout: 20_000, }); - // antd Radio.Button hides the under its