Testing
Test screens, components and whole apps without a terminal.
Screens and components
Test a screen with ComponentHarness, which runs the app one step at a time on a test terminal:
using var harness = new ComponentHarness(new ServicesScreen(fakeApi), width: 80, height: 24);
harness.Press("j j enter"); // KeyBinding names
Assert.IsType<DetailScreen>(harness.App.Screens.Top);
harness.Type("hello");
Assert.Contains(harness.Lines, l => l.Contains("hello"));
Each call handles the keys, posted work and await continuations until nothing is in flight, then draws
a frame.
Whole apps and rendering
To test a whole app, give it a TestBackend and a ScriptedInputSource (Enqueue, EnqueueText):
var backend = new TestBackend(40, 10);
var input = new ScriptedInputSource().EnqueueText("kkq");
var count = 0;
var app = App.Create().WithBackend(backend).WithInput(input).WithTickRate(null);
app.OnKey(key =>
{
if (key.KeyChar == 'k') count++;
if (key.KeyChar == 'q') app.Quit();
return true;
})
.Render((buf, _) => buf.SetString(0, 0, $"Count: {count}", Style.Default))
.Run();
Assert.Equal(2, count); // q quits before another frame is drawn; check screens with RunAsync while running
WithTimeProvider(new FakeTimeProvider()) (from Microsoft.Extensions.TimeProvider.Testing) controls ticks.
To test your own drawing code, draw into a Terminal over a TestBackend:
var backend = new TestBackend(40, 10);
using (var terminal = new Terminal(backend))
terminal.Draw(buf => buf.SetString(0, 0, "Hello", Style.Default));
Assert.Equal("Hello", backend.Lines[0].TrimEnd());
Assert.Equal(Color.Reset, backend.CellAt(0, 0).Fg);