Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions src/Spectre.Console.Testing/Cli/CommandAppTester.cs
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,52 @@ private CommandAppResult Run(string[] args, TestConsole console, Action<IConfigu

var result = app.Run(args);

var output = console.Output
.NormalizeLineEndings()
.TrimLines()
.Trim();

return new CommandAppResult(result, output, context, settings);
}

/// <summary>
/// Runs the command application asynchronously.
/// </summary>
/// <param name="args">The arguments.</param>
/// <returns>The result.</returns>
public async Task<CommandAppResult> RunAsync(params string[] args)
{
var console = new TestConsole().Width(int.MaxValue);
return await RunAsync(args, console);
}

private async Task<CommandAppResult> RunAsync(string[] args, TestConsole console, Action<IConfigurator>? config = null)
{
CommandContext? context = null;
CommandSettings? settings = null;

var app = new CommandApp(Registrar);
_appConfiguration?.Invoke(app);

if (_configuration != null)
{
app.Configure(_configuration);
}

if (config != null)
{
app.Configure(config);
}

app.Configure(c => c.ConfigureConsole(console));
app.Configure(c => c.SetInterceptor(new CallbackCommandInterceptor((ctx, s) =>
{
context = ctx;
settings = s;
})));

var result = await app.RunAsync(args);

var output = console.Output
.NormalizeLineEndings()
.TrimLines()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
namespace Spectre.Console.Tests.Data;

public sealed class AsynchronousCommand : AsyncCommand<AsynchronousCommandSettings>
{
private readonly IAnsiConsole _console;

public AsynchronousCommand(IAnsiConsole console)
{
_console = console;
}

public async override Task<int> ExecuteAsync(CommandContext context, AsynchronousCommandSettings settings)
{
// Simulate a long running asynchronous task
await Task.Delay(200);

if (settings.ThrowException)
{
throw new Exception($"Throwing exception asynchronously");
}
else
{
_console.WriteLine($"Finished executing asynchronously");
}

return 0;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,4 @@ public override int Execute(CommandContext context, ThrowingCommandSettings sett
{
throw new InvalidOperationException("W00t?");
}
}

public sealed class ThrowingCommandSettings : CommandSettings
{
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace Spectre.Console.Tests.Data;

public sealed class AsynchronousCommandSettings : CommandSettings
{
[CommandOption("--ThrowException")]
[DefaultValue(false)]
public bool ThrowException { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
namespace Spectre.Console.Tests.Data;

public sealed class ThrowingCommandSettings : CommandSettings
{
}
70 changes: 70 additions & 0 deletions test/Spectre.Console.Cli.Tests/Unit/CommandAppTests.Async.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
namespace Spectre.Console.Tests.Unit.Cli;

public sealed partial class CommandAppTests
{
public sealed class Async
{
[Fact]
public async void Should_Execute_Command_Asynchronously()
{
// Given
var app = new CommandAppTester();
app.SetDefaultCommand<AsynchronousCommand>();
app.Configure(config =>
{
config.PropagateExceptions();
});

// When
var result = await app.RunAsync();

// Then
result.ExitCode.ShouldBe(0);
result.Output.ShouldBe("Finished executing asynchronously");
}

[Fact]
public async void Should_Handle_Exception_Asynchronously()
{
// Given
var app = new CommandAppTester();
app.SetDefaultCommand<AsynchronousCommand>();

// When
var result = await app.RunAsync(new[]
{
"--ThrowException",
"true",
});

// Then
result.ExitCode.ShouldBe(-1);
}

[Fact]
public async void Should_Throw_Exception_Asynchronously()
{
// Given
var app = new CommandAppTester();
app.SetDefaultCommand<AsynchronousCommand>();
app.Configure(config =>
{
config.PropagateExceptions();
});

// When
var result = await Record.ExceptionAsync(async () =>
await app.RunAsync(new[]
{
"--ThrowException",
"true",
}));

// Then
result.ShouldBeOfType<Exception>().And(ex =>
{
ex.Message.ShouldBe("Throwing exception asynchronously");
});
}
}
}