Files
ttui/test/TinyTUI.Tests/Text/TerminalTextMeasurerTests.cs
T
chuan b26104fe95 feat: add tui test infrastructure
- add xunit regression project with virtual terminal output

- cover text input overlay rendering and component checks
2026-06-04 02:35:52 +08:00

59 lines
2.6 KiB
C#

using TinyTUI.Text;
namespace TinyTUI.Tests.Text;
public sealed class TerminalTextMeasurerTests
{
private readonly TerminalTextMeasurer _measurer = new();
[Fact]
public void GetWidthHandlesAnsiTabsAndEmojiGraphemes()
{
Assert.Equal(5, _measurer.GetWidth("\t\e[31m界\e[0m"));
Assert.Equal(2, _measurer.GetWidth("🇨"));
Assert.Equal(2, _measurer.GetWidth("🇨🇳"));
Assert.Equal(2, _measurer.GetWidth("👨‍💻"));
Assert.Equal(2, _measurer.GetWidth("⚡️"));
}
[Fact]
public void SliceTracksTabColumnsAndMeasuredWidth()
{
var strictTabSlice = _measurer.Slice("out 192M\t.pi/skill-tests/results-ha", 0, 10, strict: true);
Assert.Equal("out 192M", strictTabSlice.Text);
Assert.Equal(8, strictTabSlice.Width);
Assert.Equal(_measurer.GetWidth(strictTabSlice.Text), strictTabSlice.Width);
var afterTabSlice = _measurer.Slice("out 192M\t.pi/skill-tests/results-ha", 13, 10, strict: true);
Assert.Equal("i/skill-te", afterTabSlice.Text);
Assert.Equal(_measurer.GetWidth(afterTabSlice.Text), afterTabSlice.Width);
}
[Fact]
public void TruncateKeepsAnsiPrefixAndBracketsEllipsis()
{
var ansiText = $"\e[31m{string.Concat(Enumerable.Repeat("hello ", 100))}\e[0m";
var truncated = _measurer.Truncate(ansiText, 20, "…");
Assert.True(_measurer.GetWidth(truncated) <= 20);
Assert.Contains("\e[31m", truncated, StringComparison.Ordinal);
Assert.EndsWith("\e[0m…\e[0m", truncated, StringComparison.Ordinal);
Assert.Equal("\e[0m🙂\e[0m", _measurer.Truncate("abcdef", 2, "🙂"));
Assert.Equal(string.Empty, _measurer.Truncate("abcdef", 1, "🙂"));
}
[Fact]
public void WrapRestoresAnsiAndOsc8AcrossLines()
{
var redWrapped = _measurer.Wrap($"\e[31mhello world this is red\e[0m", 10);
Assert.All(redWrapped.Skip(1), line => Assert.StartsWith("\e[31m", line, StringComparison.Ordinal));
Assert.All(redWrapped.Take(redWrapped.Count - 1), line => Assert.False(line.EndsWith("\e[0m", StringComparison.Ordinal)));
var hyperlink = "\e]8;;https://example.com\a0123456789\e]8;;\a";
var hyperlinkWrapped = _measurer.Wrap(hyperlink, 6);
Assert.True(hyperlinkWrapped.Count > 1);
Assert.All(hyperlinkWrapped, line => Assert.Contains("\e]8;;https://example.com\a", line, StringComparison.Ordinal));
Assert.All(hyperlinkWrapped.Take(hyperlinkWrapped.Count - 1), line => Assert.EndsWith("\e]8;;\a", line, StringComparison.Ordinal));
}
}