import { expect, story } from "../../storybook/playwright/story" story("keeps file disclosures keyboard-accessible as the file list changes", async ({ mount }) => { const root = await mount("current-tool-group--patch-follow-ups") const patch = root.locator('[data-component="apply-patch-tool"]') const first = patch.getByRole("button", { name: /a\.ts/ }) const second = patch.getByRole("button", { name: /b\.ts/ }) await expect(first).toHaveAttribute("aria-expanded", "false") await first.focus() await first.press("ArrowDown") await expect(second).toBeFocused() await second.press("ArrowDown") await expect(first).toBeFocused() await first.press("End") await expect(second).toBeFocused() await second.press("Home") await expect(first).toBeFocused() await first.press("Enter") await expect(first).toHaveAttribute("aria-expanded", "true") await expect(patch.getByRole("region", { name: /a\.ts/ })).toBeVisible() await first.press("Space") await expect(first).toHaveAttribute("aria-expanded", "false") await expect(patch.getByRole("region", { name: /a\.ts/ })).toHaveCount(0) await root.getByRole("button", { name: "Finish follow-up patch", exact: true }).click() const third = patch.getByRole("button", { name: /c\.ts/ }) await expect(third).toHaveAttribute("aria-expanded", "false") await second.focus() await second.press("ArrowDown") await expect(third).toBeFocused() await third.press("ArrowUp") await expect(second).toBeFocused() }) story("merges follow-up patches into one stack with distinct files", async ({ mount }, info) => { const root = await mount("current-tool-group--patch-follow-ups") const group = root.locator('[data-component="collapsed-tool-group"]') const patches = group.locator('[data-component="apply-patch-tool"]') await expect(patches).toHaveCount(1) await expect(patches.locator('[data-slot="apply-patch-filename"]')).toHaveText(["a.ts", "b.ts"]) const first = patches.locator('[data-scope="apply-patch"] button').filter({ hasText: "a.ts" }) await first.click() await expect(first).toHaveAttribute("aria-expanded", "true") await root.getByRole("button", { name: "Start follow-up patch" }).click() await expect(group.locator('[data-component="context-tool-group-trigger"]')).toHaveAttribute( "aria-label", "Used 3 Shell, Patch", ) await expect(patches).toHaveCount(1) await expect(patches.locator('[data-slot="apply-patch-filename"]')).toHaveText(["a.ts", "b.ts"]) await root.getByRole("button", { name: "Finish follow-up patch" }).click() await expect(patches).toHaveCount(1) await expect(patches.locator('[data-slot="apply-patch-filename"]')).toHaveText(["a.ts", "b.ts", "c.ts"]) await expect(first).toHaveAttribute("aria-expanded", "true") await expect(patches.locator('[data-component="file"]')).toBeVisible() await group.screenshot({ path: info.outputPath("merged.png") }) }) for (const separator of ["shell", "error", "reasoning"]) { story(`does not merge patches across an intervening ${separator}`, async ({ mount }) => { const root = await mount("current-tool-group--patch-follow-ups", { args: { separator } }) await root.getByRole("button", { name: "Finish follow-up patch" }).click() const group = root.locator('[data-component="collapsed-tool-group"]') await expect(group.locator('[data-component="apply-patch-tool"]')).toHaveCount(2) await expect(group.locator('[data-slot="apply-patch-filename"]')).toHaveText(["a.ts", "b.ts", "a.ts", "c.ts"]) if (separator === "error") await expect(group.locator('[data-kind="tool-error-card"]')).toBeVisible() }) } story("does not retain patch files in the wrong batch when thoughts are shown", async ({ mount }) => { const root = await mount("current-tool-group--patch-follow-ups", { args: { separator: "reasoning" } }) await root.getByRole("button", { name: "Hide thoughts", exact: true }).click() await root.getByRole("button", { name: "Finish follow-up patch" }).click() const group = root.locator('[data-component="collapsed-tool-group"]') await expect(group.locator('[data-component="apply-patch-tool"]')).toHaveCount(1) await expect(group.locator('[data-slot="apply-patch-filename"]')).toHaveText(["a.ts", "b.ts", "c.ts"]) await root.getByRole("button", { name: "Show thoughts", exact: true }).click() await expect(group.locator('[data-component="apply-patch-tool"]')).toHaveCount(2) await expect(group.locator('[data-slot="apply-patch-filename"]')).toHaveText(["a.ts", "b.ts", "a.ts", "c.ts"]) })