Files
2026-09-05 21:53:46 +00:00

192 lines
6.1 KiB
C#

using Minesweeper.Cli;
using Minesweeper.Core;
namespace Minesweeper.Core.Tests;
public class CommandParserTests
{
[Theory]
[InlineData("q")]
[InlineData("quit")]
[InlineData("EXIT")]
public void Parse_QuitVerbs(string input) =>
Assert.IsType<Command.Quit>(CommandParser.Parse(input));
[Theory]
[InlineData("n")]
[InlineData("new")]
public void Parse_NewGame(string input) =>
Assert.IsType<Command.NewGame>(CommandParser.Parse(input));
[Theory]
[InlineData("h")]
[InlineData("help")]
[InlineData("?")]
[InlineData("HELP")]
public void Parse_Help(string input) =>
Assert.IsType<Command.ShowHelp>(CommandParser.Parse(input));
[Theory]
[InlineData("")]
[InlineData(" ")]
public void Parse_BlankInput_IsANoOp(string input) =>
Assert.IsType<Command.Noop>(CommandParser.Parse(input));
[Fact]
public void Parse_RevealVerb_IsZeroBased()
{
var command = Assert.IsType<Command.Reveal>(CommandParser.Parse("reveal 3 4"));
Assert.Equal(new CellLocation(2, 3), command.Cell);
}
[Theory]
[InlineData("2 5")]
[InlineData("2,5")]
[InlineData(" 2 ; 5 ")]
[InlineData("2 5")]
public void Parse_BareCoordinates_Reveal(string input)
{
var command = Assert.IsType<Command.Reveal>(CommandParser.Parse(input));
Assert.Equal(new CellLocation(1, 4), command.Cell);
}
[Theory]
[InlineData("r 1 1")]
[InlineData("open 1 1")]
public void Parse_RevealAliases(string input) =>
Assert.IsType<Command.Reveal>(CommandParser.Parse(input));
[Theory]
[InlineData("f 2 3")]
[InlineData("flag 2 3")]
[InlineData("mark 2 3")]
public void Parse_FlagAliases(string input)
{
var command = Assert.IsType<Command.Flag>(CommandParser.Parse(input));
Assert.Equal(new CellLocation(1, 2), command.Cell);
}
[Theory]
[InlineData("c 4 5")]
[InlineData("chord 4 5")]
public void Parse_ChordAliases(string input)
{
var command = Assert.IsType<Command.Chord>(CommandParser.Parse(input));
Assert.Equal(new CellLocation(3, 4), command.Cell);
}
[Fact]
public void Parse_GotoMovesTheCursor()
{
var command = Assert.IsType<Command.SetCursor>(CommandParser.Parse("go 6 7"));
Assert.Equal(new CellLocation(5, 6), command.Cell);
}
[Theory]
[InlineData("d 1", GameDifficulty.Beginner)]
[InlineData("difficulty beginner", GameDifficulty.Beginner)]
[InlineData("d EASY", GameDifficulty.Beginner)]
[InlineData("d 2", GameDifficulty.Intermediate)]
[InlineData("difficulty INTERMEDIATE", GameDifficulty.Intermediate)]
[InlineData("d medium", GameDifficulty.Intermediate)]
[InlineData("d 3", GameDifficulty.Expert)]
[InlineData("difficulty expert", GameDifficulty.Expert)]
[InlineData("d HARD", GameDifficulty.Expert)]
public void Parse_DifficultyAliases(string input, GameDifficulty expected)
{
var command = Assert.IsType<Command.ChangeDifficulty>(CommandParser.Parse(input));
Assert.Equal(expected, command.Difficulty);
}
[Fact]
public void Parse_DifficultyWithoutValue_ShowsHelp() =>
Assert.IsType<Command.ShowHelp>(CommandParser.Parse("difficulty"));
[Theory]
[InlineData("banana")]
[InlineData("reveal 3")]
[InlineData("reveal x y")]
[InlineData("flag -1 4")]
[InlineData("flag 0 4")]
[InlineData("reveal 1 0")]
[InlineData("d nonsense")]
[InlineData(" reveal")]
public void Parse_InvalidInput_ReportsUnknown(string input)
{
var command = Assert.IsType<Command.Unknown>(CommandParser.Parse(input));
Assert.NotEmpty(command.Input);
}
[Fact]
public void Parse_KeepsUnknownTextForEchoing()
{
var command = Assert.IsType<Command.Unknown>(CommandParser.Parse(" frobnicate 9 "));
Assert.Equal("frobnicate 9", command.Input);
}
[Theory]
[InlineData(ConsoleKey.UpArrow, -1, 0)]
[InlineData(ConsoleKey.DownArrow, 1, 0)]
[InlineData(ConsoleKey.LeftArrow, 0, -1)]
[InlineData(ConsoleKey.RightArrow, 0, 1)]
public void FromKey_ArrowsMoveTheCursor(ConsoleKey key, int row, int column)
{
var command = Assert.IsType<Command.MoveCursor>(CommandParser.FromKey(Key(key)));
Assert.Equal(row, command.RowDelta);
Assert.Equal(column, command.ColumnDelta);
}
[Fact]
public void FromKey_EnterAndSpaceRevealAtCursor()
{
Assert.IsType<Command.RevealAtCursor>(CommandParser.FromKey(Key(ConsoleKey.Enter)));
Assert.IsType<Command.RevealAtCursor>(CommandParser.FromKey(Key(ConsoleKey.Spacebar)));
}
[Fact]
public void FromKey_FlagAndChordActOnCursor()
{
Assert.IsType<Command.FlagAtCursor>(CommandParser.FromKey(Key(ConsoleKey.F, 'f')));
Assert.IsType<Command.ChordAtCursor>(CommandParser.FromKey(Key(ConsoleKey.C, 'c')));
}
[Fact]
public void FromKey_DifficultyShortcuts()
{
Assert.Equal(GameDifficulty.Beginner,
Assert.IsType<Command.ChangeDifficulty>(CommandParser.FromKey(Key(ConsoleKey.D1, '1'))).Difficulty);
Assert.Equal(GameDifficulty.Intermediate,
Assert.IsType<Command.ChangeDifficulty>(CommandParser.FromKey(Key(ConsoleKey.D2, '2'))).Difficulty);
Assert.Equal(GameDifficulty.Expert,
Assert.IsType<Command.ChangeDifficulty>(CommandParser.FromKey(Key(ConsoleKey.D3, '3'))).Difficulty);
}
[Fact]
public void FromKey_NewAndQuit()
{
Assert.IsType<Command.NewGame>(CommandParser.FromKey(Key(ConsoleKey.N, 'n')));
Assert.IsType<Command.Quit>(CommandParser.FromKey(Key(ConsoleKey.Escape)));
Assert.IsType<Command.Quit>(CommandParser.FromKey(Key(ConsoleKey.Q, 'q')));
}
[Fact]
public void FromKey_Help() =>
Assert.IsType<Command.ShowHelp>(CommandParser.FromKey(Key(ConsoleKey.H, 'h')));
[Fact]
public void FromKey_UnmappedKey_IsANoOp() =>
Assert.IsType<Command.Noop>(CommandParser.FromKey(Key(ConsoleKey.B, 'b')));
private static ConsoleKeyInfo Key(ConsoleKey key, char character = '\0') =>
new(character, key, shift: false, alt: false, control: false);
}