Return key in IConsole.ReadKey(...)

Closes #124
This commit is contained in:
Oleksii Holub
2022-02-19 01:32:58 +02:00
parent a396009b62
commit eb7107fb0a
4 changed files with 64 additions and 5 deletions

View File

@@ -5,6 +5,7 @@ using System.Text;
using System.Threading.Tasks;
using CliFx.Infrastructure;
using CliFx.Tests.Utils;
using CliFx.Tests.Utils.Extensions;
using CliWrap;
using CliWrap.Buffered;
using FluentAssertions;
@@ -139,6 +140,53 @@ public class Command : ICommand
stdErr.Trim().Should().Be("Hello world");
}
[Fact]
public async Task Fake_console_can_read_key_presses()
{
// Arrange
var commandType = DynamicCommandBuilder.Compile(
// language=cs
@"
[Command]
public class Command : ICommand
{
public ValueTask ExecuteAsync(IConsole console)
{
console.Output.WriteLine(console.ReadKey().Key);
console.Output.WriteLine(console.ReadKey().Key);
console.Output.WriteLine(console.ReadKey().Key);
return default;
}
}
");
var application = new CliApplicationBuilder()
.AddCommand(commandType)
.UseConsole(FakeConsole)
.Build();
// Act
FakeConsole.EnqueueKey(new ConsoleKeyInfo('0', ConsoleKey.D0, false, false, false));
FakeConsole.EnqueueKey(new ConsoleKeyInfo('a', ConsoleKey.A, false, false, false));
FakeConsole.EnqueueKey(new ConsoleKeyInfo('\0', ConsoleKey.Backspace, false, false, false));
var exitCode = await application.RunAsync(
Array.Empty<string>(),
new Dictionary<string, string>()
);
var stdOut = FakeConsole.ReadOutputString();
// Assert
exitCode.Should().Be(0);
stdOut.Trim().Should().ConsistOfLines(
"D0",
"A",
"Backspace"
);
}
[Fact]
public void Console_does_not_emit_preamble_when_used_with_encoding_that_has_it()
{

View File

@@ -1,4 +1,5 @@
using System;
using System.Collections.Concurrent;
using System.IO;
using System.Threading;
@@ -14,6 +15,7 @@ namespace CliFx.Infrastructure;
public class FakeConsole : IConsole, IDisposable
{
private readonly CancellationTokenSource _cancellationTokenSource = new();
private readonly ConcurrentQueue<ConsoleKeyInfo> _keys = new();
/// <inheritdoc />
public ConsoleReader Input { get; }
@@ -91,9 +93,18 @@ public class FakeConsole : IConsole, IDisposable
}
/// <inheritdoc />
public void ReadKey(bool intercept = false)
{
}
public ConsoleKeyInfo ReadKey(bool intercept = false) =>
_keys.TryDequeue(out var key)
? key
: throw new InvalidOperationException(
"Cannot read key because there are no key presses enqueued. " +
$"Use the `{nameof(EnqueueKey)}(...)` method to simulate a key press."
);
/// <summary>
/// Enqueues a simulated key press, which can then be read by calling <see cref="ReadKey"/>.
/// </summary>
public void EnqueueKey(ConsoleKeyInfo key) => _keys.Enqueue(key);
/// <inheritdoc />
public virtual void Dispose() => _cancellationTokenSource.Dispose();

View File

@@ -91,7 +91,7 @@ public interface IConsole
/// <summary>
/// Obtains the next character or function key pressed by the user.
/// </summary>
void ReadKey(bool intercept = false);
ConsoleKeyInfo ReadKey(bool intercept = false);
}
/// <summary>

View File

@@ -94,7 +94,7 @@ public class SystemConsole : IConsole, IDisposable
public void Clear() => Console.Clear();
/// <inheritdoc />
public void ReadKey(bool intercept = false) => Console.ReadKey(intercept);
public ConsoleKeyInfo ReadKey(bool intercept = false) => Console.ReadKey(intercept);
/// <inheritdoc />
public void Dispose()