diff --git a/src/Consolonia.Core/Assembly.cs b/src/Consolonia.Core/Assembly.cs index 7047cf80..9ce3d967 100644 --- a/src/Consolonia.Core/Assembly.cs +++ b/src/Consolonia.Core/Assembly.cs @@ -1,6 +1,6 @@ using System; using System.Runtime.CompilerServices; -[assembly: InternalsVisibleTo("Consolonia.TestsCore")] +[assembly: InternalsVisibleTo("Consolonia.Core.Tests")] [assembly: CLSCompliant(false)] //todo: should we make it compliant? \ No newline at end of file diff --git a/src/Consolonia.Core/Drawing/DrawingContextImpl.cs b/src/Consolonia.Core/Drawing/DrawingContextImpl.cs index 4d80f29d..dd90c44b 100644 --- a/src/Consolonia.Core/Drawing/DrawingContextImpl.cs +++ b/src/Consolonia.Core/Drawing/DrawingContextImpl.cs @@ -95,7 +95,7 @@ public void DrawBitmap(IBitmapImpl source, double opacity, Rect sourceRect, Rect Color background = GetBackgroundColorForQuadPixel(quadColors, quadPixel); var imagePixel = new Pixel( - new PixelForeground(new SimpleSymbol(quadPixel), color: foreground), + new PixelForeground(new SimpleSymbol(quadPixel), foreground), new PixelBackground(background)); CurrentClip.ExecuteWithClipping(new Point(px, py), () => @@ -349,10 +349,10 @@ private void ApplyTextDecorationLineInternal(ref Point head, IPen pen, Line line pixel => { var newPixelForeground = new PixelForeground(pixel.Foreground.Symbol, + pixel.Foreground.Color, pixel.Foreground.Weight, pixel.Foreground.Style, - textDecoration, - pixel.Foreground.Color); + textDecoration); return pixel.Blend(new Pixel(newPixelForeground, pixel.Background)); }); }); @@ -499,7 +499,7 @@ private void DrawPixelAndMoveHead(ref Point head, Line line, LineStyle? lineStyl // Each glyph maps to a pixel as a starting point. // Emoji's and Ligatures are complex strings, so they start at a point and then overlap following pixels // the x and y are adjusted accodingly. - foreach (string glyph in text.GetGlyphs()) + foreach (string glyph in text.GetGlyphs(_consoleWindow.Console.SupportsComplexEmoji)) { Point characterPoint = whereToDraw.Transform(Matrix.CreateTranslation(currentXPosition, currentYPosition)); diff --git a/src/Consolonia.Core/Drawing/PixelBufferImplementation/DrawingBoxSymbol.cs b/src/Consolonia.Core/Drawing/PixelBufferImplementation/DrawingBoxSymbol.cs index 11971898..e6dd1ab4 100644 --- a/src/Consolonia.Core/Drawing/PixelBufferImplementation/DrawingBoxSymbol.cs +++ b/src/Consolonia.Core/Drawing/PixelBufferImplementation/DrawingBoxSymbol.cs @@ -1,5 +1,6 @@ using System; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; namespace Consolonia.Core.Drawing.PixelBufferImplementation { @@ -7,34 +8,34 @@ namespace Consolonia.Core.Drawing.PixelBufferImplementation /// https://en.wikipedia.org/wiki/Box-drawing_character /// [DebuggerDisplay("DrawingBox {Text}")] - public struct DrawingBoxSymbol : ISymbol + public struct DrawingBoxSymbol : ISymbol, IEquatable { // all 0bXXXX_0000 are special values private const byte BoldSymbol = 0b0001_0000; private const byte EmptySymbol = 0b0; + private readonly byte _upRightDownLeft; public DrawingBoxSymbol(byte upRightDownLeft) { _upRightDownLeft = upRightDownLeft; + Text = GetBoxSymbol(_upRightDownLeft).ToString(); } - private byte _upRightDownLeft; - - public string Text => GetBoxSymbol().ToString(); + public string Text { get; private init; } public ushort Width { get; } = 1; /// /// https://en.wikipedia.org/wiki/Code_page_437 /// - private char GetBoxSymbol() + private static char GetBoxSymbol(byte upRightDownLeft) { //DOS linedraw characters are not ordered in any programmatic manner, and calculating a particular character shape needs to use a look-up table. from https://en.wikipedia.org/wiki/Box-drawing_character - byte leftPart = (byte)(_upRightDownLeft & 0b1111_0000); + byte leftPart = (byte)(upRightDownLeft & 0b1111_0000); bool hasLeftPart = leftPart > 0; - switch (_upRightDownLeft & 0b0000_1111) + switch (upRightDownLeft & 0b0000_1111) { case 0b0000_1000: case 0b0000_0010: @@ -56,7 +57,7 @@ private char GetBoxSymbol() default: { - return _upRightDownLeft switch + return upRightDownLeft switch { EmptySymbol => char.MinValue, BoldSymbol => 'β–ˆ', @@ -107,12 +108,13 @@ public ISymbol Blend(ref ISymbol symbolAbove) { if (symbolAbove.IsWhiteSpace()) return this; - if (symbolAbove is not DrawingBoxSymbol drawingBoxSymbol) return symbolAbove; + if (symbolAbove is not DrawingBoxSymbol drawingBoxSymbol) + return symbolAbove; + if (drawingBoxSymbol._upRightDownLeft == BoldSymbol || _upRightDownLeft == BoldSymbol) - _upRightDownLeft = BoldSymbol; - else - _upRightDownLeft |= drawingBoxSymbol._upRightDownLeft; - return this; + return new DrawingBoxSymbol(BoldSymbol); + + return new DrawingBoxSymbol((byte)(_upRightDownLeft | drawingBoxSymbol._upRightDownLeft)); } public static DrawingBoxSymbol UpRightDownLeftFromPattern(byte pattern, LineStyle lineStyle) @@ -131,5 +133,30 @@ public static DrawingBoxSymbol UpRightDownLeftFromPattern(byte pattern, LineStyl throw new ArgumentOutOfRangeException(nameof(lineStyle), lineStyle, null); } } + + public bool Equals(DrawingBoxSymbol other) + { + return _upRightDownLeft == other._upRightDownLeft; + } + + public override bool Equals([NotNullWhen(true)] object obj) + { + return obj is DrawingBoxSymbol other && Equals(other); + } + + public override int GetHashCode() + { + return _upRightDownLeft.GetHashCode(); + } + + public static bool operator ==(DrawingBoxSymbol left, DrawingBoxSymbol right) + { + return left.Equals(right); + } + + public static bool operator !=(DrawingBoxSymbol left, DrawingBoxSymbol right) + { + return !left.Equals(right); + } } } \ No newline at end of file diff --git a/src/Consolonia.Core/Drawing/PixelBufferImplementation/Pixel.cs b/src/Consolonia.Core/Drawing/PixelBufferImplementation/Pixel.cs index b0d670c3..027c5692 100644 --- a/src/Consolonia.Core/Drawing/PixelBufferImplementation/Pixel.cs +++ b/src/Consolonia.Core/Drawing/PixelBufferImplementation/Pixel.cs @@ -1,5 +1,6 @@ using System; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using Avalonia.Media; // ReSharper disable MemberCanBePrivate.Global @@ -8,7 +9,7 @@ namespace Consolonia.Core.Drawing.PixelBufferImplementation { [DebuggerDisplay("'{Foreground.Symbol.Text}' [{Foreground.Color}, {Background.Color}]")] - public readonly struct Pixel + public readonly struct Pixel : IEquatable { public PixelForeground Foreground { get; } @@ -18,44 +19,67 @@ public readonly struct Pixel public Pixel(bool isCaret) { - Foreground = new PixelForeground(new SimpleSymbol()); - Background = new PixelBackground(PixelBackgroundMode.Transparent); + Foreground = new PixelForeground(); + Background = new PixelBackground(); IsCaret = isCaret; } - public Pixel(ISymbol symbol, Color foregroundColor, FontStyle style = FontStyle.Normal, - FontWeight weight = FontWeight.Normal, TextDecorationCollection textDecorations = null) : this( - new PixelForeground(symbol, weight, style, textDecorations, foregroundColor), + /// + /// Make a pixel foreground with transparent background + /// + /// + /// + /// + /// + /// + public Pixel(ISymbol symbol, + Color foregroundColor, + FontStyle style = FontStyle.Normal, + FontWeight weight = FontWeight.Normal, + TextDecorationCollection textDecorations = null) : this( + new PixelForeground(symbol, foregroundColor, weight, style, textDecorations), new PixelBackground(PixelBackgroundMode.Transparent)) { } - public Pixel(Color backgroundColor) : this( - new PixelBackground(PixelBackgroundMode.Colored, backgroundColor)) - { - } - - public Pixel(PixelBackgroundMode mode) : this(new PixelBackground(mode)) - { - } - - public Pixel(PixelBackground background) : this(new PixelForeground(new SimpleSymbol()), - background) + /// + /// Make a pixel with only background color, but no foreground + /// + /// + public Pixel(PixelBackground background) : + this(new PixelForeground(new SimpleSymbol(), Colors.Transparent), + background) { } - public Pixel(PixelForeground foreground, PixelBackground background, bool isCaret = false) + /// + /// Make a pixel with foreground and background + /// + /// + /// + /// + public Pixel(PixelForeground foreground, + PixelBackground background, + bool isCaret = false) { Foreground = foreground; Background = background; IsCaret = isCaret; } + /// + /// Blend the pixelAbove with the this pixel. + /// + /// + /// + /// public Pixel Blend(Pixel pixelAbove) { PixelForeground newForeground; PixelBackground newBackground; + if (pixelAbove.IsCaret) return new Pixel(Foreground, Background, true); + switch (pixelAbove.Background.Mode) { case PixelBackgroundMode.Colored: @@ -63,7 +87,7 @@ public Pixel Blend(Pixel pixelAbove) Color mergedColors = MergeColors(Background.Color, pixelAbove.Background.Color); newForeground = pixelAbove.Foreground; newBackground = new PixelBackground(mergedColors); - return new Pixel(newForeground, newBackground); + return new Pixel(newForeground, newBackground, pixelAbove.IsCaret); case PixelBackgroundMode.Transparent: // if the foreground is transparent, ignore pixelAbove foreground. @@ -108,5 +132,32 @@ private static Color MergeColors(Color target, Color source) return new Color(0xFF, red, green, blue); } + + public bool Equals(Pixel other) + { + return Foreground.Equals(other.Foreground) && + Background.Equals(other.Background) && + IsCaret.Equals(other.IsCaret); + } + + public override bool Equals([NotNullWhen(true)] object obj) + { + return obj is Pixel other && Equals(other); + } + + public override int GetHashCode() + { + return HashCode.Combine(Foreground, Background, IsCaret); + } + + public static bool operator ==(Pixel left, Pixel right) + { + return left.Equals(right); + } + + public static bool operator !=(Pixel left, Pixel right) + { + return !left.Equals(right); + } } } \ No newline at end of file diff --git a/src/Consolonia.Core/Drawing/PixelBufferImplementation/PixelBackground.cs b/src/Consolonia.Core/Drawing/PixelBufferImplementation/PixelBackground.cs index a904e4cc..e24319a3 100644 --- a/src/Consolonia.Core/Drawing/PixelBufferImplementation/PixelBackground.cs +++ b/src/Consolonia.Core/Drawing/PixelBufferImplementation/PixelBackground.cs @@ -1,12 +1,19 @@ using System; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using Avalonia.Media; namespace Consolonia.Core.Drawing.PixelBufferImplementation { [DebuggerDisplay("[{Color}, {Mode}]")] - public readonly struct PixelBackground + public readonly struct PixelBackground : IEquatable { + public PixelBackground() + { + Mode = PixelBackgroundMode.Transparent; + Color = Colors.Transparent; + } + public PixelBackground(Color color) { Mode = color.A == 0 ? PixelBackgroundMode.Transparent : PixelBackgroundMode.Colored; @@ -15,7 +22,7 @@ public PixelBackground(Color color) public PixelBackground(PixelBackgroundMode mode, Color? color = null) { - Color = color ?? Colors.Black; + Color = color ?? Colors.Transparent; Mode = mode; } @@ -44,5 +51,30 @@ public PixelBackground Shade() return new PixelBackground(newMode, newColor); } + + public bool Equals(PixelBackground other) + { + return Color.Equals(other.Color) && Mode == other.Mode; + } + + public override bool Equals([NotNullWhen(true)] object obj) + { + return obj is PixelBackground other && Equals(other); + } + + public override int GetHashCode() + { + return HashCode.Combine(Color, Mode); + } + + public static bool operator ==(PixelBackground left, PixelBackground right) + { + return left.Equals(right); + } + + public static bool operator !=(PixelBackground left, PixelBackground right) + { + return !left.Equals(right); + } } } \ No newline at end of file diff --git a/src/Consolonia.Core/Drawing/PixelBufferImplementation/PixelBufferCoordinate.cs b/src/Consolonia.Core/Drawing/PixelBufferImplementation/PixelBufferCoordinate.cs index 24da206e..2bd57735 100644 --- a/src/Consolonia.Core/Drawing/PixelBufferImplementation/PixelBufferCoordinate.cs +++ b/src/Consolonia.Core/Drawing/PixelBufferImplementation/PixelBufferCoordinate.cs @@ -1,3 +1,4 @@ +using System; using Avalonia; // ReSharper disable UnusedMember.Global @@ -53,5 +54,10 @@ public bool Equals(PixelBufferCoordinate secondPoint) { return X == secondPoint.X && Y == secondPoint.Y; } + + public override int GetHashCode() + { + return HashCode.Combine(X, Y); + } } } \ No newline at end of file diff --git a/src/Consolonia.Core/Drawing/PixelBufferImplementation/PixelForeground.cs b/src/Consolonia.Core/Drawing/PixelBufferImplementation/PixelForeground.cs index 35ff9d39..0780757f 100644 --- a/src/Consolonia.Core/Drawing/PixelBufferImplementation/PixelForeground.cs +++ b/src/Consolonia.Core/Drawing/PixelBufferImplementation/PixelForeground.cs @@ -1,18 +1,29 @@ using System; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using Avalonia.Media; namespace Consolonia.Core.Drawing.PixelBufferImplementation { [DebuggerDisplay("'{Symbol.Text}' [{Color}]")] - public readonly struct PixelForeground + public readonly struct PixelForeground : IEquatable { - public PixelForeground(ISymbol symbol, FontWeight weight = FontWeight.Normal, - FontStyle style = FontStyle.Normal, TextDecorationCollection textDecorations = null, Color? color = null) + public PixelForeground() + { + Symbol = new SimpleSymbol(); + Color = Colors.Transparent; + Weight = FontWeight.Normal; + Style = FontStyle.Normal; + TextDecorations = null; + } + + public PixelForeground(ISymbol symbol, Color color, + FontWeight weight = FontWeight.Normal, FontStyle style = FontStyle.Normal, + TextDecorationCollection textDecorations = null) { ArgumentNullException.ThrowIfNull(symbol); Symbol = symbol; - Color = color ?? Colors.White; + Color = color; Weight = weight; Style = style; TextDecorations = textDecorations; @@ -31,7 +42,7 @@ public PixelForeground(ISymbol symbol, FontWeight weight = FontWeight.Normal, public PixelForeground Shade() { Color newColor = Color.Shade(); - return new PixelForeground(Symbol, Weight, Style, TextDecorations, newColor); + return new PixelForeground(Symbol, newColor, Weight, Style, TextDecorations); } public PixelForeground Blend(PixelForeground pixelAboveForeground) @@ -42,8 +53,37 @@ public PixelForeground Blend(PixelForeground pixelAboveForeground) ISymbol newSymbol = Symbol.Blend(ref symbolAbove); - return new PixelForeground(newSymbol, pixelAboveForeground.Weight, pixelAboveForeground.Style, - pixelAboveForeground.TextDecorations, pixelAboveForeground.Color); + return new PixelForeground(newSymbol, pixelAboveForeground.Color, pixelAboveForeground.Weight, + pixelAboveForeground.Style, pixelAboveForeground.TextDecorations); + } + + public bool Equals(PixelForeground other) + { + return Symbol.Equals(other.Symbol) && + Color.Equals(other.Color) && + Weight == other.Weight && + Style == other.Style && + Equals(TextDecorations, other.TextDecorations); + } + + public override bool Equals([NotNullWhen(true)] object obj) + { + return obj is PixelForeground other && Equals(other); + } + + public override int GetHashCode() + { + return HashCode.Combine(Symbol, Color, (int)Weight, (int)Style, TextDecorations); + } + + public static bool operator ==(PixelForeground left, PixelForeground right) + { + return left.Equals(right); + } + + public static bool operator !=(PixelForeground left, PixelForeground right) + { + return !left.Equals(right); } } } \ No newline at end of file diff --git a/src/Consolonia.Core/Drawing/PixelBufferImplementation/SimpleSymbol.cs b/src/Consolonia.Core/Drawing/PixelBufferImplementation/SimpleSymbol.cs index 997e6934..bb9da67b 100644 --- a/src/Consolonia.Core/Drawing/PixelBufferImplementation/SimpleSymbol.cs +++ b/src/Consolonia.Core/Drawing/PixelBufferImplementation/SimpleSymbol.cs @@ -1,11 +1,13 @@ +using System; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Text; using Consolonia.Core.Helpers; namespace Consolonia.Core.Drawing.PixelBufferImplementation { [DebuggerDisplay("'{Text}'")] - public readonly struct SimpleSymbol : ISymbol + public readonly struct SimpleSymbol : ISymbol, IEquatable { public SimpleSymbol() { @@ -37,12 +39,37 @@ public SimpleSymbol(Rune rune) public bool IsWhiteSpace() { - return string.IsNullOrWhiteSpace(Text); + return string.IsNullOrEmpty(Text); } public ISymbol Blend(ref ISymbol symbolAbove) { - return !string.IsNullOrEmpty(symbolAbove.Text) ? symbolAbove : this; + return symbolAbove.IsWhiteSpace() ? this : symbolAbove; + } + + public bool Equals(SimpleSymbol other) + { + return Text.Equals(other.Text, StringComparison.Ordinal); + } + + public override bool Equals([NotNullWhen(true)] object obj) + { + return obj is SimpleSymbol other && Equals(other); + } + + public override int GetHashCode() + { + return Text.GetHashCode(StringComparison.Ordinal); + } + + public static bool operator ==(SimpleSymbol left, SimpleSymbol right) + { + return left.Equals(right); + } + + public static bool operator !=(SimpleSymbol left, SimpleSymbol right) + { + return !left.Equals(right); } } } \ No newline at end of file diff --git a/src/Consolonia.Core/Drawing/RenderTarget.cs b/src/Consolonia.Core/Drawing/RenderTarget.cs index cc5d9ed2..680eab71 100644 --- a/src/Consolonia.Core/Drawing/RenderTarget.cs +++ b/src/Consolonia.Core/Drawing/RenderTarget.cs @@ -20,8 +20,8 @@ internal class RenderTarget : IDrawingContextLayerImpl private PixelBuffer _bufferBuffer; - private (Color background, Color foreground, FontWeight weight, FontStyle style, TextDecorationCollection - textDecorations, string text)?[,] _cache; + // cache of pixels written so we can ignore them if unchanged. + private Pixel?[,] _cache; internal RenderTarget(ConsoleWindow consoleWindow) { @@ -96,9 +96,7 @@ private void InitializeBuffer(Size size) private void InitializeCache(ushort width, ushort height) { - _cache = - new (Color background, Color foreground, FontWeight weight, FontStyle style, TextDecorationCollection - textDecorations, string text)?[width, height]; + _cache = new Pixel?[width, height]; } private void RenderToDevice() @@ -130,20 +128,14 @@ private void RenderToDevice() "All pixels in the buffer must have exact console color before rendering"); - (Color background, Color foreground, FontWeight weight, FontStyle style, TextDecorationCollection - textDecorations, string text) - pixelSpread = (pixel.Background.Color, pixel.Foreground.Color, pixel.Foreground.Weight, - pixel.Foreground.Style, pixel.Foreground.TextDecorations, - pixel.Foreground.Symbol.Text); - //todo: indexOutOfRange during resize - if (_cache[x, y] == pixelSpread) + if (_cache[x, y] == pixel) { x++; continue; } - _cache[x, y] = pixelSpread; + _cache[x, y] = pixel; flushingBuffer.WritePixel(new PixelBufferCoordinate(x, y), pixel); diff --git a/src/Consolonia.Core/Helpers/Extensions.cs b/src/Consolonia.Core/Helpers/Extensions.cs index 615bed6c..0c17f106 100644 --- a/src/Consolonia.Core/Helpers/Extensions.cs +++ b/src/Consolonia.Core/Helpers/Extensions.cs @@ -34,19 +34,18 @@ public static void Print(this IConsole console, PixelBufferCoordinate point, Pix /// Process text into collection of glyphs where a glyph is either text or a combination of chars which make up an /// emoji. /// - /// + /// text to get glyphs from + /// If true, emojis like πŸ‘¨β€πŸ‘©β€πŸ‘§β€πŸ‘¦ will be treated as a single glyph> /// - public static IReadOnlyList GetGlyphs(this string text) + public static IReadOnlyList GetGlyphs(this string text, bool supportsComplexEmoji) { - var console = AvaloniaLocator.Current.GetService(); - var glyphs = new List(); var emoji = new StringBuilder(); StringRuneEnumerator runes = text.EnumerateRunes(); var lastRune = new Rune(); while (runes.MoveNext()) - if (console.SupportsComplexEmoji) + if (supportsComplexEmoji) { if (lastRune.Value == Codepoints.ZWJ || lastRune.Value == Codepoints.ORC || @@ -95,13 +94,13 @@ public static IReadOnlyList GetGlyphs(this string text) public static ushort MeasureText(this string text) { var console = AvaloniaLocator.Current.GetService(); - + bool supportsComplexEmoji = console != null ? console.SupportsComplexEmoji : false; ushort width = 0; ushort lastWidth = 0; foreach (Rune rune in text.EnumerateRunes()) { ushort runeWidth = (ushort)UnicodeCalculator.GetWidth(rune); - if (console.SupportsComplexEmoji && + if (supportsComplexEmoji && (rune.Value == Emoji.ZeroWidthJoiner || rune.Value == Emoji.ObjectReplacementCharacter)) width -= lastWidth; else diff --git a/src/Consolonia.Core/Text/GlyphTypeface.cs b/src/Consolonia.Core/Text/GlyphTypeface.cs index 3d4c2d49..9f5bee0b 100644 --- a/src/Consolonia.Core/Text/GlyphTypeface.cs +++ b/src/Consolonia.Core/Text/GlyphTypeface.cs @@ -1,5 +1,4 @@ using System; -using System.Linq; using Avalonia.Media; using Consolonia.Core.Drawing; @@ -41,7 +40,9 @@ public bool TryGetGlyph(uint codepoint, out ushort glyph) public ushort[] GetGlyphs(ReadOnlySpan codepoints) { - return Enumerable.Repeat(Glyph, codepoints.Length).ToArray(); + ushort[] glyphs = new ushort[codepoints.Length]; + Array.Fill(glyphs, Glyph); + return glyphs; } public int GetGlyphAdvance(ushort glyph) @@ -51,7 +52,9 @@ public int GetGlyphAdvance(ushort glyph) public int[] GetGlyphAdvances(ReadOnlySpan glyphs) { - return Enumerable.Repeat(1, glyphs.Length).ToArray(); + int[] advances = new int[glyphs.Length]; + Array.Fill(advances, 1); + return advances; } public bool TryGetTable(uint tag, out byte[] table) diff --git a/src/Consolonia.Core/Text/TextShaper.cs b/src/Consolonia.Core/Text/TextShaper.cs index 188f73c9..be7c04a2 100644 --- a/src/Consolonia.Core/Text/TextShaper.cs +++ b/src/Consolonia.Core/Text/TextShaper.cs @@ -1,7 +1,9 @@ using System; +using Avalonia; using Avalonia.Media.TextFormatting; using Avalonia.Platform; using Consolonia.Core.Helpers; +using Consolonia.Core.Infrastructure; namespace Consolonia.Core.Text { @@ -9,7 +11,9 @@ public class TextShaper : ITextShaperImpl { public ShapedBuffer ShapeText(ReadOnlyMemory text, TextShaperOptions options) { - var glyphs = text.Span.ToString().GetGlyphs(); + var console = AvaloniaLocator.Current.GetRequiredService(); + + var glyphs = text.Span.ToString().GetGlyphs(console.SupportsComplexEmoji); var shapedBuffer = new ShapedBuffer(text, glyphs.Count, options.Typeface, 1, 0 /*todo: must be 1 for right to left?*/); diff --git a/src/Consolonia.Gallery/Assembly.cs b/src/Consolonia.Gallery/Assembly.cs index c8ea583b..edaf0372 100644 --- a/src/Consolonia.Gallery/Assembly.cs +++ b/src/Consolonia.Gallery/Assembly.cs @@ -1,3 +1,3 @@ using System.Runtime.CompilerServices; -[assembly: InternalsVisibleTo("Consolonia.GalleryTests")] \ No newline at end of file +[assembly: InternalsVisibleTo("Consolonia.Gallery.Tests")] \ No newline at end of file diff --git a/src/Consolonia.GuiCS/Assembly.cs b/src/Consolonia.GuiCS/Assembly.cs index 0eee0203..3b1e50ed 100644 --- a/src/Consolonia.GuiCS/Assembly.cs +++ b/src/Consolonia.GuiCS/Assembly.cs @@ -1,7 +1,7 @@ using System; using System.Runtime.CompilerServices; -[assembly: InternalsVisibleTo("Consolonia.TestsCore")] +[assembly: InternalsVisibleTo("Consolonia.Core.Tests")] [assembly: InternalsVisibleTo("Consolonia.PlatformSupport")] [assembly: CLSCompliant(false)] //todo: should we make it compliant? \ No newline at end of file diff --git a/src/Consolonia.GuiCS/Size.cs b/src/Consolonia.GuiCS/Size.cs index 1f7e7412..9d3d1d0a 100644 --- a/src/Consolonia.GuiCS/Size.cs +++ b/src/Consolonia.GuiCS/Size.cs @@ -206,7 +206,7 @@ public override bool Equals (object obj) public override int GetHashCode () { - return width^height; + return HashCode.Combine(width, height); } /// diff --git a/src/Tests/Consolonia.TestsCore/Assembly.cs b/src/Consolonia.NUnit/Assembly.cs similarity index 100% rename from src/Tests/Consolonia.TestsCore/Assembly.cs rename to src/Consolonia.NUnit/Assembly.cs diff --git a/src/Consolonia.NUnit/Consolonia.NUnit.csproj b/src/Consolonia.NUnit/Consolonia.NUnit.csproj new file mode 100644 index 00000000..dae1791f --- /dev/null +++ b/src/Consolonia.NUnit/Consolonia.NUnit.csproj @@ -0,0 +1,16 @@ + + + + + + true + + + + + + + + + + diff --git a/src/Tests/Consolonia.TestsCore/ConsoloniaAppTestBase.cs b/src/Consolonia.NUnit/ConsoloniaAppTestBase.cs similarity index 99% rename from src/Tests/Consolonia.TestsCore/ConsoloniaAppTestBase.cs rename to src/Consolonia.NUnit/ConsoloniaAppTestBase.cs index 2aadc3a2..9bb49037 100644 --- a/src/Tests/Consolonia.TestsCore/ConsoloniaAppTestBase.cs +++ b/src/Consolonia.NUnit/ConsoloniaAppTestBase.cs @@ -10,7 +10,7 @@ using Consolonia.Core.Drawing.PixelBufferImplementation; using NUnit.Framework; -namespace Consolonia.TestsCore +namespace Consolonia.NUnit { [NonParallelizable /*todo: switch to semaphore like https://stackoverflow.com/a/6427425/2362847 to allow other tests to execute in parallel*/] #pragma warning disable CA1001 // we are relying on TearDown by NUnit diff --git a/src/Tests/Consolonia.TestsCore/TestHelpers.cs b/src/Consolonia.NUnit/TestHelpers.cs similarity index 98% rename from src/Tests/Consolonia.TestsCore/TestHelpers.cs rename to src/Consolonia.NUnit/TestHelpers.cs index 7f480af6..590cd9b1 100644 --- a/src/Tests/Consolonia.TestsCore/TestHelpers.cs +++ b/src/Consolonia.NUnit/TestHelpers.cs @@ -3,7 +3,7 @@ using Avalonia.Threading; using NUnit.Framework; -namespace Consolonia.TestsCore +namespace Consolonia.NUnit { public static class TestHelpers { diff --git a/src/Tests/Consolonia.TestsCore/UnitTestConsole.cs b/src/Consolonia.NUnit/UnitTestConsole.cs similarity index 98% rename from src/Tests/Consolonia.TestsCore/UnitTestConsole.cs rename to src/Consolonia.NUnit/UnitTestConsole.cs index 0bb8d668..a74040ac 100644 --- a/src/Tests/Consolonia.TestsCore/UnitTestConsole.cs +++ b/src/Consolonia.NUnit/UnitTestConsole.cs @@ -13,7 +13,7 @@ using Consolonia.Core.Drawing.PixelBufferImplementation; using Consolonia.Core.Infrastructure; -namespace Consolonia.TestsCore +namespace Consolonia.NUnit { public sealed class UnitTestConsole : IConsole { @@ -66,7 +66,7 @@ void IConsole.Print(PixelBufferCoordinate bufferPoint, Color background, Color f PixelBuffer.Set(new PixelBufferCoordinate((ushort)(x + i), y), _ => // ReSharper disable once AccessToModifiedClosure we are sure about inline execution new Pixel( - new PixelForeground(new SimpleSymbol(rune), color: foreground, style: style, weight: weight, + new PixelForeground(new SimpleSymbol(rune), foreground, style: style, weight: weight, textDecorations: textDecorations), new PixelBackground(PixelBackgroundMode.Colored, background))); i++; diff --git a/src/Consolonia.PlatformSupport/Assembly.cs b/src/Consolonia.PlatformSupport/Assembly.cs index 7047cf80..9ce3d967 100644 --- a/src/Consolonia.PlatformSupport/Assembly.cs +++ b/src/Consolonia.PlatformSupport/Assembly.cs @@ -1,6 +1,6 @@ using System; using System.Runtime.CompilerServices; -[assembly: InternalsVisibleTo("Consolonia.TestsCore")] +[assembly: InternalsVisibleTo("Consolonia.Core.Tests")] [assembly: CLSCompliant(false)] //todo: should we make it compliant? \ No newline at end of file diff --git a/src/Consolonia.sln b/src/Consolonia.sln index 2880923f..d81b05ac 100644 --- a/src/Consolonia.sln +++ b/src/Consolonia.sln @@ -1,18 +1,21 @@ ο»Ώ Microsoft Visual Studio Solution File, Format Version 12.00 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Example", "Example\Example.csproj", "{E8624A2C-33B8-4D19-A0BA-1CC39FC422F7}" +# Visual Studio Version 17 +VisualStudioVersion = 17.11.35327.3 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Example", "Example\Example.csproj", "{E8624A2C-33B8-4D19-A0BA-1CC39FC422F7}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Consolonia.Core", "Consolonia.Core\Consolonia.Core.csproj", "{9ED11926-949D-4D5A-8EA7-41CAB1229C47}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Consolonia.Core", "Consolonia.Core\Consolonia.Core.csproj", "{9ED11926-949D-4D5A-8EA7-41CAB1229C47}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{18168988-BF89-4EE5-8F64-1FAFB68462A2}" -ProjectSection(SolutionItems) = preProject - readme.md = readme.md - .editorconfig = .editorconfig -EndProjectSection + ProjectSection(SolutionItems) = preProject + .editorconfig = .editorconfig + readme.md = readme.md + EndProjectSection EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Consolonia.Gallery", "Consolonia.Gallery\Consolonia.Gallery.csproj", "{70643248-718D-46F8-8775-E1674787B195}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Consolonia.Gallery", "Consolonia.Gallery\Consolonia.Gallery.csproj", "{70643248-718D-46F8-8775-E1674787B195}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Consolonia.Themes.TurboVision", "Consolonia.Themes.TurboVision\Consolonia.Themes.TurboVision.csproj", "{850A3EF5-2E1F-4876-B3DE-D5C99FDFC135}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Consolonia.Themes.TurboVision", "Consolonia.Themes.TurboVision\Consolonia.Themes.TurboVision.csproj", "{850A3EF5-2E1F-4876-B3DE-D5C99FDFC135}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{476E1582-855A-4BEB-BA7D-55302428EE62}" ProjectSection(SolutionItems) = preProject @@ -23,30 +26,32 @@ EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "RepoRoot", "RepoRoot", "{09FEC8F0-8390-4E31-9C89-9174697FF341}" ProjectSection(SolutionItems) = preProject ..\.gitignore = ..\.gitignore - ..\LICENSE = ..\LICENSE - ..\README.md = ..\README.md + ..\contributing.md = ..\contributing.md ..\Directory.Build.props = ..\Directory.Build.props ..\Directory.Core.Build.props = ..\Directory.Core.Build.props - ..\contributing.md = ..\contributing.md + ..\LICENSE = ..\LICENSE + ..\README.md = ..\README.md EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".github", ".github", "{A8CC5246-0D48-4418-B3E8-AC82ADB269E9}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "workflows", "workflows", "{7B64DD09-94E2-47DE-8490-189B9B406A5A}" ProjectSection(SolutionItems) = preProject - ..\.github\workflows\general_build.yml = ..\.github\workflows\general_build.yml ..\.github\workflows\editorconfig.yml = ..\.github\workflows\editorconfig.yml + ..\.github\workflows\general_build.yml = ..\.github\workflows\general_build.yml EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{F756B909-46C5-43FF-8322-86EC36B51841}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Consolonia.TestsCore", "Tests\Consolonia.TestsCore\Consolonia.TestsCore.csproj", "{4C915339-CE21-4E48-A97E-7F3A02AEF1FA}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Consolonia.Gallery.Tests", "Tests\Consolonia.Gallery.Tests\Consolonia.Gallery.Tests.csproj", "{1AE0207B-BF59-4473-97E1-79FEB7FA1AD5}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Consolonia.PlatformSupport", "Consolonia.PlatformSupport\Consolonia.PlatformSupport.csproj", "{175F6648-971A-4840-B2C1-0B745CF688EB}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Consolonia.GalleryTests", "Tests\Consolonia.GalleryTests\Consolonia.GalleryTests.csproj", "{1AE0207B-BF59-4473-97E1-79FEB7FA1AD5}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Consolonia.GuiCS", "Consolonia.GuiCS\Consolonia.GuiCS.csproj", "{66A9B063-A27E-4B8B-974A-C02CD838C274}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Consolonia.PlatformSupport", "Consolonia.PlatformSupport\Consolonia.PlatformSupport.csproj", "{175F6648-971A-4840-B2C1-0B745CF688EB}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Consolonia.NUnit", "Consolonia.NUnit\Consolonia.NUnit.csproj", "{76A98F78-6513-4203-AFCC-041F92579189}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Consolonia.GuiCS", "Consolonia.GuiCS\Consolonia.GuiCS.csproj", "{66A9B063-A27E-4B8B-974A-C02CD838C274}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Consolonia.Core.Tests", "Tests\Consolonia.Core.Tests\Consolonia.Core.Tests.csproj", "{58D95751-209B-4AF4-BC76-A8E52D5CEF5E}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -70,10 +75,6 @@ Global {850A3EF5-2E1F-4876-B3DE-D5C99FDFC135}.Debug|Any CPU.Build.0 = Debug|Any CPU {850A3EF5-2E1F-4876-B3DE-D5C99FDFC135}.Release|Any CPU.ActiveCfg = Release|Any CPU {850A3EF5-2E1F-4876-B3DE-D5C99FDFC135}.Release|Any CPU.Build.0 = Release|Any CPU - {4C915339-CE21-4E48-A97E-7F3A02AEF1FA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4C915339-CE21-4E48-A97E-7F3A02AEF1FA}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4C915339-CE21-4E48-A97E-7F3A02AEF1FA}.Release|Any CPU.ActiveCfg = Release|Any CPU - {4C915339-CE21-4E48-A97E-7F3A02AEF1FA}.Release|Any CPU.Build.0 = Release|Any CPU {1AE0207B-BF59-4473-97E1-79FEB7FA1AD5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {1AE0207B-BF59-4473-97E1-79FEB7FA1AD5}.Debug|Any CPU.Build.0 = Debug|Any CPU {1AE0207B-BF59-4473-97E1-79FEB7FA1AD5}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -86,13 +87,25 @@ Global {66A9B063-A27E-4B8B-974A-C02CD838C274}.Debug|Any CPU.Build.0 = Debug|Any CPU {66A9B063-A27E-4B8B-974A-C02CD838C274}.Release|Any CPU.ActiveCfg = Release|Any CPU {66A9B063-A27E-4B8B-974A-C02CD838C274}.Release|Any CPU.Build.0 = Release|Any CPU + {76A98F78-6513-4203-AFCC-041F92579189}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {76A98F78-6513-4203-AFCC-041F92579189}.Debug|Any CPU.Build.0 = Debug|Any CPU + {76A98F78-6513-4203-AFCC-041F92579189}.Release|Any CPU.ActiveCfg = Release|Any CPU + {76A98F78-6513-4203-AFCC-041F92579189}.Release|Any CPU.Build.0 = Release|Any CPU + {58D95751-209B-4AF4-BC76-A8E52D5CEF5E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {58D95751-209B-4AF4-BC76-A8E52D5CEF5E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {58D95751-209B-4AF4-BC76-A8E52D5CEF5E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {58D95751-209B-4AF4-BC76-A8E52D5CEF5E}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {4C915339-CE21-4E48-A97E-7F3A02AEF1FA} = {F756B909-46C5-43FF-8322-86EC36B51841} - {1AE0207B-BF59-4473-97E1-79FEB7FA1AD5} = {F756B909-46C5-43FF-8322-86EC36B51841} + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution {A8CC5246-0D48-4418-B3E8-AC82ADB269E9} = {09FEC8F0-8390-4E31-9C89-9174697FF341} {7B64DD09-94E2-47DE-8490-189B9B406A5A} = {A8CC5246-0D48-4418-B3E8-AC82ADB269E9} + {1AE0207B-BF59-4473-97E1-79FEB7FA1AD5} = {F756B909-46C5-43FF-8322-86EC36B51841} + {58D95751-209B-4AF4-BC76-A8E52D5CEF5E} = {F756B909-46C5-43FF-8322-86EC36B51841} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {47D28717-CF68-421D-B547-585C16AE6DE7} EndGlobalSection EndGlobal diff --git a/src/Tests/Consolonia.Core.Tests/Assembly.cs b/src/Tests/Consolonia.Core.Tests/Assembly.cs new file mode 100644 index 00000000..5d141236 --- /dev/null +++ b/src/Tests/Consolonia.Core.Tests/Assembly.cs @@ -0,0 +1,22 @@ +using System; +using Avalonia; +using Consolonia.Core.Drawing.PixelBufferImplementation; +using Consolonia.Core.Infrastructure; +using Consolonia.NUnit; +using NUnit.Framework; + +[assembly: CLSCompliant(false)] //todo: should we make it compliant? + +namespace Consolonia.Core.Tests +{ + [SetUpFixture] + public class AllTests + { + [OneTimeSetUp] + public void OneTimeSetUp() + { + AvaloniaLocator.Current = new AvaloniaLocator() + .Bind().ToConstant(new UnitTestConsole(new PixelBufferSize(100, 100))); + } + } +} \ No newline at end of file diff --git a/src/Tests/Consolonia.TestsCore/PixelTests.cs b/src/Tests/Consolonia.Core.Tests/ColorTests.cs similarity index 93% rename from src/Tests/Consolonia.TestsCore/PixelTests.cs rename to src/Tests/Consolonia.Core.Tests/ColorTests.cs index 5ffc2681..b71be7e2 100644 --- a/src/Tests/Consolonia.TestsCore/PixelTests.cs +++ b/src/Tests/Consolonia.Core.Tests/ColorTests.cs @@ -2,13 +2,13 @@ using Consolonia.Core.Drawing.PixelBufferImplementation; using NUnit.Framework; -namespace Consolonia.TestsCore +namespace Consolonia.Core.Tests { [TestFixture] - public class PixelTests + public class ColorTests { [Test] - public void TestShade() + public void Shade() { Color foreground = Colors.Gray; Color newColor = foreground.Shade(); @@ -18,7 +18,7 @@ public void TestShade() } [Test] - public void TestBrighten() + public void Brighten() { Color foreground = Colors.Gray; Color newColor = foreground.Brighten(); @@ -28,7 +28,7 @@ public void TestBrighten() } [Test] - public void TestRelativeShade() + public void RelativeShade() { Color foreground = Colors.LightGray; Color background = Colors.DarkGray; @@ -46,7 +46,7 @@ public void TestRelativeShade() } [Test] - public void TestRelativeBrighten() + public void RelativeBrighten() { Color foreground = Colors.LightGray; Color background = Colors.DarkGray; @@ -64,7 +64,7 @@ public void TestRelativeBrighten() } [Test] - public void TestShadeBoundaries() + public void ShadeBoundaries() { Color foreground = Colors.White; Color background = Colors.Black; @@ -98,7 +98,7 @@ public void TestShadeBoundaries() } [Test] - public void TestBrightenBoundaries() + public void BrightenBoundaries() { Color foreground = Colors.Black; Color background = Colors.Black; diff --git a/src/Tests/Consolonia.TestsCore/Consolonia.TestsCore.csproj b/src/Tests/Consolonia.Core.Tests/Consolonia.Core.Tests.csproj similarity index 60% rename from src/Tests/Consolonia.TestsCore/Consolonia.TestsCore.csproj rename to src/Tests/Consolonia.Core.Tests/Consolonia.Core.Tests.csproj index 2f3ae527..a237a748 100644 --- a/src/Tests/Consolonia.TestsCore/Consolonia.TestsCore.csproj +++ b/src/Tests/Consolonia.Core.Tests/Consolonia.Core.Tests.csproj @@ -10,9 +10,13 @@ + - + + + + diff --git a/src/Tests/Consolonia.Core.Tests/DrawingBoxSymbolTests.cs b/src/Tests/Consolonia.Core.Tests/DrawingBoxSymbolTests.cs new file mode 100644 index 00000000..9e4b5dcc --- /dev/null +++ b/src/Tests/Consolonia.Core.Tests/DrawingBoxSymbolTests.cs @@ -0,0 +1,116 @@ +using System.Collections.Generic; +using System.Diagnostics; +using Consolonia.Core.Drawing.PixelBufferImplementation; +using NUnit.Framework; + +namespace Consolonia.Core.Tests +{ + [TestFixture] + public class DrawingBoxSymbolTests + { + [Test] + public void Constructor() + { + ISymbol symbol = new DrawingBoxSymbol(0b0000_1111); + Assert.That(symbol.Text, Is.EqualTo("β”Ό")); + } + + [Test] + public void Blend() + { + ISymbol symbol = new DrawingBoxSymbol(0b0000_0101); + Assert.That(symbol.Text, Is.EqualTo("─")); + ISymbol symbolAbove = new DrawingBoxSymbol(0b0000_1010); + Assert.That(symbolAbove.Text, Is.EqualTo("β”‚")); + ISymbol newSymbol = symbol.Blend(ref symbolAbove); + Assert.That(newSymbol.Text, Is.EqualTo("β”Ό")); + } + + [Test] + public void BlendAllSymbols() + { + var symbols = new (byte, string)[] + { + (0b0000_0000, " "), + (0b0000_0001, "β•΅"), + (0b0000_0010, "β•Ά"), + (0b0000_0011, "β””"), + (0b0000_0100, "β•·"), + (0b0000_0101, "β”‚"), + (0b0000_0110, "β”Œ"), + (0b0000_0111, "β”œ"), + (0b0000_1000, "β•΄"), + (0b0000_1001, "β”˜"), + (0b0000_1010, "─"), + (0b0000_1011, "β”΄"), + (0b0000_1100, "┐"), + (0b0000_1101, "─"), + (0b0000_1110, "┬"), + (0b0000_1111, "β”Ό") + }; + + foreach ((byte code1, string _) in symbols) + foreach ((byte code2, string _) in symbols) + { + ISymbol symbol1 = new DrawingBoxSymbol(code1); + ISymbol symbol2 = new DrawingBoxSymbol(code2); + ISymbol blendedSymbol = symbol1.Blend(ref symbol2); + if (symbol1.Text != symbol2.Text) + Debug.WriteLine($"{symbol1.Text} + {symbol2.Text} => {blendedSymbol.Text}"); + Assert.That(blendedSymbol.Text, Is.Not.Null); + } + } + + [Test] + public void Equality() + { + var symbol = new DrawingBoxSymbol(0b0000_1111); + var symbol2 = new DrawingBoxSymbol(0b0000_1111); + Assert.That(symbol.Equals((object)symbol2)); + Assert.That(symbol.Equals(symbol2)); + Assert.That(symbol == symbol2); + } + + [Test] + public void EqualityISymbol() + { + ISymbol symbol = new DrawingBoxSymbol(0b0000_1111); + ISymbol symbol2 = new DrawingBoxSymbol(0b0000_1111); + Assert.That(symbol.Equals(symbol2)); + Assert.That(symbol.Equals(symbol2)); + } + + [Test] + public void Inequality() + { + var symbol = new DrawingBoxSymbol(0b0000_1111); + var symbol2 = new DrawingBoxSymbol(0b0000_0000); + Assert.That(!symbol.Equals((object)symbol2)); + Assert.That(!symbol.Equals(symbol2)); + Assert.That(symbol != symbol2); + } + + [Test] + public void InequalityISymbol() + { + ISymbol symbol = new DrawingBoxSymbol(0b0000_1111); + ISymbol symbol2 = new DrawingBoxSymbol(0b0000_0000); + Assert.That(!symbol.Equals(symbol2)); + Assert.That(!symbol.Equals(symbol2)); + } + + [Test] + public void Hash() + { + var set = new HashSet(); + set.Add(new DrawingBoxSymbol(0b0000_1111)); + set.Add(new DrawingBoxSymbol(0b0000_1111)); + Assert.That(set.Count, Is.EqualTo(1)); + + var set2 = new HashSet(); + set2.Add(new DrawingBoxSymbol(0b0000_1111)); + set2.Add(new DrawingBoxSymbol(0b0000_1111)); + Assert.That(set2.Count, Is.EqualTo(1)); + } + } +} \ No newline at end of file diff --git a/src/Tests/Consolonia.Core.Tests/GlyphTests.cs b/src/Tests/Consolonia.Core.Tests/GlyphTests.cs new file mode 100644 index 00000000..551bfb8e --- /dev/null +++ b/src/Tests/Consolonia.Core.Tests/GlyphTests.cs @@ -0,0 +1,106 @@ +using Consolonia.Core.Helpers; +using NUnit.Framework; + +namespace Consolonia.Core.Tests +{ + [TestFixture] + public class GlyphTests + { + [Test] + public void GetGlyphsEmptyStringReturnsEmptyList() + { + string text = string.Empty; + var glyphs = text.GetGlyphs(true); + Assert.IsEmpty(glyphs); + } + + [Test] + public void GetGlyphsSingleCharacterReturnsSingleGlyph() + { + string text = "a"; + Assert.AreEqual(1, text.MeasureText()); + + var glyphs = text.GetGlyphs(true); + Assert.AreEqual(1, glyphs.Count); + Assert.AreEqual("a", glyphs[0]); + } + + [Test] + public void GetGlyphsMultipleCharsReturnsMultipleGlyph() + { + string text = "hello"; + Assert.AreEqual(5, text.MeasureText()); + + var glyphs = text.GetGlyphs(true); + Assert.AreEqual(5, glyphs.Count); + Assert.AreEqual("h", glyphs[0]); + Assert.AreEqual("e", glyphs[1]); + Assert.AreEqual("l", glyphs[2]); + Assert.AreEqual("l", glyphs[3]); + Assert.AreEqual("o", glyphs[4]); + } + + [Test] + public void GetGlyphsComplexCharsReturnsSingleGlyph() + { + string text = "π”‰π”žπ”«π” π”Ά"; + Assert.AreEqual(5, text.MeasureText()); + + var glyphs = text.GetGlyphs(true); + Assert.AreEqual(5, glyphs.Count); + Assert.AreEqual("𝔉", glyphs[0]); + Assert.AreEqual("π”ž", glyphs[1]); + Assert.AreEqual("𝔫", glyphs[2]); + Assert.AreEqual("𝔠", glyphs[3]); + Assert.AreEqual("𝔢", glyphs[4]); + } + + [Test] + public void GetGlyphsSingleEmojiReturnsSingleGlyph() + { + string text = "πŸ‘"; + Assert.AreEqual(2, text.MeasureText()); + + var glyphs = text.GetGlyphs(true); + Assert.AreEqual(1, glyphs.Count); + Assert.AreEqual("πŸ‘", glyphs[0]); + } + + [Test] + public void GetGlyphsWithComplexEmoji() + { + string text = "πŸ‘¨β€πŸ‘©β€πŸ‘§β€πŸ‘¦"; + Assert.AreEqual(2, text.MeasureText()); + + var glyphs = text.GetGlyphs(true); + Assert.AreEqual(1, glyphs.Count); + Assert.AreEqual("πŸ‘¨β€πŸ‘©β€πŸ‘§β€πŸ‘¦", glyphs[0]); + } + + [Test] + public void GetGlyphsWithMultipleGlyphs() + { + string text = "aπŸ‘"; + Assert.AreEqual(3, text.MeasureText()); + + var glyphs = text.GetGlyphs(true); + Assert.AreEqual(2, glyphs.Count); + Assert.AreEqual("a", glyphs[0]); + Assert.AreEqual("πŸ‘", glyphs[1]); + } + + [Test] + public void GetGlyphsWithOutComplexEmojiSupport() + { + string text = "πŸ‘¨β€πŸ‘©β€πŸ‘§β€πŸ‘¦"; + Assert.AreEqual(2, text.MeasureText()); + + var glyphs = text.GetGlyphs(false); + Assert.AreEqual(4, glyphs.Count); + Assert.AreEqual("πŸ‘¨", glyphs[0]); + Assert.AreEqual("πŸ‘©", glyphs[1]); + Assert.AreEqual("πŸ‘§", glyphs[2]); + Assert.AreEqual("πŸ‘¦", glyphs[3]); + } + } +} \ No newline at end of file diff --git a/src/Tests/Consolonia.Core.Tests/PixelBackgroundTests.cs b/src/Tests/Consolonia.Core.Tests/PixelBackgroundTests.cs new file mode 100644 index 00000000..b3e259c0 --- /dev/null +++ b/src/Tests/Consolonia.Core.Tests/PixelBackgroundTests.cs @@ -0,0 +1,85 @@ +using Avalonia.Media; +using Consolonia.Core.Drawing.PixelBufferImplementation; +using NUnit.Framework; + +namespace Consolonia.Core.Tests +{ + [TestFixture] + public class PixelBackgroundTests + { + [Test] + public void Constructor() + { + var pixelBackground = new PixelBackground(); + Assert.That(pixelBackground.Color, Is.EqualTo(Colors.Transparent)); + Assert.That(pixelBackground.Mode, Is.EqualTo(PixelBackgroundMode.Transparent)); + } + + [Test] + public void ConstructorWithColor() + { + var pixelBackground = new PixelBackground(Colors.Red); + Assert.That(pixelBackground.Color, Is.EqualTo(Colors.Red)); + Assert.That(pixelBackground.Mode, Is.EqualTo(PixelBackgroundMode.Colored)); + } + + [Test] + [TestCase(PixelBackgroundMode.Transparent)] + [TestCase(PixelBackgroundMode.Colored)] + [TestCase(PixelBackgroundMode.Shaded)] + public void ConstructorWithMode(PixelBackgroundMode mode) + { + var pixelBackground = new PixelBackground(mode, Colors.Red); + Assert.That(pixelBackground.Color.Equals(Colors.Red)); + Assert.That(pixelBackground.Mode.Equals(mode)); + } + + [Test] + public void Equality() + { + var pixelBackground = new PixelBackground(Colors.Red); + var pixelBackground2 = new PixelBackground(Colors.Red); + Assert.That(pixelBackground.Equals((object)pixelBackground2)); + Assert.That(pixelBackground.Equals(pixelBackground2)); + Assert.That(pixelBackground == pixelBackground2); + + pixelBackground = new PixelBackground(PixelBackgroundMode.Transparent, Colors.Blue); + pixelBackground2 = new PixelBackground(PixelBackgroundMode.Transparent, Colors.Blue); + Assert.That(pixelBackground.Equals((object)pixelBackground2)); + Assert.That(pixelBackground.Equals(pixelBackground2)); + Assert.That(pixelBackground == pixelBackground2); + } + + [Test] + public void Inequality() + { + var pixelBackground = new PixelBackground(Colors.Red); + var pixelBackground2 = new PixelBackground(Colors.Blue); + Assert.That(!pixelBackground.Equals(pixelBackground2)); + Assert.That(pixelBackground != pixelBackground2); + + pixelBackground = new PixelBackground(PixelBackgroundMode.Colored, Colors.Red); + pixelBackground2 = new PixelBackground(PixelBackgroundMode.Transparent, Colors.Red); + Assert.That(!pixelBackground.Equals((object)pixelBackground2)); + Assert.That(!pixelBackground.Equals(pixelBackground2)); + Assert.That(pixelBackground != pixelBackground2); + } + + [Test] + public void HashCode() + { + var pixelBackground = new PixelBackground(Colors.Red); + var pixelBackground2 = new PixelBackground(Colors.Red); + Assert.That(pixelBackground.GetHashCode(), Is.EqualTo(pixelBackground2.GetHashCode())); + + pixelBackground = new PixelBackground(PixelBackgroundMode.Transparent, Colors.Blue); + pixelBackground2 = new PixelBackground(PixelBackgroundMode.Transparent, Colors.Blue); + Assert.That(pixelBackground.GetHashCode(), Is.EqualTo(pixelBackground2.GetHashCode())); + + // inequal hashcode + pixelBackground = new PixelBackground(Colors.Red); + pixelBackground2 = new PixelBackground(Colors.Blue); + Assert.That(pixelBackground.GetHashCode(), Is.Not.EqualTo(pixelBackground2.GetHashCode())); + } + } +} \ No newline at end of file diff --git a/src/Tests/Consolonia.Core.Tests/PixelForegroundTests.cs b/src/Tests/Consolonia.Core.Tests/PixelForegroundTests.cs new file mode 100644 index 00000000..7d6a4bae --- /dev/null +++ b/src/Tests/Consolonia.Core.Tests/PixelForegroundTests.cs @@ -0,0 +1,171 @@ +using System.Linq; +using System.Text; +using Avalonia.Media; +using Consolonia.Core.Drawing.PixelBufferImplementation; +using NUnit.Framework; + +namespace Consolonia.Core.Tests +{ + [TestFixture] + public class PixelForegroundTests + { + [Test] + public void Constructor() + { + var pixelForeground = new PixelForeground(); + Assert.That(pixelForeground.Color, Is.EqualTo(Colors.Transparent)); + Assert.That(pixelForeground.Symbol.Text, Is.EqualTo(string.Empty)); + Assert.That(pixelForeground.Weight, Is.EqualTo(FontWeight.Normal)); + Assert.That(pixelForeground.Style, Is.EqualTo(FontStyle.Normal)); + Assert.That(pixelForeground.TextDecorations, Is.Null); + } + + [Test] + public void ConstructorWithSymbol() + { + var symbol = new SimpleSymbol('a'); + var pixelForeground = new PixelForeground(symbol, Colors.Red); + Assert.That(pixelForeground.Color, Is.EqualTo(Colors.Red)); + Assert.That(pixelForeground.Symbol.Text, Is.EqualTo("a")); + Assert.That(pixelForeground.Weight, Is.EqualTo(FontWeight.Normal)); + Assert.That(pixelForeground.Style, Is.EqualTo(FontStyle.Normal)); + Assert.That(pixelForeground.TextDecorations, Is.Null); + } + + [Test] + public void ConstructorWithSymbolAndWeight() + { + var symbol = new SimpleSymbol('a'); + var pixelForeground = new PixelForeground(symbol, Colors.Red, FontWeight.Bold); + Assert.That(pixelForeground.Color, Is.EqualTo(Colors.Red)); + Assert.That(pixelForeground.Symbol.Text, Is.EqualTo("a")); + Assert.That(pixelForeground.Weight, Is.EqualTo(FontWeight.Bold)); + Assert.That(pixelForeground.Style, Is.EqualTo(FontStyle.Normal)); + Assert.That(pixelForeground.TextDecorations, Is.Null); + } + + [Test] + public void ConstructorWithSymbolAndStyle() + { + var symbol = new SimpleSymbol('a'); + var pixelForeground = new PixelForeground(symbol, Colors.Red, style: FontStyle.Italic); + Assert.That(pixelForeground.Color, Is.EqualTo(Colors.Red)); + Assert.That(pixelForeground.Symbol.Text, Is.EqualTo("a")); + Assert.That(pixelForeground.Weight, Is.EqualTo(FontWeight.Normal)); + Assert.That(pixelForeground.Style, Is.EqualTo(FontStyle.Italic)); + Assert.That(pixelForeground.TextDecorations, Is.Null); + } + + [Test] + public void ConstructorWithSymbolAndTextDecorations() + { + var symbol = new SimpleSymbol('a'); + TextDecorationCollection textDecorations = TextDecorations.Underline; + var pixelForeground = new PixelForeground(symbol, Colors.Red, textDecorations: textDecorations); + Assert.That(pixelForeground.Color, Is.EqualTo(Colors.Red)); + Assert.That(pixelForeground.Symbol.Text, Is.EqualTo("a")); + Assert.That(pixelForeground.Weight, Is.EqualTo(FontWeight.Normal)); + Assert.That(pixelForeground.Style, Is.EqualTo(FontStyle.Normal)); + Assert.That(pixelForeground.TextDecorations, Is.EqualTo(TextDecorations.Underline)); + } + + [Test] + public void ConstructorWithWideCharacter() + { + Rune rune = "🎡".EnumerateRunes().First(); + var symbol = new SimpleSymbol(rune); + var pixelForeground = new PixelForeground(symbol, Colors.Red); + Assert.That(pixelForeground.Color, Is.EqualTo(Colors.Red)); + Assert.That(pixelForeground.Symbol.Text, Is.EqualTo("🎡")); + Assert.That(pixelForeground.Weight, Is.EqualTo(FontWeight.Normal)); + Assert.That(pixelForeground.Style, Is.EqualTo(FontStyle.Normal)); + Assert.That(pixelForeground.TextDecorations, Is.Null); + } + + [Test] + public void Equality() + { + var pixelForeground = new PixelForeground(new SimpleSymbol('a'), Colors.Red); + var pixelForeground2 = new PixelForeground(new SimpleSymbol('a'), Colors.Red); + Assert.That(pixelForeground.Equals((object)pixelForeground2)); + Assert.That(pixelForeground.Equals(pixelForeground2)); + Assert.That(pixelForeground == pixelForeground2, Is.True); + } + + [Test] + public void Inequality() + { + var pixelForeground = new PixelForeground(new SimpleSymbol('a'), Colors.Red); + foreach (PixelForeground variation in new PixelForeground[] + { + new(new SimpleSymbol('b'), Colors.Red), + new(new SimpleSymbol('a'), Colors.Blue), + new(new SimpleSymbol('a'), Colors.Red, FontWeight.Bold), + new(new SimpleSymbol('a'), Colors.Red, style: FontStyle.Italic), + new(new SimpleSymbol('a'), Colors.Red, textDecorations: TextDecorations.Underline) + }) + { + Assert.That(!pixelForeground.Equals((object)variation)); + Assert.That(!pixelForeground.Equals(variation)); + Assert.That(pixelForeground != variation, Is.True); + } + } + + [Test] + public void Blend() + { + var symbol = new SimpleSymbol('a'); + var pixelForeground = new PixelForeground(symbol, Colors.Red); + var symbolAbove = new SimpleSymbol('b'); + var pixelForegroundAbove = new PixelForeground(symbolAbove, Colors.Blue); + PixelForeground newPixelForeground = pixelForeground.Blend(pixelForegroundAbove); + Assert.That(newPixelForeground.Color, Is.EqualTo(Colors.Blue)); + Assert.That(newPixelForeground.Symbol.Text, Is.EqualTo("b")); + } + + [Test] + public void BlendComplex() + { + var symbol = new SimpleSymbol('a'); + var pixelForeground = new PixelForeground(symbol, Colors.Red); + var symbolAbove = new SimpleSymbol('b'); + var pixelForegroundAbove = new PixelForeground(symbolAbove, Colors.Blue, FontWeight.Bold, FontStyle.Italic, + TextDecorations.Underline); + PixelForeground newPixelForeground = pixelForeground.Blend(pixelForegroundAbove); + Assert.That(newPixelForeground.Color, Is.EqualTo(Colors.Blue)); + Assert.That(newPixelForeground.Symbol.Text, Is.EqualTo("b")); + Assert.That(newPixelForeground.Weight, Is.EqualTo(FontWeight.Bold)); + Assert.That(newPixelForeground.Style, Is.EqualTo(FontStyle.Italic)); + Assert.That(newPixelForeground.TextDecorations, Is.EqualTo(TextDecorations.Underline)); + } + + [Test] + public void BlendEmoji() + { + var symbol = new SimpleSymbol("🎡"); + var pixelForeground = new PixelForeground(symbol, Colors.Red); + var symbolAbove = new SimpleSymbol("🎢"); + var pixelForegroundAbove = new PixelForeground(symbolAbove, Colors.Blue); + PixelForeground newPixelForeground = pixelForeground.Blend(pixelForegroundAbove); + Assert.That(newPixelForeground.Color, Is.EqualTo(Colors.Blue)); + Assert.That(newPixelForeground.Symbol.Text, Is.EqualTo("🎢")); + } + + [Test] + public void HashCode() + { + var pixelForeground = new PixelForeground(new SimpleSymbol('a'), Colors.Red); + var pixelForeground2 = new PixelForeground(new SimpleSymbol('a'), Colors.Red); + Assert.That(pixelForeground.GetHashCode(), Is.EqualTo(pixelForeground2.GetHashCode())); + + // inequal test + pixelForeground = new PixelForeground(new SimpleSymbol('a'), Colors.Red); + pixelForeground2 = new PixelForeground(new SimpleSymbol('b'), Colors.Red); + Assert.That(pixelForeground.GetHashCode(), Is.Not.EqualTo(pixelForeground2.GetHashCode())); + + pixelForeground = new PixelForeground(new SimpleSymbol('a'), Colors.Red); + pixelForeground2 = new PixelForeground(new SimpleSymbol('a'), Colors.Blue); + Assert.That(pixelForeground.GetHashCode(), Is.Not.EqualTo(pixelForeground2.GetHashCode())); + } + } +} \ No newline at end of file diff --git a/src/Tests/Consolonia.Core.Tests/PixelTests.cs b/src/Tests/Consolonia.Core.Tests/PixelTests.cs new file mode 100644 index 00000000..3df57b39 --- /dev/null +++ b/src/Tests/Consolonia.Core.Tests/PixelTests.cs @@ -0,0 +1,155 @@ +using System.Collections.Generic; +using Avalonia.Media; +using Consolonia.Core.Drawing.PixelBufferImplementation; +using NUnit.Framework; + +namespace Consolonia.Core.Tests +{ + [TestFixture] + public class PixelTests + { + [Test] + public void ConstructorCaret() + { + var pixel = new Pixel(true); + Assert.That(pixel.IsCaret); + Assert.That(pixel.Foreground == new PixelForeground()); + Assert.That(pixel.Background == new PixelBackground()); + } + + [Test] + public void ConstructorColorOnly() + { + var pixel = new Pixel(new PixelBackground(Colors.Red)); + Assert.That(pixel.Background.Color, Is.EqualTo(Colors.Red)); + Assert.That(pixel.Background.Mode, Is.EqualTo(PixelBackgroundMode.Colored)); + } + + [Test] + public void ConstructorColorAndSymbol() + { + var pixel = new Pixel(new SimpleSymbol("a"), Colors.Red); + Assert.That(pixel.Foreground.Symbol.Text, Is.EqualTo("a")); + Assert.That(pixel.Foreground.Color, Is.EqualTo(Colors.Red)); + Assert.That(pixel.Foreground.Style, Is.EqualTo(FontStyle.Normal)); + Assert.That(pixel.Foreground.Weight, Is.EqualTo(FontWeight.Normal)); + Assert.That(pixel.Foreground.TextDecorations, Is.Null); + Assert.That(pixel.Background.Color, Is.EqualTo(Colors.Transparent)); + Assert.That(pixel.Background.Mode, Is.EqualTo(PixelBackgroundMode.Transparent)); + } + + [Test] + public void ConstructorDrawingBoxSymbol() + { + var pixel = new Pixel(new DrawingBoxSymbol(0b0000_1111), Colors.Red); + Assert.That(pixel.Foreground.Symbol.Text, Is.EqualTo("β”Ό")); + Assert.That(pixel.Foreground.Color, Is.EqualTo(Colors.Red)); + Assert.That(pixel.Foreground.Style, Is.EqualTo(FontStyle.Normal)); + Assert.That(pixel.Foreground.Weight, Is.EqualTo(FontWeight.Normal)); + Assert.That(pixel.Foreground.TextDecorations, Is.Null); + Assert.That(pixel.Background.Color, Is.EqualTo(Colors.Transparent)); + Assert.That(pixel.Background.Mode, Is.EqualTo(PixelBackgroundMode.Transparent)); + } + + [Test] + public void ConstructorDrawingBoxSymbolAndColor() + { + var pixel = new Pixel(new PixelForeground(new DrawingBoxSymbol(0b0000_1111), Colors.Red), + new PixelBackground(Colors.Blue)); + Assert.That(pixel.Foreground.Symbol.Text, Is.EqualTo("β”Ό")); + Assert.That(pixel.Foreground.Color, Is.EqualTo(Colors.Red)); + Assert.That(pixel.Foreground.Style, Is.EqualTo(FontStyle.Normal)); + Assert.That(pixel.Foreground.Weight, Is.EqualTo(FontWeight.Normal)); + Assert.That(pixel.Foreground.TextDecorations, Is.Null); + Assert.That(pixel.Background.Color, Is.EqualTo(Colors.Blue)); + Assert.That(pixel.Background.Mode, Is.EqualTo(PixelBackgroundMode.Colored)); + } + + [Test] + public void Equality() + { + var pixel = new Pixel(new PixelForeground(new SimpleSymbol('a'), Colors.Red), + new PixelBackground(Colors.Blue)); + var pixel2 = new Pixel(new PixelForeground(new SimpleSymbol('a'), Colors.Red), + new PixelBackground(Colors.Blue)); + Assert.That(pixel.Equals((object)pixel2)); + Assert.That(pixel.Equals(pixel2)); + Assert.That(pixel == pixel2); + } + + [Test] + public void NotEqual() + { + var pixel = new Pixel(new PixelForeground(new SimpleSymbol('a'), Colors.Red), + new PixelBackground(Colors.Blue)); + var pixel2 = new Pixel(new PixelForeground(new SimpleSymbol('b'), Colors.Red), + new PixelBackground(Colors.Blue)); + Assert.That(!pixel.Equals((object)pixel2)); + Assert.That(!pixel.Equals(pixel2)); + Assert.That(pixel != pixel2); + + pixel = new Pixel(new PixelForeground(new SimpleSymbol('a'), Colors.Red), + new PixelBackground(Colors.Blue)); + pixel2 = new Pixel(new PixelForeground(new SimpleSymbol('a'), Colors.Blue), + new PixelBackground(Colors.Blue)); + Assert.That(!pixel.Equals((object)pixel2)); + Assert.That(!pixel.Equals(pixel2)); + Assert.That(pixel != pixel2); + } + + [Test] + public void EqualityCaret() + { + var pixel = new Pixel(true); + var pixel2 = new Pixel(true); + Assert.That(pixel.Equals((object)pixel2)); + Assert.That(pixel.Equals(pixel2)); + Assert.That(pixel == pixel2); + } + + [Test] + public void InequalityCaret() + { + var pixel = new Pixel(true); + var pixel2 = new Pixel(false); + Assert.That(!pixel.Equals((object)pixel2)); + Assert.That(!pixel.Equals(pixel2)); + Assert.That(pixel != pixel2); + } + + [Test] + public void BlendTransparentBackground() + { + var pixel = new Pixel(new PixelBackground(Colors.Green)); + var pixel2 = new Pixel(new PixelForeground(new SimpleSymbol('a'), Colors.Red), + new PixelBackground(Colors.Transparent)); + Pixel newPixel = pixel.Blend(pixel2); + Assert.That(newPixel.Foreground.Symbol.Text, Is.EqualTo("a")); + Assert.That(newPixel.Foreground.Color, Is.EqualTo(Colors.Red)); + Assert.That(newPixel.Background.Color, Is.EqualTo(Colors.Green)); + } + + [Test] + public void BlendColoredBackground() + { + var pixel = new Pixel(new PixelBackground(Colors.Green)); + var pixel2 = new Pixel(new PixelForeground(new SimpleSymbol('a'), Colors.Red), + new PixelBackground(Colors.Blue)); + Pixel newPixel = pixel.Blend(pixel2); + Assert.That(newPixel.Foreground.Symbol.Text, Is.EqualTo("a")); + Assert.That(newPixel.Foreground.Color, Is.EqualTo(Colors.Red)); + Assert.That(newPixel.Background.Color, Is.EqualTo(Colors.Blue)); + } + + [Test] + public void HashCode() + { + var set = new HashSet(); + set.Add(new Pixel(new PixelForeground(new SimpleSymbol('a'), Colors.Red), + new PixelBackground(Colors.Blue))); + set.Add(new Pixel(new PixelForeground(new SimpleSymbol('a'), Colors.Red), + new PixelBackground(Colors.Blue))); + Assert.That(set.Count, Is.EqualTo(1)); + } + } +} \ No newline at end of file diff --git a/src/Tests/Consolonia.Core.Tests/SimpleSymbolTests.cs b/src/Tests/Consolonia.Core.Tests/SimpleSymbolTests.cs new file mode 100644 index 00000000..db91c5cb --- /dev/null +++ b/src/Tests/Consolonia.Core.Tests/SimpleSymbolTests.cs @@ -0,0 +1,153 @@ +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Consolonia.Core.Drawing.PixelBufferImplementation; +using NUnit.Framework; + +namespace Consolonia.Core.Tests +{ + [TestFixture] + public class SimpleSymbolTests + { + [Test] + public void ConstructorChar() + { + ISymbol symbol = new SimpleSymbol('a'); + Assert.That(symbol.Text, Is.EqualTo("a")); + Assert.That(symbol.Width, Is.EqualTo(1)); + } + + [Test] + public void ConstructorString() + { + ISymbol symbol = new SimpleSymbol("a"); + Assert.That(symbol.Text, Is.EqualTo("a")); + Assert.That(symbol.Width, Is.EqualTo(1)); + } + + [Test] + public void ConstructorRune() + { + ISymbol symbol = new SimpleSymbol(new Rune('a')); + Assert.That(symbol.Text, Is.EqualTo("a")); + Assert.That(symbol.Width, Is.EqualTo(1)); + } + + [Test] + public void ConstructorRuneEmoji() + { + Rune rune = "πŸ‘".EnumerateRunes().First(); + ISymbol symbol = new SimpleSymbol(rune); + Assert.That(symbol.Text, Is.EqualTo("πŸ‘")); + Assert.That(symbol.Width, Is.EqualTo(2)); + } + + [Test] + public void ConstructorComplexEmoji() + { + ISymbol symbol = new SimpleSymbol("πŸ‘¨β€πŸ‘©β€πŸ‘§β€πŸ‘¦"); + Assert.That(symbol.Text, Is.EqualTo("πŸ‘¨β€πŸ‘©β€πŸ‘§β€πŸ‘¦")); + Assert.That(symbol.Width, Is.EqualTo(2)); + } + + [Test] + public void Equality() + { + var symbol = new SimpleSymbol("a"); + var symbol2 = new SimpleSymbol("a"); + Assert.That(symbol.Equals((object)symbol2)); + Assert.That(symbol.Equals(symbol2)); + Assert.That(symbol == symbol2); + } + + [Test] + public void EqualityISymbol() + { + ISymbol symbol = new SimpleSymbol("a"); + ISymbol symbol2 = new SimpleSymbol("a"); + Assert.That(symbol.Equals(symbol2)); + Assert.That(symbol.Equals(symbol2)); + } + + [Test] + public void Inequality() + { + var symbol = new SimpleSymbol("a"); + var symbol2 = new SimpleSymbol("b"); + Assert.That(!symbol.Equals((object)symbol2)); + Assert.That(!symbol.Equals(symbol2)); + Assert.That(symbol != symbol2); + } + + [Test] + public void InequalityISymbol() + { + ISymbol symbol = new SimpleSymbol("a"); + ISymbol symbol2 = new SimpleSymbol("b"); + Assert.That(!symbol.Equals(symbol2)); + Assert.That(!symbol.Equals(symbol2)); + } + + [Test] + public void HashCode() + { + var set = new HashSet(); + set.Add(new SimpleSymbol("a")); + set.Add(new SimpleSymbol("a")); + Assert.That(set.Count, Is.EqualTo(1)); + + var set2 = new HashSet(); + set2.Add(new SimpleSymbol("a")); + set2.Add(new SimpleSymbol("a")); + Assert.That(set2.Count, Is.EqualTo(1)); + } + + [Test] + public void IsWhiteSpace() + { + Assert.That(new SimpleSymbol(string.Empty).IsWhiteSpace(), Is.True); + Assert.That(new SimpleSymbol(" ").IsWhiteSpace(), Is.False); + Assert.That(new SimpleSymbol("a").IsWhiteSpace(), Is.False); + } + + [Test] + public void Blend() + { + ISymbol symbol = new SimpleSymbol("a"); + ISymbol symbolAbove = new SimpleSymbol("b"); + ISymbol newSymbol = symbol.Blend(ref symbolAbove); + Assert.That(newSymbol.Text, Is.EqualTo("b")); + Assert.That(newSymbol.Width, Is.EqualTo(1)); + } + + [Test] + public void BlendWithWhiteSpace() + { + ISymbol symbol = new SimpleSymbol(" "); + ISymbol symbolAbove = new SimpleSymbol("b"); + ISymbol newSymbol = symbol.Blend(ref symbolAbove); + Assert.That(newSymbol.Text, Is.EqualTo("b")); + Assert.That(newSymbol.Width, Is.EqualTo(1)); + } + + [Test] + public void BlendWithEmpty() + { + ISymbol symbol = new SimpleSymbol("a"); + ISymbol symbolAbove = new SimpleSymbol(string.Empty); + ISymbol newSymbol = symbol.Blend(ref symbolAbove); + Assert.That(newSymbol.Text, Is.EqualTo("a")); + Assert.That(newSymbol.Width, Is.EqualTo(1)); + } + + [Test] + public void BlendWithEmoji() + { + ISymbol symbol = new SimpleSymbol("a"); + ISymbol symbolAbove = new SimpleSymbol("πŸ‘"); + ISymbol newSymbol = symbol.Blend(ref symbolAbove); + Assert.That(newSymbol.Text, Is.EqualTo("πŸ‘")); + Assert.That(newSymbol.Width, Is.EqualTo(2)); + } + } +} \ No newline at end of file diff --git a/src/Tests/Consolonia.GalleryTests/Base/GalleryTestsBaseBase.cs b/src/Tests/Consolonia.Gallery.Tests/Base/GalleryTestsBaseBase.cs similarity index 76% rename from src/Tests/Consolonia.GalleryTests/Base/GalleryTestsBaseBase.cs rename to src/Tests/Consolonia.Gallery.Tests/Base/GalleryTestsBaseBase.cs index 5a08e4ce..86813e8f 100644 --- a/src/Tests/Consolonia.GalleryTests/Base/GalleryTestsBaseBase.cs +++ b/src/Tests/Consolonia.Gallery.Tests/Base/GalleryTestsBaseBase.cs @@ -1,15 +1,13 @@ using System.Threading.Tasks; using Avalonia; using Avalonia.Controls.ApplicationLifetimes; -using Avalonia.Input; using Avalonia.Threading; using Consolonia.Core.Drawing.PixelBufferImplementation; -using Consolonia.Gallery; using Consolonia.Gallery.View; -using Consolonia.TestsCore; +using Consolonia.NUnit; using NUnit.Framework; -namespace Consolonia.GalleryTests.Base +namespace Consolonia.Gallery.Tests.Base { internal abstract class GalleryTestsBaseBase : ConsoloniaAppTestBase { @@ -21,15 +19,6 @@ protected GalleryTestsBaseBase(PixelBufferSize size = default) : base(size.IsEmp Args[1] = GetType().Name[..^5]; } - [Test] - public async Task SingleTest() - { - await UITest.KeyInput(Key.Tab); - await PerformSingleTest(); - } - - protected abstract Task PerformSingleTest(); - [OneTimeSetUp] public async Task Setup() { diff --git a/src/Tests/Consolonia.GalleryTests/ButtonTests.cs b/src/Tests/Consolonia.Gallery.Tests/ButtonTests.cs similarity index 67% rename from src/Tests/Consolonia.GalleryTests/ButtonTests.cs rename to src/Tests/Consolonia.Gallery.Tests/ButtonTests.cs index 55671c2a..97d340a3 100644 --- a/src/Tests/Consolonia.GalleryTests/ButtonTests.cs +++ b/src/Tests/Consolonia.Gallery.Tests/ButtonTests.cs @@ -1,16 +1,18 @@ using System.Threading.Tasks; using Avalonia.Input; -using Consolonia.GalleryTests.Base; -using Consolonia.TestsCore; +using Consolonia.Gallery.Tests.Base; +using Consolonia.NUnit; using NUnit.Framework; -namespace Consolonia.GalleryTests +namespace Consolonia.Gallery.Tests { [TestFixture] internal class ButtonTests : GalleryTestsBaseBase { - protected override async Task PerformSingleTest() + [Test] + public async Task PerformSingleTest() { + await UITest.KeyInput(Key.Tab); await UITest.KeyInput(Key.Enter); await UITest.AssertHasText("Standard _?XAML Button", "Foreground", diff --git a/src/Tests/Consolonia.GalleryTests/CalendarPickerTests.cs b/src/Tests/Consolonia.Gallery.Tests/CalendarPickerTests.cs similarity index 78% rename from src/Tests/Consolonia.GalleryTests/CalendarPickerTests.cs rename to src/Tests/Consolonia.Gallery.Tests/CalendarPickerTests.cs index d5438066..80f41a84 100644 --- a/src/Tests/Consolonia.GalleryTests/CalendarPickerTests.cs +++ b/src/Tests/Consolonia.Gallery.Tests/CalendarPickerTests.cs @@ -1,16 +1,18 @@ -ο»Ώusing System.Threading.Tasks; +using System.Threading.Tasks; using Avalonia.Input; -using Consolonia.GalleryTests.Base; -using Consolonia.TestsCore; +using Consolonia.Gallery.Tests.Base; +using Consolonia.NUnit; using NUnit.Framework; -namespace Consolonia.GalleryTests +namespace Consolonia.Gallery.Tests { [TestFixture] internal class CalendarPickerTests : GalleryTestsBaseBase { - protected override async Task PerformSingleTest() + [Test] + public async Task PerformSingleTest() { + await UITest.KeyInput(Key.Tab); await UITest.AssertHasText("2/16/2022"); await UITest.KeyInput(Key.Right); await UITest.KeyInput(9, Key.Left); diff --git a/src/Tests/Consolonia.GalleryTests/CalendarTests.cs b/src/Tests/Consolonia.Gallery.Tests/CalendarTests.cs similarity index 78% rename from src/Tests/Consolonia.GalleryTests/CalendarTests.cs rename to src/Tests/Consolonia.Gallery.Tests/CalendarTests.cs index 329b7682..d136a8da 100644 --- a/src/Tests/Consolonia.GalleryTests/CalendarTests.cs +++ b/src/Tests/Consolonia.Gallery.Tests/CalendarTests.cs @@ -1,17 +1,19 @@ -ο»Ώusing System.Linq; +using System.Linq; using System.Threading.Tasks; using Avalonia.Input; -using Consolonia.GalleryTests.Base; -using Consolonia.TestsCore; +using Consolonia.Gallery.Tests.Base; +using Consolonia.NUnit; using NUnit.Framework; -namespace Consolonia.GalleryTests +namespace Consolonia.Gallery.Tests { [TestFixture] internal class CalendarTests : GalleryTestsBaseBase { - protected override async Task PerformSingleTest() + [Test] + public async Task PerformSingleTest() { + await UITest.KeyInput(Key.Tab); await UITest.AssertHasText("24 25 26 27 28 29 30"); await UITest.AssertHasText(@"April", @"2022"); await UITest.KeyInput(Key.Tab, Key.Back); diff --git a/src/Tests/Consolonia.GalleryTests/CheckBoxTests.cs b/src/Tests/Consolonia.Gallery.Tests/CheckBoxTests.cs similarity index 83% rename from src/Tests/Consolonia.GalleryTests/CheckBoxTests.cs rename to src/Tests/Consolonia.Gallery.Tests/CheckBoxTests.cs index dc1b9fb1..7a1f69ce 100644 --- a/src/Tests/Consolonia.GalleryTests/CheckBoxTests.cs +++ b/src/Tests/Consolonia.Gallery.Tests/CheckBoxTests.cs @@ -1,16 +1,18 @@ using System.Threading.Tasks; using Avalonia.Input; -using Consolonia.GalleryTests.Base; -using Consolonia.TestsCore; +using Consolonia.Gallery.Tests.Base; +using Consolonia.NUnit; using NUnit.Framework; -namespace Consolonia.GalleryTests +namespace Consolonia.Gallery.Tests { [TestFixture] internal class CheckBoxTests : GalleryTestsBaseBase { - protected override async Task PerformSingleTest() + [Test] + public async Task PerformSingleTest() { + await UITest.KeyInput(Key.Tab); await UITest.AssertHasText( "[ ].+Unchecked", "[V].+Checked", diff --git a/src/Tests/Consolonia.GalleryTests/ComboBoxTests.cs b/src/Tests/Consolonia.Gallery.Tests/ComboBoxTests.cs similarity index 83% rename from src/Tests/Consolonia.GalleryTests/ComboBoxTests.cs rename to src/Tests/Consolonia.Gallery.Tests/ComboBoxTests.cs index 9f76452a..7d5064a8 100644 --- a/src/Tests/Consolonia.GalleryTests/ComboBoxTests.cs +++ b/src/Tests/Consolonia.Gallery.Tests/ComboBoxTests.cs @@ -1,16 +1,18 @@ using System.Threading.Tasks; using Avalonia.Input; -using Consolonia.GalleryTests.Base; -using Consolonia.TestsCore; +using Consolonia.Gallery.Tests.Base; +using Consolonia.NUnit; using NUnit.Framework; -namespace Consolonia.GalleryTests +namespace Consolonia.Gallery.Tests { [TestFixture] internal class ComboBoxTests : GalleryTestsBaseBase { - protected override async Task PerformSingleTest() + [Test] + public async Task PerformSingleTest() { + await UITest.KeyInput(Key.Tab); await UITest.AssertHasText("Pick an Item", "Still item", "Null object"); diff --git a/src/Tests/Consolonia.GalleryTests/Consolonia.GalleryTests.csproj b/src/Tests/Consolonia.Gallery.Tests/Consolonia.Gallery.Tests.csproj similarity index 86% rename from src/Tests/Consolonia.GalleryTests/Consolonia.GalleryTests.csproj rename to src/Tests/Consolonia.Gallery.Tests/Consolonia.Gallery.Tests.csproj index d0bb359c..8715e73d 100644 --- a/src/Tests/Consolonia.GalleryTests/Consolonia.GalleryTests.csproj +++ b/src/Tests/Consolonia.Gallery.Tests/Consolonia.Gallery.Tests.csproj @@ -13,7 +13,7 @@ - + diff --git a/src/Tests/Consolonia.GalleryTests/DataGridTests.cs b/src/Tests/Consolonia.Gallery.Tests/DataGridTests.cs similarity index 73% rename from src/Tests/Consolonia.GalleryTests/DataGridTests.cs rename to src/Tests/Consolonia.Gallery.Tests/DataGridTests.cs index 063b5002..9769f7e0 100644 --- a/src/Tests/Consolonia.GalleryTests/DataGridTests.cs +++ b/src/Tests/Consolonia.Gallery.Tests/DataGridTests.cs @@ -1,16 +1,18 @@ using System.Threading.Tasks; using Avalonia.Input; -using Consolonia.GalleryTests.Base; -using Consolonia.TestsCore; +using Consolonia.Gallery.Tests.Base; +using Consolonia.NUnit; using NUnit.Framework; -namespace Consolonia.GalleryTests +namespace Consolonia.Gallery.Tests { [TestFixture] internal class DataGridTests : GalleryTestsBaseBase { - protected override async Task PerformSingleTest() + [Test] + public async Task PerformSingleTest() { + await UITest.KeyInput(Key.Tab); await UITest.AssertHasText("Co.+Region.+Population.+Area", @"Afg.+ASIA \(EX. NEAR"); await UITest.KeyInput(Key.Tab, Key.Tab); diff --git a/src/Tests/Consolonia.GalleryTests/DialogTests.cs b/src/Tests/Consolonia.Gallery.Tests/DialogTests.cs similarity index 67% rename from src/Tests/Consolonia.GalleryTests/DialogTests.cs rename to src/Tests/Consolonia.Gallery.Tests/DialogTests.cs index 5c9c4a73..4e22c4b8 100644 --- a/src/Tests/Consolonia.GalleryTests/DialogTests.cs +++ b/src/Tests/Consolonia.Gallery.Tests/DialogTests.cs @@ -1,16 +1,18 @@ using System.Threading.Tasks; using Avalonia.Input; -using Consolonia.GalleryTests.Base; -using Consolonia.TestsCore; +using Consolonia.Gallery.Tests.Base; +using Consolonia.NUnit; using NUnit.Framework; -namespace Consolonia.GalleryTests +namespace Consolonia.Gallery.Tests { [TestFixture] internal class DialogTests : GalleryTestsBaseBase { - protected override async Task PerformSingleTest() + [Test] + public async Task PerformSingleTest() { + await UITest.KeyInput(Key.Tab); await UITest.KeyInput(Key.Enter); await UITest.KeyInput(Key.Tab); await UITest.AssertHasText("One More"); diff --git a/src/Tests/Consolonia.GalleryTests/FlyoutTests.cs b/src/Tests/Consolonia.Gallery.Tests/FlyoutTests.cs similarity index 81% rename from src/Tests/Consolonia.GalleryTests/FlyoutTests.cs rename to src/Tests/Consolonia.Gallery.Tests/FlyoutTests.cs index 869768f6..700265f6 100644 --- a/src/Tests/Consolonia.GalleryTests/FlyoutTests.cs +++ b/src/Tests/Consolonia.Gallery.Tests/FlyoutTests.cs @@ -1,16 +1,18 @@ using System.Threading.Tasks; using Avalonia.Input; -using Consolonia.GalleryTests.Base; -using Consolonia.TestsCore; +using Consolonia.Gallery.Tests.Base; +using Consolonia.NUnit; using NUnit.Framework; -namespace Consolonia.GalleryTests +namespace Consolonia.Gallery.Tests { [TestFixture] internal class FlyoutTests : GalleryTestsBaseBase { - protected override async Task PerformSingleTest() + [Test] + public async Task PerformSingleTest() { + await UITest.KeyInput(Key.Tab); await UITest.KeyInput(Key.Enter); await UITest.AssertHasText(@"Item 1 \>", "Item 2"); diff --git a/src/Tests/Consolonia.GalleryTests/ListBoxTests.cs b/src/Tests/Consolonia.Gallery.Tests/ListBoxTests.cs similarity index 67% rename from src/Tests/Consolonia.GalleryTests/ListBoxTests.cs rename to src/Tests/Consolonia.Gallery.Tests/ListBoxTests.cs index c4d07fe2..3b99f9f4 100644 --- a/src/Tests/Consolonia.GalleryTests/ListBoxTests.cs +++ b/src/Tests/Consolonia.Gallery.Tests/ListBoxTests.cs @@ -1,16 +1,18 @@ using System.Threading.Tasks; using Avalonia.Input; -using Consolonia.GalleryTests.Base; -using Consolonia.TestsCore; +using Consolonia.Gallery.Tests.Base; +using Consolonia.NUnit; using NUnit.Framework; -namespace Consolonia.GalleryTests +namespace Consolonia.Gallery.Tests { [TestFixture] internal class ListBoxTests : GalleryTestsBaseBase { - protected override async Task PerformSingleTest() + [Test] + public async Task PerformSingleTest() { + await UITest.KeyInput(Key.Tab); await UITest.KeyInput(Key.Tab, RawInputModifiers.Shift); await UITest.KeyInput(Key.Tab, RawInputModifiers.Shift); await UITest.KeyInput(Key.PageDown); diff --git a/src/Tests/Consolonia.GalleryTests/MenuTests.cs b/src/Tests/Consolonia.Gallery.Tests/MenuTests.cs similarity index 77% rename from src/Tests/Consolonia.GalleryTests/MenuTests.cs rename to src/Tests/Consolonia.Gallery.Tests/MenuTests.cs index 7ae5dcf9..8b8a76eb 100644 --- a/src/Tests/Consolonia.GalleryTests/MenuTests.cs +++ b/src/Tests/Consolonia.Gallery.Tests/MenuTests.cs @@ -1,16 +1,18 @@ using System.Threading.Tasks; using Avalonia.Input; -using Consolonia.GalleryTests.Base; -using Consolonia.TestsCore; +using Consolonia.Gallery.Tests.Base; +using Consolonia.NUnit; using NUnit.Framework; -namespace Consolonia.GalleryTests +namespace Consolonia.Gallery.Tests { [TestFixture] internal class MenuTests : GalleryTestsBaseBase { - protected override async Task PerformSingleTest() + [Test] + public async Task PerformSingleTest() { + await UITest.KeyInput(Key.Tab); await UITest.AssertHasText("First", "Second"); await UITest.KeyInput(Key.Enter); await UITest.AssertHasText("Standard Menu Item", @"Ctrl\+A"); diff --git a/src/Tests/Consolonia.GalleryTests/ProgressBarTests.cs b/src/Tests/Consolonia.Gallery.Tests/ProgressBarTests.cs similarity index 62% rename from src/Tests/Consolonia.GalleryTests/ProgressBarTests.cs rename to src/Tests/Consolonia.Gallery.Tests/ProgressBarTests.cs index 9ab8b900..de17f6e9 100644 --- a/src/Tests/Consolonia.GalleryTests/ProgressBarTests.cs +++ b/src/Tests/Consolonia.Gallery.Tests/ProgressBarTests.cs @@ -1,17 +1,20 @@ using System.Threading.Tasks; -using Consolonia.GalleryTests.Base; -using Consolonia.TestsCore; +using Avalonia.Input; +using Consolonia.Gallery.Tests.Base; +using Consolonia.NUnit; using NUnit.Framework; -namespace Consolonia.GalleryTests +namespace Consolonia.Gallery.Tests { [TestFixture] [Ignore( "ProgressBar has annimation, thus application becomes never idle, thus hard to determine input, layout and other jobs are done")] //todo: internal class ProgressBarTests : GalleryTestsBaseBase { - protected override async Task PerformSingleTest() + [Test] + public async Task PerformSingleTest() { + await UITest.KeyInput(Key.Tab); await UITest.AssertHasText("5%", "50%"); } } diff --git a/src/Tests/Consolonia.GalleryTests/RadioButtonTests.cs b/src/Tests/Consolonia.Gallery.Tests/RadioButtonTests.cs similarity index 79% rename from src/Tests/Consolonia.GalleryTests/RadioButtonTests.cs rename to src/Tests/Consolonia.Gallery.Tests/RadioButtonTests.cs index 79d4408a..fd856b39 100644 --- a/src/Tests/Consolonia.GalleryTests/RadioButtonTests.cs +++ b/src/Tests/Consolonia.Gallery.Tests/RadioButtonTests.cs @@ -1,16 +1,18 @@ using System.Threading.Tasks; using Avalonia.Input; -using Consolonia.GalleryTests.Base; -using Consolonia.TestsCore; +using Consolonia.Gallery.Tests.Base; +using Consolonia.NUnit; using NUnit.Framework; -namespace Consolonia.GalleryTests +namespace Consolonia.Gallery.Tests { [TestFixture] internal class RadioButtonTests : GalleryTestsBaseBase { - protected override async Task PerformSingleTest() + [Test] + public async Task PerformSingleTest() { + await UITest.KeyInput(Key.Tab); await UITest.AssertHasText(@"\(\*\).+Option 1", @"\( \).+Option 2", @"\(β– \).+Option 3"); diff --git a/src/Tests/Consolonia.GalleryTests/ScrollViewerTests.cs b/src/Tests/Consolonia.Gallery.Tests/ScrollViewerTests.cs similarity index 66% rename from src/Tests/Consolonia.GalleryTests/ScrollViewerTests.cs rename to src/Tests/Consolonia.Gallery.Tests/ScrollViewerTests.cs index daf684d3..a9daecee 100644 --- a/src/Tests/Consolonia.GalleryTests/ScrollViewerTests.cs +++ b/src/Tests/Consolonia.Gallery.Tests/ScrollViewerTests.cs @@ -1,16 +1,18 @@ using System.Threading.Tasks; using Avalonia.Input; -using Consolonia.GalleryTests.Base; -using Consolonia.TestsCore; +using Consolonia.Gallery.Tests.Base; +using Consolonia.NUnit; using NUnit.Framework; -namespace Consolonia.GalleryTests +namespace Consolonia.Gallery.Tests { [TestFixture] internal class ScrollViewerTests : GalleryTestsBaseBase { - protected override async Task PerformSingleTest() + [Test] + public async Task PerformSingleTest() { + await UITest.KeyInput(Key.Tab); await UITest.KeyInput(Key.Tab, Key.Tab, Key.Tab); await UITest.KeyInput(30, Key.Right); diff --git a/src/Tests/Consolonia.GalleryTests/TabControlTests.cs b/src/Tests/Consolonia.Gallery.Tests/TabControlTests.cs similarity index 71% rename from src/Tests/Consolonia.GalleryTests/TabControlTests.cs rename to src/Tests/Consolonia.Gallery.Tests/TabControlTests.cs index 44451369..c2d735eb 100644 --- a/src/Tests/Consolonia.GalleryTests/TabControlTests.cs +++ b/src/Tests/Consolonia.Gallery.Tests/TabControlTests.cs @@ -1,16 +1,18 @@ using System.Threading.Tasks; using Avalonia.Input; -using Consolonia.GalleryTests.Base; -using Consolonia.TestsCore; +using Consolonia.Gallery.Tests.Base; +using Consolonia.NUnit; using NUnit.Framework; -namespace Consolonia.GalleryTests +namespace Consolonia.Gallery.Tests { [TestFixture] internal class TabControlTests : GalleryTestsBaseBase { - protected override async Task PerformSingleTest() + [Test] + public async Task PerformSingleTest() { + await UITest.KeyInput(Key.Tab); await UITest.AssertHasText("Arch", "Leaf"); await UITest.KeyInput(Key.Right); diff --git a/src/Tests/Consolonia.Gallery.Tests/TextBlockTests.cs b/src/Tests/Consolonia.Gallery.Tests/TextBlockTests.cs new file mode 100644 index 00000000..86ecf972 --- /dev/null +++ b/src/Tests/Consolonia.Gallery.Tests/TextBlockTests.cs @@ -0,0 +1,58 @@ +using System.Threading.Tasks; +using Avalonia.Input; +using Consolonia.Gallery.Tests.Base; +using Consolonia.NUnit; +using NUnit.Framework; + +namespace Consolonia.Gallery.Tests +{ + /// + /// Unit test for TextBlock view + /// + [TestFixture] + internal class TextBlockTests : GalleryTestsBaseBase + { + [Test] + public async Task DisplaysBasicText() + { + await UITest.KeyInput(Key.Tab); + await UITest.AssertHasText("This is TextBlock"); + } + + [Test] + public async Task HandlesTrimming() + { + await UITest.KeyInput(Key.Tab); + await UITest.AssertHasText( + "Text trimming with charac...", + "Text trimming with word..."); + } + + [Test] + public async Task HandlesAlignment() + { + await UITest.KeyInput(Key.Tab); + await UITest.AssertHasText( + "β”‚Left aligned text ", + " Center aligned text ", + " Right aligned textβ”‚"); + } + + [Test] + public async Task HandlesMultilineText() + { + await UITest.KeyInput(Key.Tab); + await UITest.AssertHasText( + "β”‚Vivamus magna. Cras in mi at felis aliquet congue. Ut a β”‚", + "β”‚est eget ligula molestie gravida. Curabitur massa. Donecβ”‚"); + } + + [Test] + public async Task HandlesSpecialCharacters() + { + await UITest.KeyInput(Key.Tab); + await UITest.AssertHasText( + "π“π“˜π“»π“˜π“»π“Ÿ π’»π“Ÿ", "π„ž", "🎡", "π”‰π”žπ”«π” π”Ά", "ff", "fi", "Β½"); + } + } +} \ No newline at end of file diff --git a/src/Tests/Consolonia.GalleryTests/TextBoxTests.cs b/src/Tests/Consolonia.Gallery.Tests/TextBoxTests.cs similarity index 88% rename from src/Tests/Consolonia.GalleryTests/TextBoxTests.cs rename to src/Tests/Consolonia.Gallery.Tests/TextBoxTests.cs index 1fef1355..bb9ee17b 100644 --- a/src/Tests/Consolonia.GalleryTests/TextBoxTests.cs +++ b/src/Tests/Consolonia.Gallery.Tests/TextBoxTests.cs @@ -1,16 +1,18 @@ using System.Threading.Tasks; using Avalonia.Input; -using Consolonia.GalleryTests.Base; -using Consolonia.TestsCore; +using Consolonia.Gallery.Tests.Base; +using Consolonia.NUnit; using NUnit.Framework; -namespace Consolonia.GalleryTests +namespace Consolonia.Gallery.Tests { [TestFixture] internal class TextBoxTests : GalleryTestsBaseBase { - protected override async Task PerformSingleTest() + [Test] + public async Task PerformSingleTest() { + await UITest.KeyInput(Key.Tab); await UITest.KeyInput(Key.Right); await UITest.AssertHasText(@"elit\. "); await UITest.KeyInput(Key.Right); diff --git a/src/Tests/Consolonia.GalleryTests/TextBlockTests.cs b/src/Tests/Consolonia.GalleryTests/TextBlockTests.cs deleted file mode 100644 index 8f212ea8..00000000 --- a/src/Tests/Consolonia.GalleryTests/TextBlockTests.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System.Threading.Tasks; -using Consolonia.GalleryTests.Base; -using Consolonia.TestsCore; -using NUnit.Framework; - -namespace Consolonia.GalleryTests -{ - /// - /// Unit test for TextBlock view - /// - [TestFixture] - internal class TextBlockTests : GalleryTestsBaseBase - { - protected override Task PerformSingleTest() - { - return UITest.AssertHasText("This is TextBlock", - "Text trimming with charac...", - "Text trimming with word...", - "β”‚Left aligned text ", - " Center aligned text ", - "Right aligned textβ”‚", - - // multiline - "β”‚Vivamus magna. Cras in mi at felis aliquet congue. Ut a β”‚", - "β”‚est eget ligula molestie gravida. Curabitur massa. Donecβ”‚", - // special chars, emojis, etc. - "π“π“˜π“»π“˜π“»π“Ÿ π’»π“Ÿ", "π„ž", "🎡", "β€œπ”‰π”žπ”«π” π”Άβ€", "ff", "fi", "Β½"); - } - } -} \ No newline at end of file