import { test, expect, type Page } from "./fixtures"; import { createAgent, ensureHostSelected, gotoHome, setWorkingDirectory, } from "./helpers/app"; import { createTempGitRepo } from "./helpers/workspace"; import { buildHostWorkspaceRoute } from "@/utils/host-routes"; function buildWorkspaceRoute(serverId: string, workspacePath: string): string { return buildHostWorkspaceRoute(serverId, workspacePath); } async function openWorkspaceWithAgent(page: Page, workspacePath: string): Promise { const serverId = process.env.E2E_SERVER_ID; if (!serverId) { throw new Error("E2E_SERVER_ID is not set."); } await gotoHome(page); await ensureHostSelected(page); await setWorkingDirectory(page, workspacePath); await createAgent(page, `workspace header restore ${Date.now()}`); await page.goto(buildWorkspaceRoute(serverId, workspacePath)); await expect(page).toHaveURL(new RegExp(`/h/${encodeURIComponent(serverId)}/workspace/`), { timeout: 30000, }); await expect(page.getByTestId("workspace-new-agent-tab").first()).toBeVisible({ timeout: 30000, }); await expect(page.getByTestId("workspace-new-terminal-tab").first()).toBeVisible({ timeout: 30000, }); } test("workspace new-tab buttons stay on-screen during horizontal scroll", async ({ page }) => { const repo = await createTempGitRepo("paseo-e2e-workspace-new-tab-"); try { await openWorkspaceWithAgent(page, repo.path); const agentButton = page.getByTestId("workspace-new-agent-tab").first(); const terminalButton = page.getByTestId("workspace-new-terminal-tab").first(); const tabsScroll = page.getByTestId("workspace-tabs-scroll").first(); await expect(agentButton).toBeVisible({ timeout: 30000 }); await expect(terminalButton).toBeVisible({ timeout: 30000 }); await expect(tabsScroll).toBeVisible({ timeout: 30000 }); // Create enough terminal tabs to ensure the tabs row has overflow to scroll. const terminalTabs = page.locator('[data-testid^="workspace-tab-terminal:"]'); const initialTerminalCount = await terminalTabs.count(); const targetTerminalCount = initialTerminalCount + 8; for (let attempt = initialTerminalCount; attempt < targetTerminalCount; attempt += 1) { await expect(terminalButton).toBeEnabled({ timeout: 30000 }); await terminalButton.click(); await expect .poll(async () => await terminalTabs.count(), { timeout: 30000 }) .toBeGreaterThanOrEqual(attempt + 1); } const agentBoundsBefore = await agentButton.boundingBox(); const terminalBoundsBefore = await terminalButton.boundingBox(); const viewport = page.viewportSize(); expect(agentBoundsBefore).not.toBeNull(); expect(terminalBoundsBefore).not.toBeNull(); expect(viewport).not.toBeNull(); if (!agentBoundsBefore || !terminalBoundsBefore || !viewport) { return; } expect(agentBoundsBefore.x).toBeGreaterThanOrEqual(0); expect(agentBoundsBefore.y).toBeGreaterThanOrEqual(0); expect(agentBoundsBefore.x + agentBoundsBefore.width).toBeLessThanOrEqual(viewport.width); expect(agentBoundsBefore.y + agentBoundsBefore.height).toBeLessThanOrEqual(viewport.height); expect(terminalBoundsBefore.x).toBeGreaterThanOrEqual(0); expect(terminalBoundsBefore.y).toBeGreaterThanOrEqual(0); expect(terminalBoundsBefore.x + terminalBoundsBefore.width).toBeLessThanOrEqual(viewport.width); expect(terminalBoundsBefore.y + terminalBoundsBefore.height).toBeLessThanOrEqual(viewport.height); // Scroll tabs horizontally; the new-tab buttons should remain fixed on the right edge. await tabsScroll.evaluate((el) => { (el as HTMLElement).scrollLeft = (el as HTMLElement).scrollWidth; }); await page.waitForTimeout(200); const agentBoundsAfter = await agentButton.boundingBox(); const terminalBoundsAfter = await terminalButton.boundingBox(); expect(agentBoundsAfter).not.toBeNull(); expect(terminalBoundsAfter).not.toBeNull(); if (!agentBoundsAfter || !terminalBoundsAfter) { return; } expect(agentBoundsAfter.x).toBeGreaterThanOrEqual(0); expect(agentBoundsAfter.y).toBeGreaterThanOrEqual(0); expect(agentBoundsAfter.x + agentBoundsAfter.width).toBeLessThanOrEqual(viewport.width); expect(agentBoundsAfter.y + agentBoundsAfter.height).toBeLessThanOrEqual(viewport.height); expect(terminalBoundsAfter.x).toBeGreaterThanOrEqual(0); expect(terminalBoundsAfter.y).toBeGreaterThanOrEqual(0); expect(terminalBoundsAfter.x + terminalBoundsAfter.width).toBeLessThanOrEqual(viewport.width); expect(terminalBoundsAfter.y + terminalBoundsAfter.height).toBeLessThanOrEqual(viewport.height); } finally { await repo.cleanup(); } }); test("workspace explorer toggle opens and closes explorer", async ({ page }) => { const repo = await createTempGitRepo("paseo-e2e-workspace-explorer-toggle-"); try { await openWorkspaceWithAgent(page, repo.path); const toggle = page.getByTestId("workspace-explorer-toggle").first(); const explorerHeader = page.locator('[data-testid="explorer-header"]:visible').first(); await expect(toggle).toBeVisible({ timeout: 30000 }); const initiallyExpanded = (await toggle.getAttribute("aria-expanded")) === "true"; if (initiallyExpanded) { await toggle.click(); await expect(toggle).toHaveAttribute("aria-expanded", "false"); await expect(explorerHeader).not.toBeVisible({ timeout: 10000 }); } await toggle.click(); await expect(toggle).toHaveAttribute("aria-expanded", "true"); await expect(explorerHeader).toBeVisible({ timeout: 10000 }); await toggle.click(); await expect(toggle).toHaveAttribute("aria-expanded", "false"); await expect(explorerHeader).not.toBeVisible({ timeout: 10000 }); } finally { await repo.cleanup(); } });