95 lines
2.9 KiB
TypeScript
95 lines
2.9 KiB
TypeScript
/** @jsxImportSource @opentui/solid */
|
|
import { testRender } from "@opentui/solid"
|
|
import { expect, test } from "bun:test"
|
|
import { resolve, ConfigProvider, useConfig, type Interface } from "../src/config"
|
|
|
|
test("resolves nested config and keybind defaults", () => {
|
|
const config = resolve(
|
|
{
|
|
keybinds: { leader: "ctrl+o" },
|
|
leader: { timeout: 500 },
|
|
scroll: { speed: 2, acceleration: true },
|
|
diffs: { view: "split" },
|
|
},
|
|
{ terminalSuspend: true },
|
|
)
|
|
|
|
expect(config.leader.timeout).toBe(500)
|
|
expect(config.keybinds.get("leader")?.[0]?.key).toBe("ctrl+o")
|
|
expect(config.scroll).toEqual({ speed: 2, acceleration: true })
|
|
expect(config.diffs).toEqual({ view: "split" })
|
|
})
|
|
|
|
test("provides config and its host interface", async () => {
|
|
const config = resolve({}, { terminalSuspend: true })
|
|
let current = {}
|
|
const service: Interface = {
|
|
get: async () => current,
|
|
update: async (update) => {
|
|
const draft: Record<string, any> = { ...current }
|
|
update(draft)
|
|
current = draft
|
|
return draft
|
|
},
|
|
}
|
|
let context: ReturnType<typeof useConfig> | undefined
|
|
|
|
function Consumer() {
|
|
context = useConfig()
|
|
return <text>{`${context.data.mouse ? "mouse" : "none"} ${context.data.keybinds.get("leader")?.[0]?.key}`}</text>
|
|
}
|
|
|
|
const app = await testRender(() => (
|
|
<ConfigProvider config={config} service={service}>
|
|
<Consumer />
|
|
</ConfigProvider>
|
|
))
|
|
try {
|
|
await app.renderOnce()
|
|
expect(app.captureCharFrame()).toContain("mouse ctrl+x")
|
|
if (!context) throw new Error("Config context was not provided")
|
|
await context.update((draft) => {
|
|
draft.mouse = false
|
|
draft.keybinds = { leader: "ctrl+o" }
|
|
})
|
|
await app.renderOnce()
|
|
expect(app.captureCharFrame()).toContain("none ctrl+o")
|
|
} finally {
|
|
app.renderer.destroy()
|
|
}
|
|
})
|
|
|
|
test("reconciles config updates from another process", async () => {
|
|
const config = resolve({ models: { favorites: ["anthropic/old"] } }, { terminalSuspend: true })
|
|
let listener: ((info: { models?: { favorites?: string[] } }) => void) | undefined
|
|
let unsubscribed = false
|
|
const service: Interface = {
|
|
get: async () => ({}),
|
|
update: async () => ({}),
|
|
subscribe: (next) => {
|
|
listener = next
|
|
return () => {
|
|
unsubscribed = true
|
|
}
|
|
},
|
|
}
|
|
let context: ReturnType<typeof useConfig> | undefined
|
|
|
|
function Consumer() {
|
|
context = useConfig()
|
|
return <text>{context.data.models?.favorites?.join(",")}</text>
|
|
}
|
|
|
|
const app = await testRender(() => (
|
|
<ConfigProvider config={config} service={service}>
|
|
<Consumer />
|
|
</ConfigProvider>
|
|
))
|
|
await app.renderOnce()
|
|
expect(app.captureCharFrame()).toContain("anthropic/old")
|
|
listener?.({ models: { favorites: ["anthropic/new"] } })
|
|
await app.renderOnce()
|
|
expect(app.captureCharFrame()).toContain("anthropic/new")
|
|
app.renderer.destroy()
|
|
expect(unsubscribed).toBe(true)
|
|
})
|