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(CommandParser.Parse(input)); [Theory] [InlineData("n")] [InlineData("new")] public void Parse_NewGame(string input) => Assert.IsType(CommandParser.Parse(input)); [Theory] [InlineData("h")] [InlineData("help")] [InlineData("?")] [InlineData("HELP")] public void Parse_Help(string input) => Assert.IsType(CommandParser.Parse(input)); [Theory] [InlineData("")] [InlineData(" ")] public void Parse_BlankInput_IsANoOp(string input) => Assert.IsType(CommandParser.Parse(input)); [Fact] public void Parse_RevealVerb_IsZeroBased() { var command = Assert.IsType(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(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(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(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(CommandParser.Parse(input)); Assert.Equal(new CellLocation(3, 4), command.Cell); } [Fact] public void Parse_GotoMovesTheCursor() { var command = Assert.IsType(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(CommandParser.Parse(input)); Assert.Equal(expected, command.Difficulty); } [Fact] public void Parse_DifficultyWithoutValue_ShowsHelp() => Assert.IsType(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(CommandParser.Parse(input)); Assert.NotEmpty(command.Input); } [Fact] public void Parse_KeepsUnknownTextForEchoing() { var command = Assert.IsType(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(CommandParser.FromKey(Key(key))); Assert.Equal(row, command.RowDelta); Assert.Equal(column, command.ColumnDelta); } [Fact] public void FromKey_EnterAndSpaceRevealAtCursor() { Assert.IsType(CommandParser.FromKey(Key(ConsoleKey.Enter))); Assert.IsType(CommandParser.FromKey(Key(ConsoleKey.Spacebar))); } [Fact] public void FromKey_FlagAndChordActOnCursor() { Assert.IsType(CommandParser.FromKey(Key(ConsoleKey.F, 'f'))); Assert.IsType(CommandParser.FromKey(Key(ConsoleKey.C, 'c'))); } [Fact] public void FromKey_DifficultyShortcuts() { Assert.Equal(GameDifficulty.Beginner, Assert.IsType(CommandParser.FromKey(Key(ConsoleKey.D1, '1'))).Difficulty); Assert.Equal(GameDifficulty.Intermediate, Assert.IsType(CommandParser.FromKey(Key(ConsoleKey.D2, '2'))).Difficulty); Assert.Equal(GameDifficulty.Expert, Assert.IsType(CommandParser.FromKey(Key(ConsoleKey.D3, '3'))).Difficulty); } [Fact] public void FromKey_NewAndQuit() { Assert.IsType(CommandParser.FromKey(Key(ConsoleKey.N, 'n'))); Assert.IsType(CommandParser.FromKey(Key(ConsoleKey.Escape))); Assert.IsType(CommandParser.FromKey(Key(ConsoleKey.Q, 'q'))); } [Fact] public void FromKey_Help() => Assert.IsType(CommandParser.FromKey(Key(ConsoleKey.H, 'h'))); [Fact] public void FromKey_UnmappedKey_IsANoOp() => Assert.IsType(CommandParser.FromKey(Key(ConsoleKey.B, 'b'))); private static ConsoleKeyInfo Key(ConsoleKey key, char character = '\0') => new(character, key, shift: false, alt: false, control: false); }