diff --git a/ui/src/e2e/chat-flow.e2e.test.ts b/ui/src/e2e/chat-flow.e2e.test.ts index ad7b51381545..d6e64e920a7f 100644 --- a/ui/src/e2e/chat-flow.e2e.test.ts +++ b/ui/src/e2e/chat-flow.e2e.test.ts @@ -993,6 +993,7 @@ describeControlUiE2e("Control UI mocked Gateway E2E", () => { await page.goto(`${server.baseUrl}chat`); const copyButton = page.locator(".code-block-copy").first(); await copyButton.waitFor({ timeout: 10_000 }); + await waitForChatScrollIdle(page); await copyButton.evaluate((element) => element.scrollIntoView({ block: "center" })); const thread = page.locator(".chat-thread"); const scrollTopBefore = await thread.evaluate((element) => @@ -1152,8 +1153,14 @@ describeControlUiE2e("Control UI mocked Gateway E2E", () => { await page.getByText("AGENTS.md").waitFor({ timeout: 10_000 }); expect(await gateway.getRequests("sessions.files.list")).toHaveLength(1); - await page.setViewportSize({ height: 900, width: 1000 }); - expect(await page.locator(".chat-workspace-rail").isHidden()).toBe(true); + await page.setViewportSize({ height: 900, width: 760 }); + const workbench = page.locator(".chat-workbench"); + await expect + .poll(() => workbench.getAttribute("class")) + .toContain("chat-workbench--dock-bottom"); + expect(await page.locator(".chat-workspace-rail").isVisible()).toBe(true); + expect(await page.locator(".chat-workspace-rail__dock").count()).toBe(0); + expect(await page.locator(".chat-workspace-rail__grip").count()).toBe(0); } finally { await closeBrowserContext(context); } @@ -1403,28 +1410,26 @@ describeControlUiE2e("Control UI mocked Gateway E2E", () => { } }); - it("creates a worktree chat from the git-backed agent sidebar action", async () => { + it("opens a git-backed agent draft from the sidebar new-session action", async () => { const context = await newBrowserContext({ locale: "en-US", serviceWorkers: "block", viewport: { height: 900, width: 1280 }, }); const page = await context.newPage(); - const gateway = await installMockGateway(page, { - methodResponses: { - "sessions.create": { key: "agent:main:dashboard:worktree", ok: true }, - }, - workspaceGit: true, - }); + const gateway = await installMockGateway(page, { workspaceGit: true }); try { await page.goto(`${server.baseUrl}chat`); - const worktreeButton = page.getByRole("button", { name: "New chat in worktree" }); - await worktreeButton.waitFor({ state: "visible", timeout: 10_000 }); - await worktreeButton.click(); + const newSessionButton = page + .locator("openclaw-app-sidebar") + .getByRole("button", { name: "New session" }); + await newSessionButton.waitFor({ state: "visible", timeout: 10_000 }); + await newSessionButton.click(); - const request = await gateway.waitForRequest("sessions.create"); - expect(requireRecord(request.params)).toMatchObject({ agentId: "main", worktree: true }); + await expect.poll(() => new URL(page.url()).pathname).toBe("/new"); + await expect.poll(() => new URL(page.url()).searchParams.get("agent")).toBe("main"); + expect(await gateway.getRequests("sessions.create")).toHaveLength(0); } finally { await closeBrowserContext(context); } @@ -2538,6 +2543,8 @@ describeControlUiE2e("Control UI mocked Gateway E2E", () => { .waitFor({ timeout: 10_000, }); + await expect.poll(() => sidebarSessionOrder(page)).toEqual(createdOrder.slice(0, 10)); + await page.getByRole("button", { name: "Load more" }).click(); await expect.poll(() => sidebarSessionOrder(page)).toEqual(createdOrder); await page diff --git a/ui/src/e2e/native-link-routing.e2e.test.ts b/ui/src/e2e/native-link-routing.e2e.test.ts index 64b1ee7d9170..ca6fba6a0f73 100644 --- a/ui/src/e2e/native-link-routing.e2e.test.ts +++ b/ui/src/e2e/native-link-routing.e2e.test.ts @@ -242,7 +242,10 @@ describeControlUiE2e("native link routing", () => { document.querySelector("#native-link-routing-modal")?.remove(); }); - await page.getByRole("link", { name: "Usage" }).click({ button: "right" }); + await page + .getByRole("paragraph") + .getByRole("link", { name: "Usage" }) + .click({ button: "right" }); expect(await page.locator("openclaw-native-link-menu").count()).toBe(0); const messageMenu = page.getByRole("menu", { name: "Message actions" }); await expect.poll(() => messageMenu.isVisible()).toBe(true); diff --git a/ui/src/e2e/session-management.e2e.test.ts b/ui/src/e2e/session-management.e2e.test.ts index c7a14b70b8fb..5153e30576db 100644 --- a/ui/src/e2e/session-management.e2e.test.ts +++ b/ui/src/e2e/session-management.e2e.test.ts @@ -263,12 +263,13 @@ describeControlUiE2e("Control UI session management mocked Gateway E2E", () => { const sidebarReleasePin = sidebarRows .filter({ hasText: "Release planning" }) .getByRole("button", { name: "Unpin session" }); - // Pinned badge stays visible without hover. - await expect.poll(() => actionOpacity(sidebarReleasePin)).toBe("1"); + await expect.poll(() => actionOpacity(sidebarReleasePin)).toBe("0"); await sidebarResearch.hover(); await expect.poll(() => actionOpacity(sidebarResearchPin)).toBe("1"); await captureUiProof(page, "sidebar-sessions.png"); + await sidebarRows.filter({ hasText: "Release planning" }).hover(); + await expect.poll(() => actionOpacity(sidebarReleasePin)).toBe("1"); await sidebarReleasePin.click(); const pinPatch = await waitForPatch( gateway,