* fix(app): make session rename reachable in the mobile sessions dropdown The per-session actions menu in the mobile tab switcher (a gorhom bottom sheet) opened as an anchored popover, which on native renders a second RN Modal stacked on the sheet — the fragile nested-overlay case docs/floating-panels.md warns about. The actions menu (incl. Rename) never appeared on native, so sessions could not be renamed from the dropdown. Give the menu compactMode="sheet" like every other mobile menu in the file, so it stacks as a gorhom sheet on a gorhom sheet (the supported path). Extract the accessory into workspace-tab-trailing-accessory.tsx and add a reachability test that fails if the sheet presentation regresses. * test(app): cover compact session rename via the tab switcher e2e Adds a Playwright spec that drives the mobile-viewport sessions dropdown -> per-session actions sheet -> Rename, exercising the real gorhom sheet interaction the fix restores (the desktop rename specs only cover the right-click context menu, and the unit test mocks the menu engine). --------- Co-authored-by: Klaude <klaude@Klaudes-MacBook-Pro.local> Co-authored-by: Mohamed Boudra <boudra.moha@gmail.com>
77 lines
3.2 KiB
TypeScript
77 lines
3.2 KiB
TypeScript
import { randomUUID } from "node:crypto";
|
|
import { test, expect } from "../support/fixtures";
|
|
import { openAgentRoute, seedMockAgentWorkspace } from "../support/helpers/mock-agent";
|
|
import { renameModalInput, renameModalSubmit } from "../support/helpers/rename";
|
|
import type { SeedDaemonClient } from "../support/helpers/seed-client";
|
|
|
|
const MOBILE_VIEWPORT = { width: 390, height: 844 };
|
|
|
|
async function fetchAgentTitle(client: SeedDaemonClient, agentId: string): Promise<string | null> {
|
|
const result = await client.fetchAgents({ scope: "active" });
|
|
return result.entries.find((entry) => entry.agent.id === agentId)?.agent.title ?? null;
|
|
}
|
|
|
|
/**
|
|
* Compact "sessions dropdown" rename path. The desktop rename specs drive the right-click
|
|
* `workspace-tab-context-*` menu, which portals into overlay-root and was never broken. This
|
|
* exercises the tab switcher's per-session actions on a phone-sized viewport — the path that
|
|
* regressed when the actions menu presented as a popover instead of a bottom sheet.
|
|
*/
|
|
test.describe("Workspace session rename (compact tab switcher)", () => {
|
|
test("renames an agent session from the switcher's per-session actions sheet", async ({
|
|
page,
|
|
}) => {
|
|
test.setTimeout(120_000);
|
|
|
|
await page.setViewportSize(MOBILE_VIEWPORT);
|
|
const initialTitle = `switcher-rename-${randomUUID().slice(0, 8)}`;
|
|
const session = await seedMockAgentWorkspace({
|
|
repoPrefix: "workspace-switcher-rename-",
|
|
title: initialTitle,
|
|
});
|
|
|
|
try {
|
|
await openAgentRoute(page, session);
|
|
await expect(page.getByTestId("workspace-tab-switcher-trigger")).toBeVisible({
|
|
timeout: 30_000,
|
|
});
|
|
|
|
// Open the sessions dropdown (a bottom sheet on compact).
|
|
await page.getByRole("button", { name: /Switch tabs/ }).click();
|
|
await expect(page.getByRole("button", { name: "Bottom sheet backdrop" }).first()).toBeVisible(
|
|
{
|
|
timeout: 10_000,
|
|
},
|
|
);
|
|
|
|
// Open this session's "…" actions. Before the fix this tried to open a popover-Modal
|
|
// that never surfaced over the sheet on native; it now opens as a stacked sheet.
|
|
const menuBase = `workspace-tab-menu-agent_${session.agentId}`;
|
|
const actionsTrigger = page.getByTestId(`${menuBase}-trigger`);
|
|
await expect(actionsTrigger).toBeVisible({ timeout: 15_000 });
|
|
await actionsTrigger.click();
|
|
|
|
const renameItem = page.getByTestId(`${menuBase}-rename`);
|
|
await expect(renameItem).toBeVisible({ timeout: 10_000 });
|
|
await renameItem.click();
|
|
|
|
const modalPrefix = `workspace-tab-rename-modal-agent-${session.agentId}`;
|
|
const input = renameModalInput(page, modalPrefix);
|
|
await expect(input).toBeVisible({ timeout: 10_000 });
|
|
await expect(input).toHaveValue(initialTitle);
|
|
|
|
const renamed = "Renamed from the dropdown";
|
|
await input.fill(renamed);
|
|
await renameModalSubmit(page, modalPrefix).click();
|
|
|
|
await expect(input).toHaveCount(0, { timeout: 15_000 });
|
|
await expect(page.getByTestId("workspace-tab-switcher-trigger")).toContainText(renamed, {
|
|
timeout: 15_000,
|
|
});
|
|
await expect.poll(() => fetchAgentTitle(session.client, session.agentId)).toBe(renamed);
|
|
} finally {
|
|
await session.cleanup();
|
|
}
|
|
});
|
|
});
|