/** @jsxImportSource @opentui/solid */ import { testRender } from "@opentui/solid" import { expect, test } from "bun:test" import { createSignal, onCleanup } from "solid-js" import { DialogUpdate } from "../../src/component/dialog-update" import { ConfigProvider } from "../../src/config" import type { UpdateState } from "../../src/context/update-notification" import { Keymap } from "../../src/context/keymap" import { ThemeProvider } from "../../src/context/theme" import { DialogProvider } from "../../src/ui/dialog" import { ToastProvider } from "../../src/ui/toast" import { emptyThemeSource, tmpdir } from "../fixture/fixture" import { TestTuiContexts } from "../fixture/tui-environment" import { createTuiResolvedConfig } from "../fixture/tui-runtime" test("installation progress replaces checking while the update job is still pending", async () => { await using temporary = await tmpdir() const [state, setState] = createSignal() const pending = Promise.withResolvers() const app = await testRender( () => ( pending.promise} state={state} skip={() => {}} install={() => Promise.resolve()} restart={() => {}} /> ), { width: 80, height: 24, kittyKeyboard: true }, ) try { app.renderer.start() await app.waitForFrame((frame) => frame.includes("Checking for updates")) setState({ type: "installing", version: "2.0.0" }) await app.waitForFrame( (frame) => frame.includes("Updating OpenCode") && frame.includes("Installing OpenCode 2.0.0") && !frame.includes("Checking"), ) expect(app.captureCharFrame()).not.toContain("Skip") pending.reject(new Error("Update service unavailable")) await app.waitForFrame((frame) => frame.includes("Update service unavailable") && !frame.includes("Installing")) } finally { pending.resolve(undefined) app.renderer.destroy() } }) test.each([false, true])("update choices are keyboard-navigable buttons with new designs %p", async (newDesigns) => { await using temporary = await tmpdir() const [state] = createSignal({ type: "available", version: "2.0.0" } as UpdateState) const ran: string[] = [] const app = await testRender( () => ( ran.push("skip")} install={async () => void ran.push("install")} restart={() => {}} /> ), { width: 80, height: 24, kittyKeyboard: true }, ) try { app.renderer.start() await app.waitForFrame((frame) => frame.includes("Update available") && frame.includes("Skip")) const frame = app.captureCharFrame() expect(frame).toMatch(/Skip\s+Update/) expect(frame).not.toContain("enter") app.mockInput.pressArrow("left") app.mockInput.pressEnter() await app.waitFor(() => ran.length > 0) expect(ran).toEqual(["skip"]) } finally { app.renderer.destroy() } }) function ModalUpdate(props: Parameters[0]) { onCleanup(Keymap.use().mode.push("modal")) return }