Files
ttui/test/TinyTUI.Tests/Components/ComponentRegressionTests.cs
T
chuan c435df9fcd
ci / restore build format test pack (push) Failing after 22s
test: converge smoke checks into xunit suite
- 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
2026-06-04 10:15:57 +08:00

128 lines
5.2 KiB
C#

using TinyTUI.Autocomplete;
using TinyTUI.Components;
using TinyTUI.Input;
using TinyTUI.Rendering;
using TinyTUI.Terminal.Images;
using TinyTUI.Text;
namespace TinyTUI.Tests.Components;
public sealed class ComponentRegressionTests
{
private readonly TerminalTextMeasurer _measurer = new();
[Fact]
public void FocusableComponentsOnlyRenderCursorMarkerWhenFocused()
{
var input = new TinyTUI.Components.Input(_measurer) { Prompt = "> " };
Assert.DoesNotContain(CursorMarker.Marker, input.Render(20)[0], StringComparison.Ordinal);
input.Focused = true;
Assert.Contains(CursorMarker.Marker, input.Render(20)[0], StringComparison.Ordinal);
var editor = new Editor(_measurer) { Placeholder = "type here" };
Assert.DoesNotContain(CursorMarker.Marker, editor.Render(20)[0], StringComparison.Ordinal);
editor.Focused = true;
Assert.Contains(CursorMarker.Marker, editor.Render(20)[0], StringComparison.Ordinal);
var list = new SelectList(_measurer);
list.SetItems(["alpha", "beta"]);
Assert.DoesNotContain(CursorMarker.Marker, list.Render(20)[0], StringComparison.Ordinal);
list.Focused = true;
Assert.Contains(CursorMarker.Marker, list.Render(20)[0], StringComparison.Ordinal);
}
[Fact]
public void BasicLayoutComponentsClampAndPadRenderedLines()
{
Assert.Equal(3, new Spacer(3).Render(10).Count);
Assert.Empty(new Spacer(-1).Render(10));
var truncated = new TruncatedText("abcdef\nignored", _measurer)
{
PaddingX = 1,
PaddingY = 1,
};
var lines = truncated.Render(6);
Assert.Equal(3, lines.Count);
Assert.Equal(6, _measurer.GetWidth(lines[1]));
// TruncatedText 是单行组件 这里确认换行后的内容不会泄漏到渲染结果
Assert.Contains("abc", lines[1], StringComparison.Ordinal);
Assert.DoesNotContain("ignored", string.Concat(lines), StringComparison.Ordinal);
}
[Fact]
public void CancellableLoaderCancelsTokenAndRunsCallback()
{
using var loader = new CancellableLoader(keybindings: KeybindingRegistry.CreateDefault());
var canceled = false;
loader.OnCanceled = () => canceled = true;
loader.HandleInput(new TuiInputEvent(TuiInputEventKind.Key, KeyNames.Escape));
Assert.True(loader.IsCanceled);
Assert.True(loader.Token.IsCancellationRequested);
Assert.True(canceled);
}
[Fact]
public void SlashCommandAutocompleteCanRenderConfirmAndCancel()
{
var editor = new Editor(_measurer)
{
AutocompleteProvider = new SlashCommandAutocompleteProvider(
[
new SlashCommand("help", "show help"),
new SlashCommand("history", "show history"),
]),
};
editor.HandleInput(new TuiInputEvent(TuiInputEventKind.Text, "/h"));
Assert.True(editor.IsAutocompleteActive);
Assert.Contains(editor.RenderAutocomplete(40), line => line.Contains("help", StringComparison.Ordinal));
editor.HandleInput(new TuiInputEvent(TuiInputEventKind.Key, KeyNames.Down));
editor.HandleInput(new TuiInputEvent(TuiInputEventKind.Key, KeyNames.Tab));
Assert.Equal("/history ", editor.Value);
Assert.False(editor.IsAutocompleteActive);
editor.Value = "/h";
editor.HandleInput(new TuiInputEvent(TuiInputEventKind.Key, KeyNames.Tab));
editor.HandleInput(new TuiInputEvent(TuiInputEventKind.Key, KeyNames.Escape));
Assert.False(editor.IsAutocompleteActive);
Assert.Equal("/h", editor.Value);
}
[Fact]
public void ImageComponentRendersKittySequenceAndFallback()
{
var imageService = new TerminalImageService();
imageService.SetCapabilities(new TerminalCapabilities(ImageProtocol.Kitty, true, true));
imageService.SetCellDimensions(new CellDimensions(10, 10));
Assert.Equal(new ImageCellSize(2, 2), imageService.CalculateCellSize(new ImageDimensions(20, 20), 2));
Assert.Equal(new ImageDimensions(2, 3), imageService.TryGetDimensions(Png2x3, "image/png"));
var image = new Image([1, 2, 3, 4], "image/png", imageService: imageService, dimensions: new ImageDimensions(20, 20))
{
MaxWidthCells = 2,
};
var imageLines = image.Render(4);
Assert.Equal(2, imageLines.Count);
Assert.True(image.ImageId is > 0);
Assert.StartsWith("\e_G", imageLines[0], StringComparison.Ordinal);
Assert.Contains(",C=1,", imageLines[0], StringComparison.Ordinal);
Assert.True(TerminalImageService.IsImageLine($"prefix {imageLines[0]} suffix"));
imageService.SetCapabilities(TerminalCapabilities.Conservative);
var fallback = new Image([1, 2, 3], "image/jpeg", imageService: imageService, dimensions: new ImageDimensions(8, 9))
{
FileName = "photo.jpg",
}.Render(80)[0];
Assert.Contains("[Image: photo.jpg [image/jpeg] 8x9]", fallback, StringComparison.Ordinal);
}
private static readonly byte[] Png2x3 = Convert.FromBase64String(
"iVBORw0KGgoAAAANSUhEUgAAAAIAAAADCAIAAADZrBkAAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAFElEQVR4nGNgYGBgYGBgYGBgAAAABQABJzQnCgAAAABJRU5ErkJggg==");
}