← All libraries

CandyTesting

🍬 CandyTesting

Test harness for TEA programs

pioneering (no upstream) testing tea foundation-package

The test harness SugarCraft pioneers that bubble-tea issue #1654 never shipped: ProgramSimulator for driving TEA programs with scripted input, Assertions for golden-file and cell-grid snapshots, and TapeRecorder for VHS demo capture.

Install

composer require sugarcraft/candy-testing:@dev

Quickstart

use SugarCraft\Testing\ProgramSimulator;
use SugarCraft\Testing\Input\ScriptedInput;
use SugarCraft\Testing\Snapshot\Assertions;
use SugarCraft\Core\Msg\KeyMsg;
use SugarCraft\Core\KeyType;

$sim = ProgramSimulator::for($program)
    ->send(new KeyMsg(KeyType::Character, '+'))
    ->send(new KeyMsg(KeyType::Enter))
    ->run();

Assertions::assertGoldenAnsi(__DIR__ . '/fixtures/counter.golden', $sim->view);
echo "Final count: " . $sim->model->count();

ProgramSimulator

for(Program)Factory: wrap a Program for deterministic testing.
send(Msg)Fluent message enqueue — chain multiple sends.
withFakeCmdRunner()Intercept commands instead of executing them.
run()Drain the queue, return TestResult with model/view/cmds/output.

Assertions

assertGoldenAnsiSnapshot test — auto-creates golden on UPDATE_GOLDENS=1.
assertCellGridCell-by-cell diff for Buffer-based renderers.
assertAnsiEqualsByte-exact ANSI comparison with readable ESC diff.

TapeRecorder

to(path)Factory: create a tape recorder writing to the given path.
header()Write VHS header (theme, font size, width, height).
type() / enter() / sleep()Record keypresses and delays for demo playback.
save()Write the completed .tape file.

Use it for

Source & demos

Try the quickstart →

API

ClassMethodDescription
ProgramSimulatorfor(Program): selfFactory: wrap a Program
ProgramSimulatorsend(Msg): selfFluent message enqueue
ProgramSimulatorwithFakeCmdRunner(callable): selfIntercept commands
ProgramSimulatorrun(): TestResultDrain queue, return result
TestResultmodel: objectFinal model after all messages
TestResultview: stringLast view() output
TestResultcmds: list<Closure>Captured commands
TestResultoutput: stringRaw accumulated ANSI bytes
AssertionsassertGoldenAnsi(string, string): voidGolden file snapshot assertion
AssertionsassertCellGrid(array, Buffer): voidCell-by-cell buffer comparison
AssertionsassertAnsiEquals(string, string): voidByte-exact ANSI diff
GoldenFileload(string): ?stringLoad golden file contents
GoldenFilesave(string, string): voidSave golden file
TapeRecorderto(string): selfFactory: create recorder
TapeRecorderheader(...): selfWrite VHS header
TapeRecordertype(string): selfRecord keypress
TapeRecorderenter(): selfRecord Enter key
TapeRecordersleep(float): selfRecord delay
TapeRecordersave(): voidWrite .tape file
ScriptedInputnew(): selfFactory: empty input builder
ScriptedInputkey(string): selfAppend character key
ScriptedInputenter(): selfAppend Enter key
ScriptedInputarrow(string): selfAppend arrow key
ScriptedInputbuild(): list<Msg>Return message sequence