mirror of
https://github.com/gui-cs/Terminal.Gui.git
synced 2025-12-26 07:47:54 +01:00
* Fixes #4449. Regression in IsLegacyConsole mode where dirty cells are not handled correctly * Cursor position is always set in the beginning a new row or on non-dirty flags
218 lines
7.4 KiB
C#
218 lines
7.4 KiB
C#
#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 (2, 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 ();
|
|
}
|
|
} |