Table of Contents

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);