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
128 lines
5.2 KiB
C#
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==");
|
|
}
|