Skip to content

Testing

Classes in the Phui\Testing and Phui\Debug namespaces, and the phui-snapshot command.

TestScreen

final class Phui\Testing\TestScreen

Mounts a component against a fake terminal and drives it a frame at a time.

Mounting

php
static mount(
    Component|string $component,
    int $width = 80,
    int $height = 24,
): self

Mounts $component on a fake terminal of the given cell size.

php
TestScreen::mount(Counter::class)
    ->press(Keypress::ENTER)
    ->assertSee('1');
php
theme(Theme $theme): static
colours(ColourMode $mode): static
service(string $class, object $instance): static
inline(int $height = 15): static

Mirror the same setters on the Screen.

Driving input

php
press(
    Keypress|string $key,
    array $modifiers = [],
): static

Sends a keypress.

php
type(string $text): static

Sends each character of $text as a separate keypress.

php
click(
    int $x,
    int $y,
    string $button = MouseClickEvent::LEFT,
): static

Sends a full click — a press then a release — at a screen cell.

php
mouseDown(
    int $x,
    int $y,
    string $button = MouseClickEvent::LEFT,
): static
mouseUp(
    int $x,
    int $y,
    string $button = MouseClickEvent::LEFT,
): static

Send a lone press or release at a screen cell, for driving a drag or the two phases of a click apart.

php
scroll(
    int $x,
    int $y,
    string $direction = MouseScrollEvent::DOWN,
    int $amount = 1,
): static

Sends a scroll at a screen cell.

php
paste(string $content): static

Sends a paste.

php
resize(int $width, int $height): static

Resizes the fake terminal.

Controlling time

php
advance(int $milliseconds): static

Moves the fake clock forward, running any timers that fall due.

php
tick(): static

Processes pending work and renders one frame.

php
hasPendingHandlers(): bool

Returns whether handlers are still suspended and waiting to resume.

php
settle(
    ?Closure $using = null,
    int $maxTicks = 25,
): static

Ticks until nothing is pending or $maxTicks is reached. $using runs between ticks to drive an external event loop.

Reading the result

php
capture(): Capture

Returns a Capture of the current frame.

php
assertSee(string $text): static

Asserts the rendered frame contains $text.

php
assertDontSee(string $text): static

Asserts the rendered frame does not contain $text.

php
completed(): bool

Returns whether the app has completed.

php
result(): mixed

Returns the value passed to complete().

php
commands(?string $commandClass = null): array

Returns the terminal commands issued, optionally filtered to one command class.

Capture

final readonly class Phui\Testing\Capture implements Stringable

A rendered frame, readable as text or cell by cell.

php
public int $width
public int $height

The captured frame's cell dimensions.

php
cellAt(int $x, int $y): ?Cell

Returns the cell at a position, or null when out of bounds.

php
toText(): string

Returns the frame as plain text, without styling.

php
toAnsi(): string

Returns the frame with its ANSI escape sequences intact.

php
diff(self $other): array

Returns the cells that differ between this capture and $other.

Snapshot CLI

vendor/bin/phui-snapshot renders a component to an ANSI frame or an image, with no TTY and no running app. For what it's for and how to write a target file, see Agents & Snapshotting.

bash
vendor/bin/phui-snapshot <target.php> [options]

The target is a PHP file that returns a Component instance or class name; --class constructs a class directly instead.

Options

OptionDefaultDoes
--size=WxH120x32Terminal dimensions
--keys=TOKENSSpace-separated input tokens, played in order
--settle=N2Frames run after each token
--trimoffCrops blank rows and columns off the right and bottom
--out=PATH<target>.ansiWhere the ANSI frame goes
--png[=PATH]offAlso renders a PNG, via freeze
--film[=PATH]offFilmstrip PNG, one frame per token
--gif[=PATH]offAnimated GIF, one frame per token
--font=NAMEMenloFont family passed to freeze
--class=NAMEConstructs this class instead of requiring a return

The image options shell out to freeze (brew install charmbracelet/tap/freeze); --film and --gif additionally need ImageMagick. The ANSI path needs neither.

Input tokens

The tokens --keys takes:

TokenDoes
a 1 ?Types the character
enter tab esc spacePresses that key
up down left right home end pageup pagedownMoves
backspace deleteDeletes
ctrl:X alt:XPresses X with a modifier, e.g. ctrl:enter
click:X,YLeft-clicks cell X,Y
wheel:up:X,Y wheel:down:X,YScrolls at cell X,Y
advance:MSAdvances the clock, for timers and animation
settleTicks until suspended handlers finish
resize:WxHResizes the terminal

Logger

final class Phui\Debug\Logger

Writes to a file rather than the terminal, which the rendered frame owns.

php
static configure(?string $path): void

Sets the log file path. null disables logging.

php
static installErrorHandler(): void

Routes PHP errors and uncaught exceptions to the log.

php
static debug(string $message): void
static info(string $message): void
static warn(string $message): void
static error(string $message): void

Write a message at that level.

Released under the MIT License.