feat(interop): add safe handle wrappers and configuration options
Implement SafeHandle wrappers for native resources (SafeGtkWidgetHandle, SafeGObjectHandle, SafeX11DisplayHandle, SafeX11CursorHandle, SafeDlopenHandle) to prevent memory leaks. Move gesture and rendering configuration from static properties to LinuxApplicationOptions for better testability and DI compatibility. Add THREADING.md and DI-MIGRATION.md documentation. Include LayoutIntegrationTests for Measure/Arrange pipeline and SkiaViewTheoryTests with parameterized test cases using [Theory] attributes.
This commit is contained in:
430
tests/Views/LayoutIntegrationTests.cs
Normal file
430
tests/Views/LayoutIntegrationTests.cs
Normal file
@@ -0,0 +1,430 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
using FluentAssertions;
|
||||
using Microsoft.Maui.Graphics;
|
||||
using Microsoft.Maui.Platform;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.Maui.Controls.Linux.Tests.Views;
|
||||
|
||||
/// <summary>
|
||||
/// Minimal concrete SkiaView that uses base MeasureOverride (respects WidthRequest/HeightRequest).
|
||||
/// SkiaLabel overrides MeasureOverride to use font metrics, so we need this for layout tests.
|
||||
/// </summary>
|
||||
internal class TestView : SkiaView
|
||||
{
|
||||
protected override void OnDraw(SkiaSharp.SKCanvas canvas, SkiaSharp.SKRect bounds) { }
|
||||
}
|
||||
|
||||
#region StackLayoutIntegrationTests
|
||||
|
||||
public class StackLayoutIntegrationTests
|
||||
{
|
||||
[Fact]
|
||||
public void VerticalStack_MeasuresChildrenSequentially()
|
||||
{
|
||||
// Arrange
|
||||
var stack = new SkiaStackLayout
|
||||
{
|
||||
Orientation = Microsoft.Maui.Platform.StackOrientation.Vertical
|
||||
};
|
||||
|
||||
var child1 = new TestView { HeightRequest = 30, WidthRequest = 100 };
|
||||
var child2 = new TestView { HeightRequest = 30, WidthRequest = 100 };
|
||||
var child3 = new TestView { HeightRequest = 30, WidthRequest = 100 };
|
||||
|
||||
stack.AddChild(child1);
|
||||
stack.AddChild(child2);
|
||||
stack.AddChild(child3);
|
||||
|
||||
// Act
|
||||
var size = stack.Measure(new Size(400, 600));
|
||||
|
||||
// Assert - 3 children each 30px tall => total height >= 90
|
||||
size.Height.Should().BeGreaterThanOrEqualTo(90);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void HorizontalStack_MeasuresChildrenSideToSide()
|
||||
{
|
||||
// Arrange
|
||||
var stack = new SkiaStackLayout
|
||||
{
|
||||
Orientation = Microsoft.Maui.Platform.StackOrientation.Horizontal
|
||||
};
|
||||
|
||||
var child1 = new TestView { WidthRequest = 50, HeightRequest = 30 };
|
||||
var child2 = new TestView { WidthRequest = 50, HeightRequest = 30 };
|
||||
var child3 = new TestView { WidthRequest = 50, HeightRequest = 30 };
|
||||
|
||||
stack.AddChild(child1);
|
||||
stack.AddChild(child2);
|
||||
stack.AddChild(child3);
|
||||
|
||||
// Act
|
||||
var size = stack.Measure(new Size(600, 400));
|
||||
|
||||
// Assert - 3 children each 50px wide => total width >= 150
|
||||
size.Width.Should().BeGreaterThanOrEqualTo(150);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VerticalStack_ArrangePositionsChildrenVertically()
|
||||
{
|
||||
// Arrange
|
||||
var stack = new SkiaStackLayout
|
||||
{
|
||||
Orientation = Microsoft.Maui.Platform.StackOrientation.Vertical
|
||||
};
|
||||
|
||||
var child1 = new TestView { HeightRequest = 40, WidthRequest = 100 };
|
||||
var child2 = new TestView { HeightRequest = 40, WidthRequest = 100 };
|
||||
var child3 = new TestView { HeightRequest = 40, WidthRequest = 100 };
|
||||
|
||||
stack.AddChild(child1);
|
||||
stack.AddChild(child2);
|
||||
stack.AddChild(child3);
|
||||
|
||||
stack.Measure(new Size(400, 600));
|
||||
|
||||
// Act
|
||||
stack.Arrange(new Rect(0, 0, 400, 600));
|
||||
|
||||
// Assert - children should have increasing Y positions
|
||||
child2.Bounds.Top.Should().BeGreaterThan(child1.Bounds.Top);
|
||||
child3.Bounds.Top.Should().BeGreaterThan(child2.Bounds.Top);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void HorizontalStack_ArrangePositionsChildrenHorizontally()
|
||||
{
|
||||
// Arrange
|
||||
var stack = new SkiaStackLayout
|
||||
{
|
||||
Orientation = Microsoft.Maui.Platform.StackOrientation.Horizontal
|
||||
};
|
||||
|
||||
var child1 = new TestView { WidthRequest = 60, HeightRequest = 30 };
|
||||
var child2 = new TestView { WidthRequest = 60, HeightRequest = 30 };
|
||||
var child3 = new TestView { WidthRequest = 60, HeightRequest = 30 };
|
||||
|
||||
stack.AddChild(child1);
|
||||
stack.AddChild(child2);
|
||||
stack.AddChild(child3);
|
||||
|
||||
stack.Measure(new Size(600, 400));
|
||||
|
||||
// Act
|
||||
stack.Arrange(new Rect(0, 0, 600, 400));
|
||||
|
||||
// Assert - children should have increasing X positions
|
||||
child2.Bounds.Left.Should().BeGreaterThan(child1.Bounds.Left);
|
||||
child3.Bounds.Left.Should().BeGreaterThan(child2.Bounds.Left);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NestedStacks_MeasureCorrectly()
|
||||
{
|
||||
// Arrange
|
||||
var outerStack = new SkiaStackLayout
|
||||
{
|
||||
Orientation = Microsoft.Maui.Platform.StackOrientation.Vertical
|
||||
};
|
||||
|
||||
var innerStack = new SkiaStackLayout
|
||||
{
|
||||
Orientation = Microsoft.Maui.Platform.StackOrientation.Horizontal
|
||||
};
|
||||
|
||||
var innerChild1 = new TestView { WidthRequest = 50, HeightRequest = 30 };
|
||||
var innerChild2 = new TestView { WidthRequest = 50, HeightRequest = 30 };
|
||||
|
||||
innerStack.AddChild(innerChild1);
|
||||
innerStack.AddChild(innerChild2);
|
||||
|
||||
var outerChild = new TestView { WidthRequest = 100, HeightRequest = 40 };
|
||||
|
||||
outerStack.AddChild(innerStack);
|
||||
outerStack.AddChild(outerChild);
|
||||
|
||||
// Act
|
||||
var size = outerStack.Measure(new Size(400, 600));
|
||||
|
||||
// Assert - should measure without error and produce positive size
|
||||
size.Width.Should().BeGreaterThan(0);
|
||||
size.Height.Should().BeGreaterThan(0);
|
||||
// Height should include both the inner stack's height and the outer child
|
||||
size.Height.Should().BeGreaterThanOrEqualTo(30 + 40);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InvisibleChildren_ExcludedFromLayout()
|
||||
{
|
||||
// Arrange
|
||||
var stack = new SkiaStackLayout
|
||||
{
|
||||
Orientation = Microsoft.Maui.Platform.StackOrientation.Vertical
|
||||
};
|
||||
|
||||
var child1 = new TestView { HeightRequest = 30, WidthRequest = 100 };
|
||||
var child2 = new TestView { HeightRequest = 30, WidthRequest = 100, IsVisible = false };
|
||||
var child3 = new TestView { HeightRequest = 30, WidthRequest = 100 };
|
||||
|
||||
stack.AddChild(child1);
|
||||
stack.AddChild(child2);
|
||||
stack.AddChild(child3);
|
||||
|
||||
// Act
|
||||
var size = stack.Measure(new Size(400, 600));
|
||||
|
||||
// Assert - only 2 visible children, so height should reflect only 2 x 30 = 60
|
||||
// The invisible child should not contribute to measured height
|
||||
size.Height.Should().BeLessThan(90);
|
||||
size.Height.Should().BeGreaterThanOrEqualTo(60);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Spacing_AppliedBetweenVisibleChildrenOnly()
|
||||
{
|
||||
// Arrange - 3 children with spacing=10, middle one invisible
|
||||
var stack = new SkiaStackLayout
|
||||
{
|
||||
Orientation = Microsoft.Maui.Platform.StackOrientation.Vertical,
|
||||
Spacing = 10
|
||||
};
|
||||
|
||||
var child1 = new TestView { HeightRequest = 30, WidthRequest = 100 };
|
||||
var child2 = new TestView { HeightRequest = 30, WidthRequest = 100, IsVisible = false };
|
||||
var child3 = new TestView { HeightRequest = 30, WidthRequest = 100 };
|
||||
|
||||
stack.AddChild(child1);
|
||||
stack.AddChild(child2);
|
||||
stack.AddChild(child3);
|
||||
|
||||
// Act
|
||||
var size = stack.Measure(new Size(400, 600));
|
||||
|
||||
// Assert - 2 visible children with 1 gap of spacing=10
|
||||
// Expected: 30 + 10 + 30 = 70
|
||||
size.Height.Should().Be(70);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region GridIntegrationTests
|
||||
|
||||
public class GridIntegrationTests
|
||||
{
|
||||
[Fact]
|
||||
public void SingleCell_MeasuresChild()
|
||||
{
|
||||
// Arrange
|
||||
var grid = new SkiaGrid();
|
||||
grid.RowDefinitions.Add(Microsoft.Maui.Platform.GridLength.Auto);
|
||||
grid.ColumnDefinitions.Add(Microsoft.Maui.Platform.GridLength.Auto);
|
||||
|
||||
var button = new TestView { WidthRequest = 80, HeightRequest = 40 };
|
||||
grid.AddChild(button, row: 0, column: 0);
|
||||
|
||||
// Act
|
||||
var size = grid.Measure(new Size(400, 300));
|
||||
|
||||
// Assert - grid should measure to at least the child's requested size
|
||||
size.Width.Should().BeGreaterThanOrEqualTo(80);
|
||||
size.Height.Should().BeGreaterThanOrEqualTo(40);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TwoRows_ArrangePositionsCorrectly()
|
||||
{
|
||||
// Arrange
|
||||
var grid = new SkiaGrid();
|
||||
grid.RowDefinitions.Add(new Microsoft.Maui.Platform.GridLength(50));
|
||||
grid.RowDefinitions.Add(new Microsoft.Maui.Platform.GridLength(50));
|
||||
grid.ColumnDefinitions.Add(Microsoft.Maui.Platform.GridLength.Star);
|
||||
|
||||
var child1 = new TestView { WidthRequest = 100, HeightRequest = 30 };
|
||||
var child2 = new TestView { WidthRequest = 100, HeightRequest = 30 };
|
||||
|
||||
grid.AddChild(child1, row: 0, column: 0);
|
||||
grid.AddChild(child2, row: 1, column: 0);
|
||||
|
||||
grid.Measure(new Size(400, 300));
|
||||
|
||||
// Act
|
||||
grid.Arrange(new Rect(0, 0, 400, 300));
|
||||
|
||||
// Assert - second row child should be at Y >= 50
|
||||
child2.Bounds.Top.Should().BeGreaterThanOrEqualTo(50);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TwoColumns_ArrangePositionsCorrectly()
|
||||
{
|
||||
// Arrange
|
||||
var grid = new SkiaGrid();
|
||||
grid.RowDefinitions.Add(Microsoft.Maui.Platform.GridLength.Star);
|
||||
grid.ColumnDefinitions.Add(new Microsoft.Maui.Platform.GridLength(100));
|
||||
grid.ColumnDefinitions.Add(new Microsoft.Maui.Platform.GridLength(100));
|
||||
|
||||
var child1 = new TestView { WidthRequest = 80, HeightRequest = 30 };
|
||||
var child2 = new TestView { WidthRequest = 80, HeightRequest = 30 };
|
||||
|
||||
grid.AddChild(child1, row: 0, column: 0);
|
||||
grid.AddChild(child2, row: 0, column: 1);
|
||||
|
||||
grid.Measure(new Size(400, 300));
|
||||
|
||||
// Act
|
||||
grid.Arrange(new Rect(0, 0, 400, 300));
|
||||
|
||||
// Assert - second column child should be at X >= 100
|
||||
child2.Bounds.Left.Should().BeGreaterThanOrEqualTo(100);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EmptyGrid_MeasuresWithDefinitions()
|
||||
{
|
||||
// Arrange
|
||||
var grid = new SkiaGrid();
|
||||
grid.RowDefinitions.Add(new Microsoft.Maui.Platform.GridLength(60));
|
||||
grid.RowDefinitions.Add(new Microsoft.Maui.Platform.GridLength(40));
|
||||
grid.ColumnDefinitions.Add(new Microsoft.Maui.Platform.GridLength(120));
|
||||
grid.ColumnDefinitions.Add(new Microsoft.Maui.Platform.GridLength(80));
|
||||
|
||||
// Act - no children added
|
||||
var size = grid.Measure(new Size(400, 300));
|
||||
|
||||
// Assert - should still measure based on definitions
|
||||
// Width = 120 + 80 = 200, Height = 60 + 40 = 100
|
||||
size.Width.Should().BeGreaterThanOrEqualTo(200);
|
||||
size.Height.Should().BeGreaterThanOrEqualTo(100);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RowSpacing_IncludedInMeasure()
|
||||
{
|
||||
// Arrange
|
||||
var grid = new SkiaGrid { RowSpacing = 20 };
|
||||
grid.RowDefinitions.Add(new Microsoft.Maui.Platform.GridLength(50));
|
||||
grid.RowDefinitions.Add(new Microsoft.Maui.Platform.GridLength(50));
|
||||
grid.ColumnDefinitions.Add(Microsoft.Maui.Platform.GridLength.Star);
|
||||
|
||||
var child1 = new TestView { WidthRequest = 100, HeightRequest = 30 };
|
||||
var child2 = new TestView { WidthRequest = 100, HeightRequest = 30 };
|
||||
|
||||
grid.AddChild(child1, row: 0, column: 0);
|
||||
grid.AddChild(child2, row: 1, column: 0);
|
||||
|
||||
// Act
|
||||
var size = grid.Measure(new Size(400, 300));
|
||||
|
||||
// Assert - height should include row spacing: 50 + 20 + 50 = 120
|
||||
size.Height.Should().BeGreaterThanOrEqualTo(120);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region MeasureArrangePipelineTests
|
||||
|
||||
public class MeasureArrangePipelineTests
|
||||
{
|
||||
[Fact]
|
||||
public void Measure_PropagatesConstraints()
|
||||
{
|
||||
// Arrange - parent with padding subtracts from available space
|
||||
var stack = new SkiaStackLayout
|
||||
{
|
||||
Orientation = Microsoft.Maui.Platform.StackOrientation.Vertical,
|
||||
Padding = new Thickness(20)
|
||||
};
|
||||
|
||||
var child = new TestView { WidthRequest = 500, HeightRequest = 50 };
|
||||
stack.AddChild(child);
|
||||
|
||||
// Act
|
||||
stack.Measure(new Size(400, 600));
|
||||
|
||||
// Assert - child's DesiredSize should reflect WidthRequest/HeightRequest
|
||||
child.DesiredSize.Width.Should().Be(500);
|
||||
child.DesiredSize.Height.Should().Be(50);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Arrange_SetsBoundsOnChildren()
|
||||
{
|
||||
// Arrange
|
||||
var stack = new SkiaStackLayout
|
||||
{
|
||||
Orientation = Microsoft.Maui.Platform.StackOrientation.Vertical
|
||||
};
|
||||
|
||||
var child1 = new TestView { WidthRequest = 100, HeightRequest = 40 };
|
||||
var child2 = new TestView { WidthRequest = 100, HeightRequest = 40 };
|
||||
|
||||
stack.AddChild(child1);
|
||||
stack.AddChild(child2);
|
||||
|
||||
stack.Measure(new Size(400, 600));
|
||||
|
||||
// Act
|
||||
stack.Arrange(new Rect(0, 0, 400, 600));
|
||||
|
||||
// Assert - children should have non-zero bounds after arrange
|
||||
child1.Bounds.Width.Should().BeGreaterThan(0);
|
||||
child1.Bounds.Height.Should().BeGreaterThan(0);
|
||||
child2.Bounds.Width.Should().BeGreaterThan(0);
|
||||
child2.Bounds.Height.Should().BeGreaterThan(0);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InvalidateMeasure_CausesMeasureRecalculation()
|
||||
{
|
||||
// Arrange
|
||||
var stack = new SkiaStackLayout
|
||||
{
|
||||
Orientation = Microsoft.Maui.Platform.StackOrientation.Vertical
|
||||
};
|
||||
|
||||
var child = new TestView { WidthRequest = 100, HeightRequest = 30 };
|
||||
stack.AddChild(child);
|
||||
|
||||
// First measure
|
||||
var size1 = stack.Measure(new Size(400, 600));
|
||||
|
||||
// Act - change child property and invalidate
|
||||
child.HeightRequest = 60;
|
||||
child.InvalidateMeasure();
|
||||
|
||||
// Re-measure
|
||||
var size2 = stack.Measure(new Size(400, 600));
|
||||
|
||||
// Assert - new measured size should reflect the change
|
||||
size2.Height.Should().BeGreaterThan(size1.Height);
|
||||
size2.Height.Should().BeGreaterThanOrEqualTo(60);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DesiredSize_SetAfterMeasure()
|
||||
{
|
||||
// Arrange
|
||||
var view = new TestView { WidthRequest = 120, HeightRequest = 45 };
|
||||
|
||||
// Before measure, DesiredSize should be zero
|
||||
view.DesiredSize.Should().Be(Size.Zero);
|
||||
|
||||
// Act
|
||||
var measured = view.Measure(new Size(400, 600));
|
||||
|
||||
// Assert - DesiredSize should reflect the measured size
|
||||
view.DesiredSize.Width.Should().Be(measured.Width);
|
||||
view.DesiredSize.Height.Should().Be(measured.Height);
|
||||
view.DesiredSize.Width.Should().BeGreaterThan(0);
|
||||
view.DesiredSize.Height.Should().BeGreaterThan(0);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
201
tests/Views/SkiaViewTheoryTests.cs
Normal file
201
tests/Views/SkiaViewTheoryTests.cs
Normal file
@@ -0,0 +1,201 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
using FluentAssertions;
|
||||
using Microsoft.Maui.Graphics;
|
||||
using Microsoft.Maui.Platform;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.Maui.Controls.Linux.Tests.Views;
|
||||
|
||||
public class SkiaLabelTheoryTests
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(FontAttributes.None)]
|
||||
[InlineData(FontAttributes.Bold)]
|
||||
[InlineData(FontAttributes.Italic)]
|
||||
[InlineData(FontAttributes.Bold | FontAttributes.Italic)]
|
||||
public void FontAttributes_AllValues_CanBeSet(FontAttributes attributes)
|
||||
{
|
||||
// Arrange
|
||||
var label = new SkiaLabel();
|
||||
|
||||
// Act
|
||||
label.FontAttributes = attributes;
|
||||
|
||||
// Assert
|
||||
label.FontAttributes.Should().Be(attributes);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(TextAlignment.Start)]
|
||||
[InlineData(TextAlignment.Center)]
|
||||
[InlineData(TextAlignment.End)]
|
||||
public void HorizontalTextAlignment_AllValues_CanBeSet(TextAlignment alignment)
|
||||
{
|
||||
// Arrange
|
||||
var label = new SkiaLabel();
|
||||
|
||||
// Act
|
||||
label.HorizontalTextAlignment = alignment;
|
||||
|
||||
// Assert
|
||||
label.HorizontalTextAlignment.Should().Be(alignment);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(TextAlignment.Start)]
|
||||
[InlineData(TextAlignment.Center)]
|
||||
[InlineData(TextAlignment.End)]
|
||||
public void VerticalTextAlignment_AllValues_CanBeSet(TextAlignment alignment)
|
||||
{
|
||||
// Arrange
|
||||
var label = new SkiaLabel();
|
||||
|
||||
// Act
|
||||
label.VerticalTextAlignment = alignment;
|
||||
|
||||
// Assert
|
||||
label.VerticalTextAlignment.Should().Be(alignment);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(TextDecorations.None)]
|
||||
[InlineData(TextDecorations.Underline)]
|
||||
[InlineData(TextDecorations.Strikethrough)]
|
||||
public void TextDecorations_AllValues_CanBeSet(TextDecorations decorations)
|
||||
{
|
||||
// Arrange
|
||||
var label = new SkiaLabel();
|
||||
|
||||
// Act
|
||||
label.TextDecorations = decorations;
|
||||
|
||||
// Assert
|
||||
label.TextDecorations.Should().Be(decorations);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(LineBreakMode.NoWrap)]
|
||||
[InlineData(LineBreakMode.WordWrap)]
|
||||
[InlineData(LineBreakMode.CharacterWrap)]
|
||||
[InlineData(LineBreakMode.HeadTruncation)]
|
||||
[InlineData(LineBreakMode.TailTruncation)]
|
||||
[InlineData(LineBreakMode.MiddleTruncation)]
|
||||
public void LineBreakMode_AllValues_CanBeSet(LineBreakMode mode)
|
||||
{
|
||||
// Arrange
|
||||
var label = new SkiaLabel();
|
||||
|
||||
// Act
|
||||
label.LineBreakMode = mode;
|
||||
|
||||
// Assert
|
||||
label.LineBreakMode.Should().Be(mode);
|
||||
}
|
||||
}
|
||||
|
||||
public class SkiaViewVisibilityTheoryTests
|
||||
{
|
||||
public static IEnumerable<object[]> ViewInstances()
|
||||
{
|
||||
yield return new object[] { new SkiaLabel() };
|
||||
yield return new object[] { new SkiaButton() };
|
||||
yield return new object[] { new SkiaCheckBox() };
|
||||
yield return new object[] { new SkiaEntry() };
|
||||
yield return new object[] { new SkiaProgressBar() };
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(ViewInstances))]
|
||||
public void AllViews_DefaultVisible(SkiaView view)
|
||||
{
|
||||
// Assert
|
||||
view.IsVisible.Should().BeTrue();
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(ViewInstances))]
|
||||
public void AllViews_DefaultEnabled(SkiaView view)
|
||||
{
|
||||
// Assert
|
||||
view.IsEnabled.Should().BeTrue();
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(ViewInstances))]
|
||||
public void AllViews_CanBeDisabled(SkiaView view)
|
||||
{
|
||||
// Act
|
||||
view.IsEnabled = false;
|
||||
|
||||
// Assert
|
||||
view.IsEnabled.Should().BeFalse();
|
||||
}
|
||||
}
|
||||
|
||||
public class SkiaSliderTheoryTests
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(0, 100, 50, 50)]
|
||||
[InlineData(0, 100, -10, 0)]
|
||||
[InlineData(0, 100, 200, 100)]
|
||||
[InlineData(0, 1, 0.5, 0.5)]
|
||||
[InlineData(10, 20, 15, 15)]
|
||||
public void Value_ClampsToRange(double min, double max, double setValue, double expectedValue)
|
||||
{
|
||||
// Arrange
|
||||
var slider = new SkiaSlider();
|
||||
|
||||
// Always set Maximum before Minimum when Minimum > default (1.0)
|
||||
slider.Maximum = max;
|
||||
slider.Minimum = min;
|
||||
|
||||
// Act
|
||||
slider.Value = setValue;
|
||||
|
||||
// Assert
|
||||
slider.Value.Should().Be(expectedValue);
|
||||
}
|
||||
}
|
||||
|
||||
public class SkiaEntryTextTheoryTests
|
||||
{
|
||||
[Theory]
|
||||
[InlineData("")]
|
||||
[InlineData("Hello")]
|
||||
[InlineData("Hello World with spaces")]
|
||||
[InlineData("Special chars: !@#$%^&*()")]
|
||||
[InlineData("Unicode: \u3053\u3093\u306B\u3061\u306F")]
|
||||
[InlineData("This is a very long string that exceeds one hundred characters in length to test how the SkiaEntry control handles lengthy text input values properly")]
|
||||
public void Text_VariousStrings_SetCorrectly(string text)
|
||||
{
|
||||
// Arrange
|
||||
var entry = new SkiaEntry();
|
||||
|
||||
// Act
|
||||
entry.Text = text;
|
||||
|
||||
// Assert
|
||||
entry.Text.Should().Be(text);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("")]
|
||||
[InlineData("Hello")]
|
||||
[InlineData("Hello World with spaces")]
|
||||
[InlineData("Special chars: !@#$%^&*()")]
|
||||
[InlineData("Unicode: \u3053\u3093\u306B\u3061\u306F")]
|
||||
[InlineData("This is a very long string that exceeds one hundred characters in length to test how the SkiaEntry control handles lengthy placeholder text values properly")]
|
||||
public void Placeholder_VariousStrings_SetCorrectly(string placeholder)
|
||||
{
|
||||
// Arrange
|
||||
var entry = new SkiaEntry();
|
||||
|
||||
// Act
|
||||
entry.Placeholder = placeholder;
|
||||
|
||||
// Assert
|
||||
entry.Placeholder.Should().Be(placeholder);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user