test: pin the dev tunnel row in the TUI system panel

Covers the render both ways: the Tunnel row appears with its URL when a
tunnel is published, and is absent for an ordinary `fn dashboard` run.
Verified by mutation — deleting the row from app.tsx fails the first test.

Driving this through a real TTY proved impractical from a non-interactive
shell (isTTYAvailable needs stdin AND stdout to be TTYs, which neither
`docker exec -t` nor a detached `script` provides), so the render is pinned
here instead of by observation.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
gsxdsm
2026-08-18 21:30:47 -07:00
parent 204772bcc3
commit 5422063fb9

View File

@@ -244,6 +244,33 @@ describe("DashboardApp smoke", () => {
unmount();
});
/*
FNXC:DevTunnel 2026-08-19-04:30:
`pnpm dev --tunnel` prints its banner to stdout, but a TTY run hands the screen to this TUI, which
repaints over it — the public URL, the whole output of the flag, was unreadable. The wrapper now
forwards it over IPC and it belongs in the system panel beside URL and Token.
*/
it("renders the dev tunnel URL in the system panel when one is published", () => {
const controller = newController();
const { lastFrame, unmount, rerender } = render(renderDashboardAppNode(controller));
controller.setSystemInfo({ ...makeSystemInfo(), devTunnelUrl: "https://sign-bear-kinds-lay.trycloudflare.com" });
rerender(renderDashboardAppNode(controller));
const frame = lastFrame() ?? "";
expect(frame).toContain("Tunnel");
expect(frame).toContain("https://sign-bear-kinds-lay.trycloudflare.com");
unmount();
});
it("shows no tunnel row when no tunnel is running", () => {
const controller = newController();
const { lastFrame, unmount, rerender } = render(renderDashboardAppNode(controller));
controller.setSystemInfo(makeSystemInfo());
rerender(renderDashboardAppNode(controller));
// The row must not appear for the ordinary `fn dashboard` case.
expect(lastFrame() ?? "").not.toContain("Tunnel");
unmount();
});
it("renders ready duration when startup has completed", () => {
const controller = newController();
const { lastFrame, unmount, rerender } = render(renderDashboardAppNode(controller));