import { afterEach, expect, test } from "bun:test"; import { act } from "react"; import { Box } from "../../../ui"; import { PaneFooterBar, PaneFooterProvider } from "../../../components/layout/pane/footer"; import { testRender } from "../../../renderers/opentui/test-utils"; import { createInitialState } from "../../../state/app/context"; import { createTestPluginRuntime } from "../../../test-support/plugin-runtime"; import { TestPaneProvider, createTestPaneConfig } from "../../../test-support/pane"; import { createTestDataProvider } from "../../../test-support/data-provider"; import { MarketDataCoordinator, setSharedMarketDataCoordinator } from "../../../market-data/coordinator"; import { exportPaneTable } from "../../../state/pane-table-export-registry"; import { takeSavedTextFile } from "../../../renderers/opentui/test-utils"; import { RelativeValuationPane } from "./relative-valuation-pane"; let setup: Awaited> | undefined; const paneId = "relative-valuation:test"; function Harness({ width }: { width: number }) { const config = createTestPaneConfig("/tmp/gloom-relative-valuation-test", { instanceId: paneId, paneId: "relative-valuation-pane", settings: { symbols: ["PLD", "FRESH", "MISSING"] }, }); const state = createInitialState(config); return {(footer) => } ; } async function settle() { for (let i = 0; i < 5; i++) await act(async () => { await new Promise((r) => setTimeout(r, 0)); await setup!.renderOnce(); }); } afterEach(async () => { if (setup) await act(async () => { setup!.renderer.destroy(); }); setup = undefined; setSharedMarketDataCoordinator(null); }); test("stale peer remains inspectable with contextual failure, excluded quote values and healthy peers intact", async () => { let stale = true; setSharedMarketDataCoordinator(new MarketDataCoordinator(createTestDataProvider({ getTickerFinancials: async (symbol) => { if (symbol === "MISSING") throw new Error("source unavailable"); return { annualStatements: [], quarterlyStatements: [], priceHistory: [], quote: { symbol, price: symbol === "PLD" ? 135.75 : 200, change: 1, changePercent: 1, currency: "USD", lastUpdated: 1789167600002, stale: symbol === "PLD" && stale, marketCap: 1000 }, fundamentals: { trailingPE: 30.2, operatingMargin: .4, financialCurrency: "USD" }, }; } }))); await act(async () => { setup = await testRender(, { width: 120, height: 16 }); }); await settle(); const frame = setup!.captureCharFrame(); if (process.env.RV_AUDIT_EVIDENCE) await Bun.write(`${process.env.RV_AUDIT_EVIDENCE}/stale-ui.txt`, frame); expect(frame).toContain("Stale quotes: PLD"); expect(frame).toContain("MISSING: source unavailable"); expect(frame).toContain("PLD"); expect(frame).toContain("$200.00"); expect(frame).not.toContain("$135.75"); await exportPaneTable(paneId, "rv-stale.csv"); const csv = takeSavedTextFile()!.text; if (process.env.RV_AUDIT_EVIDENCE) await Bun.write(`${process.env.RV_AUDIT_EVIDENCE}/stale-ui.csv`, csv); expect(csv).toContain("PLD,'-,'-,—,30.2"); stale = false; await act(async () => { setup!.mockInput.pressKey("r"); }); await settle(); const recovered = setup!.captureCharFrame(); expect(recovered).toContain("$135.75"); expect(recovered).not.toContain("Stale quotes:"); expect(recovered).toContain("MISSING: source unavailable"); if (process.env.RV_AUDIT_EVIDENCE) await Bun.write(`${process.env.RV_AUDIT_EVIDENCE}/recovered-ui.txt`, recovered); }); test("stale fundamentals retain their disclosure and export provenance with a fresh quote, then clear on refresh", async () => { let stale = true; setSharedMarketDataCoordinator(new MarketDataCoordinator(createTestDataProvider({ getTickerFinancials: async (symbol) => ({ annualStatements: [], quarterlyStatements: [], priceHistory: [], quote: { symbol, price: 135.75, change: 1, changePercent: 1, currency: "USD", lastUpdated: 1789567200000, stale: false, marketCap: 131e9 }, fundamentals: { trailingPE: 30.2, financialCurrency: "USD", source: "yahoo", fetchedAt: "2026-09-11T23:52:16.139Z", stale: symbol === "PLD" && stale }, }) }))); setup = await testRender(, { width: 120, height: 16 }); await settle(); expect(setup.captureCharFrame()).toContain("$135.75"); expect(setup.captureCharFrame()).not.toContain("Fundamentals stale"); await act(async () => setup!.mockInput.pressKey("!")); await settle(); expect(setup.captureCharFrame()).toContain("PLD: Fundamentals stale"); await act(async () => setup!.mockInput.pressKey("escape")); await settle(); await exportPaneTable(paneId, "rv-stale-fundamentals.csv"); const csv = takeSavedTextFile()!.text; expect(csv).toContain("PLD,Fundamentals retrieved,2026-09-11T23:52:16.139Z,Stale,true"); expect(csv).not.toContain("yahoo"); expect(csv).toContain("PLD,Fundamentals stale"); stale = false; await act(async () => setup!.mockInput.pressKey("r")); await settle(); await act(async () => setup!.mockInput.pressKey("!")); await settle(); expect(setup.captureCharFrame()).not.toContain("Fundamentals stale"); await exportPaneTable(paneId, "rv-fresh-fundamentals.csv"); expect(takeSavedTextFile()!.text).toContain("PLD,Fundamentals retrieved,2026-09-11T23:52:16.139Z,Stale,false"); });