테스트
@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");});Bun, Vitest, Jest를 비롯해 async 테스트를 지원하는 모든 러너에서 작동해요.
렌더링
| 메서드 | 설명 |
|---|---|
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프레임의 오른쪽과 아래쪽 공백을 제거하므로, 공백 때문에 스냅샷이 계속 바뀌지 않아요.