charmbracelet / charmbracelet/bubbletea

Proposal: Testing framework for Bubble Tea applications (charm-test)

Open
#1,654 0 comments 1 reaction 0 assignees View on GitHub
Dominant language
Go
Stars
44.9k
Forks
1.3k
PR merge metrics
No merged PRs in 30d

Description

## Problem

There is no standard way to test Bubble Tea applications. Developers either:
- Test manually (slow, not CI-friendly)
- Call `Update()` manually and inspect model internals (brittle, verbose)
- Skip testing TUI logic entirely

Other UI frameworks have dedicated testing tools (React Testing Library, Flutter widget tests), but Bubble Tea has none.

## Proposed Solution

**charm-test** — a testing framework that simulates the Bubble Tea runtime without a real terminal.

```go
func TestLoginForm(t *testing.T) {
sim := charmtest.New(NewLoginModel())

sim.Type("user@email.com")
sim.SendKey("tab")
sim.Type("password123")
sim.SendKey("enter")

charmtest.RequireViewContains(t, sim, "Welcome")
charmtest.RequireSnapshot(t, sim) // golden file comparison
}
```

### Features
- **Simulator** — drives Model synchronously through Init/Update/View (no goroutines, deterministic)
- **Input simulation** — `SendKey("enter")`, `Type("hello")`, `Resize(80, 24)`
- **Assertions** — `RequireView()`, `RequireViewContains()`, `RequireViewLines()` with automatic ANSI stripping
- **Snapshot testing** — golden file comparison with `CHARM_TEST_UPDATE=1` to refresh
- **Debugging** — `DumpView()`, `DumpMessages()` for test failure diagnosis

### Design Principles
- Deterministic: same input → same output, always
- Fast: microseconds per test, not seconds
- Simple: one import, one constructor
- ANSI-aware: all comparisons strip escape sequences

## Working POC

https://github.com/junhinhow/charm-test

Includes a complete counter example with 5 test cases. Bilingual docs (EN/PT-BR).

## Questions

1. Would this fit as an official package (e.g. `charm.land/bubbletea/v2/test`)?
2. Or better as a standalone community package?
3. Should the Simulator also handle async commands (timers, HTTP) via a mock clock?

Contributor guide

Open the contributing guide

Research direction

Start by reviewing the linked charm-test proof of concept and its counter example, then compare its simulator and assertion design with Bubble Tea's existing Model, Update, and View interfaces. The issue is complete only after the project decides whether this belongs in Bubble Tea or as a standalone package and resolves the async-command design.

Written by the indexing model from the issue text.

Assessment

Tech stack
go
Domain
cli, testing-qa
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.