using System.Collections.Concurrent; using Terminal.Gui.Examples; namespace Terminal.Gui.Drivers; /// /// implementation for fake/mock console I/O used in unit tests. /// This factory creates instances that simulate console behavior without requiring a real terminal. /// public class FakeComponentFactory : ComponentFactoryImpl { /// /// Creates a new FakeComponentFactory with optional output capture. /// /// /// Optional fake output to capture what would be written to console. /// public FakeComponentFactory (FakeInput? input = null, IOutput? output = null, ISizeMonitor? sizeMonitor = null) { _input = input; _output = output; _sizeMonitor = sizeMonitor; } private readonly FakeInput? _input; private readonly IOutput? _output; private readonly ISizeMonitor? _sizeMonitor; /// public override IInput CreateInput () { // Use provided input instance or create a new one if none was provided FakeInput fakeInput = _input ?? new FakeInput (); // Check for test context in environment variable string? contextJson = Environment.GetEnvironmentVariable (ExampleContext.ENVIRONMENT_VARIABLE_NAME); if (!string.IsNullOrEmpty (contextJson)) { ExampleContext? context = ExampleContext.FromJson (contextJson); if (context is { }) { foreach (string keyStr in context.KeysToInject) { if (Key.TryParse (keyStr, out Key? key) && key is { }) { ConsoleKeyInfo consoleKeyInfo = ConvertKeyToConsoleKeyInfo (key); fakeInput.AddInput (consoleKeyInfo); } } } } return fakeInput; } /// public override IInputProcessor CreateInputProcessor (ConcurrentQueue inputBuffer) { return new FakeInputProcessor (inputBuffer); } /// public override IOutput CreateOutput () { return _output ?? new FakeOutput (); } /// public override ISizeMonitor CreateSizeMonitor (IOutput consoleOutput, IOutputBuffer outputBuffer) { return _sizeMonitor ?? new SizeMonitorImpl (consoleOutput); } private static ConsoleKeyInfo ConvertKeyToConsoleKeyInfo (Key key) { ConsoleModifiers modifiers = 0; if (key.IsShift) { modifiers |= ConsoleModifiers.Shift; } if (key.IsAlt) { modifiers |= ConsoleModifiers.Alt; } if (key.IsCtrl) { modifiers |= ConsoleModifiers.Control; } // Remove the modifier masks to get the base key code KeyCode baseKeyCode = key.KeyCode & KeyCode.CharMask; // Map KeyCode to ConsoleKey ConsoleKey consoleKey = baseKeyCode switch { KeyCode.A => ConsoleKey.A, KeyCode.B => ConsoleKey.B, KeyCode.C => ConsoleKey.C, KeyCode.D => ConsoleKey.D, KeyCode.E => ConsoleKey.E, KeyCode.F => ConsoleKey.F, KeyCode.G => ConsoleKey.G, KeyCode.H => ConsoleKey.H, KeyCode.I => ConsoleKey.I, KeyCode.J => ConsoleKey.J, KeyCode.K => ConsoleKey.K, KeyCode.L => ConsoleKey.L, KeyCode.M => ConsoleKey.M, KeyCode.N => ConsoleKey.N, KeyCode.O => ConsoleKey.O, KeyCode.P => ConsoleKey.P, KeyCode.Q => ConsoleKey.Q, KeyCode.R => ConsoleKey.R, KeyCode.S => ConsoleKey.S, KeyCode.T => ConsoleKey.T, KeyCode.U => ConsoleKey.U, KeyCode.V => ConsoleKey.V, KeyCode.W => ConsoleKey.W, KeyCode.X => ConsoleKey.X, KeyCode.Y => ConsoleKey.Y, KeyCode.Z => ConsoleKey.Z, KeyCode.D0 => ConsoleKey.D0, KeyCode.D1 => ConsoleKey.D1, KeyCode.D2 => ConsoleKey.D2, KeyCode.D3 => ConsoleKey.D3, KeyCode.D4 => ConsoleKey.D4, KeyCode.D5 => ConsoleKey.D5, KeyCode.D6 => ConsoleKey.D6, KeyCode.D7 => ConsoleKey.D7, KeyCode.D8 => ConsoleKey.D8, KeyCode.D9 => ConsoleKey.D9, KeyCode.Enter => ConsoleKey.Enter, KeyCode.Esc => ConsoleKey.Escape, KeyCode.Space => ConsoleKey.Spacebar, KeyCode.Tab => ConsoleKey.Tab, KeyCode.Backspace => ConsoleKey.Backspace, KeyCode.Delete => ConsoleKey.Delete, KeyCode.Home => ConsoleKey.Home, KeyCode.End => ConsoleKey.End, KeyCode.PageUp => ConsoleKey.PageUp, KeyCode.PageDown => ConsoleKey.PageDown, KeyCode.CursorUp => ConsoleKey.UpArrow, KeyCode.CursorDown => ConsoleKey.DownArrow, KeyCode.CursorLeft => ConsoleKey.LeftArrow, KeyCode.CursorRight => ConsoleKey.RightArrow, KeyCode.F1 => ConsoleKey.F1, KeyCode.F2 => ConsoleKey.F2, KeyCode.F3 => ConsoleKey.F3, KeyCode.F4 => ConsoleKey.F4, KeyCode.F5 => ConsoleKey.F5, KeyCode.F6 => ConsoleKey.F6, KeyCode.F7 => ConsoleKey.F7, KeyCode.F8 => ConsoleKey.F8, KeyCode.F9 => ConsoleKey.F9, KeyCode.F10 => ConsoleKey.F10, KeyCode.F11 => ConsoleKey.F11, KeyCode.F12 => ConsoleKey.F12, _ => 0 }; var keyChar = '\0'; Rune rune = key.AsRune; if (Rune.IsValid (rune.Value)) { keyChar = (char)rune.Value; } return new (keyChar, consoleKey, key.IsShift, key.IsAlt, key.IsCtrl); } }