Show worktree names in workspace hover cards (#2711)

* fix(app): show worktree names in workspace hover cards

Managed worktree paths exposed Paseo's internal directory layout instead of the useful worktree name. Carry the owned worktree root through the sidebar model while preserving the full workspace path as the copy target.

* fix(workspaces): source owned worktree names from daemon

The daemon owns worktree path semantics, so expose the managed worktree slug and let the sidebar model produce a display-ready label. This keeps path parsing out of the hover-card component while preserving the full path for copying.

* fix(app): preserve worktree labels in replica cache
This commit is contained in:
Mohamed Boudra
2026-08-01 05:17:47 +08:00
committed by GitHub
parent d2de309fc3
commit 9d19e90323
15 changed files with 137 additions and 13 deletions
+56 -5
View File
@@ -47,6 +47,51 @@ async function waitForSidebarWorkspace(page: import("@playwright/test").Page, wo
return row;
}
async function openWorkspaceHoverCard(page: import("@playwright/test").Page, workspaceId: string) {
const row = await waitForSidebarWorkspace(page, workspaceId);
await row.hover();
const hoverCard = page.getByRole("menu", { name: "Workspace scripts" });
await expect(hoverCard).toBeVisible({ timeout: 30_000 });
return hoverCard;
}
interface PaseoOwnedWorktree {
projectName: string;
workspaceId: string;
worktreeSlug: string;
}
async function withPaseoOwnedWorktree(
run: (workspace: PaseoOwnedWorktree) => Promise<void>,
): Promise<void> {
const project = await seedWorkspace({ repoPrefix: "sidebar-hover-owned-worktree-" });
const worktreeSlug = "hover-card-owned-worktree";
try {
const created = await project.client.createWorkspace({
source: {
kind: "worktree",
cwd: project.repoPath,
projectId: project.projectId,
worktreeSlug,
},
});
if (!created.workspace) {
throw new Error(created.error ?? "Failed to create Paseo-owned worktree");
}
expect(path.basename(created.workspace.workspaceDirectory)).toBe(worktreeSlug);
await run({
projectName: path.basename(project.repoPath),
workspaceId: created.workspace.id,
worktreeSlug,
});
} finally {
await project.cleanup();
}
}
test.describe("Sidebar workspace list", () => {
test("project with GitHub remote shows its selected folder name in sidebar", async ({ page }) => {
const workspace = await seedWorkspace({
@@ -146,17 +191,23 @@ test.describe("Sidebar workspace list", () => {
await gotoAppShell(page);
await waitForSidebarProject(page, path.basename(workspace.repoPath));
const row = await waitForSidebarWorkspace(page, workspace.workspaceId);
await row.hover();
const hoverCard = page.getByTestId("workspace-hover-card");
await expect(hoverCard).toBeVisible({ timeout: 30_000 });
const hoverCard = await openWorkspaceHoverCard(page, workspace.workspaceId);
await expect(page.getByTestId("hover-card-workspace-host")).toHaveText("localhost");
await expect(hoverCard).not.toContainText(/\b(Online|Connecting|Offline|Error|Idle)\b/);
} finally {
await workspace.cleanup();
}
});
test("Paseo-owned worktree hover card shows the worktree directory name", async ({ page }) => {
await withPaseoOwnedWorktree(async ({ projectName, workspaceId, worktreeSlug }) => {
await gotoAppShell(page);
await waitForSidebarProject(page, projectName);
await openWorkspaceHoverCard(page, workspaceId);
await expect(page.getByTestId("hover-card-workspace-cwd")).toHaveText(worktreeSlug);
});
});
});
test.describe("Mobile sidebar panelState transition", () => {