c435df9fcd
ci / restore build format test pack (push) Failing after 22s
- migrate remaining text and component smoke assertions into TinyTUI.Tests - remove legacy TextChecks and ComponentChecks projects from solution - update README test guidance to use the unified xUnit suite
68 lines
3.2 KiB
C#
68 lines
3.2 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 plainWrapped = _measurer.Wrap("hello world this is a test", 10);
|
|
Assert.True(plainWrapped.Count > 1);
|
|
Assert.All(plainWrapped, line => Assert.True(_measurer.GetWidth(line) <= 10));
|
|
|
|
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 underlinedUrl = _measurer.Wrap($"read this thread \e[4mhttps://example.com/very/long/path/that/will/definitely/wrap\e[24m", 40);
|
|
Assert.Equal("read this thread", underlinedUrl[0]);
|
|
Assert.StartsWith("\e[4m", underlinedUrl[1], StringComparison.Ordinal);
|
|
Assert.Contains(underlinedUrl.Take(underlinedUrl.Count - 1), line => line.EndsWith("\e[24m", 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));
|
|
}
|
|
}
|