test(app): address workspace layout regression review

Give the tab close control an accessible button name so browser regressions use the same control exposed to assistive technology. Exercise both Explorer visibility scenarios with explicit setup commands.
This commit is contained in:
Mohamed Boudra
2026-09-14 14:28:43 +02:00
parent cc2b96bf1a
commit 022c5053c1
3 changed files with 34 additions and 28 deletions
@@ -225,7 +225,7 @@ test.describe("explorer pane tab placement", () => {
async function closeOnlyDraft(page: Page): Promise<void> {
await draftTabChip(page).hover();
await page.locator('[data-testid^="workspace-draft-close-"]').filter({ visible: true }).click();
await page.getByRole("button", { name: "Close", exact: true }).click();
}
async function moveOnlyDraftIntoRightSplit(page: Page): Promise<void> {
@@ -740,6 +740,7 @@ function TabChip({
dragHandleProps: DraggableListDragHandleProps | undefined;
}) {
const { closeButtonTestId, contextMenuTestId, menuEntries } = resolvedTab;
const { t } = useTranslation();
const middleClickRef = useMiddleClickClose(
useCallback(() => void onCloseTab(tab.tabId), [onCloseTab, tab.tabId]),
);
@@ -889,6 +890,8 @@ function TabChip({
<Pressable
{...(closeButtonDragBlockers as object | undefined)}
testID={closeButtonTestId}
accessibilityRole="button"
accessibilityLabel={t("workspace.tabs.menu.close")}
disabled={isClosingTab}
onPressIn={handleCloseButtonPressIn}
onHoverIn={handleCloseButtonHoverIn}
@@ -1085,35 +1085,38 @@ describe("workspace-layout-store actions", () => {
expect(workspaceLayoutStore.getState().layoutByWorkspace[workspaceKey]).toBe(before);
});
it.each([true, false])("retains the last ordinary split when Explorer hidden=%s", (hidden) => {
const workspaceKey = createWorkspaceKey();
const store = workspaceLayoutStore.getState();
const tabId = store.openTab({
workspaceKey,
target: { kind: "draft", draftId: "draft-origin" },
intent: "new",
}) as string;
if (!hidden) store.showExplorerSidebar(workspaceKey);
const splitPaneId = store.splitPaneEmpty(workspaceKey, {
targetPaneId: "main",
position: "right",
}) as string;
store.moveTabToPane(workspaceKey, tabId, splitPaneId);
expect(
findPaneById(workspaceLayoutStore.getState().layoutByWorkspace[workspaceKey].root, "main"),
).toBeNull();
it.each(["hideExplorerSidebar", "showExplorerSidebar"] as const)(
"retains the last ordinary split after %s",
(setExplorerVisibility) => {
const workspaceKey = createWorkspaceKey();
const store = workspaceLayoutStore.getState();
const tabId = store.openTab({
workspaceKey,
target: { kind: "draft", draftId: "draft-origin" },
intent: "new",
}) as string;
store[setExplorerVisibility](workspaceKey);
const splitPaneId = store.splitPaneEmpty(workspaceKey, {
targetPaneId: "main",
position: "right",
}) as string;
store.moveTabToPane(workspaceKey, tabId, splitPaneId);
expect(
findPaneById(workspaceLayoutStore.getState().layoutByWorkspace[workspaceKey].root, "main"),
).toBeNull();
store.closeTab(workspaceKey, tabId);
store.closeTab(workspaceKey, tabId);
const layout = workspaceLayoutStore.getState().layoutByWorkspace[workspaceKey];
expect(
collectAllPanes(layout.root)
.filter((pane) => pane.id !== "explorer")
.map((pane) => pane.id),
).toEqual([splitPaneId]);
expect(findPaneById(layout.root, splitPaneId)?.tabIds).toHaveLength(1);
expect(layout.focusedPaneId).toBe(splitPaneId);
});
const layout = workspaceLayoutStore.getState().layoutByWorkspace[workspaceKey];
expect(
collectAllPanes(layout.root)
.filter((pane) => pane.id !== "explorer")
.map((pane) => pane.id),
).toEqual([splitPaneId]);
expect(findPaneById(layout.root, splitPaneId)?.tabIds).toHaveLength(1);
expect(layout.focusedPaneId).toBe(splitPaneId);
},
);
it.each(["explorer", "pane_generated_explorer"])(
"restores an ordinary pane beside saved hidden %s without losing tabs",