feat: add adaptive agent workspace windows
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import {
|
||||
MAX_ANALYSIS_WINDOWS,
|
||||
closeAnalysisWindow,
|
||||
createInitialWorkspaceState,
|
||||
maximizeWorkspaceWindow,
|
||||
minimizeWorkspaceWindow,
|
||||
openAnalysisDocument,
|
||||
resizeWorkspace,
|
||||
restoreWorkspaceWindow,
|
||||
updateWorkspaceWindowRect,
|
||||
type AnalysisDocument
|
||||
} from "./workspace-model";
|
||||
|
||||
const bounds = { width: 1180, height: 760 };
|
||||
|
||||
function documentAt(index: number): AnalysisDocument {
|
||||
return {
|
||||
id: `analysis-${index}`,
|
||||
title: `分析 ${index}`,
|
||||
subtitle: "测试",
|
||||
generatedAt: "10:40:00",
|
||||
blocks: []
|
||||
};
|
||||
}
|
||||
|
||||
describe("workspace window lifecycle", () => {
|
||||
it("minimizes the map for the first analysis and restores it after the last window closes", () => {
|
||||
const initial = createInitialWorkspaceState(bounds);
|
||||
const opened = openAnalysisDocument(initial, documentAt(1), bounds);
|
||||
|
||||
expect(opened.map.mode).toBe("minimized");
|
||||
expect(opened.analyses).toHaveLength(1);
|
||||
|
||||
const closed = closeAnalysisWindow(opened, "analysis-1");
|
||||
expect(closed.analyses).toHaveLength(0);
|
||||
expect(closed.map.mode).toBe("docked");
|
||||
expect(closed.activeWindowId).toBe("workspace-map");
|
||||
});
|
||||
|
||||
it("supports minimize, maximize and bounded restore", () => {
|
||||
const opened = openAnalysisDocument(createInitialWorkspaceState(bounds), documentAt(1), bounds);
|
||||
const minimized = minimizeWorkspaceWindow(opened, "analysis-1");
|
||||
expect(minimized.analyses[0]?.mode).toBe("minimized");
|
||||
|
||||
const restored = restoreWorkspaceWindow(minimized, "analysis-1", bounds);
|
||||
expect(restored.analyses[0]?.mode).toBe("floating");
|
||||
|
||||
const maximized = maximizeWorkspaceWindow(restored, "analysis-1");
|
||||
expect(maximized.analyses[0]?.mode).toBe("maximized");
|
||||
|
||||
const resized = updateWorkspaceWindowRect(
|
||||
maximized,
|
||||
"analysis-1",
|
||||
{ x: -100, y: -80, width: 4000, height: 3000 },
|
||||
bounds
|
||||
);
|
||||
expect(resized.analyses[0]?.rect).toEqual({ x: 12, y: 12, width: 1156, height: 736 });
|
||||
});
|
||||
|
||||
it("caps transient analysis windows without deleting an existing result", () => {
|
||||
const state = Array.from({ length: MAX_ANALYSIS_WINDOWS }, (_, index) => index + 1).reduce(
|
||||
(current, index) => openAnalysisDocument(current, documentAt(index), bounds),
|
||||
createInitialWorkspaceState(bounds)
|
||||
);
|
||||
|
||||
const overflow = openAnalysisDocument(state, documentAt(99), bounds);
|
||||
expect(overflow).toBe(state);
|
||||
expect(overflow.analyses).toHaveLength(MAX_ANALYSIS_WINDOWS);
|
||||
});
|
||||
|
||||
it("reclamps current and restore rectangles when the workspace shrinks", () => {
|
||||
const opened = openAnalysisDocument(createInitialWorkspaceState(bounds), documentAt(1), bounds);
|
||||
const moved = updateWorkspaceWindowRect(
|
||||
opened,
|
||||
"analysis-1",
|
||||
{ x: 500, y: 260, width: 660, height: 480 },
|
||||
bounds
|
||||
);
|
||||
|
||||
const resized = resizeWorkspace(moved, { width: 800, height: 600 });
|
||||
const analysis = resized.analyses[0];
|
||||
expect(analysis?.rect).toEqual({ x: 128, y: 108, width: 660, height: 480 });
|
||||
expect(analysis?.restoreRect).toEqual(analysis?.rect);
|
||||
expect(resized.map.restoreRect.x + resized.map.restoreRect.width).toBeLessThanOrEqual(788);
|
||||
expect(resized.map.restoreRect.y + resized.map.restoreRect.height).toBeLessThanOrEqual(588);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user