Documentation
¶
Overview ¶
Package btest provides a virtual terminal screen and assertion helpers for testing Bubble Tea TUI applications. It uses go-te to emulate a terminal and parse ANSI escape sequences, enabling screen-based assertions on rendered View() output.
Package btest session record/replay.
A .tuisess file captures a deterministic sequence of input events against a tea.Model and the resulting screen after each step. Consumer apps can commit these files under `testdata/sessions/` as end-to-end regression fixtures; running Replay against the same model should yield identical screens at every step.
Format (JSON):
{
"version": 1,
"cols": 80,
"lines": 24,
"steps": [
{"kind": "key", "key": "down"},
{"kind": "screen", "screen": "..."},
{"kind": "type", "text": "abc"},
{"kind": "screen", "screen": "..."}
]
}
The "screen" steps are the expected screen strings captured right after the previous input step. Replay compares the live screen to the expected screen and fails the test on any divergence.
Index ¶
- Constants
- Variables
- func AssertBgAt(t testing.TB, s *Screen, row, col int, color string)
- func AssertBoldAt(t testing.TB, s *Screen, row, col int)
- func AssertColumnContains(t testing.TB, s *Screen, col, startRow, endRow int, text string)
- func AssertColumnCount(t testing.TB, s *Screen, col, startRow, endRow int, text string, want int)
- func AssertContains(t testing.TB, s *Screen, text string)
- func AssertContainsAt(t testing.TB, s *Screen, row, col int, text string)
- func AssertContainsCount(t testing.TB, s *Screen, text string, n int)
- func AssertCursorAt(t testing.TB, s *Screen, row, col int)
- func AssertCursorRowContains(t testing.TB, s *Screen, text string)
- func AssertEmpty(t testing.TB, s *Screen)
- func AssertFgAt(t testing.TB, s *Screen, row, col int, color string)
- func AssertGolden(t testing.TB, s *Screen, name string)
- func AssertItalicAt(t testing.TB, s *Screen, row, col int)
- func AssertKeybind(t testing.TB, s *Screen, key, description string)
- func AssertMatches(t testing.TB, s *Screen, pattern string)
- func AssertNoANSI(t testing.TB, s *Screen)
- func AssertNotContains(t testing.TB, s *Screen, text string)
- func AssertNotEmpty(t testing.TB, s *Screen)
- func AssertRegionBg(t testing.TB, s *Screen, row, col, width, height int, color string)
- func AssertRegionBold(t testing.TB, s *Screen, row, col, width, height int)
- func AssertRegionContains(t testing.TB, s *Screen, row, col, width, height int, text string)
- func AssertRegionFg(t testing.TB, s *Screen, row, col, width, height int, color string)
- func AssertRegionNotContains(t testing.TB, s *Screen, row, col, width, height int, text string)
- func AssertReverseAt(t testing.TB, s *Screen, row, col int)
- func AssertRowContains(t testing.TB, s *Screen, row int, text string)
- func AssertRowCount(t testing.TB, s *Screen, want int)
- func AssertRowEquals(t testing.TB, s *Screen, row int, text string)
- func AssertRowMatches(t testing.TB, s *Screen, row int, pattern string)
- func AssertRowNotContains(t testing.TB, s *Screen, row int, text string)
- func AssertScreenEquals(t testing.TB, s *Screen, expected string)
- func AssertScreenMatches(t testing.TB, s *Screen, pattern string)
- func AssertScreensEqual(t testing.TB, a, b *Screen)
- func AssertScreensNotEqual(t testing.TB, a, b *Screen)
- func AssertSnapshot(t testing.TB, scr *Screen, name string)
- func AssertStyleAt(t testing.TB, s *Screen, row, col int, style CellStyle)
- func AssertTextAt(t testing.TB, s *Screen, row, col int, text string)
- func AssertUnderlineAt(t testing.TB, s *Screen, row, col int)
- func HTMLReporter(t testing.TB, report *Report, path string)
- func JUnitReporter(t testing.TB, report *Report, path string)
- func KeyMsgForTesting(key string) tea.KeyMsg
- func KeyNames() []string
- func ListFailureCaptures() ([]string, error)
- func PendingGoldenPath(goldenPath string) string
- func Replay(t testing.TB, model tea.Model, path string)
- func SaveFailureCapture(t testing.TB, fc FailureCapture)
- func SnapshotApp(t testing.TB, app interface{ ... }, cols, lines int, name string)
- func SnapshotPath(name string) string
- func UntilContains(text string) screenPredicate
- func UntilNotContains(text string) screenPredicate
- func UntilRowContains(row int, text string) screenPredicate
- type CellDiff
- type CellKind
- type CellStyle
- type Clock
- type Diff
- type DiffLine
- type DiffMode
- type DiffViewer
- func (dv *DiffViewer) Focused() bool
- func (dv *DiffViewer) Init() tea.Cmd
- func (dv *DiffViewer) KeyBindings() []interface{}
- func (dv *DiffViewer) Mode() DiffMode
- func (dv *DiffViewer) SetFocused(f bool)
- func (dv *DiffViewer) SetMode(m DiffMode)
- func (dv *DiffViewer) SetSize(w, h int)
- func (dv *DiffViewer) Update(msg tea.Msg, _ interface{}) (*DiffViewer, tea.Cmd)
- func (dv *DiffViewer) View() string
- type DiffViewerBackMsg
- type FailureCapture
- type FailureKind
- type FakeClock
- type Harness
- func (h *Harness) Advance(d time.Duration) *Harness
- func (h *Harness) Click(x, y int) *Harness
- func (h *Harness) Done()
- func (h *Harness) Expect(text string) *Harness
- func (h *Harness) ExpectNot(text string) *Harness
- func (h *Harness) ExpectRow(row int, text string) *Harness
- func (h *Harness) Keys(keys ...string) *Harness
- func (h *Harness) OnSetup(fn func()) *Harness
- func (h *Harness) OnTeardown(fn func()) *Harness
- func (h *Harness) Resize(cols, lines int) *Harness
- func (h *Harness) Screen() *Screen
- func (h *Harness) Send(msg tea.Msg) *Harness
- func (h *Harness) Snapshot(name string) *Harness
- func (h *Harness) TestModel() *TestModel
- func (h *Harness) Type(text string) *Harness
- type IndexedRow
- type PendingGolden
- type RealClock
- type Region
- func (r *Region) AllRows() []string
- func (r *Region) Contains(text string) bool
- func (r *Region) CountOccurrences(text string) int
- func (r *Region) FindText(text string) (row, col int)
- func (r *Region) IsEmpty() bool
- func (r *Region) Row(row int) string
- func (r *Region) RowCount() int
- func (r *Region) String() string
- func (r *Region) StyleAt(row, col int) CellStyle
- type Report
- type Screen
- func (s *Screen) AllRows() []string
- func (s *Screen) Column(col, startRow, endRow int) string
- func (s *Screen) Contains(text string) bool
- func (s *Screen) ContainsAt(row, col int, text string) bool
- func (s *Screen) CountOccurrences(text string) int
- func (s *Screen) CursorPos() (row, col int)
- func (s *Screen) FindAllText(text string) [][2]int
- func (s *Screen) FindRegexp(pattern string) (row, col int)
- func (s *Screen) FindText(text string) (row, col int)
- func (s *Screen) IsEmpty() bool
- func (s *Screen) MatchesRegexp(pattern string) bool
- func (s *Screen) NonEmptyRows() []IndexedRow
- func (s *Screen) Region(row, col, width, height int) *Region
- func (s *Screen) Render(output string)
- func (s *Screen) Row(row int) string
- func (s *Screen) RowCount() int
- func (s *Screen) Size() (cols, lines int)
- func (s *Screen) String() string
- func (s *Screen) StyleAt(row, col int) CellStyle
- func (s *Screen) TextAt(row, startCol, endCol int) string
- type Session
- type SessionRecorder
- type SessionStep
- type Stopwatch
- type TestModel
- func (tm *TestModel) Cols() int
- func (tm *TestModel) Lines() int
- func (tm *TestModel) Model() tea.Model
- func (tm *TestModel) RequireScreen(fn func(t testing.TB, s *Screen))
- func (tm *TestModel) Screen() *Screen
- func (tm *TestModel) SendKey(key string)
- func (tm *TestModel) SendKeys(keys ...string)
- func (tm *TestModel) SendMouse(x, y int, button tea.MouseButton)
- func (tm *TestModel) SendMsg(msg tea.Msg)
- func (tm *TestModel) SendResize(cols, lines int)
- func (tm *TestModel) SendTick()
- func (tm *TestModel) Type(text string)
- func (tm *TestModel) WaitFor(predicate func(*Screen) bool, maxTicks int) bool
- type TestResult
- type TickMsgPlaceholder
Constants ¶
const SessionFormatVersion = 2
SessionFormatVersion is the on-disk version marker. Bump whenever the step schema changes in a backwards-incompatible way.
History:
v1 – initial format (blit ≤ v0.7.1) v2 – adds Name, RecordedAt, Command metadata fields (blit v0.11+)
Variables ¶
var SnapshotDir = filepath.Join("testdata", "__snapshots__")
SnapshotDir is the subdirectory (relative to the test file's package) where snapshot files are written. Kept exported so users can override it for a specific package if they dislike the default.
Functions ¶
func AssertBgAt ¶
AssertBgAt fails if the background color at (row, col) doesn't match.
func AssertBoldAt ¶
AssertBoldAt fails the test if the cell at (row, col) is not bold.
func AssertColumnContains ¶
AssertColumnContains asserts any row in column range [startRow,endRow] contains text.
func AssertColumnCount ¶
AssertColumnCount asserts how many non-empty rows contain text in the given column range.
func AssertContains ¶
AssertContains fails the test if the screen doesn't contain the text.
func AssertContainsAt ¶
AssertContainsAt fails the test if text doesn't appear at (row, col).
func AssertContainsCount ¶
AssertContainsCount fails if text doesn't appear exactly n times on screen.
func AssertCursorAt ¶
AssertCursorAt fails the test if the cursor isn't at (row, col).
func AssertCursorRowContains ¶
AssertCursorRowContains asserts the row under the cursor contains text.
func AssertEmpty ¶
AssertEmpty fails if the screen has any visible content.
func AssertFgAt ¶
AssertFgAt fails if the foreground color at (row, col) doesn't match.
func AssertGolden ¶
AssertGolden compares the screen content against a golden file. If the file doesn't exist or -update flag is set, it creates/updates the golden file. Golden files are stored in testdata/ relative to the test file.
func AssertItalicAt ¶
AssertItalicAt fails if the cell at (row, col) is not italic.
func AssertKeybind ¶
AssertKeybind asserts the screen's footer/help line contains the given key label. It searches the whole screen for a "key description" pattern anywhere.
func AssertMatches ¶
AssertMatches fails if the screen content doesn't match the regular expression.
func AssertNoANSI ¶
AssertNoANSI asserts the screen's rendered text contains no raw ANSI escape sequences. Raw ANSI in the decoded virtual screen indicates a broken writer that emitted literal bytes instead of styled runs.
func AssertNotContains ¶
AssertNotContains fails the test if the screen contains the text.
func AssertNotEmpty ¶
AssertNotEmpty fails if the screen has no visible content.
func AssertRegionBg ¶
AssertRegionBg asserts every non-space cell in a region has the given bg color.
func AssertRegionBold ¶
AssertRegionBold asserts every non-space cell in a region is bold.
func AssertRegionContains ¶
AssertRegionContains fails if the region doesn't contain the text.
func AssertRegionFg ¶
AssertRegionFg asserts every non-space cell in a region has the given fg color.
func AssertRegionNotContains ¶
AssertRegionNotContains fails if the region contains the text.
func AssertReverseAt ¶
AssertReverseAt fails if the cell at (row, col) is not reversed.
func AssertRowContains ¶
AssertRowContains fails if the given row doesn't contain the text.
func AssertRowCount ¶
AssertRowCount fails if the number of non-empty rows doesn't match.
func AssertRowEquals ¶
AssertRowEquals fails if the given row doesn't exactly equal text (trimmed).
func AssertRowMatches ¶
AssertRowMatches fails if the given row doesn't match the regular expression.
func AssertRowNotContains ¶
AssertRowNotContains fails if the given row contains the text.
func AssertScreenEquals ¶
AssertScreenEquals fails if the full screen text doesn't exactly match expected. On failure it also persists a FailureCapture so `blit diff` can replay it.
func AssertScreenMatches ¶
AssertScreenMatches is a regexp variant of AssertScreenEquals for fuzzier matches.
func AssertScreensEqual ¶
AssertScreensEqual fails if two screens don't have identical text content. On failure it also persists a FailureCapture so `blit diff` can replay it.
func AssertScreensNotEqual ¶
AssertScreensNotEqual fails if two screens have identical text content.
func AssertSnapshot ¶
AssertSnapshot compares scr's current screen contents against a previously stored snapshot named <name>.snap under SnapshotDir. On first run (or when -btest.update is passed), the snapshot is (re)generated. Line endings are normalized to \n so snapshots round-trip across OSes.
Example:
scr := tm.Screen() btest.AssertSnapshot(t, scr, "login-form")
func AssertStyleAt ¶
AssertStyleAt fails the test if the cell at (row, col) doesn't match the style.
func AssertTextAt ¶
AssertTextAt fails if the text at (row, col) through (row, col+len) doesn't match.
func AssertUnderlineAt ¶
AssertUnderlineAt fails if the cell at (row, col) is not underlined.
func HTMLReporter ¶
HTMLReporter registers a t.Cleanup hook that writes the report as HTML to path when the test finishes.
func JUnitReporter ¶
JUnitReporter registers a t.Cleanup hook that writes the report as JUnit XML to path when the test (or parent TestMain) finishes. The caller owns the Report and is responsible for populating Results before teardown.
func KeyMsgForTesting ¶
KeyMsgForTesting converts a key name to a tea.KeyMsg for use in unit tests that call Component.Update directly without a full TestModel.
func KeyNames ¶
func KeyNames() []string
KeyNames returns the list of all recognized key names for documentation.
func ListFailureCaptures ¶
ListFailureCaptures returns test names for all persisted failure captures.
func PendingGoldenPath ¶
PendingGoldenPath returns the path of the pending-review file for a golden. The pending file is <goldenPath>.new and is written by AssertGolden on mismatch so that `blit review` can enumerate it.
func Replay ¶
Replay drives the given model through a recorded session, asserting that each screen step matches the live screen. It fails the test on any divergence. Cols/lines from the session override the model's initial size.
func SaveFailureCapture ¶
func SaveFailureCapture(t testing.TB, fc FailureCapture)
SaveFailureCapture persists fc to .blit/failures/<testname>.json. If fc.TestName is empty and t implements Name(), the test name is filled in. Errors are logged via t but never fatal — failure capture is best-effort.
func SnapshotApp ¶ added in v0.1.2
SnapshotApp is a one-liner that creates a harness from a full application, takes a named golden snapshot, and cleans up. Use this when you only need to verify the initial render of the real app layout:
btest.SnapshotApp(t, myApp, 80, 24, "initial")
For interactive tests (key presses, resizes, multiple snapshots), use NewAppHarness instead.
func SnapshotPath ¶
SnapshotPath returns the full on-disk path for the named snapshot. Exposed so tests can assert on where a snapshot landed.
func UntilContains ¶
func UntilContains(text string) screenPredicate
UntilContains returns a predicate that is satisfied when the screen contains text.
func UntilNotContains ¶
func UntilNotContains(text string) screenPredicate
UntilNotContains returns a predicate satisfied when the screen no longer contains text.
func UntilRowContains ¶
UntilRowContains returns a predicate satisfied when the given row contains text.
Types ¶
type CellDiff ¶
type CellDiff struct {
Row int
Col int
ExpectedText string
ActualText string
ExpectedStyle CellStyle
ActualStyle CellStyle
Kind CellKind
}
CellDiff holds the comparison result for a single terminal cell.
func ScreenCellDiff ¶
ScreenCellDiff performs a per-cell comparison between two screens, returning one CellDiff per cell that differs (text or style).
type CellKind ¶
type CellKind int
CellKind classifies the type of difference at a single cell position.
type CellStyle ¶
type CellStyle struct {
Fg string // foreground color (empty = default)
Bg string // background color (empty = default)
Bold bool
Italic bool
Underline bool
Reverse bool
}
CellStyle represents the visual attributes of a terminal cell.
type Clock ¶
type Clock interface {
// Now returns the current time as seen by this clock.
Now() time.Time
// Sleep blocks until the clock has advanced by d.
// FakeClock implementations return immediately but still honor Advance.
Sleep(d time.Duration)
}
Clock is an abstraction over time.Now used by Poller-like components so tests can drive time deterministically. The real clock uses time.Now and time.Sleep; FakeClock lets tests advance time manually.
type Diff ¶
type Diff struct {
Lines []DiffLine
}
Diff represents a line-by-line comparison between two screen states.
func ScreenDiff ¶
ScreenDiff compares two screens and returns a Diff showing changed lines.
func (Diff) ChangedLines ¶
ChangedLines returns only the lines that differ.
func (Diff) HasChanges ¶
HasChanges reports whether any lines differ.
type DiffViewer ¶
type DiffViewer struct {
// contains filtered or unexported fields
}
DiffViewer is a blit Component that renders a side-by-side (or unified / cells-only) comparison of two screens captured from a failing btest assertion. It implements the blit Component interface so it can be embedded in any App layout.
Keybindings:
s — side-by-side mode u — unified mode d — cells-only mode q — signal back-to-runner (emits DiffViewerBackMsg)
func NewDiffViewer ¶
func NewDiffViewer(fc *FailureCapture) *DiffViewer
NewDiffViewer constructs a DiffViewer from a persisted FailureCapture.
func (*DiffViewer) Focused ¶
func (dv *DiffViewer) Focused() bool
Focused implements blit.Component.
func (*DiffViewer) KeyBindings ¶
func (dv *DiffViewer) KeyBindings() []interface{}
KeyBindings implements blit.Component.
func (*DiffViewer) Mode ¶
func (dv *DiffViewer) Mode() DiffMode
Mode returns the current display mode.
func (*DiffViewer) SetFocused ¶
func (dv *DiffViewer) SetFocused(f bool)
SetFocused implements blit.Component.
func (*DiffViewer) SetMode ¶
func (dv *DiffViewer) SetMode(m DiffMode)
SetMode sets the display mode directly (used by the CLI one-shot renderer).
func (*DiffViewer) SetSize ¶
func (dv *DiffViewer) SetSize(w, h int)
SetSize implements blit.Component.
func (*DiffViewer) Update ¶
func (dv *DiffViewer) Update(msg tea.Msg, _ interface{}) (*DiffViewer, tea.Cmd)
Update implements blit.Component. ctx is the ambient blit.Context but the DiffViewer only needs key messages, so it accepts tea.Msg directly and ignores the ctx value (kept as interface{} to avoid importing blit from inside the btest sub-package, which would create a cycle).
type DiffViewerBackMsg ¶
type DiffViewerBackMsg struct{}
DiffViewerBackMsg is sent when the user presses q to return to the runner.
type FailureCapture ¶
type FailureCapture struct {
TestName string `json:"test_name"`
Kind FailureKind `json:"kind"`
// For FailureScreenEqual: both fields populated.
ExpectedScreen string `json:"expected_screen,omitempty"`
ActualScreen string `json:"actual_screen,omitempty"`
// For FailureGolden: golden file path + expected/actual bytes.
GoldenPath string `json:"golden_path,omitempty"`
GoldenExpected string `json:"golden_expected,omitempty"`
GoldenActual string `json:"golden_actual,omitempty"`
}
FailureCapture holds the screens (or golden bytes) captured when an assertion fails. It is persisted to .blit/failures/<testname>.json so that `blit diff <testname>` can replay the diff offline.
func LoadFailureCapture ¶
func LoadFailureCapture(testName string) (*FailureCapture, error)
LoadFailureCapture reads the persisted capture for a test name.
type FailureKind ¶
type FailureKind string
FailureKind identifies what kind of assertion failed.
const ( // FailureScreenEqual is produced by screen-equality assertions. FailureScreenEqual FailureKind = "screen_equal" // FailureGolden is produced by AssertGolden when the file differs. FailureGolden FailureKind = "golden" )
type FakeClock ¶
type FakeClock struct {
// contains filtered or unexported fields
}
FakeClock is a deterministic Clock for tests. Create one with NewFakeClock and advance it with Advance. Now and Sleep are safe for concurrent use.
func NewFakeClock ¶
NewFakeClock returns a FakeClock anchored at the given time. If t is the zero value, it is anchored at a fixed epoch (2026-01-01 UTC) so tests are reproducible across machines.
func (*FakeClock) Advance ¶
Advance moves the fake clock forward by d. Negative durations are ignored.
type Harness ¶
type Harness struct {
// contains filtered or unexported fields
}
Harness is a fluent wrapper around TestModel for concise, chainable test scripts. Each method returns *Harness so calls can be chained:
btest.NewHarness(t, model, 80, 24).
Keys("down", "down", "enter").
Expect("Loaded").
ExpectRow(2, "selected").
Done()
func NewAppHarness ¶ added in v0.1.2
NewAppHarness creates a test harness from a full application, using the real component tree (Tabs, DualPane, StatusBar, overlays, etc.). This ensures golden snapshots cover the actual production layout, not a simplified reconstruction. app must implement Model() tea.Model (e.g., *blit.App).
h := btest.NewAppHarness(t, myApp, 80, 24)
defer h.Done()
h.Send(someMsg).Expect("loaded").Snapshot("initial")
func NewHarness ¶
NewHarness creates a new test harness around the given model.
func (*Harness) Advance ¶
Advance is a placeholder for time-based drivers. It accepts a duration so call sites read naturally; the underlying TestModel does not yet integrate a FakeClock directly, but tests that own the FakeClock can chain .Advance(d) purely for documentation.
func (*Harness) Done ¶
func (h *Harness) Done()
Done runs registered teardown callbacks in LIFO order. Safe to call multiple times; subsequent calls are no-ops.
func (*Harness) Expect ¶
Expect asserts that the current screen contains text anywhere. Fails the test with a helpful diff if not.
func (*Harness) OnSetup ¶
OnSetup registers a function to run once when the first action fires. Use this for things like seeding state that depends on Harness being wired up but shouldn't run in NewHarness.
func (*Harness) OnTeardown ¶
OnTeardown registers a function to run when Done() is called. Registered functions run in reverse order (last-registered first) so they match a deferred-cleanup mental model.
func (*Harness) Screen ¶
Screen returns the current screen for ad-hoc assertions outside the fluent API.
type IndexedRow ¶
IndexedRow pairs a row index with its text content.
type PendingGolden ¶
type PendingGolden struct {
// GoldenPath is the path to the accepted golden file (may not exist yet
// if the golden was never written).
GoldenPath string
// NewPath is the .golden.new file written by AssertGolden on mismatch.
NewPath string
// Expected is the current accepted content (empty if golden doesn't exist).
Expected string
// Actual is the candidate content from the .golden.new file.
Actual string
}
PendingGolden describes a single pending snapshot review item: the canonical .golden path plus the candidate .golden.new content.
func FindPendingGoldens ¶
func FindPendingGoldens(root string) ([]PendingGolden, error)
FindPendingGoldens walks root recursively and returns all .golden.new files as PendingGolden items. root is typically "." (the package under test).
func (PendingGolden) Accept ¶
func (p PendingGolden) Accept() error
Accept writes Actual atomically to GoldenPath and removes NewPath. It uses a temp-file + rename so the update is atomic.
func (PendingGolden) Reject ¶
func (p PendingGolden) Reject() error
Reject removes the .golden.new file without touching the accepted golden.
func (PendingGolden) TestName ¶
func (p PendingGolden) TestName() string
TestName returns a short human-readable label derived from the golden path. It strips the leading testdata/ prefix and the .golden suffix.
type RealClock ¶
type RealClock struct{}
RealClock is a Clock backed by the real time package. Safe for concurrent use.
type Region ¶
type Region struct {
// contains filtered or unexported fields
}
Region is a rectangular sub-area of a Screen for scoped assertions.
func (*Region) CountOccurrences ¶
CountOccurrences returns how many times text appears in the region.
func (*Region) FindText ¶
FindText returns the (relativeRow, relativeCol) of the first occurrence of text within the region. Returns (-1, -1) if not found.
func (*Region) Row ¶
Row returns the text content of a row within the region (0-indexed relative to the region's top-left corner), trimmed of trailing spaces.
type Report ¶
type Report struct {
Suite string
StartedAt time.Time
Results []TestResult
}
Report is a collection of test results plus suite metadata.
func (*Report) TotalDuration ¶
TotalDuration sums the duration of all results.
func (*Report) WriteJUnit ¶
WriteJUnit writes the report as a JUnit XML file at path. Parent directories are created as needed.
type Screen ¶
type Screen struct {
// contains filtered or unexported fields
}
Screen wraps go-te to provide a virtual terminal for testing TUI output.
func (*Screen) Column ¶
Column extracts a vertical column of text from startRow to endRow (exclusive).
func (*Screen) ContainsAt ¶
ContainsAt reports whether the given text appears starting at (row, col).
func (*Screen) CountOccurrences ¶
CountOccurrences returns how many times text appears on the screen.
func (*Screen) FindAllText ¶
FindAllText returns all (row, col) positions where text appears.
func (*Screen) FindRegexp ¶
FindRegexp returns the (row, col) of the first regexp match. Returns (-1, -1) if not found.
func (*Screen) FindText ¶
FindText returns the (row, col) of the first occurrence of text on the screen. Returns (-1, -1) if not found.
func (*Screen) MatchesRegexp ¶
MatchesRegexp reports whether the screen content matches the regular expression.
func (*Screen) NonEmptyRows ¶
func (s *Screen) NonEmptyRows() []IndexedRow
NonEmptyRows returns only the non-empty rows with their row indices.
func (*Screen) Render ¶
Render feeds View() output (with ANSI codes) into the virtual terminal. It translates bare \n to \r\n (mimicking the terminal's ONLCR flag) so that Bubble Tea View() output renders correctly.
func (*Screen) String ¶
String returns a plain text representation of the entire screen (for debugging/golden files).
type Session ¶
type Session struct {
Version int `json:"version"`
Cols int `json:"cols"`
Lines int `json:"lines"`
Name string `json:"name,omitempty"` // v2+: logical session name
RecordedAt string `json:"recorded_at,omitempty"` // v2+: RFC3339 timestamp
Command []string `json:"command,omitempty"` // v2+: recorded command args
Steps []SessionStep `json:"steps"`
}
Session is the on-disk representation of a .tuisess file.
func LoadSession ¶
LoadSession reads a .tuisess file. Versions 1 and 2 are both accepted; v1 files are loaded without the metadata fields introduced in v2.
type SessionRecorder ¶
type SessionRecorder struct {
// contains filtered or unexported fields
}
SessionRecorder captures input + screen steps against a live TestModel.
func NewSessionRecorder ¶
func NewSessionRecorder(tm *TestModel) *SessionRecorder
NewSessionRecorder returns a recorder bound to an existing TestModel.
func (*SessionRecorder) Key ¶
func (r *SessionRecorder) Key(key string) *SessionRecorder
Key sends a named key and records the key + resulting screen.
func (*SessionRecorder) Resize ¶
func (r *SessionRecorder) Resize(cols, lines int) *SessionRecorder
Resize updates the simulated terminal size and records the step.
func (*SessionRecorder) Save ¶
func (r *SessionRecorder) Save(path string) error
Save writes the recorded session to the given path as a .tuisess file. Missing parent directories are created. If path has no extension it is given ".tuisess".
func (*SessionRecorder) Type ¶
func (r *SessionRecorder) Type(text string) *SessionRecorder
Type sends text one char at a time and records the aggregated step.
type SessionStep ¶
type SessionStep struct {
Kind string `json:"kind"` // "key", "type", "resize", "screen"
Key string `json:"key,omitempty"` // for kind=key
Text string `json:"text,omitempty"` // for kind=type
Cols int `json:"cols,omitempty"` // for kind=resize
Lines int `json:"lines,omitempty"` // for kind=resize
Screen string `json:"screen,omitempty"` // for kind=screen (expected post-state)
}
SessionStep is a single input or screen assertion.
type Stopwatch ¶
type Stopwatch struct {
// contains filtered or unexported fields
}
Stopwatch measures elapsed time for performance assertions in tests.
func StartStopwatch ¶
func StartStopwatch() Stopwatch
StartStopwatch begins a new timing measurement.
func (Stopwatch) AssertUnder ¶
AssertUnder fails the test if the elapsed time exceeds the given duration.
type TestModel ¶
type TestModel struct {
// contains filtered or unexported fields
}
TestModel wraps a tea.Model for easy testing.
func NewTestModel ¶
NewTestModel creates a test wrapper around a Bubble Tea model. Calls Init() and processes any returned commands that produce messages.
func (*TestModel) RequireScreen ¶
RequireScreen renders the model and runs assertions against the screen in one call. The callback receives the screen and can use assert helpers on it.
func (*TestModel) SendKey ¶
SendKey sends a key event to the model. Supports special key names like "enter", "tab", "up", "down", "left", "right", "esc", "backspace", "space", and single characters.
func (*TestModel) SendKeys ¶
SendKeys sends a sequence of named keys. Each key is processed individually. Example: tm.SendKeys("down", "down", "enter")
func (*TestModel) SendMouse ¶
func (tm *TestModel) SendMouse(x, y int, button tea.MouseButton)
SendMouse sends a mouse event to the model.
func (*TestModel) SendMsg ¶
SendMsg sends an arbitrary tea.Msg to the model and processes any resulting command.
func (*TestModel) SendResize ¶
SendResize sends a window resize event.
func (*TestModel) SendTick ¶
func (tm *TestModel) SendTick()
SendTick sends a generic tick message. Useful for testing time-based components like pollers, spinners, and animations.
type TestResult ¶
type TestResult struct {
Name string
Package string
Duration time.Duration
Passed bool
Failure string
Skipped bool
Before string // optional screen before failure
After string // optional screen after failure
}
TestResult describes one test outcome used by the reporters.
type TickMsgPlaceholder ¶
TickMsgPlaceholder is a btest-local tick shape used by Harness.Advance so we don't depend on an external TickMsg definition here. Consumers that care about tick semantics should use SendMsg directly.