FakeComponentFactory.cs 6.0 KB

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