Merge branch 'main' into feature/multi-profiles-codex-claude-model-catalogue
This commit is contained in:
@ -263,6 +263,13 @@ describe("TerminalView — visible launch-failure surface (ticket #14 F3)", () =
|
||||
globalThis.ResizeObserver = savedResizeObserver;
|
||||
});
|
||||
|
||||
function setTerminalBoxSize(width: number, height: number) {
|
||||
const container = screen.getByTestId("terminal-xterm-container");
|
||||
Object.defineProperty(container, "clientWidth", { value: width, configurable: true });
|
||||
Object.defineProperty(container, "clientHeight", { value: height, configurable: true });
|
||||
return container;
|
||||
}
|
||||
|
||||
it("sanity: with the polyfills xterm mounts and the opener runs", async () => {
|
||||
// Guards the premise of the tests below: if this fails, the opener never
|
||||
// fired and the error assertions would be vacuous.
|
||||
@ -309,6 +316,48 @@ describe("TerminalView — visible launch-failure surface (ticket #14 F3)", () =
|
||||
expect(screen.queryByTestId("terminal-error")).toBeNull();
|
||||
});
|
||||
|
||||
it("keeps a boot placeholder while the terminal box has no usable size", async () => {
|
||||
const handle = makeHandle({ sessionId: "boot-zero-1" });
|
||||
const open = vi.fn(async () => handle);
|
||||
|
||||
renderView(new MockTerminalGateway(), "/cwd", { open, refitSignal: 1 });
|
||||
await waitFor(() => expect(open).toHaveBeenCalledTimes(1));
|
||||
await new Promise((resolve) => requestAnimationFrame(resolve));
|
||||
|
||||
expect(screen.getByTestId("terminal-boot-placeholder")).toBeTruthy();
|
||||
expect(screen.getByTestId("terminal-xterm-container").style.visibility).toBe(
|
||||
"hidden",
|
||||
);
|
||||
expect(handle.resize).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("reveals xterm and resizes the handle after the first useful fit", async () => {
|
||||
const handle = makeHandle({ sessionId: "boot-ready-1" });
|
||||
const open = vi.fn(async () => handle);
|
||||
|
||||
const { rerender } = renderView(new MockTerminalGateway(), "/cwd", {
|
||||
open,
|
||||
refitSignal: 1,
|
||||
});
|
||||
await waitFor(() => expect(open).toHaveBeenCalledTimes(1));
|
||||
expect(screen.getByTestId("terminal-boot-placeholder")).toBeTruthy();
|
||||
|
||||
setTerminalBoxSize(480, 240);
|
||||
rerender(
|
||||
<DIProvider gateways={{ terminal: new MockTerminalGateway() } as unknown as Gateways}>
|
||||
<TerminalView cwd="/cwd" open={open} refitSignal={2} />
|
||||
</DIProvider>,
|
||||
);
|
||||
|
||||
await waitFor(() =>
|
||||
expect(screen.queryByTestId("terminal-boot-placeholder")).toBeNull(),
|
||||
);
|
||||
expect(screen.getByTestId("terminal-xterm-container").style.visibility).toBe(
|
||||
"visible",
|
||||
);
|
||||
await waitFor(() => expect(handle.resize).toHaveBeenCalled());
|
||||
});
|
||||
|
||||
describe("refitSignal (ticket #61 — refit after split/merge)", () => {
|
||||
it("refits WITHOUT reopening the terminal when refitSignal changes", async () => {
|
||||
// Simulates LayoutGrid bumping `useLayout`'s layout version after a
|
||||
@ -322,18 +371,14 @@ describe("TerminalView — visible launch-failure surface (ticket #14 F3)", () =
|
||||
refitSignal: 1,
|
||||
});
|
||||
await waitFor(() => expect(open).toHaveBeenCalledTimes(1));
|
||||
|
||||
const fitCallsAtMount = fitSpy.mock.calls.length;
|
||||
expect(fitCallsAtMount).toBeGreaterThan(0);
|
||||
fitSpy.mockClear();
|
||||
|
||||
// jsdom reports a zero-size layout box, which the coalesced refit
|
||||
// deliberately skips (the same guard that protects the resize-observer
|
||||
// path from fitting to a transient zero size). Stub a real size on the
|
||||
// inner xterm container so the refit triggered below actually reaches
|
||||
// `fit.fit()` instead of bailing on the zero-size guard.
|
||||
const container = screen.getByTestId("terminal-view").firstElementChild as HTMLElement;
|
||||
Object.defineProperty(container, "clientWidth", { value: 400, configurable: true });
|
||||
Object.defineProperty(container, "clientHeight", { value: 200, configurable: true });
|
||||
setTerminalBoxSize(400, 200);
|
||||
|
||||
rerender(
|
||||
<DIProvider gateways={{ terminal: new MockTerminalGateway() } as unknown as Gateways}>
|
||||
@ -341,9 +386,7 @@ describe("TerminalView — visible launch-failure surface (ticket #14 F3)", () =
|
||||
</DIProvider>,
|
||||
);
|
||||
|
||||
await waitFor(() =>
|
||||
expect(fitSpy.mock.calls.length).toBeGreaterThan(fitCallsAtMount),
|
||||
);
|
||||
await waitFor(() => expect(fitSpy).toHaveBeenCalled());
|
||||
// The structural-mutation refit must never reopen the PTY.
|
||||
expect(open).toHaveBeenCalledTimes(1);
|
||||
|
||||
@ -365,7 +408,7 @@ describe("TerminalView — visible launch-failure surface (ticket #14 F3)", () =
|
||||
await waitFor(() => expect(open).toHaveBeenCalledTimes(1));
|
||||
fitSpy.mockClear();
|
||||
|
||||
const container = screen.getByTestId("terminal-view").firstElementChild as HTMLElement;
|
||||
const container = screen.getByTestId("terminal-xterm-container");
|
||||
// jsdom's default layout box is 0x0 — exactly the transient-zero case:
|
||||
// left as-is, the container "hasn't settled" yet.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user