tuitest

package
v1.92.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 30, 2026 License: Apache-2.0 Imports: 14 Imported by: 0

Documentation

Overview

Package tuitest is a black-box end-to-end harness for the docker-agent TUI.

It drives the real top-level Bubble Tea model through a real tea.Program so that the full event path — keyboard input, the chat page, the runtime event stream, and the session supervisor that routes events back via program.Send — is exercised exactly as in production. The only thing it fakes is the terminal: the renderer is disabled and each rendered frame is captured inside the model's Update (which runs on the program's single message-loop goroutine), so frame capture is race-free and independent of renderer timing.

The result is a fluent, Selenium-like DSL without Selenium's flakiness:

tuitest.New(t, model, 120, 40).
    Type("What's 2+2?").
    Enter().
    WaitFor(tuitest.Contains("4")).
    AssertGolden("basic_math")

Synchronization is expressed through WaitFor: it polls the latest captured frame until a Matcher passes or a deadline elapses. Because runtime events arrive asynchronously (the agent streams its answer), tests wait for visible outcomes rather than sleeping.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Driver

type Driver struct {
	// contains filtered or unexported fields
}

Driver drives a TUI model and exposes a fluent assertion API. Every method that advances state returns the Driver so calls can be chained. Assertion failures are reported through testing.TB and stop the test.

func New

func New(tb testing.TB, model tea.Model, width, height int, opts ...Option) *Driver

New starts model in a real, renderer-less tea.Program and returns a Driver. width and height seed the initial window size. The program is stopped and awaited automatically via t.Cleanup.

model is typically the value returned by tui.New. If it implements SetProgram (as the docker-agent TUI does) the running program is wired into it so the session supervisor can deliver routed runtime events.

func (*Driver) Assert

func (d *Driver) Assert(m Matcher) *Driver

Assert immediately checks m against the latest frame without waiting.

func (*Driver) AssertClipboard

func (d *Driver) AssertClipboard(m Matcher) *Driver

AssertClipboard immediately checks the latest copied text with m.

func (*Driver) AssertGolden

func (d *Driver) AssertGolden(name string) *Driver

AssertGolden compares the latest frame against the golden file testdata/<name>.golden. With -tuitest.update the golden file is (re)written from the current frame, which is how you record or refresh a snapshot after an intentional UI change.

Goldens are the regression net for "we didn't mean to change the finished product": any unintended visual drift in a covered screen turns into a diff.

func (*Driver) Click

func (d *Driver) Click(x, y int) *Driver

Click sends a left-click followed by a release at screen coordinates x,y.

func (*Driver) ClickText

func (d *Driver) ClickText(text string) *Driver

ClickText clicks the first visible occurrence of text.

func (*Driver) Clipboard

func (d *Driver) Clipboard() string

Clipboard returns the latest text copied through the TUI's clipboard path. The tuitest driver installs a spy so tests never touch the real system clipboard.

func (*Driver) Enter

func (d *Driver) Enter() *Driver

Enter is shorthand for Press(tea.KeyEnter).

func (*Driver) FindText

func (d *Driver) FindText(text string) (x, y int, ok bool)

FindText returns the coordinates of the first occurrence of text in the latest captured frame. The x coordinate is display width, not byte offset, so it works for wide Unicode before the matched text.

func (*Driver) Frame

func (d *Driver) Frame() string

Frame returns the most recently captured, ANSI-stripped frame.

func (*Driver) MoveMouse

func (d *Driver) MoveMouse(x, y int) *Driver

MoveMouse sends a mouse-motion event at screen coordinates x,y.

func (*Driver) MoveMouseToText

func (d *Driver) MoveMouseToText(text string) *Driver

MoveMouseToText moves the mouse to the first visible occurrence of text.

func (*Driver) MustFindText

func (d *Driver) MustFindText(text string) (x, y int)

MustFindText is like FindText but fails the test when text is not visible.

func (*Driver) Press

func (d *Driver) Press(code rune, mods ...tea.KeyMod) *Driver

Press sends a single key by its code (e.g. tea.KeyEnter, tea.KeyEsc) with optional modifiers.

func (*Driver) Resize

func (d *Driver) Resize(width, height int) *Driver

Resize sends a new terminal size.

func (*Driver) Send

func (d *Driver) Send(msg tea.Msg) *Driver

Send delivers an arbitrary message to the model. Useful for injecting runtime events or custom messages a scenario can't reach through the keyboard alone.

func (*Driver) Type

func (d *Driver) Type(s string) *Driver

Type sends s to the model one key press at a time, mirroring real typing.

func (*Driver) WaitFor

func (d *Driver) WaitFor(m Matcher) *Driver

WaitFor polls the latest frame until m passes or the timeout elapses. On timeout it fails the test with the last frame for context.

func (*Driver) WaitForClipboard

func (d *Driver) WaitForClipboard(substr string) *Driver

WaitForClipboard polls until the latest copied text contains substr, or the driver's timeout elapses.

func (*Driver) WaitForStable

func (d *Driver) WaitForStable(quiet time.Duration) *Driver

WaitForStable blocks until no new frame has been captured for quiet, then returns. Use it before AssertGolden so the snapshot is taken once streaming has settled. It still respects the overall wait timeout.

type Matcher

type Matcher interface {
	// contains filtered or unexported methods
}

Matcher tests a captured frame. Matchers are the vocabulary WaitFor and Assert speak; they replace Selenium's brittle selectors with simple, composable predicates over the rendered text.

func Absent

func Absent(substr string) Matcher

Absent matches when the frame does NOT contain substr. Pair it with a prior WaitFor on something positive, since "absent" is trivially true before the UI has rendered anything.

func Contains

func Contains(substr string) Matcher

Contains matches when the frame contains substr.

func ContainsAll

func ContainsAll(substrs ...string) Matcher

ContainsAll matches when the frame contains every substring.

func Matches

func Matches(pattern string) Matcher

Matches matches when the frame matches the regular expression pattern. It panics if pattern does not compile, surfacing the mistake at test authoring time.

func Not

func Not(m Matcher) Matcher

Not inverts a matcher.

type Option

type Option func(*Driver)

Option configures a Driver.

func WithTimeout

func WithTimeout(d time.Duration) Option

WithTimeout overrides the default WaitFor deadline.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL