Files
paseo/packages/app/e2e/support/helpers/branch-switcher.ts
T
Mohamed BoudraandGitHub ab274d635e Make the workspace right pane a first-class tab host (#3287)
* feat(app): add persistent workspace side panes

Keep the common review and file-browsing workflow beside the active agent without tearing down pane contents. Workspace tabs now share one compact chip language, assistant file links route into the retained right pane, and diff/file trees share stable geometry.

* fix(app): localize pull request empty state

* test(app): update explorer pane coverage

* fix(app): preserve explorer pane workflows

* test(app): make explorer tab selection idempotent

* fix(app): persist workspace review pins

* fix(app): preserve sidebar scrim drag hook

* fix(app): restore companion pane interactions

* test(app): follow selected sidebar surface
2026-08-16 18:18:32 +02:00

60 lines
2.7 KiB
TypeScript

import { expect, type Page } from "@playwright/test";
import { escapeRegex } from "./regex";
import { openChangesPanel as openWorkspaceChangesPanel } from "./workspace-tabs";
// The branch switcher lives in the Changes tab, not in the workspace header. It renders as a button whose
// accessible name carries the current branch ("Current branch: <name>. Press to
// switch branch."). Matching on the accessible name keeps these helpers tied to
// what a screen reader user hears, and it proves the panel resolved a real
// checkout directory from the opaque workspace id. Scoping to the changes header
// keeps the matcher unambiguous even when the header is shared with diff actions.
function branchSwitcherTrigger(page: Page, branchName: string) {
return page
.getByTestId("changes-header")
.getByRole("button", { name: new RegExp(`Current branch: ${escapeRegex(branchName)}\\b`) })
.filter({ visible: true })
.first();
}
// Opens the fixed pane and lands on the Changes tab, where the switcher and diff live.
export async function openChangesPanel(page: Page): Promise<void> {
await openWorkspaceChangesPanel(page);
await expect(page.getByTestId("changes-header").filter({ visible: true }).first()).toBeVisible({
timeout: 30_000,
});
}
export async function expectWorkspaceBranch(page: Page, branchName: string): Promise<void> {
await expect(branchSwitcherTrigger(page, branchName)).toBeVisible({ timeout: 30_000 });
}
export async function switchBranchFromChangesPanel(
page: Page,
input: { from: string; to: string },
): Promise<void> {
await branchSwitcherTrigger(page, input.from).click();
const picker = page.getByTestId("combobox-desktop-container");
await expect(picker).toBeVisible({ timeout: 30_000 });
// The branch switcher combobox renders its options as plain text rows with no ARIA
// role, so filter by the visible branch name and click the matching row. Filtering
// first guarantees a single, unambiguous match.
const search = page.getByPlaceholder("Filter branches...");
await expect(search).toBeVisible({ timeout: 30_000 });
await search.fill(input.to);
const option = picker.getByText(input.to, { exact: true });
await expect(option).toBeVisible({ timeout: 30_000 });
await option.click();
await expect(picker).not.toBeVisible({ timeout: 30_000 });
}
// The workspace header title is a plain static title in Model B; the branch
// switcher must never appear there. Asserting on the header testID keeps this
// honest even as the switcher continues to exist inside the Changes panel.
export async function expectNoBranchSwitcherInWorkspaceHeader(page: Page): Promise<void> {
await expect(page.getByTestId("workspace-header-branch-switcher")).toHaveCount(0);
}