FakeComponentFactory.cs 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. using System.Collections.Concurrent;
  2. using Terminal.Gui.Examples;
  3. namespace Terminal.Gui.Drivers;
  4. /// <summary>
  5. /// <see cref="IComponentFactory{T}"/> implementation for fake/mock console I/O used in unit tests.
  6. /// This factory creates instances that simulate console behavior without requiring a real terminal.
  7. /// </summary>
  8. public class FakeComponentFactory : ComponentFactoryImpl<ConsoleKeyInfo>
  9. {
  10. /// <summary>
  11. /// Creates a new FakeComponentFactory with optional output capture.
  12. /// </summary>
  13. /// <param name="input"></param>
  14. /// <param name="output">Optional fake output to capture what would be written to console.</param>
  15. /// <param name="sizeMonitor"></param>
  16. public FakeComponentFactory (FakeInput? input = null, IOutput? output = null, ISizeMonitor? sizeMonitor = null)
  17. {
  18. _input = input;
  19. _output = output;
  20. _sizeMonitor = sizeMonitor;
  21. }
  22. private readonly FakeInput? _input;
  23. private readonly IOutput? _output;
  24. private readonly ISizeMonitor? _sizeMonitor;
  25. /// <inheritdoc/>
  26. public override IInput<ConsoleKeyInfo> CreateInput ()
  27. {
  28. // Use provided input instance or create a new one if none was provided
  29. FakeInput fakeInput = _input ?? new FakeInput ();
  30. // Check for test context in environment variable
  31. string? contextJson = Environment.GetEnvironmentVariable (ExampleContext.ENVIRONMENT_VARIABLE_NAME);
  32. if (!string.IsNullOrEmpty (contextJson))
  33. {
  34. ExampleContext? context = ExampleContext.FromJson (contextJson);
  35. if (context is { })
  36. {
  37. foreach (string keyStr in context.KeysToInject)
  38. {
  39. if (Key.TryParse (keyStr, out Key? key) && key is { })
  40. {
  41. ConsoleKeyInfo consoleKeyInfo = ConvertKeyToConsoleKeyInfo (key);
  42. fakeInput.AddInput (consoleKeyInfo);
  43. }
  44. }
  45. }
  46. }
  47. return fakeInput;
  48. }
  49. /// <inheritdoc/>
  50. public override IInputProcessor CreateInputProcessor (ConcurrentQueue<ConsoleKeyInfo> inputBuffer) { return new FakeInputProcessor (inputBuffer); }
  51. /// <inheritdoc/>
  52. public override IOutput CreateOutput () { return _output ?? new FakeOutput (); }
  53. /// <inheritdoc/>
  54. public override ISizeMonitor CreateSizeMonitor (IOutput consoleOutput, IOutputBuffer outputBuffer)
  55. {
  56. return _sizeMonitor ?? new SizeMonitorImpl (consoleOutput);
  57. }
  58. private static ConsoleKeyInfo ConvertKeyToConsoleKeyInfo (Key key)
  59. {
  60. ConsoleModifiers modifiers = 0;
  61. if (key.IsShift)
  62. {
  63. modifiers |= ConsoleModifiers.Shift;
  64. }
  65. if (key.IsAlt)
  66. {
  67. modifiers |= ConsoleModifiers.Alt;
  68. }
  69. if (key.IsCtrl)
  70. {
  71. modifiers |= ConsoleModifiers.Control;
  72. }
  73. // Remove the modifier masks to get the base key code
  74. KeyCode baseKeyCode = key.KeyCode & KeyCode.CharMask;
  75. // Map KeyCode to ConsoleKey
  76. ConsoleKey consoleKey = baseKeyCode switch
  77. {
  78. KeyCode.A => ConsoleKey.A,
  79. KeyCode.B => ConsoleKey.B,
  80. KeyCode.C => ConsoleKey.C,
  81. KeyCode.D => ConsoleKey.D,
  82. KeyCode.E => ConsoleKey.E,
  83. KeyCode.F => ConsoleKey.F,
  84. KeyCode.G => ConsoleKey.G,
  85. KeyCode.H => ConsoleKey.H,
  86. KeyCode.I => ConsoleKey.I,
  87. KeyCode.J => ConsoleKey.J,
  88. KeyCode.K => ConsoleKey.K,
  89. KeyCode.L => ConsoleKey.L,
  90. KeyCode.M => ConsoleKey.M,
  91. KeyCode.N => ConsoleKey.N,
  92. KeyCode.O => ConsoleKey.O,
  93. KeyCode.P => ConsoleKey.P,
  94. KeyCode.Q => ConsoleKey.Q,
  95. KeyCode.R => ConsoleKey.R,
  96. KeyCode.S => ConsoleKey.S,
  97. KeyCode.T => ConsoleKey.T,
  98. KeyCode.U => ConsoleKey.U,
  99. KeyCode.V => ConsoleKey.V,
  100. KeyCode.W => ConsoleKey.W,
  101. KeyCode.X => ConsoleKey.X,
  102. KeyCode.Y => ConsoleKey.Y,
  103. KeyCode.Z => ConsoleKey.Z,
  104. KeyCode.D0 => ConsoleKey.D0,
  105. KeyCode.D1 => ConsoleKey.D1,
  106. KeyCode.D2 => ConsoleKey.D2,
  107. KeyCode.D3 => ConsoleKey.D3,
  108. KeyCode.D4 => ConsoleKey.D4,
  109. KeyCode.D5 => ConsoleKey.D5,
  110. KeyCode.D6 => ConsoleKey.D6,
  111. KeyCode.D7 => ConsoleKey.D7,
  112. KeyCode.D8 => ConsoleKey.D8,
  113. KeyCode.D9 => ConsoleKey.D9,
  114. KeyCode.Enter => ConsoleKey.Enter,
  115. KeyCode.Esc => ConsoleKey.Escape,
  116. KeyCode.Space => ConsoleKey.Spacebar,
  117. KeyCode.Tab => ConsoleKey.Tab,
  118. KeyCode.Backspace => ConsoleKey.Backspace,
  119. KeyCode.Delete => ConsoleKey.Delete,
  120. KeyCode.Home => ConsoleKey.Home,
  121. KeyCode.End => ConsoleKey.End,
  122. KeyCode.PageUp => ConsoleKey.PageUp,
  123. KeyCode.PageDown => ConsoleKey.PageDown,
  124. KeyCode.CursorUp => ConsoleKey.UpArrow,
  125. KeyCode.CursorDown => ConsoleKey.DownArrow,
  126. KeyCode.CursorLeft => ConsoleKey.LeftArrow,
  127. KeyCode.CursorRight => ConsoleKey.RightArrow,
  128. KeyCode.F1 => ConsoleKey.F1,
  129. KeyCode.F2 => ConsoleKey.F2,
  130. KeyCode.F3 => ConsoleKey.F3,
  131. KeyCode.F4 => ConsoleKey.F4,
  132. KeyCode.F5 => ConsoleKey.F5,
  133. KeyCode.F6 => ConsoleKey.F6,
  134. KeyCode.F7 => ConsoleKey.F7,
  135. KeyCode.F8 => ConsoleKey.F8,
  136. KeyCode.F9 => ConsoleKey.F9,
  137. KeyCode.F10 => ConsoleKey.F10,
  138. KeyCode.F11 => ConsoleKey.F11,
  139. KeyCode.F12 => ConsoleKey.F12,
  140. _ => 0
  141. };
  142. var keyChar = '\0';
  143. Rune rune = key.AsRune;
  144. if (Rune.IsValid (rune.Value))
  145. {
  146. keyChar = (char)rune.Value;
  147. }
  148. return new (keyChar, consoleKey, key.IsShift, key.IsAlt, key.IsCtrl);
  149. }
  150. }