test(tui): await diff tree context readiness (#37501)

Co-authored-by: James Long <longster@gmail.com>
This commit is contained in:
opencode-agent[bot] 2026-07-17 10:41:00 -04:00 committed by GitHub
parent 44f7bb71c1
commit 651751405d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -3,6 +3,7 @@ import { describe, expect, test } from "bun:test"
import { RGBA } from "@opentui/core"
import { testRender } from "@opentui/solid"
import type { JSX } from "solid-js"
import { onMount, type ParentProps } from "solid-js"
import { createTuiResolvedConfig } from "../../fixture/tui-runtime"
import { ThemeProvider } from "../../../src/context/theme"
import { ConfigProvider } from "../../../src/config"
@ -27,42 +28,33 @@ const theme = {
describe("DiffViewerFileTree", () => {
test.skip("renders sorted hierarchical file rows", async () => {
const app = await testRender(
() =>
withTheme(() => (
<DiffViewerFileTree
width={32}
files={[
{ file: "z-file.ts" },
{ file: "b/file.ts" },
{ file: "a/zeta.ts" },
{ file: "b/alpha.ts" },
{ file: "a/alpha.ts" },
]}
loading={false}
error={undefined}
theme={theme}
focused={true}
/>
)),
{ width: 40, height: 20 },
const lines = visibleLines(
await renderFrame(() => (
<DiffViewerFileTree
width={32}
files={[
{ file: "z-file.ts" },
{ file: "b/file.ts" },
{ file: "a/zeta.ts" },
{ file: "b/alpha.ts" },
{ file: "a/alpha.ts" },
]}
loading={false}
error={undefined}
theme={theme}
focused={true}
/>
)),
)
try {
await renderOnceSettled(app)
const lines = visibleLines(app.captureCharFrame())
expect(lines).toEqual([
"▾ a",
"│ ├─ alpha.ts ?",
"│ └─ zeta.ts ?",
"├─ ▾ b",
"│ ├─ alpha.ts ?",
"│ └─ file.ts ?",
])
} finally {
app.renderer.destroy()
}
expect(lines).toEqual([
"▾ a",
"│ ├─ alpha.ts ?",
"│ └─ zeta.ts ?",
"├─ ▾ b",
"│ ├─ alpha.ts ?",
"│ └─ file.ts ?",
])
})
test("keeps loading and error quiet while rendering an empty settled state", async () => {
@ -152,41 +144,35 @@ describe("DiffViewerFileTree", () => {
})
async function renderFrame(component: () => JSX.Element) {
const app = await testRender(() => withTheme(component), { width: 40, height: 10 })
const mounted = Promise.withResolvers<void>()
const app = await testRender(() => withTheme(component, mounted.resolve), { width: 40, height: 10 })
try {
await renderOnceSettled(app)
return await captureSettledFrame(app)
await mounted.promise
await app.renderOnce()
await app.renderOnce()
return app.captureCharFrame()
} finally {
app.renderer.destroy()
}
}
async function renderOnceSettled(app: Awaited<ReturnType<typeof testRender>>) {
await app.renderOnce()
await new Promise((resolve) => setTimeout(resolve, 25))
await app.renderOnce()
}
async function captureSettledFrame(app: Awaited<ReturnType<typeof testRender>>) {
for (let attempt = 0; attempt < 5; attempt++) {
const frame = app.captureCharFrame()
if (visibleLines(frame).length > 0) return frame
await new Promise((resolve) => setTimeout(resolve, 25))
await app.renderOnce()
}
return app.captureCharFrame()
}
function withTheme(component: () => JSX.Element) {
function withTheme(component: () => JSX.Element, onReady = () => {}) {
return (
<TestTuiContexts>
<ConfigProvider config={createTuiResolvedConfig()}>
<ThemeProvider mode="dark">{component()}</ThemeProvider>
<ThemeProvider mode="dark">
<Ready onReady={onReady}>{component()}</Ready>
</ThemeProvider>
</ConfigProvider>
</TestTuiContexts>
)
}
function Ready(props: ParentProps<{ onReady: () => void }>) {
onMount(props.onReady)
return props.children
}
function visibleLines(frame: string) {
return frame
.split("\n")