tuistory — ターミナルUI向けのPlaywrightライクなテストライブラリ
概要
tuistoryは、ターミナルベースのユーザーインターフェース(TUI)アプリケーション向けに設計されたテストライブラリです。Playwrightのアイデアをターミナルに持ち込み、プロセスの起動や端末サイズ(cols/rows)の指定、出力に対する待機(waitForText)や入力送信などを非同期APIで提供します。Bun向けの配布が想定され、TypeScriptで実装されているためモダンなJS/TSエコシステムに自然に馴染みます。CLIツールや対話型アプリのE2Eテストをプログラム的に書きたい開発者向けのライブラリです。
リポジトリの統計情報
- スター数: 10
- フォーク数: 0
- ウォッチャー数: 10
- コミット数: 8
- ファイル数: 7
- メインの言語: TypeScript
主な特徴
- Playwrightに似たAPIデザインでターミナルアプリのE2Eテストを直感的に記述可能
- コマンド起動、TTYサイズ指定、出力の待機・検証、入力送信など基本操作をシンプルに提供
- Bunでのインストールが想定された軽量パッケージ(bun.lockを含む)
- TypeScript実装で型安全、モダンな開発体験に対応
技術的なポイント
tuistoryは「ターミナルのためのPlaywright」というコンセプトを中心に、CLIアプリケーションの自動化で必要となる要素を揃えています。主な機能はプロセスの起動(launchTerminal)、端末の列数/行数(cols/rows)を指定して疑似TTY環境を構築する点、標準出力/標準エラーの内容に対して特定文字列が出るまで待機するwaitForTextのような同期的な検証APIを備える点です。これにより、対話的なプロンプトや段階的に更新されるUI、ページネーションされた出力などに対して確実にアサーションを行えます。
内部ではNode系のプロセス制御(またはBunのランタイムAPI)を利用して擬似TTY(pseudoterminal)を生成し、アプリと双方向通信(入力送信と出力取得)を行う設計が想定されます。TypeScriptで型定義が行われており、async/awaitベースのAPIで直感的に記述できるためテストコードの読みやすさが高いです。タイムアウトや部分一致、正規表現によるマッチングといった待機条件の指定が可能で、リアルタイムに変化する画面にも対応します。
パッケージはbun add tuistoryでインストールできる点から、Bun環境での利用を考慮した構成になっています。リポジトリ構成は小規模で、READMEやCHANGELOG、package.json、bun.lockなど基本ファイルを備え、早期段階のプロジェクトであることが窺えます。テストフレームワーク自体を内包するのではなく、既存のテストランナー(JestやVitestなど)と組み合わせてE2Eの一部として利用する設計が想像され、CI環境での自動実行やスクリーンショット取得(将来的な拡張)など拡張の余地もあります。
現状ではコミット数・ファイル数ともに小規模なため、APIの安定性やエッジケースの対応(複雑な端末制御、カラーコードやカーソル移動の処理、シグナルハンドリングなど)は今後の発展が期待されます。導入時はREADMEのUsage例に従い、まずは基本的な起動/出力待機/入力送信のワークフローを確認すると良いでしょう。
プロジェクトの構成
主要なファイルとディレクトリ:
- .gitignore: file
- CHANGELOG.md: file
- README.md: file
- bun.lock: file
- package.json: file
…他 2 ファイル
まとめ
ターミナルUIのE2EテストをPlaywrightライクに扱える軽量ライブラリ。導入が容易で将来性あり。
リポジトリ情報:
- 名前: tuistory
- 説明: Playwright for terminal user interfaces
- スター数: 10
- 言語: TypeScript
- URL: https://github.com/remorses/tuistory
- オーナー: remorses
- アバター: https://avatars.githubusercontent.com/u/31321188?v=4
READMEの抜粋:
tuistory
Playwright for terminal user interfaces
Write end-to-end tests for terminal applications
Installation
bun add tuistory
Usage
import { launchTerminal } from 'tuistory'
const session = await launchTerminal({
command: 'claude',
args: [],
cols: 100,
rows: 30,
})
await session.waitForText('claude', { timeout: 10000 })
const initialText = await session....