| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422 |
- namespace UnitTests_Parallelizable.DriverTests;
- public class ConsoleKeyMappingTests
- {
- [Theory]
- [InlineData ('a', ConsoleKey.A, false, false, false, (KeyCode)'a')]
- [InlineData ('A', ConsoleKey.A, true, false, false, KeyCode.A | KeyCode.ShiftMask)]
- [InlineData ('á', ConsoleKey.A, false, false, false, (KeyCode)'á')]
- [InlineData ('Á', ConsoleKey.A, true, false, false, (KeyCode)'Á' | KeyCode.ShiftMask)]
- [InlineData ('à', ConsoleKey.A, false, false, false, (KeyCode)'à')]
- [InlineData ('À', ConsoleKey.A, true, false, false, (KeyCode)'À' | KeyCode.ShiftMask)]
- [InlineData ('5', ConsoleKey.D5, false, false, false, KeyCode.D5)]
- [InlineData ('%', ConsoleKey.D5, true, false, false, (KeyCode)'%' | KeyCode.ShiftMask)]
- [InlineData ('€', ConsoleKey.D5, false, true, true, (KeyCode)'€' | KeyCode.AltMask | KeyCode.CtrlMask)]
- [InlineData ('?', ConsoleKey.Oem4, true, false, false, (KeyCode)'?' | KeyCode.ShiftMask)]
- [InlineData ('\'', ConsoleKey.Oem4, false, false, false, (KeyCode)'\'')]
- [InlineData ('q', ConsoleKey.Q, false, false, false, (KeyCode)'q')]
- [InlineData ('\0', ConsoleKey.F2, false, false, false, KeyCode.F2)]
- [InlineData ('英', ConsoleKey.None, false, false, false, (KeyCode)'英')]
- [InlineData ('\r', ConsoleKey.Enter, false, false, false, KeyCode.Enter)]
- public void MapConsoleKeyInfoToKeyCode_Also_Return_Modifiers (
- char keyChar,
- ConsoleKey consoleKey,
- bool shift,
- bool alt,
- bool control,
- KeyCode expectedKeyCode
- )
- {
- var consoleKeyInfo = new ConsoleKeyInfo (keyChar, consoleKey, shift, alt, control);
- KeyCode keyCode = ConsoleKeyMapping.MapConsoleKeyInfoToKeyCode (consoleKeyInfo);
- Assert.Equal (keyCode, expectedKeyCode);
- }
- [Theory]
- [InlineData ('a', false, false, false, (KeyCode)'a')]
- [InlineData ('A', true, false, false, KeyCode.A | KeyCode.ShiftMask)]
- [InlineData ('á', false, false, false, (KeyCode)'á')]
- [InlineData ('Á', true, false, false, (KeyCode)'Á' | KeyCode.ShiftMask)]
- [InlineData ('à', false, false, false, (KeyCode)'à')]
- [InlineData ('À', true, false, false, (KeyCode)'À' | KeyCode.ShiftMask)]
- [InlineData ('5', false, false, false, KeyCode.D5)]
- [InlineData ('%', true, false, false, (KeyCode)'%' | KeyCode.ShiftMask)]
- [InlineData ('€', false, true, true, (KeyCode)'€' | KeyCode.AltMask | KeyCode.CtrlMask)]
- [InlineData ('?', true, false, false, (KeyCode)'?' | KeyCode.ShiftMask)]
- [InlineData ('\'', false, false, false, (KeyCode)'\'')]
- [InlineData ('q', false, false, false, (KeyCode)'q')]
- [InlineData ((uint)KeyCode.F2, false, false, false, KeyCode.F2)]
- [InlineData ('英', false, false, false, (KeyCode)'英')]
- [InlineData ('\r', false, false, false, KeyCode.Enter)]
- [InlineData ('\n', false, false, false, (KeyCode)'\n')]
- public void MapToKeyCodeModifiers_Tests (
- uint keyChar,
- bool shift,
- bool alt,
- bool control,
- KeyCode expectedKeyCode
- )
- {
- ConsoleModifiers modifiers = ConsoleKeyMapping.GetModifiers (shift, alt, control);
- var keyCode = (KeyCode)keyChar;
- keyCode = ConsoleKeyMapping.MapToKeyCodeModifiers (modifiers, keyCode);
- Assert.Equal (keyCode, expectedKeyCode);
- }
- public static IEnumerable<object []> UnShiftedChars =>
- new List<object []>
- {
- new object [] { 'a', 'A', KeyCode.A | KeyCode.ShiftMask },
- new object [] { 'z', 'Z', KeyCode.Z | KeyCode.ShiftMask },
- new object [] { 'á', 'Á', (KeyCode)'Á' | KeyCode.ShiftMask },
- new object [] { 'à', 'À', (KeyCode)'À' | KeyCode.ShiftMask },
- new object [] { 'ý', 'Ý', (KeyCode)'Ý' | KeyCode.ShiftMask },
- new object [] { '1', '!', (KeyCode)'!' | KeyCode.ShiftMask },
- new object [] { '2', '"', (KeyCode)'"' | KeyCode.ShiftMask },
- new object [] { '3', '#', (KeyCode)'#' | KeyCode.ShiftMask },
- new object [] { '4', '$', (KeyCode)'$' | KeyCode.ShiftMask },
- new object [] { '5', '%', (KeyCode)'%' | KeyCode.ShiftMask },
- new object [] { '6', '&', (KeyCode)'&' | KeyCode.ShiftMask },
- new object [] { '7', '/', (KeyCode)'/' | KeyCode.ShiftMask },
- new object [] { '8', '(', (KeyCode)'(' | KeyCode.ShiftMask },
- new object [] { '9', ')', (KeyCode)')' | KeyCode.ShiftMask },
- new object [] { '0', '=', (KeyCode)'=' | KeyCode.ShiftMask },
- new object [] { '\\', '|', (KeyCode)'|' | KeyCode.ShiftMask },
- new object [] { '\'', '?', (KeyCode)'?' | KeyCode.ShiftMask },
- new object [] { '«', '»', (KeyCode)'»' | KeyCode.ShiftMask },
- new object [] { '+', '*', (KeyCode)'*' | KeyCode.ShiftMask },
- new object [] { '´', '`', (KeyCode)'`' | KeyCode.ShiftMask },
- new object [] { 'º', 'ª', (KeyCode)'ª' | KeyCode.ShiftMask },
- new object [] { '~', '^', (KeyCode)'^' | KeyCode.ShiftMask },
- new object [] { '<', '>', (KeyCode)'>' | KeyCode.ShiftMask },
- new object [] { ',', ';', (KeyCode)';' | KeyCode.ShiftMask },
- new object [] { '.', ':', (KeyCode)':' | KeyCode.ShiftMask },
- new object [] { '-', '_', (KeyCode)'_' | KeyCode.ShiftMask }
- };
- [Theory]
- [InlineData (KeyCode.A, false, false, false)] // Unshifted A (lowercase)
- [InlineData (KeyCode.B, false, false, false)]
- [InlineData (KeyCode.Z, false, false, false)]
- [InlineData (KeyCode.A | KeyCode.ShiftMask, true, false, false)] // Shifted A (uppercase)
- [InlineData (KeyCode.Z | KeyCode.ShiftMask, true, false, false)]
- [InlineData (KeyCode.A | KeyCode.CtrlMask, false, false, true)] // Ctrl+A
- [InlineData (KeyCode.A | KeyCode.AltMask, false, true, false)] // Alt+A
- [InlineData (KeyCode.A | KeyCode.ShiftMask | KeyCode.CtrlMask, true, false, true)] // Ctrl+Shift+A
- [InlineData (KeyCode.A | KeyCode.ShiftMask | KeyCode.AltMask, true, true, false)] // Alt+Shift+A
- [InlineData (KeyCode.A | KeyCode.CtrlMask | KeyCode.AltMask, false, true, true)] // Ctrl+Alt+A
- [InlineData (KeyCode.A | KeyCode.ShiftMask | KeyCode.CtrlMask | KeyCode.AltMask, true, true, true)] // All modifiers
- public void MapToConsoleModifiers_LetterKeys_ReturnsCorrectModifiers (
- KeyCode key,
- bool expectedShift,
- bool expectedAlt,
- bool expectedControl
- )
- {
- // Act
- ConsoleModifiers result = ConsoleKeyMapping.MapToConsoleModifiers (key);
- // Assert
- Assert.Equal (expectedShift, result.HasFlag (ConsoleModifiers.Shift));
- Assert.Equal (expectedAlt, result.HasFlag (ConsoleModifiers.Alt));
- Assert.Equal (expectedControl, result.HasFlag (ConsoleModifiers.Control));
- }
- [Theory]
- [InlineData (KeyCode.A)] // 65 = 'A' in ASCII, but represents unshifted key
- [InlineData (KeyCode.B)]
- [InlineData (KeyCode.M)]
- [InlineData (KeyCode.Z)]
- public void MapToConsoleModifiers_UnshiftedLetterKeys_DoesNotSetShiftFlag (KeyCode key)
- {
- // This test verifies the BUGFIX: KeyCode.A-Z (65-90) represent UNSHIFTED keys,
- // even though their numeric values match uppercase ASCII characters.
- // The old code incorrectly checked char.IsUpper((char)key) which would fail this test.
- // Act
- ConsoleModifiers result = ConsoleKeyMapping.MapToConsoleModifiers (key);
- // Assert - Shift should NOT be set for unshifted letter keys
- Assert.False (result.HasFlag (ConsoleModifiers.Shift),
- $"Shift should not be set for unshifted {key}. The KeyCode value {(int)key} represents a lowercase, unshifted key.");
- }
- [Theory]
- [InlineData (KeyCode.D1, false)] // Unshifted number keys
- [InlineData (KeyCode.D5, false)]
- [InlineData (KeyCode.Space, false)]
- [InlineData (KeyCode.Enter, false)]
- [InlineData (KeyCode.Tab, false)]
- [InlineData (KeyCode.D1 | KeyCode.ShiftMask, true)] // Shifted number keys
- public void MapToConsoleModifiers_NonLetterKeys_ReturnsCorrectShiftState (KeyCode key, bool expectedShift)
- {
- // Act
- ConsoleModifiers result = ConsoleKeyMapping.MapToConsoleModifiers (key);
- // Assert
- Assert.Equal (expectedShift, result.HasFlag (ConsoleModifiers.Shift));
- }
- [Theory]
- [InlineData (KeyCode.A, 'a', ConsoleKey.A, false)] // Unshifted A = lowercase 'a'
- [InlineData (KeyCode.B, 'b', ConsoleKey.B, false)]
- [InlineData (KeyCode.M, 'm', ConsoleKey.M, false)]
- [InlineData (KeyCode.Z, 'z', ConsoleKey.Z, false)]
- public void GetConsoleKeyInfoFromKeyCode_UnshiftedLetterKeys_ReturnsLowercaseChar (
- KeyCode key,
- char expectedChar,
- ConsoleKey expectedKey,
- bool expectedShift
- )
- {
- // This test verifies the BUGFIX: Key.A through Key.Z should produce lowercase characters
- // when no ShiftMask is set. The old code would incorrectly return uppercase 'A'.
- // Act
- ConsoleKeyInfo result = ConsoleKeyMapping.GetConsoleKeyInfoFromKeyCode (key);
- // Assert
- Assert.Equal (expectedChar, result.KeyChar);
- Assert.Equal (expectedKey, result.Key);
- Assert.Equal (expectedShift, (result.Modifiers & ConsoleModifiers.Shift) != 0);
- }
- [Theory]
- [InlineData (KeyCode.A | KeyCode.ShiftMask, 'A', ConsoleKey.A, true)] // Shifted A = uppercase 'A'
- [InlineData (KeyCode.B | KeyCode.ShiftMask, 'B', ConsoleKey.B, true)]
- [InlineData (KeyCode.M | KeyCode.ShiftMask, 'M', ConsoleKey.M, true)]
- [InlineData (KeyCode.Z | KeyCode.ShiftMask, 'Z', ConsoleKey.Z, true)]
- public void GetConsoleKeyInfoFromKeyCode_ShiftedLetterKeys_ReturnsUppercaseChar (
- KeyCode key,
- char expectedChar,
- ConsoleKey expectedKey,
- bool expectedShift
- )
- {
- // Act
- ConsoleKeyInfo result = ConsoleKeyMapping.GetConsoleKeyInfoFromKeyCode (key);
- // Assert
- Assert.Equal (expectedChar, result.KeyChar);
- Assert.Equal (expectedKey, result.Key);
- Assert.Equal (expectedShift, (result.Modifiers & ConsoleModifiers.Shift) != 0);
- }
- [Theory]
- [InlineData (KeyCode.A | KeyCode.CtrlMask, ConsoleKey.A, false, false, true)]
- [InlineData (KeyCode.A | KeyCode.AltMask, ConsoleKey.A, false, true, false)]
- [InlineData (KeyCode.A | KeyCode.ShiftMask | KeyCode.CtrlMask, ConsoleKey.A, true, false, true)]
- [InlineData (KeyCode.Z | KeyCode.CtrlMask, ConsoleKey.Z, false, false, true)]
- public void GetConsoleKeyInfoFromKeyCode_LetterKeysWithModifiers_ReturnsCorrectModifiers (
- KeyCode key,
- ConsoleKey expectedConsoleKey,
- bool expectedShift,
- bool expectedAlt,
- bool expectedControl
- )
- {
- // Act
- ConsoleKeyInfo result = ConsoleKeyMapping.GetConsoleKeyInfoFromKeyCode (key);
- // Assert
- Assert.Equal (expectedConsoleKey, result.Key);
- Assert.Equal (expectedShift, (result.Modifiers & ConsoleModifiers.Shift) != 0);
- Assert.Equal (expectedAlt, (result.Modifiers & ConsoleModifiers.Alt) != 0);
- Assert.Equal (expectedControl, (result.Modifiers & ConsoleModifiers.Control) != 0);
- }
- [Theory]
- [InlineData (KeyCode.Enter, '\r', ConsoleKey.Enter)]
- [InlineData (KeyCode.Tab, '\t', ConsoleKey.Tab)]
- [InlineData (KeyCode.Esc, '\u001B', ConsoleKey.Escape)]
- [InlineData (KeyCode.Backspace, '\b', ConsoleKey.Backspace)]
- [InlineData (KeyCode.Space, ' ', ConsoleKey.Spacebar)]
- public void GetConsoleKeyInfoFromKeyCode_SpecialKeys_ReturnsCorrectKeyChar (
- KeyCode key,
- char expectedChar,
- ConsoleKey expectedKey
- )
- {
- // Act
- ConsoleKeyInfo result = ConsoleKeyMapping.GetConsoleKeyInfoFromKeyCode (key);
- // Assert
- Assert.Equal (expectedChar, result.KeyChar);
- Assert.Equal (expectedKey, result.Key);
- }
- [Theory]
- [InlineData (KeyCode.F1, ConsoleKey.F1)]
- [InlineData (KeyCode.F5, ConsoleKey.F5)]
- [InlineData (KeyCode.F12, ConsoleKey.F12)]
- [InlineData (KeyCode.CursorUp, ConsoleKey.UpArrow)]
- [InlineData (KeyCode.CursorDown, ConsoleKey.DownArrow)]
- [InlineData (KeyCode.CursorLeft, ConsoleKey.LeftArrow)]
- [InlineData (KeyCode.CursorRight, ConsoleKey.RightArrow)]
- [InlineData (KeyCode.Home, ConsoleKey.Home)]
- [InlineData (KeyCode.End, ConsoleKey.End)]
- [InlineData (KeyCode.PageUp, ConsoleKey.PageUp)]
- [InlineData (KeyCode.PageDown, ConsoleKey.PageDown)]
- [InlineData (KeyCode.Delete, ConsoleKey.Delete)]
- [InlineData (KeyCode.Insert, ConsoleKey.Insert)]
- public void GetConsoleKeyInfoFromKeyCode_NavigationAndFunctionKeys_ReturnsCorrectConsoleKey (
- KeyCode key,
- ConsoleKey expectedKey
- )
- {
- // Act
- ConsoleKeyInfo result = ConsoleKeyMapping.GetConsoleKeyInfoFromKeyCode (key);
- // Assert
- Assert.Equal (expectedKey, result.Key);
- }
- [Theory]
- [InlineData (KeyCode.D0, '0', ConsoleKey.D0)]
- [InlineData (KeyCode.D1, '1', ConsoleKey.D1)]
- [InlineData (KeyCode.D5, '5', ConsoleKey.D5)]
- [InlineData (KeyCode.D9, '9', ConsoleKey.D9)]
- public void GetConsoleKeyInfoFromKeyCode_NumberKeys_ReturnsCorrectKeyChar (
- KeyCode key,
- char expectedChar,
- ConsoleKey expectedKey
- )
- {
- // Act
- ConsoleKeyInfo result = ConsoleKeyMapping.GetConsoleKeyInfoFromKeyCode (key);
- // Assert
- Assert.Equal (expectedChar, result.KeyChar);
- Assert.Equal (expectedKey, result.Key);
- }
- [Fact]
- public void MapToConsoleModifiers_AllLetterKeys_UnshiftedDoesNotSetShift ()
- {
- // This comprehensive test ensures ALL letter keys A-Z without ShiftMask
- // do not have Shift set in the returned modifiers.
- // This will fail if the old "char.IsUpper" check is present.
- for (KeyCode key = KeyCode.A; key <= KeyCode.Z; key++)
- {
- // Act
- ConsoleModifiers result = ConsoleKeyMapping.MapToConsoleModifiers (key);
- // Assert
- Assert.False (
- result.HasFlag (ConsoleModifiers.Shift),
- $"Shift should not be set for unshifted {key} (value {(int)key}). " +
- $"KeyCode.{key} represents a lowercase, unshifted key even though its numeric value is {(int)key}."
- );
- }
- }
- [Fact]
- public void MapToConsoleModifiers_AllLetterKeysShifted_SetsShift ()
- {
- // Verify that WITH ShiftMask, all letter keys DO set Shift
- for (KeyCode key = KeyCode.A; key <= KeyCode.Z; key++)
- {
- KeyCode shiftedKey = key | KeyCode.ShiftMask;
- // Act
- ConsoleModifiers result = ConsoleKeyMapping.MapToConsoleModifiers (shiftedKey);
- // Assert
- Assert.True (
- result.HasFlag (ConsoleModifiers.Shift),
- $"Shift should be set for {shiftedKey}"
- );
- }
- }
- [Fact]
- public void GetConsoleKeyInfoFromKeyCode_AllUnshiftedLetterKeys_ReturnLowercaseChars ()
- {
- // This comprehensive test verifies ALL letter keys A-Z produce lowercase characters
- // when no ShiftMask is set. This is the KEY test that will fail with the old code.
- for (KeyCode key = KeyCode.A; key <= KeyCode.Z; key++)
- {
- // Act
- ConsoleKeyInfo result = ConsoleKeyMapping.GetConsoleKeyInfoFromKeyCode (key);
- // Calculate expected lowercase character
- char expectedChar = (char)('a' + (key - KeyCode.A));
- // Assert
- Assert.True (
- char.IsLower (result.KeyChar),
- $"KeyChar for unshifted {key} should be lowercase, but got '{result.KeyChar}' (0x{(int)result.KeyChar:X2}). " +
- $"Expected lowercase '{expectedChar}' (0x{(int)expectedChar:X2})."
- );
- Assert.Equal (
- expectedChar,
- result.KeyChar
- );
- Assert.False (
- (result.Modifiers & ConsoleModifiers.Shift) != 0,
- $"Shift modifier should not be set for unshifted {key}"
- );
- }
- }
- [Fact]
- public void GetConsoleKeyInfoFromKeyCode_AllShiftedLetterKeys_ReturnUppercaseChars ()
- {
- // Verify that WITH ShiftMask, all letter keys produce uppercase characters
- for (KeyCode key = KeyCode.A; key <= KeyCode.Z; key++)
- {
- KeyCode shiftedKey = key | KeyCode.ShiftMask;
- // Act
- ConsoleKeyInfo result = ConsoleKeyMapping.GetConsoleKeyInfoFromKeyCode (shiftedKey);
- // Calculate expected uppercase character
- char expectedChar = (char)('A' + (key - KeyCode.A));
- // Assert
- Assert.True (
- char.IsUpper (result.KeyChar),
- $"KeyChar for shifted {shiftedKey} should be uppercase, but got '{result.KeyChar}'"
- );
- Assert.Equal (expectedChar, result.KeyChar);
- Assert.True (
- (result.Modifiers & ConsoleModifiers.Shift) != 0,
- $"Shift modifier should be set for {shiftedKey}"
- );
- }
- }
- [Theory]
- [InlineData (KeyCode.A, KeyCode.A | KeyCode.ShiftMask, 'a', 'A')] // Without vs With Shift
- [InlineData (KeyCode.M, KeyCode.M | KeyCode.ShiftMask, 'm', 'M')]
- [InlineData (KeyCode.Z, KeyCode.Z | KeyCode.ShiftMask, 'z', 'Z')]
- public void GetConsoleKeyInfoFromKeyCode_ShiftMaskChangesCase (
- KeyCode unshifted,
- KeyCode shifted,
- char expectedUnshiftedChar,
- char expectedShiftedChar
- )
- {
- // Act
- ConsoleKeyInfo unshiftedResult = ConsoleKeyMapping.GetConsoleKeyInfoFromKeyCode (unshifted);
- ConsoleKeyInfo shiftedResult = ConsoleKeyMapping.GetConsoleKeyInfoFromKeyCode (shifted);
- // Assert - Unshifted should be lowercase
- Assert.Equal (expectedUnshiftedChar, unshiftedResult.KeyChar);
- Assert.False ((unshiftedResult.Modifiers & ConsoleModifiers.Shift) != 0);
- // Assert - Shifted should be uppercase
- Assert.Equal (expectedShiftedChar, shiftedResult.KeyChar);
- Assert.True ((shiftedResult.Modifiers & ConsoleModifiers.Shift) != 0);
- }
- }
|