import { afterEach, describe, expect, test } from "bun:test"; import { act } from "react"; import { Box } from "../../../../ui"; import { testRender } from "../../../../renderers/opentui/test-utils"; import { PaneFooterBar, PaneFooterProvider, usePaneFooter, } from "./index"; import { useExternalLinkFooter } from "../../../use-external-link-footer"; import { setLanguage, t } from "../../../../i18n"; let testSetup: Awaited> | undefined; afterEach(async () => { if (testSetup) { await act(async () => testSetup?.renderer.destroy()); testSetup = undefined; } setLanguage("en"); }); function Registration({ onOpen, openDisabled = false, }: { onOpen?: () => void; openDisabled?: boolean; }) { usePaneFooter("test", () => { return { info: [ { id: "rows", parts: [ { text: "Rows", tone: "label" }, { text: "12", tone: "value", bold: true }, ], }, ], hints: [ { id: "open", key: "o", label: "pen", onPress: onOpen, disabled: openDisabled }, ], }; }, [onOpen, openDisabled]); return null; } function ExternalLinkRegistration() { useExternalLinkFooter({ registrationId: "external-link", focused: true, url: "https://example.com/story?utm=raw", source: "Reuters", }); return null; } function TranslatedRegistration() { usePaneFooter("translated", () => ({ info: [{ id: "state", parts: [{ text: t("Open"), tone: "value" }] }], }), []); return null; } function TranslatedFooterHarness() { return ( {(footer) => ( )} ); } function FooterHarness({ focused = false, onOpen, openDisabled = false, }: { focused?: boolean; onOpen?: () => void; openDisabled?: boolean; }) { return ( {(footer) => ( )} ); } function ExternalLinkFooterHarness() { return ( {(footer) => ( )} ); } describe("PaneFooterBar", () => { test("rebuilds translated registrations when the app language changes", async () => { testSetup = await testRender(, { width: 40, height: 1 }); await act(async () => { await testSetup?.renderOnce(); await testSetup?.renderOnce(); }); expect(testSetup.captureCharFrame()).toContain("Open"); await act(async () => { setLanguage("zh-CN"); await Promise.resolve(); }); await act(async () => { await testSetup?.renderOnce(); await testSetup?.renderOnce(); await Promise.resolve(); await testSetup?.renderOnce(); }); expect(testSetup.captureCharFrame()).toContain("打开"); }); test("hides hints on inactive footers but keeps info visible", async () => { testSetup = await testRender(, { width: 64, height: 1 }); await act(async () => { await testSetup!.renderOnce(); await testSetup!.renderOnce(); }); const frame = testSetup.captureCharFrame(); expect(frame).toContain("Rows 12"); expect(frame).not.toContain("[o]pen"); }); test("keeps raw external URLs out of footer text", async () => { testSetup = await testRender(, { width: 80, height: 1 }); await act(async () => { await testSetup!.renderOnce(); await testSetup!.renderOnce(); }); const frame = testSetup.captureCharFrame(); expect(frame).toContain("source Reuters"); expect(frame).toContain("[o]pen"); expect(frame).not.toContain("https://example.com"); }); test("omits disabled controls instead of rendering muted hints", async () => { testSetup = await testRender( {}} />, { width: 64, height: 1 }, ); await act(async () => { await testSetup!.renderOnce(); await testSetup!.renderOnce(); }); const frame = testSetup.captureCharFrame(); expect(frame).toContain("Rows 12"); expect(frame).not.toContain("[o]pen"); }); test("calls hint onPress from mouse interaction", async () => { let openCount = 0; testSetup = await testRender( { openCount += 1; }} />, { width: 64, height: 1 }); await act(async () => { await testSetup!.renderOnce(); await testSetup!.renderOnce(); }); const line = testSetup.captureCharFrame().split("\n")[0] ?? ""; const col = line.indexOf("[o]pen"); expect(col).toBeGreaterThanOrEqual(0); await act(async () => { await testSetup!.mockMouse.release(col + 1, 0); await testSetup!.renderOnce(); }); expect(openCount).toBe(0); await act(async () => { await testSetup!.mockMouse.click(col + 1, 0); await testSetup!.renderOnce(); }); expect(openCount).toBe(1); }); });