Files
kandev/apps/web/components/task/dockview-session-tabs.test-utils.ts
T
2026-07-27 20:48:20 +01:00

88 lines
2.8 KiB
TypeScript

import { vi } from "vitest";
import type { DockviewApi } from "dockview-react";
import { CENTER_GROUP, RIGHT_TOP_GROUP } from "@/lib/state/layout-manager";
type HandoffPanel = {
id: string;
group: HandoffGroup;
api: {
close: ReturnType<typeof vi.fn<() => void>>;
component: string;
};
};
type HandoffGroup = {
id: string;
panels: HandoffPanel[];
};
type HandoffAddOptions = {
id: string;
component: string;
position?: { referenceGroup?: string; index?: number };
};
/**
* Models the Dockview behavior behind the layout corruption: closing the
* final panel synchronously destroys its group. The right-side groups remain
* so a later fallback would attach the incoming session in the wrong split.
*/
export function makeSharedEnvironmentHandoffApi(): {
api: DockviewApi;
events: string[];
groupIds: () => string[];
} {
const center: HandoffGroup = { id: CENTER_GROUP, panels: [] };
const rightTop: HandoffGroup = { id: RIGHT_TOP_GROUP, panels: [] };
const rightBottom: HandoffGroup = { id: "group-right-bottom", panels: [] };
const groups = [center, rightTop, rightBottom];
const panels: HandoffPanel[] = [];
const events: string[] = [];
const removePanel = (panel: HandoffPanel) => {
events.push(`close:${panel.id}`);
const panelIndex = panels.indexOf(panel);
if (panelIndex !== -1) panels.splice(panelIndex, 1);
const groupPanelIndex = panel.group.panels.indexOf(panel);
if (groupPanelIndex !== -1) panel.group.panels.splice(groupPanelIndex, 1);
if (panel.group.panels.length === 0) {
const groupIndex = groups.indexOf(panel.group);
if (groupIndex !== -1) groups.splice(groupIndex, 1);
}
};
const createPanel = (id: string, component: string, group: HandoffGroup, index?: number) => {
const panel: HandoffPanel = {
id,
group,
api: {
close: vi.fn(() => removePanel(panel)),
component,
},
};
panels.push(panel);
group.panels.splice(index ?? group.panels.length, 0, panel);
};
createPanel("session:outgoing", "chat", center);
createPanel("files", "files", rightTop);
createPanel("changes", "changes", rightTop);
createPanel("terminal-default", "terminal", rightBottom);
return {
api: {
panels,
groups,
getPanel: (id: string) => panels.find((panel) => panel.id === id) ?? null,
addPanel: (options: HandoffAddOptions) => {
const group = groups.find((candidate) => candidate.id === options.position?.referenceGroup);
if (!group) throw new Error("expected a live reference group");
events.push(`add:${options.id}`);
createPanel(options.id, options.component, group, options.position?.index);
},
} as unknown as DockviewApi,
events,
groupIds: () => groups.map((group) => group.id),
};
}