Переглянути джерело

test(tui): add shortcut screenshot harness

Kit Langton 1 місяць тому
батько
коміт
d239923b90

+ 2 - 1
packages/tui/package.json

@@ -7,7 +7,8 @@
   "license": "MIT",
   "scripts": {
     "test": "bun test --timeout 30000 --only-failures",
-    "typecheck": "tsgo --noEmit"
+    "typecheck": "tsgo --noEmit",
+    "screenshots:shortcuts": "bun run script/shortcut-screenshots.ts"
   },
   "exports": {
     ".": "./src/index.tsx",

+ 71 - 0
packages/tui/script/shortcut-screenshots.drive.ts

@@ -0,0 +1,71 @@
+import { defineScript, wait, type ScriptUi } from "opencode-drive"
+
+const settle = () => wait(100)
+
+async function screenshot(ui: ScriptUi, name: string) {
+  await settle()
+  const path = await ui.screenshot(name)
+  console.log(`${name}: ${path}`)
+}
+
+async function closeDialog(ui: ScriptUi) {
+  await ui.press("escape")
+  await ui.waitFor("commands")
+  await settle()
+  await ui.waitFor((state) => state.focused.editor)
+}
+
+async function runPalette(ui: ScriptUi, command: string, text: string, name: string) {
+  await settle()
+  await ui.press("p", { ctrl: true })
+  await ui.waitFor("Commands")
+  await settle()
+  await ui.type(command)
+  await ui.waitFor(command)
+  await ui.enter()
+  await ui.waitFor(text)
+  await screenshot(ui, name)
+}
+
+export default defineScript({
+  viewport: { cols: 120, rows: 36 },
+  setup({ config }) {
+    config.autoupdate = false
+  },
+  async run({ ui }) {
+    await ui.waitFor((state) => state.focused.editor)
+    await screenshot(ui, "01-home-key-first")
+
+    await ui.type("!")
+    await ui.waitFor("exit shell mode")
+    await screenshot(ui, "02-shell-key-first")
+    await ui.press("escape")
+    await ui.waitFor("commands")
+    await ui.waitFor((state) => state.focused.editor)
+
+    await ui.press("p", { ctrl: true })
+    await ui.waitFor("Commands")
+    await screenshot(ui, "03-command-palette")
+    await closeDialog(ui)
+
+    await runPalette(ui, "Switch model", "Select model", "04-model-actions")
+    await closeDialog(ui)
+
+    await runPalette(ui, "Help", "Press", "05-help-header-prose")
+    await closeDialog(ui)
+
+    await runPalette(ui, "View debug info", "Share this", "06-debug-action-first")
+    await closeDialog(ui)
+
+    await runPalette(ui, "Switch session", "Sessions", "07-session-actions")
+    await closeDialog(ui)
+
+    await runPalette(ui, "Plugins", "Plugins", "08-plugin-actions")
+    await closeDialog(ui)
+
+    await runPalette(ui, "Install plugin", "scope:", "09-plugin-install")
+    await closeDialog(ui)
+
+    await runPalette(ui, "Open diff viewer", "opencode crashed", "10-crash-stacked")
+  },
+})

+ 31 - 0
packages/tui/script/shortcut-screenshots.ts

@@ -0,0 +1,31 @@
+import { mkdir, rm } from "node:fs/promises"
+import { resolve } from "node:path"
+
+const root = resolve(import.meta.dir, "../../..")
+const script = resolve(import.meta.dir, "shortcut-screenshots.drive.ts")
+const output = resolve(process.env.OPENCODE_SHORTCUT_SCREENSHOTS_DIR ?? resolve(root, "tmp/tui-shortcut-screenshots"))
+const drive = Bun.which("opencode-drive")
+
+if (!drive) throw new Error("opencode-drive is required: https://github.com/jlongster/opencode-drive")
+
+await rm(output, { recursive: true, force: true })
+await mkdir(output, { recursive: true })
+
+const check = Bun.spawn([drive, "check", script], {
+  cwd: root,
+  stdin: "inherit",
+  stdout: "inherit",
+  stderr: "inherit",
+})
+if ((await check.exited) !== 0) throw new Error("OpenCode Drive script typecheck failed")
+
+const run = Bun.spawn([drive, "start", "--name", `tui-shortcuts-${process.pid}`, "--dev", root, "--script", script], {
+  cwd: root,
+  env: { ...process.env, OPENCODE_DRIVE_MEDIA_DIR: output },
+  stdin: "inherit",
+  stdout: "inherit",
+  stderr: "inherit",
+})
+if ((await run.exited) !== 0) throw new Error("OpenCode Drive screenshot run failed")
+
+console.log(`Shortcut screenshots: ${output}`)

+ 2 - 1
packages/tui/tsconfig.json

@@ -6,5 +6,6 @@
     "jsxImportSource": "@opentui/solid",
     "lib": ["ESNext", "DOM", "DOM.Iterable"],
     "noUncheckedIndexedAccess": false
-  }
+  },
+  "exclude": ["script/*.drive.ts"]
 }