fix(web): recalculate dockview layout after fast-path session switch (#571)
* fix(web): recalculate dockview layout after fast-path session switch The fast path in tryFastSessionSwitch removed ephemeral panels but never called api.layout() to redistribute column widths, leaving a gap on the right side of the screen. Both slow-path branches already make this call. * test(web): add regression test for fast-path layout call Verifies that performSessionSwitch calls api.layout() on both the fast path and slow path, preventing the squished-layout regression. * test(web): cover saved-layout fast path branch * fix(web): replace no-explicit-any cast in test * fix(web): fix test isolation with mockReturnValueOnce Use mockReturnValueOnce and clearAllMocks for proper test isolation between fast-path and slow-path test cases. * test(web): fix mock shape to match LayoutGroupIds type
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
import { describe, it, expect, vi, beforeEach } from "vitest";
|
||||
import { performSessionSwitch, type SessionSwitchParams } from "./dockview-session-switch";
|
||||
|
||||
// Mock dependencies
|
||||
vi.mock("@/lib/local-storage", () => ({
|
||||
getSessionLayout: vi.fn(() => null),
|
||||
}));
|
||||
|
||||
vi.mock("./dockview-layout-builders", () => ({
|
||||
applyLayoutFixups: vi.fn(() => ({
|
||||
sidebarGroupId: "g1",
|
||||
centerGroupId: "g2",
|
||||
rightTopGroupId: "g3",
|
||||
rightBottomGroupId: "g4",
|
||||
})),
|
||||
}));
|
||||
|
||||
vi.mock("./layout-manager", () => ({
|
||||
fromDockviewApi: vi.fn(() => ({ columns: [] })),
|
||||
savedLayoutMatchesLive: vi.fn(() => false),
|
||||
layoutStructuresMatch: vi.fn(() => false),
|
||||
}));
|
||||
|
||||
import { getSessionLayout } from "@/lib/local-storage";
|
||||
import { layoutStructuresMatch, savedLayoutMatchesLive } from "./layout-manager";
|
||||
|
||||
function makeMockApi() {
|
||||
return {
|
||||
panels: [],
|
||||
layout: vi.fn(),
|
||||
fromJSON: vi.fn(),
|
||||
getPanel: vi.fn(),
|
||||
} as unknown as SessionSwitchParams["api"];
|
||||
}
|
||||
|
||||
function makeParams(overrides?: Partial<SessionSwitchParams>): SessionSwitchParams {
|
||||
return {
|
||||
api: makeMockApi(),
|
||||
oldSessionId: "old-session",
|
||||
newSessionId: "new-session",
|
||||
safeWidth: 800,
|
||||
safeHeight: 600,
|
||||
buildDefault: vi.fn(),
|
||||
getDefaultLayout: vi.fn(() => ({ columns: [] })),
|
||||
...overrides,
|
||||
};
|
||||
}
|
||||
|
||||
describe("performSessionSwitch", () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
it("calls api.layout on the fast path when structures match", () => {
|
||||
vi.mocked(layoutStructuresMatch).mockReturnValueOnce(true);
|
||||
const params = makeParams();
|
||||
|
||||
performSessionSwitch(params);
|
||||
|
||||
expect(params.api.layout).toHaveBeenCalledWith(800, 600);
|
||||
});
|
||||
|
||||
it("calls api.layout on the fast path when saved layout matches", () => {
|
||||
vi.mocked(getSessionLayout).mockReturnValueOnce({ grid: {} } as unknown as ReturnType<
|
||||
typeof getSessionLayout
|
||||
>);
|
||||
vi.mocked(savedLayoutMatchesLive).mockReturnValueOnce(true);
|
||||
const params = makeParams();
|
||||
|
||||
performSessionSwitch(params);
|
||||
|
||||
expect(params.api.layout).toHaveBeenCalledWith(800, 600);
|
||||
expect(params.api.fromJSON).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("calls api.layout on the slow path (buildDefault fallback)", () => {
|
||||
const params = makeParams();
|
||||
|
||||
performSessionSwitch(params);
|
||||
|
||||
expect(params.api.layout).toHaveBeenCalledWith(800, 600);
|
||||
expect(params.buildDefault).toHaveBeenCalledWith(params.api);
|
||||
});
|
||||
});
|
||||
@@ -83,6 +83,7 @@ function tryFastSessionSwitch(params: SessionSwitchParams): LayoutGroupIds | nul
|
||||
// Session-scoped portals (terminal, browser, etc.) will be re-acquired
|
||||
// via usePortalSlot's sessionId dependency change.
|
||||
removeEphemeralPanels(api, newSessionId);
|
||||
api.layout(params.safeWidth, params.safeHeight);
|
||||
return applyLayoutFixups(api);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user