Files
paseo/packages/app/e2e/browser/sidebar-title-width.spec.ts

156 lines
5.6 KiB
TypeScript

import { rm, writeFile } from "node:fs/promises";
import path from "node:path";
import type { Locator, Page, TestInfo } from "@playwright/test";
import { expect, test } from "../support/fixtures";
import { gotoAppShell } from "../support/helpers/app";
import { seedWorkspace, type SeededWorkspace } from "../support/helpers/seed-client";
import {
closeSidebarDisplayPreferences,
openMobileAgentSidebar,
openSidebarDisplayPage,
selectSidebarStatusGrouping,
} from "../support/helpers/sidebar";
const TITLE = "Linux desktop sandbox launch support";
async function seedChangedWorkspace() {
const workspace = await seedWorkspace({
repoPrefix: "sidebar-title-",
title: TITLE,
repo: { withRemote: true },
});
try {
await rm(path.join(workspace.repoPath, "remote.git"), { recursive: true });
await workspace.client.renameProject(workspace.projectId, "Paseo");
await writeFile(path.join(workspace.repoPath, "README.md"), "Changed line\n".repeat(12345));
await workspace.client.checkoutRefresh(workspace.repoPath);
await expect
.poll(async () => {
const { entries } = await workspace.client.fetchWorkspaces();
return entries.find((entry) => entry.id === workspace.workspaceId)?.diffStat?.additions;
})
.toBe(12345);
return workspace;
} catch (error) {
await workspace.cleanup();
throw error;
}
}
function workspaceRow(page: Page) {
return page.getByRole("button", { name: new RegExp(TITLE) }).filter({ visible: true });
}
async function titleWidth(row: Locator) {
return row
.getByText(TITLE, { exact: true })
.evaluate((element) => element.getBoundingClientRect().width);
}
async function toggleTrailing(page: Page, label: "Diff stats" | "Last activity", touch = false) {
await openSidebarDisplayPage(page, "sidebar-display-show");
await page.getByRole("menuitem", { name: label, exact: true }).click();
if (touch) {
await page
.getByRole("button", { name: "Bottom sheet backdrop", exact: true })
.click({ position: { x: 5, y: 5 } });
await expect(
page.getByRole("button", { name: "Bottom sheet backdrop", exact: true }),
).toHaveCount(0);
} else {
await closeSidebarDisplayPreferences(page);
}
await page.mouse.move(0, 0);
}
async function expectTouchTitleWidth(page: Page) {
const row = workspaceRow(page);
const withDiff = await titleWidth(row);
await toggleTrailing(page, "Diff stats", true);
const withoutStats = await titleWidth(row);
expect(withDiff).toBeCloseTo(withoutStats, 0);
await toggleTrailing(page, "Last activity", true);
expect(await titleWidth(row)).toBeCloseTo(withoutStats, 0);
await toggleTrailing(page, "Diff stats", true);
}
let workspace: SeededWorkspace;
test.beforeEach(async () => {
workspace = await seedChangedWorkspace();
});
test.afterEach(async () => {
await workspace?.cleanup();
});
async function openTouchWorkspaceList(page: Page, testInfo: TestInfo) {
await page.setViewportSize({ width: 390, height: 844 });
await page.emulateMedia({ colorScheme: "dark" });
await gotoAppShell(page);
await openMobileAgentSidebar(page);
await expect(workspaceRow(page)).toBeVisible();
await toggleTrailing(page, "Diff stats", true);
await page.mouse.move(0, 0);
await page.screenshot({ path: testInfo.outputPath("sidebar.png") });
}
async function pinWorkspaceForLayout(page: Page) {
await workspace.client.setWorkspacePinned(workspace.workspaceId, true);
await expect(page.getByTestId("sidebar-pinned-section")).toBeVisible();
}
async function moveWorkspaceToStatusGrouping(page: Page) {
await workspace.client.setWorkspacePinned(workspace.workspaceId, false);
await selectSidebarStatusGrouping(page);
}
async function openDesktopWorkspaceList(page: Page) {
await gotoAppShell(page);
const row = workspaceRow(page);
await expect(row).toBeVisible();
await toggleTrailing(page, "Diff stats");
await page.mouse.move(0, 0);
await expect(row.getByText("+12.3k", { exact: true })).toBeVisible();
return titleWidth(row);
}
async function expectHoverKeepsTitleWidth(page: Page, width: number, testInfo: TestInfo) {
const row = workspaceRow(page);
await row.hover();
await expect(row.getByLabel("Workspace actions", { exact: true })).toBeVisible();
expect(await titleWidth(row)).toBeCloseTo(width, 0);
await page.screenshot({ path: testInfo.outputPath("desktop-hover.png") });
}
async function expectShortcutHintsKeepTitleWidth(page: Page, width: number, testInfo: TestInfo) {
const row = workspaceRow(page);
await page.keyboard.down("Alt");
await expect(row.getByText("1", { exact: true })).toBeVisible();
expect(await titleWidth(row)).toBeCloseTo(width, 0);
await page.screenshot({ path: testInfo.outputPath("desktop-shortcuts.png") });
await page.keyboard.up("Alt");
await expect(row.getByText("1", { exact: true })).toHaveCount(0);
}
async function expectDisablingStatsExpandsTitle(page: Page, width: number) {
await toggleTrailing(page, "Diff stats");
expect(await titleWidth(workspaceRow(page))).toBeGreaterThan(width);
}
test("touch titles use the space occupied by hidden stats in every grouping", async ({
page,
}, testInfo) => {
await openTouchWorkspaceList(page, testInfo);
await expectTouchTitleWidth(page);
await pinWorkspaceForLayout(page);
await expectTouchTitleWidth(page);
await moveWorkspaceToStatusGrouping(page);
await expectTouchTitleWidth(page);
});
test("desktop hover and shortcut hints preserve title width", async ({ page }, testInfo) => {
const width = await openDesktopWorkspaceList(page);
await expectHoverKeepsTitleWidth(page, width, testInfo);
await expectShortcutHintsKeepTitleWidth(page, width, testInfo);
await expectDisablingStatsExpandsTitle(page, width);
});