Merge remote-tracking branch 'origin/max/tui-renderer' into max/tui-cursor-fixes

* origin/max/tui-renderer:
  fix(desktop): preserve terminal mode while tab attaches

Signed-off-by: npub1mprnacetjua2xx3p5eddmhxyk6wv929ymm5py8kd2xfxurxahspqqlgyta <d8473ee32b973aa31a21a65adddcc4b69cc2a8a4dee8121ecd51926e0cddbc02@buzz.block.builderlab.xyz>
This commit is contained in:
npub1mprnacetjua2xx3p5eddmhxyk6wv929ymm5py8kd2xfxurxahspqqlgyta
2026-08-02 16:55:54 -04:00
2 changed files with 58 additions and 2 deletions
@@ -130,7 +130,7 @@ test("mounted bootstrap passes GUI context and ACKs only after consuming a frame
const { ThemeProvider } = await import("@/shared/theme/ThemeProvider");
const { TerminalBootstrap } = await import("./TerminalBootstrap.tsx");
render(
const view = render(
createElement(
StrictMode,
null,
@@ -205,6 +205,7 @@ test("mounted bootstrap passes GUI context and ACKs only after consuming a frame
calls.filter(({ command }) => command === "terminal_ack").length,
1,
);
view.unmount();
});
test("resize during in-flight catch-up keeps the newest viewport ready", async () => {
const { createElement } = await import("react");
@@ -262,3 +263,58 @@ test("resize during in-flight catch-up keeps the newest viewport ready", async (
assert.equal(readyCalls.at(-1).args.viewport.columns, 200);
view.unmount();
});
test("opening a tab keeps terminal ownership while its attachment is pending", async () => {
const { createElement } = await import("react");
const { act, fireEvent, render, waitFor } = await import(
"@testing-library/react"
);
const { ThemeProvider } = await import("@/shared/theme/ThemeProvider");
const { TerminalBootstrap } = await import("./TerminalBootstrap.tsx");
const view = render(
createElement(
ThemeProvider,
null,
createElement("div", {
className: "buzz-huddle-app-surface",
tabIndex: -1,
}),
createElement(TerminalBootstrap, {
channelId: "channel-1",
channelName: "general",
npub: "npub1owner",
relayUrl: "wss://relay.example",
threadId: null,
}),
),
);
await waitFor(() =>
assert.ok(calls.some(({ command }) => command === "terminal_attach")),
);
await act(async () => {
await Promise.resolve();
});
const substrate = view.container.querySelector(".buzz-terminal-substrate");
const chord = { bubbles: true, code: "KeyJ", metaKey: true };
act(() => {
window.dispatchEvent(new KeyboardEvent("keydown", chord));
window.dispatchEvent(new KeyboardEvent("keyup", chord));
});
await waitFor(() =>
assert.equal(substrate.dataset.terminalOwner, "terminal"),
);
attachResolver = () => {};
fireEvent.click(view.getByLabelText("New Buzz Term tab"));
await waitFor(() => assert.equal(typeof attachResolver, "function"));
assert.equal(
substrate.dataset.terminalOwner,
"terminal",
"an attaching session must not force the substrate back to Buzz",
);
assert.equal(view.getAllByRole("tab").length, 2);
await act(async () => attachResolver());
view.unmount();
});
@@ -209,7 +209,7 @@ export function TerminalBootstrap({
<TerminalSubstrate
bracketedPaste={active?.frame?.bracketedPaste ?? false}
channelName={channelName}
enabled={available && Boolean(active?.connection)}
enabled={available && Boolean(active)}
focusReportingEnabled={active?.frame?.focusReporting ?? false}
frame={active?.frame}
sessionFrames={sessions.flatMap((session) =>