2ed65cfde3
* fix(web): guard dockview measure against mid-transition sidebar width The unified AppSidebar (#1165) animates its width over 300ms; the dockview content container (a flex sibling) can be measured mid-transition at a tiny positive width in onReady, so the default layout builds too narrow and dockview collapses the horizontal columns into a vertical stack. measureDockviewContainer trusted any positive parent clientWidth. Reject an implausibly-small live width (< 50% of viewport) as a not-yet-laid-out transient and fall back to the viewport; the resize observer then snaps to the exact size. * fix(web): preserve live height when width guard fires; assert it
62 lines
2.9 KiB
TypeScript
62 lines
2.9 KiB
TypeScript
import { afterEach, describe, expect, it } from "vitest";
|
||
import type { DockviewApi } from "dockview-react";
|
||
import { measureDockviewContainer } from "./dockview-measure";
|
||
|
||
function fakeApi(width: number, height: number): DockviewApi {
|
||
return { width, height } as unknown as DockviewApi;
|
||
}
|
||
|
||
describe("measureDockviewContainer", () => {
|
||
afterEach(() => {
|
||
document.body.innerHTML = "";
|
||
});
|
||
|
||
it("uses the live container size when it is laid out", () => {
|
||
const parent = document.createElement("div");
|
||
Object.defineProperty(parent, "clientWidth", { value: 1500, configurable: true });
|
||
Object.defineProperty(parent, "clientHeight", { value: 700, configurable: true });
|
||
const dv = document.createElement("div");
|
||
dv.className = "dv-dockview";
|
||
parent.appendChild(dv);
|
||
document.body.appendChild(parent);
|
||
|
||
expect(measureDockviewContainer(fakeApi(0, 0))).toEqual({ width: 1500, height: 700 });
|
||
});
|
||
|
||
it("ignores an implausibly-narrow live width (sidebar mid-transition) but keeps the live height", () => {
|
||
// Regression (post unified-sidebar #1165): the AppSidebar is a root-layout
|
||
// flex sibling with `transition-all duration-300`, so the dockview content
|
||
// container can be measured mid-animation at a tiny positive width. Building
|
||
// the default layout at that width collapses the horizontal columns into a
|
||
// vertical stack (chat / files+changes / terminal). On desktop the sidebar
|
||
// maxes at 30vw, so content is always >= ~70vw — a sub-half-viewport read is
|
||
// definitionally a transient: fall back the width to the viewport so the
|
||
// build stays horizontal (the resize observer then snaps to the exact size).
|
||
// The animation is horizontal, so the live height is reliable and is kept.
|
||
const parent = document.createElement("div");
|
||
Object.defineProperty(parent, "clientWidth", { value: 80, configurable: true });
|
||
Object.defineProperty(parent, "clientHeight", { value: 700, configurable: true });
|
||
const dv = document.createElement("div");
|
||
dv.className = "dv-dockview";
|
||
parent.appendChild(dv);
|
||
document.body.appendChild(parent);
|
||
|
||
const result = measureDockviewContainer(fakeApi(0, 0));
|
||
expect(result.width).toBe(window.innerWidth);
|
||
expect(result.height).toBe(700);
|
||
});
|
||
|
||
it("never returns a zero size on a fresh mount (no container, api not laid out yet)", () => {
|
||
// Regression: a 0×0 measurement builds the default layout at zero width, so
|
||
// dockview collapses the horizontal columns into a vertical stack (chat /
|
||
// files+changes / terminal). Fall back to the viewport instead so the
|
||
// default builds horizontally; the resize observer then snaps it to the
|
||
// exact container size.
|
||
const { width, height } = measureDockviewContainer(fakeApi(0, 0));
|
||
expect(width).toBeGreaterThan(0);
|
||
expect(height).toBeGreaterThan(0);
|
||
expect(width).toBe(window.innerWidth);
|
||
expect(height).toBe(window.innerHeight);
|
||
});
|
||
});
|