using XFESystem.Console; using XFESystem.ConsoleDemo; using XFEExtension.NetCore.XFEConsole.Terminal; using XFEConsoleApi = XFEExtension.NetCore.XFEConsole.XFEConsole; namespace XFESystem.Console.Tests; public sealed class ConsoleDemoTests { [Fact] public void RealXfePackageProducesSequencesConsumedByTheSystemTerminal() { var terminal = new TerminalBuffer(80, 20); using var writer = new TerminalTextWriter(terminal); ConsoleDemoScenario.Run(writer); Assert.Equal("XFESystem C# Console Demo", terminal.GetLine(0)); Assert.Equal("RGB: #75C9F5", terminal.GetLine(1)); Assert.Equal(new TerminalColor(117, 201, 245), terminal.GetCell(0, 1).Style.Foreground); Assert.Equal(new TerminalColor(255, 95, 0), terminal.GetCell(0, 2).Style.Foreground); Assert.Equal(new TerminalColor(48, 48, 48), terminal.GetCell(0, 2).Style.Background); Assert.Equal(TerminalColor.FromConsoleColor(ConsoleColor.Blue), terminal.GetCell(0, 3).Style.Foreground); Assert.True(terminal.GetCell(0, 4).Style.Bold && terminal.GetCell(0, 4).Style.Underline); Assert.Equal(TerminalStyle.Default, terminal.GetCell(0, 5).Style); Assert.Equal("Edit: OK", terminal.GetLine(6)); Assert.Equal("Cursor: x!", terminal.GetLine(7)); Assert.Equal("Unicode: 中文 g y", terminal.GetLine(8)); Assert.Equal(ConsoleDemoScenario.SuccessMarker, terminal.GetLine(9)); Assert.DoesNotContain('\u001b', terminal.GetText()); } [Fact] public void PackageTerminalStyleUsesAnActualPackageAssembly() { var assembly = typeof(XFETerminalStyle).Assembly; Assert.Equal("XFEExtension.NetCore.XFEConsole", assembly.GetName().Name); var sequence = new XFETerminalStyle { Foreground = XFETerminalColor.FromRgb(1, 2, 3) }.Apply("A"); Assert.Equal("\u001b[38;2;1;2;3mA\u001b[0m", sequence); } [Fact] public void DirectXfeConsoleApiWritesToProvidedOutputAndRestoresItsGlobalWriter() { var oldWriter = XFEExtension.NetCore.XFEConsole.XFEConsole.CurrentConsoleTextWriter; using var captured = new StringWriter(); ConsoleDemoScenario.RunXfeConsoleApi(captured); Assert.Contains("XFEConsole API: Real NuGet 2.6.0", captured.ToString(), StringComparison.Ordinal); Assert.Same(oldWriter, XFEExtension.NetCore.XFEConsole.XFEConsole.CurrentConsoleTextWriter); } [Fact] public void FailedRealXfeConsoleOutputPropagatesAndRestoresEveryGlobalSetting() { var originalWriter = XFEConsoleApi.CurrentConsoleTextWriter; var originalDebug = XFEConsoleApi.ShowInDebug; var originalLocal = XFEConsoleApi.ShowInLocalConsole; var originalLog = XFEConsoleApi.EnableLog; using var previousOutput = new StringWriter(); var expectedWriter = new XFEExtension.NetCore.XFEConsole.XFEConsoleTextWriter(previousOutput); try { XFEConsoleApi.CurrentConsoleTextWriter = expectedWriter; XFEConsoleApi.ShowInDebug = true; XFEConsoleApi.ShowInLocalConsole = false; XFEConsoleApi.EnableLog = true; var error = Assert.Throws(() => ConsoleDemoScenario.RunXfeConsoleApi(new FailingTextWriter())); Assert.Equal("Controlled XFE output failure", error.Message); Assert.Same(expectedWriter, XFEConsoleApi.CurrentConsoleTextWriter); Assert.True(XFEConsoleApi.ShowInDebug); Assert.False(XFEConsoleApi.ShowInLocalConsole); Assert.True(XFEConsoleApi.EnableLog); Assert.Equal(string.Empty, previousOutput.ToString()); } finally { XFEConsoleApi.CurrentConsoleTextWriter = originalWriter; XFEConsoleApi.ShowInDebug = originalDebug; XFEConsoleApi.ShowInLocalConsole = originalLocal; XFEConsoleApi.EnableLog = originalLog; } } [Fact] public void TextWriterMakesEachLineAtomicForConcurrentWriters() { var terminal = new TerminalBuffer(32, 101, scrollbackLimit: 0); using var writer = new TerminalTextWriter(terminal); Parallel.For(0, 100, index => writer.WriteLine($"Line {index:D3}")); var lines = Enumerable.Range(0, 100).Select(row => terminal.GetLine(row)).ToArray(); Assert.Equal(100, lines.Distinct(StringComparer.Ordinal).Count()); Assert.All(lines, line => Assert.Matches("^Line [0-9]{3}$", line)); Assert.Equal(100, writer.Snapshot().CursorRow); } private sealed class FailingTextWriter : TextWriter { public override System.Text.Encoding Encoding => System.Text.Encoding.UTF8; public override void WriteLine(string? value) => throw new IOException("Controlled XFE output failure"); } }