mirror of
https://github.com/gui-cs/Terminal.Gui.git
synced 2025-12-26 15:57:56 +01:00
* Fixed warnings I recently introduced. Replaced nullable App references with null-forgiving operator (!) in MessageBox and dialog calls to suppress nullable warnings. Updated XML docs to use Dim.Fill() and clarified method references. Made Application.Popover registration null-safe. Fixed test output helper usage in ShadowTests. No functional changes. * Fixes Release build warnings
584 lines
21 KiB
C#
584 lines
21 KiB
C#
using System.Text;
|
||
using UnitTests;
|
||
using Xunit.Abstractions;
|
||
|
||
namespace ViewBaseTests.Adornments;
|
||
|
||
[Collection ("Global Test Setup")]
|
||
|
||
public class ShadowTests (ITestOutputHelper output)
|
||
{
|
||
private readonly ITestOutputHelper _output = output;
|
||
|
||
[Fact]
|
||
public void Default_None ()
|
||
{
|
||
var view = new View ();
|
||
Assert.Equal (ShadowStyle.None, view.ShadowStyle);
|
||
Assert.Equal (ShadowStyle.None, view.Margin!.ShadowStyle);
|
||
view.Dispose ();
|
||
}
|
||
|
||
[Theory]
|
||
[InlineData (ShadowStyle.None)]
|
||
[InlineData (ShadowStyle.Opaque)]
|
||
[InlineData (ShadowStyle.Transparent)]
|
||
public void Set_View_Sets_Margin (ShadowStyle style)
|
||
{
|
||
var view = new View ();
|
||
|
||
view.ShadowStyle = style;
|
||
Assert.Equal (style, view.ShadowStyle);
|
||
Assert.Equal (style, view.Margin!.ShadowStyle);
|
||
view.Dispose ();
|
||
}
|
||
|
||
|
||
[Theory]
|
||
[InlineData (ShadowStyle.None, 0, 0, 0, 0)]
|
||
[InlineData (ShadowStyle.Opaque, 0, 0, 1, 1)]
|
||
[InlineData (ShadowStyle.Transparent, 0, 0, 1, 1)]
|
||
public void ShadowStyle_Margin_Thickness (ShadowStyle style, int expectedLeft, int expectedTop, int expectedRight, int expectedBottom)
|
||
{
|
||
var superView = new View
|
||
{
|
||
Height = 10, Width = 10
|
||
};
|
||
|
||
View view = new ()
|
||
{
|
||
Width = Dim.Auto (),
|
||
Height = Dim.Auto (),
|
||
Text = "0123",
|
||
HighlightStates = MouseState.Pressed,
|
||
ShadowStyle = style,
|
||
CanFocus = true
|
||
};
|
||
|
||
superView.Add (view);
|
||
superView.BeginInit ();
|
||
superView.EndInit ();
|
||
|
||
Assert.Equal (new (expectedLeft, expectedTop, expectedRight, expectedBottom), view.Margin!.Thickness);
|
||
}
|
||
|
||
|
||
[Theory]
|
||
[InlineData (ShadowStyle.None, 3)]
|
||
[InlineData (ShadowStyle.Opaque, 4)]
|
||
[InlineData (ShadowStyle.Transparent, 4)]
|
||
public void Style_Changes_Margin_Thickness (ShadowStyle style, int expected)
|
||
{
|
||
var view = new View ();
|
||
view.Margin!.Thickness = new (3);
|
||
view.ShadowStyle = style;
|
||
Assert.Equal (new (3, 3, expected, expected), view.Margin.Thickness);
|
||
|
||
view.ShadowStyle = ShadowStyle.None;
|
||
Assert.Equal (new (3), view.Margin.Thickness);
|
||
view.Dispose ();
|
||
}
|
||
|
||
[Theory]
|
||
[InlineData (ShadowStyle.None)]
|
||
[InlineData (ShadowStyle.Opaque)]
|
||
[InlineData (ShadowStyle.Transparent)]
|
||
public void ShadowWidth_ShadowHeight_Defaults (ShadowStyle style)
|
||
{
|
||
View view = new () { ShadowStyle = style };
|
||
|
||
if (view.ShadowStyle == ShadowStyle.None)
|
||
{
|
||
Assert.Equal (new (0, 0), view.Margin!.ShadowSize);
|
||
}
|
||
else
|
||
{
|
||
Assert.Equal (new (1, 1), view.Margin!.ShadowSize);
|
||
}
|
||
}
|
||
|
||
[Fact]
|
||
public void ShadowStyle_Opaque_Margin_ShadowWidth_ShadowHeight_Cannot_Be_Set_Different_Of_One ()
|
||
{
|
||
View view = new () { ShadowStyle = ShadowStyle.Opaque };
|
||
view.Margin!.ShadowSize = new (3, 4);
|
||
Assert.Equal (1, view.Margin.ShadowSize.Width);
|
||
Assert.Equal (1, view.Margin.ShadowSize.Height);
|
||
}
|
||
|
||
[Theory]
|
||
[InlineData (ShadowStyle.None, 0)]
|
||
[InlineData (ShadowStyle.Opaque, 1)]
|
||
[InlineData (ShadowStyle.Transparent, 1)]
|
||
public void Margin_ShadowWidth_ShadowHeight_Cannot_Be_Set_Less_Than_Zero (ShadowStyle style, int expectedLength)
|
||
{
|
||
View view = new () { ShadowStyle = style };
|
||
view.Margin!.ShadowSize = new (-1, -1);
|
||
Assert.Equal (expectedLength, view.Margin!.ShadowSize.Width);
|
||
Assert.Equal (expectedLength, view.Margin!.ShadowSize.Height);
|
||
}
|
||
|
||
[Fact]
|
||
public void Changing_ShadowStyle_Correctly_Set_ShadowWidth_ShadowHeight_Thickness ()
|
||
{
|
||
View view = new () { ShadowStyle = ShadowStyle.Transparent };
|
||
view.Margin!.ShadowSize = new (2, 2);
|
||
|
||
Assert.Equal (new (2, 2), view.Margin!.ShadowSize);
|
||
Assert.Equal (new (0, 0, 2, 2), view.Margin.Thickness);
|
||
|
||
view.ShadowStyle = ShadowStyle.None;
|
||
Assert.Equal (new (2, 2), view.Margin!.ShadowSize);
|
||
Assert.Equal (new (0, 0, 0, 0), view.Margin.Thickness);
|
||
|
||
view.ShadowStyle = ShadowStyle.Opaque;
|
||
Assert.Equal (new (1, 1), view.Margin!.ShadowSize);
|
||
Assert.Equal (new (0, 0, 1, 1), view.Margin.Thickness);
|
||
}
|
||
|
||
[Theory]
|
||
[InlineData (ShadowStyle.None, 2, 1, 3, 0, 0, 0)]
|
||
[InlineData (ShadowStyle.Opaque, 1, 1, 1, 1, 1, 1)]
|
||
[InlineData (ShadowStyle.Transparent, 2, 1, 3, 2, 2, 3)]
|
||
public void Changing_ShadowWidth_ShadowHeight_Correctly_Set_Thickness (
|
||
ShadowStyle style,
|
||
int expectedLength1,
|
||
int expectedLength2,
|
||
int expectedLength3,
|
||
int expectedThickness1,
|
||
int expectedThickness2,
|
||
int expectedThickness3
|
||
)
|
||
{
|
||
View view = new () { ShadowStyle = style };
|
||
view.Margin!.ShadowSize = new (2, 2);
|
||
Assert.Equal (expectedLength1, view.Margin!.ShadowSize.Width);
|
||
Assert.Equal (expectedLength1, view.Margin.ShadowSize.Height);
|
||
Assert.Equal (new (0, 0, expectedThickness1, expectedThickness1), view.Margin.Thickness);
|
||
|
||
view.Margin!.ShadowSize = new (1, 1);
|
||
Assert.Equal (expectedLength2, view.Margin!.ShadowSize.Width);
|
||
Assert.Equal (expectedLength2, view.Margin.ShadowSize.Height);
|
||
Assert.Equal (new (0, 0, expectedThickness2, expectedThickness2), view.Margin.Thickness);
|
||
|
||
view.Margin!.ShadowSize = new (3, 3);
|
||
Assert.Equal (expectedLength3, view.Margin!.ShadowSize.Width);
|
||
Assert.Equal (expectedLength3, view.Margin.ShadowSize.Height);
|
||
Assert.Equal (new (0, 0, expectedThickness3, expectedThickness3), view.Margin.Thickness);
|
||
|
||
view.ShadowStyle = ShadowStyle.None;
|
||
Assert.Equal (expectedLength3, view.Margin!.ShadowSize.Width);
|
||
Assert.Equal (expectedLength3, view.Margin.ShadowSize.Height);
|
||
Assert.Equal (new (0, 0, 0, 0), view.Margin.Thickness);
|
||
}
|
||
|
||
[Theory]
|
||
[InlineData (ShadowStyle.None, 0, 1)]
|
||
[InlineData (ShadowStyle.Opaque, 1, 1)]
|
||
[InlineData (ShadowStyle.Transparent, 1, 1)]
|
||
public void Changing_Thickness_Correctly_Set_Thickness (ShadowStyle style, int expectedLength, int expectedThickness)
|
||
{
|
||
View view = new () { ShadowStyle = style };
|
||
|
||
Assert.Equal (new (0, 0, expectedLength, expectedLength), view.Margin!.Thickness);
|
||
|
||
view.Margin!.Thickness = new (0, 0, 1, 1);
|
||
Assert.Equal (expectedLength, view.Margin!.ShadowSize.Width);
|
||
Assert.Equal (expectedLength, view.Margin.ShadowSize.Height);
|
||
Assert.Equal (new (0, 0, expectedThickness, expectedThickness), view.Margin.Thickness);
|
||
}
|
||
|
||
[Fact]
|
||
public void ShadowStyle_Transparent_Handles_Wide_Glyphs_Correctly ()
|
||
{
|
||
IApplication app = Application.Create ();
|
||
app.Init ("fake");
|
||
|
||
app.Driver?.SetScreenSize (6, 5);
|
||
|
||
// Using a replacement char to make sure wide glyphs are handled correctly
|
||
// in the shadow area, to not confusing with a space char.
|
||
app.Driver?.GetOutputBuffer ().SetWideGlyphReplacement (Rune.ReplacementChar);
|
||
|
||
Runnable superview = new () { Width = Dim.Fill (), Height = Dim.Fill () };
|
||
|
||
superview.Text = """
|
||
🍎🍎🍎
|
||
🍎🍎🍎
|
||
🍎🍎🍎
|
||
🍎🍎🍎
|
||
🍎🍎🍎
|
||
""";
|
||
|
||
View view = new () { Width = Dim.Fill (), Height = Dim.Fill (), BorderStyle = LineStyle.Single, ShadowStyle = ShadowStyle.Transparent };
|
||
view.Margin!.ShadowSize = view.Margin!.ShadowSize with { Width = 2 };
|
||
superview.Add (view);
|
||
|
||
app.Begin (superview);
|
||
Assert.Equal (new (2, 1), view.Margin!.ShadowSize);
|
||
Assert.Equal (new (0, 0, 2, 1), view.Margin!.Thickness);
|
||
|
||
DriverAssert.AssertDriverContentsAre (
|
||
"""
|
||
┌──┐🍎
|
||
│ │🍎
|
||
│ │🍎
|
||
└──┘🍎
|
||
<EFBFBD> 🍎🍎
|
||
""",
|
||
_output,
|
||
app.Driver);
|
||
|
||
view.Margin!.ShadowSize = new (1, 2);
|
||
|
||
app.LayoutAndDraw ();
|
||
Assert.Equal (new (1, 2), view.Margin!.ShadowSize);
|
||
Assert.Equal (new (0, 0, 2, 2), view.Margin!.Thickness);
|
||
|
||
DriverAssert.AssertDriverContentsAre (
|
||
"""
|
||
┌──┐🍎
|
||
│ │<EFBFBD>
|
||
└──┘<EFBFBD>
|
||
<EFBFBD> 🍎🍎
|
||
<EFBFBD> 🍎🍎
|
||
""",
|
||
_output,
|
||
app.Driver);
|
||
|
||
view.Width = Dim.Fill (1);
|
||
app.LayoutAndDraw ();
|
||
Assert.Equal (new (1, 2), view.Margin!.ShadowSize);
|
||
Assert.Equal (new (0, 0, 2, 2), view.Margin!.Thickness);
|
||
|
||
DriverAssert.AssertDriverContentsAre (
|
||
"""
|
||
┌─┐ 🍎
|
||
│ │ <EFBFBD>
|
||
└─┘ <EFBFBD>
|
||
<EFBFBD> 🍎<EFBFBD>
|
||
<EFBFBD> 🍎<EFBFBD>
|
||
""",
|
||
_output,
|
||
app.Driver);
|
||
}
|
||
|
||
[Fact]
|
||
public void ShadowStyle_Opaque_Change_Thickness_On_Mouse_Pressed_Released ()
|
||
{
|
||
IApplication app = Application.Create ();
|
||
app.Init ("fake");
|
||
|
||
app.Driver?.SetScreenSize (10, 4);
|
||
|
||
Runnable superview = new () { Width = Dim.Fill (), Height = Dim.Fill () };
|
||
View view = new () { Width = 7, Height = 2, ShadowStyle = ShadowStyle.Opaque, Text = "| Hi |", HighlightStates = MouseState.Pressed };
|
||
superview.Add (view);
|
||
|
||
app.Begin (superview);
|
||
|
||
DriverAssert.AssertDriverContentsAre (
|
||
"""
|
||
| Hi |▖
|
||
▝▀▀▀▀▀▘
|
||
""",
|
||
_output,
|
||
app.Driver);
|
||
|
||
app.Mouse.RaiseMouseEvent (new () { ScreenPosition = new (2, 0), Flags = MouseFlags.Button1Pressed });
|
||
app.LayoutAndDraw ();
|
||
|
||
DriverAssert.AssertDriverContentsAre (
|
||
"""
|
||
| Hi |
|
||
""",
|
||
_output,
|
||
app.Driver);
|
||
|
||
app.Mouse.RaiseMouseEvent (new () { ScreenPosition = new (2, 0), Flags = MouseFlags.Button1Released });
|
||
app.LayoutAndDraw ();
|
||
|
||
DriverAssert.AssertDriverContentsAre (
|
||
"""
|
||
| Hi |▖
|
||
▝▀▀▀▀▀▘
|
||
""",
|
||
_output,
|
||
app.Driver);
|
||
}
|
||
|
||
[Fact]
|
||
public void ShadowStyle_Transparent_Never_Throws_Navigating_Outside_Bounds ()
|
||
{
|
||
IApplication app = Application.Create ();
|
||
app.Init ("fake");
|
||
|
||
app.Driver?.SetScreenSize (6, 5);
|
||
|
||
Runnable superview = new () { Width = Dim.Fill (), Height = Dim.Fill () };
|
||
|
||
superview.Text = """
|
||
🍎🍎🍎
|
||
🍎🍎🍎
|
||
🍎🍎🍎
|
||
🍎🍎🍎
|
||
🍎🍎🍎
|
||
""";
|
||
|
||
View view = new ()
|
||
{
|
||
Width = Dim.Fill (), Height = Dim.Fill (), BorderStyle = LineStyle.Single, ShadowStyle = ShadowStyle.Transparent,
|
||
Arrangement = ViewArrangement.Movable, CanFocus = true
|
||
};
|
||
view.Margin!.ShadowSize = view.Margin!.ShadowSize with { Width = 2 };
|
||
superview.Add (view);
|
||
|
||
app.Begin (superview);
|
||
|
||
Assert.Equal (new (0, 0), view.Frame.Location);
|
||
|
||
Assert.True (app.Keyboard.RaiseKeyDownEvent (Key.F5.WithCtrl));
|
||
|
||
int i = 0;
|
||
DecrementValue (-10, Key.CursorLeft);
|
||
Assert.Equal (-10, i);
|
||
|
||
IncrementValue (0, Key.CursorRight);
|
||
Assert.Equal (0, i);
|
||
|
||
DecrementValue (-10, Key.CursorUp);
|
||
Assert.Equal (-10, i);
|
||
|
||
IncrementValue (20, Key.CursorDown);
|
||
Assert.Equal (20, i);
|
||
|
||
DecrementValue (0, Key.CursorUp);
|
||
Assert.Equal (0, i);
|
||
|
||
IncrementValue (20, Key.CursorRight);
|
||
Assert.Equal (20, i);
|
||
|
||
return;
|
||
|
||
void DecrementValue (int count, Key key)
|
||
{
|
||
for (; i > count; i--)
|
||
{
|
||
Assert.True (app.Keyboard.RaiseKeyDownEvent (key));
|
||
app.LayoutAndDraw ();
|
||
|
||
CheckAssertion (new (i - 1, 0), new (0, i - 1), key);
|
||
}
|
||
}
|
||
|
||
void IncrementValue (int count, Key key)
|
||
{
|
||
for (; i < count; i++)
|
||
{
|
||
Assert.True (app.Keyboard.RaiseKeyDownEvent (key));
|
||
app.LayoutAndDraw ();
|
||
|
||
CheckAssertion (new (i + 1, 0), new (0, i + 1), key);
|
||
}
|
||
}
|
||
|
||
bool? IsColumn (Key key)
|
||
{
|
||
if (key == Key.CursorLeft || key == Key.CursorRight)
|
||
{
|
||
return true;
|
||
}
|
||
|
||
if (key == Key.CursorUp || key == Key.CursorDown)
|
||
{
|
||
return false;
|
||
}
|
||
|
||
return null;
|
||
}
|
||
|
||
void CheckAssertion (Point colLocation, Point rowLocation, Key key)
|
||
{
|
||
bool? isCol = IsColumn (key);
|
||
|
||
switch (isCol)
|
||
{
|
||
case true:
|
||
Assert.Equal (colLocation, view.Frame.Location);
|
||
|
||
break;
|
||
case false:
|
||
Assert.Equal (rowLocation, view.Frame.Location);
|
||
|
||
break;
|
||
default:
|
||
throw new InvalidOperationException ();
|
||
}
|
||
}
|
||
}
|
||
|
||
[Theory]
|
||
[InlineData (ShadowStyle.None, 3, 4, 4)]
|
||
[InlineData (ShadowStyle.Opaque, 4, 5, 4)]
|
||
[InlineData (ShadowStyle.Transparent, 4, 5, 4)]
|
||
public void Margin_Thickness_Changes_Adjust_Correctly (ShadowStyle style, int expectedThickness, int expectedThicknessAdjust, int expectedThicknessNone)
|
||
{
|
||
var view = new View ();
|
||
view.Margin!.Thickness = new (3);
|
||
view.ShadowStyle = style;
|
||
Assert.Equal (new (3, 3, expectedThickness, expectedThickness), view.Margin.Thickness);
|
||
|
||
view.Margin.Thickness = new (3, 3, expectedThickness + 1, expectedThickness + 1);
|
||
Assert.Equal (new (3, 3, expectedThicknessAdjust, expectedThicknessAdjust), view.Margin.Thickness);
|
||
view.ShadowStyle = ShadowStyle.None;
|
||
Assert.Equal (new (3, 3, expectedThicknessNone, expectedThicknessNone), view.Margin.Thickness);
|
||
view.Dispose ();
|
||
}
|
||
|
||
[Fact]
|
||
public void Runnable_View_Overlap_Other_Runnables ()
|
||
{
|
||
IApplication app = Application.Create ();
|
||
app.Init ("fake");
|
||
|
||
app.Driver?.SetScreenSize (10, 5);
|
||
|
||
Runnable superview = new () { Width = Dim.Fill (), Height = Dim.Fill (), Text = "🍎".Repeat (25)! };
|
||
View view = new () { Width = 7, Height = 2, ShadowStyle = ShadowStyle.Opaque, Text = "| Hi |" };
|
||
superview.Add (view);
|
||
|
||
app.Begin (superview);
|
||
|
||
DriverAssert.AssertDriverContentsAre (
|
||
"""
|
||
| Hi |▖ 🍎
|
||
▝▀▀▀▀▀▘ 🍎
|
||
🍎🍎🍎🍎🍎
|
||
🍎🍎🍎🍎🍎
|
||
🍎🍎🍎🍎🍎
|
||
""",
|
||
_output,
|
||
app.Driver);
|
||
|
||
Runnable modalSuperview = new () { Y = 1, Width = Dim.Fill (), Height = 4, BorderStyle = LineStyle.Single };
|
||
View view1 = new () { Width = 8, Height = 2, ShadowStyle = ShadowStyle.Opaque, Text = "| Hey |" };
|
||
modalSuperview.Add (view1);
|
||
|
||
app.Begin (modalSuperview);
|
||
|
||
Assert.True (modalSuperview.IsModal);
|
||
|
||
DriverAssert.AssertDriverContentsAre (
|
||
"""
|
||
| Hi |▖ 🍎
|
||
┌────────┐
|
||
│| Hey |▖│
|
||
│▝▀▀▀▀▀▀▘│
|
||
└────────┘
|
||
""",
|
||
_output,
|
||
app.Driver);
|
||
|
||
|
||
app.Dispose ();
|
||
}
|
||
|
||
[Fact]
|
||
public void TransparentShadow_Draws_Transparent_At_Driver_Output ()
|
||
{
|
||
// Arrange
|
||
using IApplication app = Application.Create ();
|
||
app.Init ("fake");
|
||
app.Driver!.SetScreenSize (2, 1);
|
||
app.Driver.Force16Colors = true;
|
||
|
||
using Runnable superView = new ();
|
||
superView.Width = Dim.Fill ();
|
||
superView.Height = Dim.Fill ();
|
||
superView.Text = "AB";
|
||
superView.TextFormatter.WordWrap = true;
|
||
superView.SetScheme (new (new Attribute (Color.Black, Color.White)));
|
||
|
||
// Create view with transparent shadow
|
||
View viewWithShadow = new ()
|
||
{
|
||
Width = Dim.Auto (),
|
||
Height = Dim.Auto (),
|
||
Text = "*",
|
||
ShadowStyle = ShadowStyle.Transparent
|
||
};
|
||
// Make it so the margin is only on the right for simplicity
|
||
viewWithShadow.Margin!.Thickness = new (0, 0, 1, 0);
|
||
viewWithShadow.SetScheme (new (new Attribute (Color.Black, Color.White)));
|
||
|
||
superView.Add (viewWithShadow);
|
||
|
||
// Act
|
||
app.Begin (superView);
|
||
app.LayoutAndDraw ();
|
||
app.Driver.Refresh ();
|
||
|
||
// Assert
|
||
Assert.Equal (new (0, 0, 2, 2), viewWithShadow.Frame);
|
||
Assert.Equal (new (0, 0, 1, 1), viewWithShadow.Viewport);
|
||
|
||
_output.WriteLine ("Actual driver contents:");
|
||
_output.WriteLine (app.Driver.ToString ());
|
||
_output.WriteLine ("\nActual driver output:");
|
||
string? output = app.Driver.GetOutput ().GetLastOutput ();
|
||
_output.WriteLine (output);
|
||
|
||
// Printed with bright black (dark gray) text on bright black (dark gray) background making it invisible
|
||
DriverAssert.AssertDriverOutputIs ("""
|
||
\x1b[30m\x1b[107m*\x1b[90m\x1b[100mB
|
||
""", _output, app.Driver);
|
||
}
|
||
|
||
[Fact]
|
||
public void TransparentShadow_OverWide_Draws_Transparent_At_Driver_Output ()
|
||
{
|
||
// Arrange
|
||
using IApplication app = Application.Create ();
|
||
app.Init ("fake");
|
||
app.Driver!.SetScreenSize (2, 3);
|
||
app.Driver.Force16Colors = true;
|
||
|
||
using Runnable superView = new ();
|
||
superView.Width = Dim.Fill ();
|
||
superView.Height = Dim.Fill ();
|
||
superView.Text = "🍎🍎🍎🍎";
|
||
superView.TextFormatter.WordWrap = true;
|
||
superView.SetScheme (new (new Attribute (Color.Black, Color.White)));
|
||
|
||
// Create view with transparent shadow
|
||
View viewWithShadow = new ()
|
||
{
|
||
Width = Dim.Auto (),
|
||
Height = Dim.Auto (),
|
||
Text = "*",
|
||
ShadowStyle = ShadowStyle.Transparent
|
||
};
|
||
// Make it so the margin is only on the bottom for simplicity
|
||
viewWithShadow.Margin!.Thickness = new (0, 0, 0, 1);
|
||
viewWithShadow.SetScheme (new (new Attribute (Color.Black, Color.White)));
|
||
|
||
superView.Add (viewWithShadow);
|
||
|
||
// Act
|
||
app.Begin (superView);
|
||
app.LayoutAndDraw ();
|
||
app.Driver.Refresh ();
|
||
|
||
// Assert
|
||
_output.WriteLine ("Actual driver contents:");
|
||
_output.WriteLine (app.Driver.ToString ());
|
||
_output.WriteLine ("\nActual driver output:");
|
||
string? output = app.Driver.GetOutput ().GetLastOutput ();
|
||
_output.WriteLine (output);
|
||
|
||
DriverAssert.AssertDriverOutputIs ("""
|
||
\x1b[30m\x1b[107m*\x1b[90m\x1b[103m \x1b[97m\x1b[40m \x1b[90m\x1b[100m \x1b[97m\x1b[40m🍎
|
||
""", _output, app.Driver);
|
||
}
|
||
}
|