hashgraph / hashgraph/solo-weaver
Add TUI unit tests using `charmbracelet/bubbletea/teatest`
- Dominant language
- Go
- Stars
- 3
- Forks
- 0
- Avg merge
- 3d 2h
- Merged PRs (30d)
- 46
Description
# Add TUI unit tests using `charmbracelet/bubbletea/teatest`
## Summary
The `internal/ui` package contains the core Bubble Tea model (`model.go`, `view.go`, `handler.go`) but has no tests for the model's `Update()` or `View()` logic. The bubbletea framework ships a first-party test helper — [`charmbracelet/x/exp/teatest`](https://github.com/charmbracelet/x/tree/main/exp/teatest) — that makes it straightforward to drive a model programmatically and assert on rendered output.
## Current State
- `internal/ui/logging_test.go` — tests log hooks in isolation (no model involvement)
- `internal/ui/prompt/prompt_test.go` — tests prompt helpers
- No tests exercise `Model.Update()` or `Model.View()` end-to-end
## What to Add
Add a `model_test.go` (and/or `view_test.go`) in `internal/ui/` covering:
| Scenario | Messages to send | Assertions |
|---|---|---|
| Phase starts | `PhaseStartedMsg` | spinner visible, phase name rendered |
| Step succeeds | `StepStartedMsg` → `StepDoneMsg` | success icon, step label present |
| Step fails | `StepStartedMsg` → `StepFailedMsg` | failure icon rendered |
| Step skipped | `StepStartedMsg` → `StepDoneMsg{Skipped}` | skipped icon rendered |
| Transient detail shown/hidden | `StepDetailMsg` at verbosity 0 vs 1 | detail hidden at v0, visible at v1 |
| Workflow done | `WorkflowDoneMsg` | final report rendered, no spinner |
| Compact vs expanded view | verbosity 0 vs 1 | progress bar at v0, all steps at v1 |
## Technical Approach
`teatest` is part of the same charmbracelet org. Since the project already uses `bubbletea v1.3.10`, add the test-only dependency:
```
go get github.com/charmbracelet/x/exp/teatest@latest
```
Basic pattern:
```go
func TestPhaseStarted(t *testing.T) {
m := ui.NewModel(ui.Config{Verbosity: 1})
tm := teatest.NewTestModel(t, m, teatest.WithInitialTermSize(120, 40))
tm.Send(ui.PhaseStartedMsg{Name: "install"})
teatest.WaitFor(t, tm.Output(), func(bts []byte) bool {
return bytes.Contains(bts, []byte("install"))
}, teatest.WithCheckInterval(time.Millisecond*100), teatest.WithDuration(time.Second*3))
tm.Quit()
}
```
## Acceptance Criteria
- [ ] `teatest` (or equivalent) added as a test-only dependency and vendored
- [ ] At minimum, tests covering each message type in `messages.go`
- [ ] Tests for both verbosity levels (compact and expanded rendering)
- [ ] All tests pass with `go test ./internal/ui/...`
## References
- bubbletea `teatest` package: https://github.com/charmbracelet/x/tree/main/exp/teatest
- Existing model: `internal/ui/model.go`
- Message types: `internal/ui/messages.go`
- Demo command (good reference for realistic message sequences): `cmd/weaver/commands/demo.go`
Contributor guide
Assessment
This issue has not been assessed yet.