Files
Terminal.Gui/Tests/UnitTestsParallelizable/Drivers/AddRuneTests.cs
BDisp cd75a20c60 Fixes #4387. Runes should not be used on a cell, but rather should use a single grapheme rendering 1 or 2 columns (#4388)
* Fixes #4382. StringExtensions.GetColumns method should only return the total text width and not the sum of all runes width

* Trying to fix unit test error

* Update StringExtensions.cs

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Resolving merge conflicts

* Prevents Runes throwing if Grapheme is null

* Add unit test to prove that null and empty string doesn't not throws anything.

* Fix unit test failure

* Fix IsValidLocation for wide graphemes

* Add more combining

* Prevent set invalid graphemes

* Fix unit tests

* Grapheme doesn't support invalid code points like lone surrogates

* Fixes more unit tests

* Fix unit test

* Seems all test are fixed now

* Adjust CharMap scenario with graphemes

* Upgrade Wcwidth to version 4.0.0

* Reformat

* Trying fix CheckDefaultState assertion

* Revert "Trying fix CheckDefaultState assertion"

This reverts commit c9b46b796a.

* Forgot to include driver.End in the test

* Reapply "Trying fix CheckDefaultState assertion"

This reverts commit 1060ac9b63.

* Remove ToString

* Fix merge errors

* Change to conditional expression

* Assertion to prove that no exception throws during cell initialization.

* Remove unnecessary assignment

* Remove assignment to end

* Replace string concatenation with 'StringBuilder'.

* Replace more string concatenation with 'StringBuilder'

* Remove redundant call to 'ToString' because Rune cast to a String object.

* Replace foreach loop with Sum linq

---------

Co-authored-by: Tig <tig@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-11-20 13:45:13 -05:00

183 lines
5.6 KiB
C#

using System.Buffers;
using System.Text;
using UnitTests;
using Xunit.Abstractions;
// Alias Console to MockConsole so we don't accidentally use Console
namespace UnitTests_Parallelizable.DriverTests;
public class AddRuneTests (ITestOutputHelper output) : FakeDriverBase
{
private readonly ITestOutputHelper _output = output;
[Fact]
public void AddRune ()
{
IDriver driver = CreateFakeDriver ();
driver.Rows = 25;
driver.Cols = 80;
driver.AddRune (new Rune ('a'));
Assert.Equal ("a", driver.Contents [0, 0].Grapheme);
driver.End ();
}
[Fact]
public void AddRune_Accented_Letter_With_Three_Combining_Unicode_Chars ()
{
IDriver driver = CreateFakeDriver ();
var expected = "ắ";
var text = "\u1eaf";
driver.AddStr (text);
Assert.Equal (expected, driver.Contents [0, 0].Grapheme);
Assert.Equal (" ", driver.Contents [0, 1].Grapheme);
driver.ClearContents ();
driver.Move (0, 0);
expected = "ắ";
text = "\u0103\u0301";
driver.AddStr (text);
Assert.Equal (expected, driver.Contents [0, 0].Grapheme);
Assert.Equal (" ", driver.Contents [0, 1].Grapheme);
driver.ClearContents ();
driver.Move (0, 0);
expected = "ắ";
text = "\u0061\u0306\u0301";
driver.AddStr (text);
Assert.Equal (expected, driver.Contents [0, 0].Grapheme);
Assert.Equal (" ", driver.Contents [0, 1].Grapheme);
// var s = "a\u0301\u0300\u0306";
// DriverAsserts.AssertDriverContentsWithFrameAre (@"
//ắ", output);
// tf.Text = "\u1eaf";
// Application.Refresh ();
// DriverAsserts.AssertDriverContentsWithFrameAre (@"
//ắ", output);
// tf.Text = "\u0103\u0301";
// Application.Refresh ();
// DriverAsserts.AssertDriverContentsWithFrameAre (@"
//ắ", output);
// tf.Text = "\u0061\u0306\u0301";
// Application.Refresh ();
// DriverAsserts.AssertDriverContentsWithFrameAre (@"
//ắ", output);
driver.End ();
}
[Fact]
public void AddRune_InvalidLocation_DoesNothing ()
{
IDriver driver = CreateFakeDriver ();
driver.Move (driver.Cols, driver.Rows);
driver.AddRune ('a');
for (var col = 0; col < driver.Cols; col++)
{
for (var row = 0; row < driver.Rows; row++)
{
Assert.Equal (" ", driver.Contents [row, col].Grapheme);
}
}
driver.End ();
}
[Fact]
public void AddRune_MovesToNextColumn ()
{
IDriver driver = CreateFakeDriver ();
driver.AddRune ('a');
Assert.Equal ("a", driver.Contents [0, 0].Grapheme);
Assert.Equal (0, driver.Row);
Assert.Equal (1, driver.Col);
driver.AddRune ('b');
Assert.Equal ("b", driver.Contents [0, 1].Grapheme);
Assert.Equal (0, driver.Row);
Assert.Equal (2, driver.Col);
// Move to the last column of the first row
int lastCol = driver.Cols - 1;
driver.Move (lastCol, 0);
Assert.Equal (0, driver.Row);
Assert.Equal (lastCol, driver.Col);
// Add a rune to the last column of the first row; should increment the row or col even though it's now invalid
driver.AddRune ('c');
Assert.Equal ("c", driver.Contents [0, lastCol].Grapheme);
Assert.Equal (lastCol + 1, driver.Col);
// Add a rune; should succeed but do nothing as it's outside of Contents
driver.AddRune ('d');
Assert.Equal (lastCol + 2, driver.Col);
for (var col = 0; col < driver.Cols; col++)
{
for (var row = 0; row < driver.Rows; row++)
{
Assert.NotEqual ("d", driver.Contents [row, col].Grapheme);
}
}
driver.End ();
}
[Fact]
public void AddRune_MovesToNextColumn_Wide ()
{
IDriver driver = CreateFakeDriver ();
// 🍕 Slice of Pizza "\U0001F355"
OperationStatus operationStatus = Rune.DecodeFromUtf16 ("\U0001F355", out Rune rune, out int charsConsumed);
Assert.Equal (OperationStatus.Done, operationStatus);
Assert.Equal (charsConsumed, rune.Utf16SequenceLength);
Assert.Equal (2, rune.GetColumns ());
driver.AddRune (rune);
Assert.Equal (rune.ToString (), driver.Contents [0, 0].Grapheme);
Assert.Equal (0, driver.Row);
Assert.Equal (2, driver.Col);
//driver.AddRune ('b');
//Assert.Equal ((Text)'b', driver.Contents [0, 1].Text);
//Assert.Equal (0, driver.Row);
//Assert.Equal (2, driver.Col);
//// Move to the last column of the first row
//var lastCol = driver.Cols - 1;
//driver.Move (lastCol, 0);
//Assert.Equal (0, driver.Row);
//Assert.Equal (lastCol, driver.Col);
//// Add a rune to the last column of the first row; should increment the row or col even though it's now invalid
//driver.AddRune ('c');
//Assert.Equal ((Text)'c', driver.Contents [0, lastCol].Text);
//Assert.Equal (lastCol + 1, driver.Col);
//// Add a rune; should succeed but do nothing as it's outside of Contents
//driver.AddRune ('d');
//Assert.Equal (lastCol + 2, driver.Col);
//for (var col = 0; col < driver.Cols; col++) {
// for (var row = 0; row < driver.Rows; row++) {
// Assert.NotEqual ((Text)'d', driver.Contents [row, col].Text);
// }
//}
driver.End ();
}
}