| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218 |
- #nullable enable
- namespace DriverTests;
- public class OutputBaseTests
- {
- [Fact]
- public void ToAnsi_SingleCell_NoAttribute_ReturnsGraphemeAndNewline ()
- {
- // Arrange
- var output = new FakeOutput ();
- IOutputBuffer buffer = output.LastBuffer!;
- buffer.SetSize (1, 1);
- // Act
- buffer.AddStr ("A");
- string ansi = output.ToAnsi (buffer);
- // Assert: single grapheme plus newline (BuildAnsiForRegion appends a newline per row)
- Assert.Contains ("A" + Environment.NewLine, ansi);
- }
- [Theory]
- [InlineData (true, false)]
- [InlineData (true, true)]
- [InlineData (false, false)]
- [InlineData (false, true)]
- public void ToAnsi_WithAttribute_AppendsCorrectColorSequence_BasedOnIsLegacyConsole_And_Force16Colors (bool isLegacyConsole, bool force16Colors)
- {
- // Arrange
- var output = new FakeOutput { IsLegacyConsole = isLegacyConsole };
- // Create DriverImpl and associate it with the FakeOutput to test Sixel output
- IDriver driver = new DriverImpl (
- new FakeInputProcessor (null!),
- new OutputBufferImpl (),
- output,
- new (new AnsiResponseParser ()),
- new SizeMonitorImpl (output));
- driver.Force16Colors = force16Colors;
- IOutputBuffer buffer = output.LastBuffer!;
- buffer.SetSize (1, 1);
- // Use a known RGB color and attribute
- var fg = new Color (1, 2, 3);
- var bg = new Color (4, 5, 6);
- buffer.CurrentAttribute = new Attribute (fg, bg);
- buffer.AddStr ("X");
- // Act
- string ansi = output.ToAnsi (buffer);
- // Assert: when true color expected, we should see the RGB CSI; otherwise we should see the 16-color CSI
- if (!isLegacyConsole && !force16Colors)
- {
- Assert.Contains ("\u001b[38;2;1;2;3m", ansi);
- }
- else if (!isLegacyConsole && force16Colors)
- {
- var expected16 = EscSeqUtils.CSI_SetForegroundColor (fg.GetAnsiColorCode ());
- Assert.Contains (expected16, ansi);
- }
- else
- {
- var expected16 = (ConsoleColor)fg.GetClosestNamedColor16 ();
- Assert.Equal (ConsoleColor.Black, expected16);
- Assert.DoesNotContain ('\u001b', ansi);
- }
- // Grapheme and newline should always be present
- Assert.Contains ("X" + Environment.NewLine, ansi);
- }
- [Fact]
- public void Write_WritesDirtyCellsAndClearsDirtyFlags ()
- {
- // Arrange
- var output = new FakeOutput ();
- IOutputBuffer buffer = output.LastBuffer!;
- buffer.SetSize (2, 1);
- // Mark two characters as dirty by writing them into the buffer
- buffer.AddStr ("AB");
- // Sanity: ensure cells are dirty before calling Write
- Assert.True (buffer.Contents! [0, 0].IsDirty);
- Assert.True (buffer.Contents! [0, 1].IsDirty);
- // Act
- output.Write (buffer); // calls OutputBase.Write via FakeOutput
- // Assert: content was written to the fake output and dirty flags cleared
- Assert.Contains ("AB", output.Output);
- Assert.False (buffer.Contents! [0, 0].IsDirty);
- Assert.False (buffer.Contents! [0, 1].IsDirty);
- }
- [Theory]
- [InlineData (true)]
- [InlineData (false)]
- public void Write_Virtual_Or_NonVirtual_Uses_WriteToConsole_And_Clears_Dirty_Flags (bool isLegacyConsole)
- {
- // Arrange
- // FakeOutput exposes this because it's in test scope
- var output = new FakeOutput { IsLegacyConsole = isLegacyConsole };
- IOutputBuffer buffer = output.LastBuffer!;
- buffer.SetSize (3, 1);
- // Write 'A' at col 0 and 'C' at col 2; leave col 1 untouched (not dirty)
- buffer.Move (0, 0);
- buffer.AddStr ("A");
- buffer.Move (2, 0);
- buffer.AddStr ("C");
- // Confirm some dirtiness before to write
- Assert.True (buffer.Contents! [0, 0].IsDirty);
- Assert.True (buffer.Contents! [0, 2].IsDirty);
- // Act
- output.Write (buffer);
- // Assert: both characters were written (use Contains to avoid CI side effects)
- Assert.Contains ("A", output.Output);
- Assert.Contains ("C", output.Output);
- // Dirty flags cleared for the written cells
- Assert.False (buffer.Contents! [0, 0].IsDirty);
- Assert.False (buffer.Contents! [0, 2].IsDirty);
- // Verify SetCursorPositionImpl was invoked by WriteToConsole (cursor set to a written column)
- Assert.Equal (new Point (0, 0), output.GetCursorPosition ());
- // Now write 'X' at col 0 to verify subsequent writes also work
- buffer.Move (0, 0);
- buffer.AddStr ("X");
- // Confirm dirtiness state before to write
- Assert.True (buffer.Contents! [0, 0].IsDirty);
- Assert.False (buffer.Contents! [0, 2].IsDirty);
- output.Write (buffer);
- // Assert: both characters were written (use Contains to avoid CI side effects)
- Assert.Contains ("A", output.Output);
- Assert.Contains ("C", output.Output);
- // Dirty flags cleared for the written cells
- Assert.False (buffer.Contents! [0, 0].IsDirty);
- Assert.False (buffer.Contents! [0, 2].IsDirty);
- // Verify SetCursorPositionImpl was invoked by WriteToConsole (cursor set to a written column)
- Assert.Equal (new Point (0, 0), output.GetCursorPosition ());
- }
- [Theory]
- [InlineData (true)]
- [InlineData (false)]
- public void Write_EmitsSixelDataAndPositionsCursor (bool isLegacyConsole)
- {
- // Arrange
- var output = new FakeOutput ();
- IOutputBuffer buffer = output.LastBuffer!;
- buffer.SetSize (1, 1);
- // Ensure the buffer has some content so Write traverses rows
- buffer.AddStr (".");
- // Create a Sixel to render
- var s = new SixelToRender
- {
- SixelData = "SIXEL-DATA",
- ScreenPosition = new Point (4, 2)
- };
- // Create DriverImpl and associate it with the FakeOutput to test Sixel output
- IDriver driver = new DriverImpl (
- new FakeInputProcessor (null!),
- new OutputBufferImpl (),
- output,
- new (new AnsiResponseParser ()),
- new SizeMonitorImpl (output));
- // Add the Sixel to the driver
- driver.GetSixels ().Enqueue (s);
- // FakeOutput exposes this because it's in test scope
- output.IsLegacyConsole = isLegacyConsole;
- // Act
- output.Write (buffer);
- if (!isLegacyConsole)
- {
- // Assert: Sixel data was emitted (use Contains to avoid equality/side-effects)
- Assert.Contains ("SIXEL-DATA", output.Output);
- // Cursor was moved to Sixel position
- Assert.Equal (s.ScreenPosition, output.GetCursorPosition ());
- }
- else
- {
- // Assert: Sixel data was NOT emitted
- Assert.DoesNotContain ("SIXEL-DATA", output.Output);
- // Cursor was NOT moved to Sixel position
- Assert.NotEqual (s.ScreenPosition, output.GetCursorPosition ());
- }
- IApplication app = Application.Create ();
- app.Driver = driver;
- Assert.Equal (driver.GetSixels (), app.Driver.GetSixels ());
- app.Dispose ();
- }
- }
|