测试
使用 @textjs/app/testing 离屏渲染应用、模拟按键并断言帧。
@textjs/app/testing(或 @textjs/react/testing)离屏渲染应用,模拟按键,并以文本形式返回帧。测试无需浏览器或 DevTools 即可运行。
counter.test.tsxtsx
import { afterEach, expect, test } from "bun:test";import { cleanup, render } from "@textjs/app/testing";import { Counter } from "./counter";afterEach(cleanup);test("counts up", async () => { const app = await render(<Counter />, { cols: 40, rows: 6 }); await app.press("up up"); expect(app.lastFrame()).toContain("count = 2");});支持任何能运行 async 测试的测试运行器,包括 Bun、Vitest 和 Jest。
渲染
| 方法 | 描述 |
|---|---|
render(el, { cols, rows, theme }) | 离屏挂载(默认 80×24) |
lastFrame() | 纯文本形式的帧 |
lines() | 行数组形式的帧 |
frames | 到目前为止所有不同的帧 |
toAnsi() | 用于快照的真彩色 ANSI |
cell(x, y) | { char, fg, bg, attrs } |
locate(text) | 首个匹配项的 { x, y } |
rerender(el) / unmount() | 更新或卸载 |
renderToString(el, options) 渲染一次并返回文本。
输入
await app.press("down");await app.press("ctrl+k"); // modifiersawait app.press("g g"); // a sequenceawait app.press("G"); // Shift+Gawait app.type("hello\n"); // one key per character, \n is Enterawait app.paste("multi\nline");await app.wheel(3);await app.resize(120, 36);每次调用都在 act() 内运行,并刷新生成的帧,因此下一条断言能看到更新。
时间
await app.wait(300); // real time passes, then frames flushawait app.waitForText("Deployed"); // poll until the frame contains itawait app.waitFor(() => expect(saved).toBe(true), { timeout: 2000 });动画、加载指示器和提示消息使用真实计时器,因此使用 wait 和 waitFor 可以可靠地观察这些变化。
快照
expect(app.lastFrame()).toMatchSnapshot();expect(app.toAnsi()).toMatchSnapshot(); // colors too帧右侧和底部的空白会被裁剪,因此快照不会因空白而反复变化。