Skip to content

Commit 2762efb

Browse files
saravmajesticclaude
andcommitted
test(tui): render-test the welcome panel variants (real component)
Mounts the real WelcomePanel through the app context stack at fixed available sizes and asserts each variant renders its distinct content (full: "What is Altimate Code"; medium: the condensed line, no what-is section; compact: the single connect-CTA line). Covers the .tsx Switch that the pure welcomePanelVariant unit test can't. Deliberately not a full Home/Session route render — that drags in Prompt's ~28-context dependency graph; the route wiring is now a shared one-liner through homeAvailable/sessionAvailable. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 9d4c36c commit 2762efb

1 file changed

Lines changed: 97 additions & 0 deletions

File tree

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
/** @jsxImportSource @opentui/solid */
2+
import { testRender } from "@opentui/solid"
3+
import { afterEach, expect, test } from "bun:test"
4+
import { resetSetupComplete } from "../../src/component/altimate-onboarding"
5+
import { WelcomePanel } from "../../src/component/welcome-panel"
6+
import { TuiConfigProvider } from "../../src/config"
7+
import { FULL_MIN_HEIGHT, FULL_MIN_WIDTH, MEDIUM_MIN_WIDTH } from "../../src/component/welcome-panel-utils"
8+
import { ArgsProvider } from "../../src/context/args"
9+
import { ExitProvider } from "../../src/context/exit"
10+
import { KVProvider } from "../../src/context/kv"
11+
import { ProjectProvider } from "../../src/context/project"
12+
import { RouteProvider } from "../../src/context/route"
13+
import { SDKProvider } from "../../src/context/sdk"
14+
import { SyncProvider } from "../../src/context/sync"
15+
import { ThemeProvider } from "../../src/context/theme"
16+
import { ToastProvider } from "../../src/ui/toast"
17+
import { TestTuiContexts } from "../fixture/tui-environment"
18+
import { createTuiResolvedConfig } from "../fixture/tui-runtime"
19+
import { createEventSource, createFetch, directory } from "../fixture/tui-sdk"
20+
21+
// Render the REAL WelcomePanel through the routes' variant sizing and assert the
22+
// rendered content per variant — the piece the pure welcomePanelVariant unit test
23+
// can't cover (that the .tsx Switch actually renders the right box for a variant).
24+
// Sizing is driven by the availableWidth/availableHeight props exactly as the
25+
// routes pass them; the canvas is generous so content is captured without clipping.
26+
async function renderPanel(availableWidth: number, availableHeight: number) {
27+
resetSetupComplete() // ready() = false → deterministic (unconnected: shows the connect CTA)
28+
const calls = createFetch()
29+
const source = createEventSource()
30+
const app = await testRender(
31+
() => (
32+
<TestTuiContexts>
33+
<ExitProvider exit={() => {}}>
34+
<TuiConfigProvider config={createTuiResolvedConfig()}>
35+
<ArgsProvider>
36+
<KVProvider>
37+
<ToastProvider>
38+
<RouteProvider>
39+
<SDKProvider url="http://test" directory={directory} fetch={calls.fetch} events={source.source}>
40+
<ProjectProvider>
41+
<SyncProvider>
42+
<ThemeProvider mode="dark">
43+
<WelcomePanel availableWidth={availableWidth} availableHeight={availableHeight} />
44+
</ThemeProvider>
45+
</SyncProvider>
46+
</ProjectProvider>
47+
</SDKProvider>
48+
</RouteProvider>
49+
</ToastProvider>
50+
</KVProvider>
51+
</ArgsProvider>
52+
</TuiConfigProvider>
53+
</ExitProvider>
54+
</TestTuiContexts>
55+
),
56+
{ width: 160, height: 40 },
57+
)
58+
await app.renderOnce()
59+
await new Promise((resolve) => setTimeout(resolve, 25))
60+
await app.renderOnce()
61+
let frame = app.captureCharFrame()
62+
for (let attempt = 0; attempt < 5 && frame.trim().length === 0; attempt++) {
63+
await new Promise((resolve) => setTimeout(resolve, 25))
64+
await app.renderOnce()
65+
frame = app.captureCharFrame()
66+
}
67+
return { app, frame }
68+
}
69+
70+
let current: Awaited<ReturnType<typeof testRender>> | undefined
71+
afterEach(() => {
72+
current?.renderer.destroy()
73+
current = undefined
74+
})
75+
76+
test("full variant renders the wordmark + what-is section at a large available size", async () => {
77+
const { app, frame } = await renderPanel(FULL_MIN_WIDTH, FULL_MIN_HEIGHT)
78+
current = app
79+
// "What is Altimate Code" is unique to the full two-column box.
80+
expect(frame).toContain("What is Altimate Code")
81+
})
82+
83+
test("medium variant renders the condensed line (no what-is section) below the full width floor", async () => {
84+
const { app, frame } = await renderPanel(FULL_MIN_WIDTH - 1, FULL_MIN_HEIGHT)
85+
current = app
86+
expect(frame).toContain("Gives your AI real context")
87+
expect(frame).not.toContain("What is Altimate Code")
88+
})
89+
90+
test("compact variant renders a single line below the medium width floor", async () => {
91+
const { app, frame } = await renderPanel(MEDIUM_MIN_WIDTH - 1, FULL_MIN_HEIGHT)
92+
current = app
93+
// Unconnected → the connect CTA; neither the medium nor full body is present.
94+
expect(frame).toContain("Connect your AI model to start")
95+
expect(frame).not.toContain("Gives your AI real context")
96+
expect(frame).not.toContain("What is Altimate Code")
97+
})

0 commit comments

Comments
 (0)