diff --git a/.github/workflows/build_artifacts.yml b/.github/workflows/build_artifacts.yml index 851278a9dc..389c02a410 100644 --- a/.github/workflows/build_artifacts.yml +++ b/.github/workflows/build_artifacts.yml @@ -54,7 +54,7 @@ jobs: uses: actions/upload-artifact@v4 with: name: Screenshots-${{ github.run_number }} - path: ${{ github.workspace }}tests\MaterialDesignThemes.UITests\bin\${{ inputs.build-configuration }}\net8.0-windows7\Screenshots + path: ${{ github.workspace }}\tests\MaterialDesignThemes.UITests\bin\${{ inputs.build-configuration }}\net9.0-windows\Screenshots if-no-files-found: ignore - name: Build NuGets diff --git a/Directory.packages.props b/Directory.packages.props index 8fa27d2bfd..37ca871f37 100644 --- a/Directory.packages.props +++ b/Directory.packages.props @@ -1,9 +1,9 @@ - + - + @@ -14,7 +14,7 @@ - + @@ -24,11 +24,10 @@ + + - - - - + diff --git a/src/MaterialDesignColors.Wpf/SwatchesProvider.cs b/src/MaterialDesignColors.Wpf/SwatchesProvider.cs index 81385d83bb..3caefa06bc 100644 --- a/src/MaterialDesignColors.Wpf/SwatchesProvider.cs +++ b/src/MaterialDesignColors.Wpf/SwatchesProvider.cs @@ -12,6 +12,7 @@ namespace MaterialDesignColors; /// public class SwatchesProvider { + private static readonly object _syncLock = new(); /// /// Generates an instance reading swatches from the provided assembly, allowing /// colours outside of the standard material palette to be loaded provided the are stored in the expected XAML format. @@ -39,12 +40,7 @@ public SwatchesProvider(Assembly assembly) Read(assemblyName, x.SingleOrDefault(y => y.match.Groups["type"].Value == "primary")?.key), Read(assemblyName, x.SingleOrDefault(y => y.match.Groups["type"].Value == "secondary")?.key) )) - .ToList() ?? -#if NETCOREAPP3_1_OR_GREATER - (IEnumerable)Array.Empty(); -#else - (IEnumerable)new Swatch[0]; -#endif + .ToList() ?? []; } /// @@ -98,8 +94,12 @@ static Hue GetHue(ResourceDictionary dictionary, DictionaryEntry entry) if (assemblyName is null || path is null) return null; - return (ResourceDictionary)Application.LoadComponent(new Uri( - $"/{assemblyName};component/{path.Replace(".baml", ".xaml")}", - UriKind.RelativeOrAbsolute)); + lock (_syncLock) + { + //NB: Application.LoadComponent is not thread safe + return (ResourceDictionary)Application.LoadComponent(new Uri( + $"/{assemblyName};component/{path.Replace(".baml", ".xaml")}", + UriKind.RelativeOrAbsolute)); + } } } diff --git a/src/MaterialDesignThemes.Wpf/DialogHost.cs b/src/MaterialDesignThemes.Wpf/DialogHost.cs index 2a3bd59f77..a1b31e2e9c 100644 --- a/src/MaterialDesignThemes.Wpf/DialogHost.cs +++ b/src/MaterialDesignThemes.Wpf/DialogHost.cs @@ -50,7 +50,7 @@ public class DialogHost : ContentControl /// public static readonly RoutedCommand CloseDialogCommand = new(); - private static readonly HashSet> LoadedInstances = new(); + private static readonly HashSet> LoadedInstances = []; private DialogOpenedEventHandler? _asyncShowOpenedEventHandler; private DialogClosingEventHandler? _asyncShowClosingEventHandler; @@ -221,7 +221,7 @@ private static DialogHost GetInstance(object? dialogIdentifier) if (LoadedInstances.Count == 0) throw new InvalidOperationException("No loaded DialogHost instances."); - List targets = new(); + List targets = []; foreach (var instance in LoadedInstances.ToList()) { if (instance.TryGetTarget(out DialogHost? dialogInstance)) diff --git a/src/MaterialDesignThemes.Wpf/Internal/TreeListViewItemsCollection.cs b/src/MaterialDesignThemes.Wpf/Internal/TreeListViewItemsCollection.cs index 324e1c1b69..0405bf0498 100644 --- a/src/MaterialDesignThemes.Wpf/Internal/TreeListViewItemsCollection.cs +++ b/src/MaterialDesignThemes.Wpf/Internal/TreeListViewItemsCollection.cs @@ -6,8 +6,8 @@ namespace MaterialDesignThemes.Wpf.Internal; public class TreeListViewItemsCollection : ObservableCollection { - private List ItemLevels { get; } = new(); - private List ItemIsExpanded { get; } = new(); + private List ItemLevels { get; } = []; + private List ItemIsExpanded { get; } = []; public TreeListViewItemsCollection(object? wrappedSource) { diff --git a/src/MaterialDesignThemes.Wpf/RatingBar.cs b/src/MaterialDesignThemes.Wpf/RatingBar.cs index 2f1b43c3ac..fd45af708b 100644 --- a/src/MaterialDesignThemes.Wpf/RatingBar.cs +++ b/src/MaterialDesignThemes.Wpf/RatingBar.cs @@ -378,7 +378,7 @@ internal class TextBlockForegroundConverter : IMultiValueConverter public static TextBlockForegroundConverter Instance { get; } = new(); - public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) + public object? Convert(object?[]? values, Type targetType, object? parameter, CultureInfo culture) { if (values?.Length == 5 && values[0] is SolidColorBrush brush @@ -411,28 +411,28 @@ public object Convert(object[] values, Type targetType, object parameter, Cultur return new SolidColorBrush(semiTransparent); } - GradientStopCollection CreateGradientStopCollection(Color originalColor, Color semiTransparent, double offset, bool invertDirection) + static GradientStopCollection CreateGradientStopCollection(Color originalColor, Color semiTransparent, double offset, bool invertDirection) { if (invertDirection) { - return new() - { - new GradientStop {Color = semiTransparent, Offset = offset}, - new GradientStop {Color = originalColor, Offset = offset}, - }; - } - return new() - { + return + [ + new GradientStop {Color = semiTransparent, Offset = offset}, new GradientStop {Color = originalColor, Offset = offset}, - new GradientStop {Color = semiTransparent, Offset = offset} - }; + ]; + } + return + [ + new GradientStop {Color = originalColor, Offset = offset}, + new GradientStop {Color = semiTransparent, Offset = offset} + ]; } // This should never happen (returning actual brush to avoid the compilers squiggly line warning) return Brushes.Transparent; } - public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) => throw new NotImplementedException(); + public object?[]? ConvertBack(object? value, Type[] targetTypes, object? parameter, CultureInfo culture) => throw new NotImplementedException(); } internal class PreviewIndicatorTransformXConverter : IMultiValueConverter @@ -441,9 +441,9 @@ internal class PreviewIndicatorTransformXConverter : IMultiValueConverter internal static double Margin => 2.0; - public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) + public object? Convert(object?[]? values, Type targetType, object? parameter, CultureInfo culture) { - if (values.Length >= 7 + if (values?.Length >= 7 && values[0] is double ratingBarButtonActualWidth && values[1] is double previewValueActualWidth && values[2] is Orientation ratingBarOrientation @@ -482,7 +482,7 @@ public object Convert(object[] values, Type targetType, object parameter, Cultur return 1.0; } - public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) => throw new NotImplementedException(); + public object?[]? ConvertBack(object? value, Type[] targetTypes, object? parameter, CultureInfo culture) => throw new NotImplementedException(); } internal class PreviewIndicatorTransformYConverter : IMultiValueConverter @@ -491,9 +491,9 @@ internal class PreviewIndicatorTransformYConverter : IMultiValueConverter internal static double Margin => 2.0; - public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) + public object? Convert(object?[]? values, Type targetType, object? parameter, CultureInfo culture) { - if (values.Length >= 7 + if (values?.Length >= 7 && values[0] is double ratingBarButtonActualHeight && values[1] is double previewValueActualHeight && values[2] is Orientation ratingBarOrientation @@ -531,6 +531,6 @@ public object Convert(object[] values, Type targetType, object parameter, Cultur return 1.0; } - public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) => throw new NotImplementedException(); + public object?[]? ConvertBack(object? value, Type[] targetTypes, object? parameter, CultureInfo culture) => throw new NotImplementedException(); } } diff --git a/src/MaterialDesignThemes.Wpf/ResourceDictionaryExtensions.g.cs b/src/MaterialDesignThemes.Wpf/ResourceDictionaryExtensions.g.cs index 0bbf247c4b..e80cc45778 100644 --- a/src/MaterialDesignThemes.Wpf/ResourceDictionaryExtensions.g.cs +++ b/src/MaterialDesignThemes.Wpf/ResourceDictionaryExtensions.g.cs @@ -1,6 +1,6 @@ //------------------------------------------------------------------------------ // -// This code was generated by mdresgen. +// This code was generated by MaterialDesignToolkit.ResourceGeneration. // //------------------------------------------------------------------------------ diff --git a/src/MaterialDesignThemes.Wpf/Theme.g.cs b/src/MaterialDesignThemes.Wpf/Theme.g.cs index 77720d50fe..d6cdffd3a6 100644 --- a/src/MaterialDesignThemes.Wpf/Theme.g.cs +++ b/src/MaterialDesignThemes.Wpf/Theme.g.cs @@ -1,6 +1,6 @@ //------------------------------------------------------------------------------ // -// This code was generated by mdresgen. +// This code was generated by MaterialDesignToolkit.ResourceGeneration. // //------------------------------------------------------------------------------ diff --git a/src/MaterialDesignThemes.Wpf/ThemeExtensions.g.cs b/src/MaterialDesignThemes.Wpf/ThemeExtensions.g.cs index 366f190e7e..a304456e89 100644 --- a/src/MaterialDesignThemes.Wpf/ThemeExtensions.g.cs +++ b/src/MaterialDesignThemes.Wpf/ThemeExtensions.g.cs @@ -1,6 +1,6 @@ //------------------------------------------------------------------------------ // -// This code was generated by mdresgen. +// This code was generated by MaterialDesignToolkit.ResourceGeneration. // //------------------------------------------------------------------------------ diff --git a/src/MaterialDesignToolkit.ResourceGeneration/Brushes.cs b/src/MaterialDesignToolkit.ResourceGeneration/Brushes.cs index ca1354b481..212aadb789 100644 --- a/src/MaterialDesignToolkit.ResourceGeneration/Brushes.cs +++ b/src/MaterialDesignToolkit.ResourceGeneration/Brushes.cs @@ -482,7 +482,7 @@ void WriteBrush(Brush brush, string name) {{indent}}{{indent}}{ {{indent}}{{indent}}{{indent}}IVisualElement textBlock = await panel.GetElement("[Text=\"{{name}}\"]"); {{indent}}{{indent}}{{indent}}Color? textBlockBackground = await textBlock.GetBackgroundColor(); - {{indent}}{{indent}}{{indent}}Assert.Equal(await GetResourceColor("{{brush.Name}}"), textBlockBackground); + {{indent}}{{indent}}{{indent}}await Assert.That(textBlockBackground).IsEqualTo(await GetResourceColor("{{brush.Name}}")); {{indent}}{{indent}}} """); } diff --git a/tests/MaterialDesignColors.Wpf.Tests/ColorAssistTests.cs b/tests/MaterialDesignColors.Wpf.Tests/ColorAssistTests.cs index 47b0bf905a..919c47035a 100644 --- a/tests/MaterialDesignColors.Wpf.Tests/ColorAssistTests.cs +++ b/tests/MaterialDesignColors.Wpf.Tests/ColorAssistTests.cs @@ -1,13 +1,12 @@ using System.Windows.Media; using MaterialDesignColors.ColorManipulation; -using Xunit; namespace MaterialDesignColors.Wpf.Tests; public class ColorAssistTests { - [Fact] - public void EnsureContrastRatio_AdjustsColor() + [Test] + public async Task EnsureContrastRatio_AdjustsColor() { var background = Color.FromRgb(0xFA, 0xFA, 0xFA); var foreground = Color.FromRgb(0xFF, 0xC1, 0x07); @@ -15,7 +14,7 @@ public void EnsureContrastRatio_AdjustsColor() var adjusted = foreground.EnsureContrastRatio(background, 3.0f); double contrastRatio = adjusted.ContrastRatio(background); - Assert.True(contrastRatio >= 2.9); - Assert.True(contrastRatio <= 3.1); + await Assert.That(contrastRatio).IsGreaterThanOrEqualTo(2.9); + await Assert.That(contrastRatio).IsLessThanOrEqualTo(3.1); } } diff --git a/tests/MaterialDesignColors.Wpf.Tests/MaterialDesignColors.Wpf.Tests.csproj b/tests/MaterialDesignColors.Wpf.Tests/MaterialDesignColors.Wpf.Tests.csproj index f2ab67fc5e..079e511042 100644 --- a/tests/MaterialDesignColors.Wpf.Tests/MaterialDesignColors.Wpf.Tests.csproj +++ b/tests/MaterialDesignColors.Wpf.Tests/MaterialDesignColors.Wpf.Tests.csproj @@ -4,6 +4,9 @@ net472;net8.0-windows MaterialDesignColors.Wpf.Tests MaterialDesignColors.Wpf.Tests + true + Exe + true @@ -25,9 +28,9 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - - - - + + + + \ No newline at end of file diff --git a/tests/MaterialDesignColors.Wpf.Tests/ResourceProviderFixture.cs b/tests/MaterialDesignColors.Wpf.Tests/ResourceProviderFixture.cs index d54a25183a..4f3eeac307 100644 --- a/tests/MaterialDesignColors.Wpf.Tests/ResourceProviderFixture.cs +++ b/tests/MaterialDesignColors.Wpf.Tests/ResourceProviderFixture.cs @@ -1,65 +1,62 @@ -using Shouldly; -using Xunit; - -namespace MaterialDesignColors.Wpf.Fixture; +namespace MaterialDesignColors.Wpf.Tests; public class ResourceProviderFixture { - [Fact] - public void ExcludesBlack() + [Test] + public async Task ExcludesBlack() { SwatchesProvider swatchesProvider = new (); bool containsBlack = swatchesProvider.Swatches.Any( swatch => string.Compare(swatch.Name, "Black", StringComparison.InvariantCultureIgnoreCase) == 0); - containsBlack.ShouldBe(false); + await Assert.That(containsBlack).IsFalse(); } - [Fact] - public void IncludesGrey() + [Test] + public async Task IncludesGrey() { SwatchesProvider swatchesProvider = new (); bool containsBlack = swatchesProvider.Swatches.Any( swatch => string.Compare(swatch.Name, "Grey", StringComparison.InvariantCultureIgnoreCase) == 0); - containsBlack.ShouldBe(true); + await Assert.That(containsBlack).IsTrue(); } - [Fact] - public void BrownHasNoSecondary() + [Test] + public async Task BrownHasNoSecondary() { SwatchesProvider swatchesProvider = new (); var brownSwatch = swatchesProvider.Swatches.Single( swatch => swatch.Name == "brown"); - brownSwatch.SecondaryHues.ShouldNotBeNull(); - brownSwatch.SecondaryHues.Count.ShouldBe(0); + await Assert.That(brownSwatch.SecondaryHues).IsNotNull(); + await Assert.That(brownSwatch.SecondaryHues.Count).IsEqualTo(0); } - [Fact] - public void BrownHasPrimaries() + [Test] + public async Task BrownHasPrimaries() { SwatchesProvider swatchesProvider = new (); var brownSwatch = swatchesProvider.Swatches.Single( swatch => swatch.Name == "brown"); - brownSwatch.PrimaryHues.ShouldNotBeNull(); - brownSwatch.PrimaryHues.Count.ShouldBe(10); + await Assert.That(brownSwatch.PrimaryHues).IsNotNull(); + await Assert.That(brownSwatch.PrimaryHues.Count).IsEqualTo(10); } - [Fact] - public void IndigoHasSecondaries() + [Test] + public async Task IndigoHasSecondaries() { SwatchesProvider swatchesProvider = new (); var brownSwatch = swatchesProvider.Swatches.Single( swatch => swatch.Name == "indigo"); - brownSwatch.SecondaryHues.ShouldNotBeNull(); - brownSwatch.SecondaryHues.Count.ShouldBe(4); + await Assert.That(brownSwatch.SecondaryHues).IsNotNull(); + await Assert.That(brownSwatch.SecondaryHues.Count).IsEqualTo(4); } } diff --git a/tests/MaterialDesignThemes.UITests/AllStyles.cs b/tests/MaterialDesignThemes.UITests/AllStyles.cs index 2710e4b0fe..5d3c6c0f01 100644 --- a/tests/MaterialDesignThemes.UITests/AllStyles.cs +++ b/tests/MaterialDesignThemes.UITests/AllStyles.cs @@ -1,40 +1,35 @@ -using System.Reflection; -using MaterialDesignColors; +using MaterialDesignColors; namespace MaterialDesignThemes.UITests; public class AllStyles : TestBase { - public AllStyles(ITestOutputHelper output) - : base(output) - { } - - [Theory] - [InlineData("Button", "MaterialDesignRaisedButton")] - [InlineData("Calendar", "MaterialDesignCalendarPortrait")] - [InlineData("CheckBox", "MaterialDesignCheckBox")] - [InlineData("ComboBox", "MaterialDesignComboBox")] - [InlineData("DataGrid", "MaterialDesignDataGrid")] - [InlineData("DatePicker", "MaterialDesignDatePicker")] - [InlineData("Expander", "MaterialDesignExpander")] - [InlineData("GridSplitter", "MaterialDesignGridSplitter")] - [InlineData("GroupBox", "MaterialDesignGroupBox")] - [InlineData("Label", "MaterialDesignLabel")] - [InlineData("ListBox", "MaterialDesignListBox")] - [InlineData("ListView", "MaterialDesignListView")] - [InlineData("Menu", "MaterialDesignMenu")] - [InlineData("PasswordBox", "MaterialDesignPasswordBox")] - [InlineData("ProgressBar", "MaterialDesignLinearProgressBar")] - [InlineData("RadioButton", "MaterialDesignRadioButton")] - [InlineData("RichTextBox", "MaterialDesignRichTextBox")] - [InlineData("ScrollBar", "MaterialDesignScrollBar")] - [InlineData("ScrollViewer", "MaterialDesignScrollViewer")] - [InlineData("Slider", "MaterialDesignSlider")] - [InlineData("TabControl", "MaterialDesignTabControl")] - [InlineData("TextBox", "MaterialDesignTextBox")] - [InlineData("ToggleButton", "MaterialDesignSwitchToggleButton")] - [InlineData("ToolBar", "MaterialDesignToolBar")] - [InlineData("TreeView", "MaterialDesignTreeView")] + [Test] + [Arguments("Button", "MaterialDesignRaisedButton")] + [Arguments("Calendar", "MaterialDesignCalendarPortrait")] + [Arguments("CheckBox", "MaterialDesignCheckBox")] + [Arguments("ComboBox", "MaterialDesignComboBox")] + [Arguments("DataGrid", "MaterialDesignDataGrid")] + [Arguments("DatePicker", "MaterialDesignDatePicker")] + [Arguments("Expander", "MaterialDesignExpander")] + [Arguments("GridSplitter", "MaterialDesignGridSplitter")] + [Arguments("GroupBox", "MaterialDesignGroupBox")] + [Arguments("Label", "MaterialDesignLabel")] + [Arguments("ListBox", "MaterialDesignListBox")] + [Arguments("ListView", "MaterialDesignListView")] + [Arguments("Menu", "MaterialDesignMenu")] + [Arguments("PasswordBox", "MaterialDesignPasswordBox")] + [Arguments("ProgressBar", "MaterialDesignLinearProgressBar")] + [Arguments("RadioButton", "MaterialDesignRadioButton")] + [Arguments("RichTextBox", "MaterialDesignRichTextBox")] + [Arguments("ScrollBar", "MaterialDesignScrollBar")] + [Arguments("ScrollViewer", "MaterialDesignScrollViewer")] + [Arguments("Slider", "MaterialDesignSlider")] + [Arguments("TabControl", "MaterialDesignTabControl")] + [Arguments("TextBox", "MaterialDesignTextBox")] + [Arguments("ToggleButton", "MaterialDesignSwitchToggleButton")] + [Arguments("ToolBar", "MaterialDesignToolBar")] + [Arguments("TreeView", "MaterialDesignTreeView")] public async Task LoadStyleInIsolation_CanBeLoaded(string controlName, string styleName) { await using var recorder = new TestRecorder(App); @@ -57,7 +52,7 @@ public async Task LoadStyleInIsolation_CanBeLoaded(string controlName, string st await App.Initialize(applicationResourceXaml, Path.GetFullPath("MaterialDesignColors.dll"), Path.GetFullPath("MaterialDesignThemes.Wpf.dll"), - Assembly.GetExecutingAssembly().Location); + System.Reflection.Assembly.GetExecutingAssembly().Location); IWindow window = await App.CreateWindow($$""" """); - Assert.True(await window.GetIsVisible()); + await Assert.That(await window.GetIsVisible()).IsTrue(); recorder.Success(); } diff --git a/tests/MaterialDesignThemes.UITests/MaterialDesignSpec.cs b/tests/MaterialDesignThemes.UITests/MaterialDesignSpec.cs index 7247b4d8a6..4de16f29ee 100644 --- a/tests/MaterialDesignThemes.UITests/MaterialDesignSpec.cs +++ b/tests/MaterialDesignThemes.UITests/MaterialDesignSpec.cs @@ -17,11 +17,12 @@ public static class MaterialDesignSpec /// public const double MinimumContrastLargeText = 3.0; - public static void AssertContrastRatio(Color foreground, Color background, double minimumContrastRatio) + public static async Task AssertContrastRatio(Color foreground, Color background, double minimumContrastRatio) { const double tolerance = 0.1; - var ratio = ColorAssist.ContrastRatio(foreground, background); - Assert.True(ratio >= minimumContrastRatio - tolerance, $"Contrast ratio '{ratio}' is less than {minimumContrastRatio} with a tolerance of 0.1"); + double ratio = ColorAssist.ContrastRatio(foreground, background); + await Assert.That(ratio).IsGreaterThanOrEqualTo(minimumContrastRatio - tolerance) + .Because($"Contrast ratio '{ratio}' is less than {minimumContrastRatio} with a tolerance of 0.1"); } } diff --git a/tests/MaterialDesignThemes.UITests/MaterialDesignThemes.UITests.csproj b/tests/MaterialDesignThemes.UITests/MaterialDesignThemes.UITests.csproj index 2612cc5af3..8e78308ec4 100644 --- a/tests/MaterialDesignThemes.UITests/MaterialDesignThemes.UITests.csproj +++ b/tests/MaterialDesignThemes.UITests/MaterialDesignThemes.UITests.csproj @@ -6,6 +6,9 @@ true $(NoWarn);CA1707 true + true + Exe + true @@ -19,18 +22,13 @@ - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - + + - - diff --git a/tests/MaterialDesignThemes.UITests/Samples/Validation/ValidationUpdates.xaml.cs b/tests/MaterialDesignThemes.UITests/Samples/Validation/ValidationUpdates.xaml.cs index 719ead86b2..6d830021a8 100644 --- a/tests/MaterialDesignThemes.UITests/Samples/Validation/ValidationUpdates.xaml.cs +++ b/tests/MaterialDesignThemes.UITests/Samples/Validation/ValidationUpdates.xaml.cs @@ -1,6 +1,6 @@ using System.Collections; using System.ComponentModel; -using System.ComponentModel.DataAnnotations; +using System.Threading; using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; @@ -46,7 +46,7 @@ private async Task CauseErrors() { Error = "Some error"; ErrorsChanged?.Invoke(this, new DataErrorsChangedEventArgs(nameof(Text))); - await Task.Delay(100); + await Task.Delay(100, CancellationToken.None); Error += " + more"; ErrorsChanged?.Invoke(this, new DataErrorsChangedEventArgs(nameof(Text))); } diff --git a/tests/MaterialDesignThemes.UITests/TUnit/IsCloseToExtensions.cs b/tests/MaterialDesignThemes.UITests/TUnit/IsCloseToExtensions.cs new file mode 100644 index 0000000000..1ae6934500 --- /dev/null +++ b/tests/MaterialDesignThemes.UITests/TUnit/IsCloseToExtensions.cs @@ -0,0 +1,51 @@ +using System.Numerics; +using System.Runtime.CompilerServices; +using TUnit.Assertions.AssertConditions; +using TUnit.Assertions.AssertConditions.Interfaces; +using TUnit.Assertions.AssertionBuilders; + +namespace MaterialDesignThemes.Tests.TUnit; + +public static class IsCloseToExtensions +{ + public static IsCloseToWrapper IsCloseTo(this IValueSource valueSource, double expected, double precision, [CallerArgumentExpression(nameof(expected))] string? doNotPopulateThisValue1 = null, [CallerArgumentExpression(nameof(precision))] string? doNotPopulateThisValue2 = null) + { + var assertionBuilder = valueSource.RegisterAssertion(new IsCloseToCondition(expected, precision) + , [doNotPopulateThisValue1, doNotPopulateThisValue2]); + + return new IsCloseToWrapper(assertionBuilder); + } + + public static IsCloseToWrapper IsCloseTo(this IValueSource valueSource, float expected, float precision, [CallerArgumentExpression(nameof(expected))] string? doNotPopulateThisValue1 = null, [CallerArgumentExpression(nameof(precision))] string? doNotPopulateThisValue2 = null) + { + var assertionBuilder = valueSource.RegisterAssertion(new IsCloseToCondition(expected, precision) + , [doNotPopulateThisValue1, doNotPopulateThisValue2]); + + return new IsCloseToWrapper(assertionBuilder); + } +} + +public class IsCloseToWrapper(InvokableAssertionBuilder invokableAssertionBuilder) + : InvokableValueAssertionBuilder(invokableAssertionBuilder); + +file class IsCloseToCondition(TActual expected, TActual tolerance) : BaseAssertCondition + where TActual : + IFloatingPoint, + INumberBase +{ + protected override string GetExpectation() => $"to be within {tolerance} of {expected}"; + + protected override ValueTask GetResult( + TActual? actualValue, Exception? exception, + AssertionMetadata assertionMetadata + ) + { + if(actualValue is null) + return AssertionResult.Fail("received null"); + + TActual difference = actualValue - expected; + TActual absoluteDifference = TActual.Abs(difference); + bool isInRange = absoluteDifference <= tolerance; + return AssertionResult.FailIf(!isInRange, $"received {actualValue}"); + } +} diff --git a/tests/MaterialDesignThemes.UITests/TestBase.cs b/tests/MaterialDesignThemes.UITests/TestBase.cs index 66615f971c..e2aeac2535 100644 --- a/tests/MaterialDesignThemes.UITests/TestBase.cs +++ b/tests/MaterialDesignThemes.UITests/TestBase.cs @@ -1,7 +1,10 @@ using System.Diagnostics.CodeAnalysis; using System.Windows.Media; +using MaterialDesignThemes.UITests; +using TUnit.Core.Interfaces; + +[assembly: ParallelLimiter] -[assembly: CollectionBehavior(DisableTestParallelization = true)] [assembly: GenerateHelpers(typeof(AutoSuggestBox))] [assembly: GenerateHelpers(typeof(ColorPicker))] [assembly: GenerateHelpers(typeof(DecimalUpDown))] @@ -16,10 +19,15 @@ namespace MaterialDesignThemes.UITests; -public abstract class TestBase(ITestOutputHelper output) : IAsyncLifetime +public record SingleParallelLimit : IParallelLimit +{ + public int Limit => 1; +} + +public abstract class TestBase() { protected bool AttachedDebuggerToRemoteProcess { get; set; } = true; - protected ITestOutputHelper Output { get; } = output ?? throw new ArgumentNullException(nameof(output)); + protected static TextWriter Output => TestContext.Current?.OutputWriter ?? throw new InvalidOperationException("Could not find output writer"); [NotNull] protected IApp? App { get; set; } @@ -46,7 +54,8 @@ protected async Task LoadUserControl(Type userControlType) return await App.CreateWindowWithUserControl(userControlType); } - public async Task InitializeAsync() => + [Before(Test)] + public async ValueTask InitializeAsync() => App = await XamlTest.App.StartRemote(new AppOptions { #if !DEBUG @@ -55,5 +64,7 @@ public async Task InitializeAsync() => AllowVisualStudioDebuggerAttach = AttachedDebuggerToRemoteProcess, LogMessage = Output.WriteLine }); - public async Task DisposeAsync() => await App.DisposeAsync(); + + [After(Test)] + public async ValueTask DisposeAsync() => await App.DisposeAsync(); } diff --git a/tests/MaterialDesignThemes.UITests/WPF/AutoSuggestBoxes/AutoSuggestTextBoxTests.cs b/tests/MaterialDesignThemes.UITests/WPF/AutoSuggestBoxes/AutoSuggestTextBoxTests.cs index 59e2fc3f75..f1302b56bf 100644 --- a/tests/MaterialDesignThemes.UITests/WPF/AutoSuggestBoxes/AutoSuggestTextBoxTests.cs +++ b/tests/MaterialDesignThemes.UITests/WPF/AutoSuggestBoxes/AutoSuggestTextBoxTests.cs @@ -1,19 +1,17 @@ using System.ComponentModel; using MaterialDesignThemes.UITests.Samples.AutoSuggestBoxes; using MaterialDesignThemes.UITests.Samples.AutoSuggestTextBoxes; -using Xunit.Sdk; - +using TUnit.Core.Exceptions; namespace MaterialDesignThemes.UITests.WPF.AutoSuggestBoxes; public class AutoSuggestBoxTests : TestBase { - public AutoSuggestBoxTests(ITestOutputHelper output) - : base(output) + public AutoSuggestBoxTests() { - AttachedDebuggerToRemoteProcess = true; + AttachedDebuggerToRemoteProcess = false; } - [Fact] + [Test] public async Task CanFilterItems_WithSuggestionsAndDisplayMember_FiltersSuggestions() { await using var recorder = new TestRecorder(App); @@ -29,8 +27,8 @@ public async Task CanFilterItems_WithSuggestionsAndDisplayMember_FiltersSuggesti //Assert - Assert.True(await suggestBox.GetIsSuggestionOpen()); - Assert.True(await popup.GetIsOpen()); + await Assert.That(await suggestBox.GetIsSuggestionOpen()).IsTrue(); + await Assert.That(await popup.GetIsOpen()).IsTrue(); //Validates these elements are found await AssertExists(suggestionListBox, "Bananas"); @@ -44,7 +42,7 @@ public async Task CanFilterItems_WithSuggestionsAndDisplayMember_FiltersSuggesti recorder.Success(); } - [Fact] + [Test] public async Task CanChoiceItem_FromTheSuggestions_AssertTheTextUpdated() { await using var recorder = new TestRecorder(App); @@ -59,8 +57,8 @@ public async Task CanChoiceItem_FromTheSuggestions_AssertTheTextUpdated() await suggestBox.SendInput(new KeyboardInput("B")); //Assert - Assert.True(await suggestBox.GetIsSuggestionOpen()); - Assert.True(await popup.GetIsOpen()); + await Assert.That(await suggestBox.GetIsSuggestionOpen()).IsTrue(); + await Assert.That(await popup.GetIsOpen()).IsTrue(); double? lastHeight = null; await Wait.For(async () => @@ -71,7 +69,7 @@ await Wait.For(async () => lastHeight = currentHeight; if (!rv) { - await Task.Delay(100); + await Task.Delay(100, TestContext.Current!.CancellationToken); } return rv; }); @@ -82,16 +80,16 @@ await Wait.For(async () => await bananas.LeftClick(); // Wait for the text to be updated - await Task.Delay(50); + await Task.Delay(50, TestContext.Current!.CancellationToken); var suggestBoxText = await suggestBox.GetText(); //Validate that the current text is the same as the selected item - Assert.Equal("Bananas", suggestBoxText); + await Assert.That(suggestBoxText).IsEqualTo("Bananas"); recorder.Success(); } - [Fact] + [Test] public async Task CanFilterItems_WithCollectionView_FiltersSuggestions() { await using var recorder = new TestRecorder(App); @@ -108,8 +106,8 @@ public async Task CanFilterItems_WithCollectionView_FiltersSuggestions() //Assert - Assert.True(await suggestBox.GetIsSuggestionOpen()); - Assert.True(await popup.GetIsOpen()); + await Assert.That(await suggestBox.GetIsSuggestionOpen()).IsTrue(); + await Assert.That(await popup.GetIsOpen()).IsTrue(); //Validates these elements are found await AssertExists(suggestionListBox, "Bananas"); @@ -123,7 +121,7 @@ public async Task CanFilterItems_WithCollectionView_FiltersSuggestions() recorder.Success(); } - [Fact] + [Test] [Description("Issue 3761")] public async Task AutoSuggestBox_MovesFocusToNextElement_WhenPopupIsClosed() { @@ -144,22 +142,22 @@ public async Task AutoSuggestBox_MovesFocusToNextElement_WhenPopupIsClosed() // Act await suggestBox.MoveKeyboardFocus(); - await Task.Delay(50); + await Task.Delay(50, TestContext.Current!.CancellationToken); await suggestBox.SendInput(new KeyboardInput("B")); // Open the popup - await Task.Delay(50); + await Task.Delay(50, TestContext.Current.CancellationToken); await suggestBox.SendInput(new KeyboardInput(Key.Escape)); // Close the popup - await Task.Delay(50); + await Task.Delay(50, TestContext.Current.CancellationToken); await suggestBox.SendInput(new KeyboardInput(Key.Tab)); // Press TAB to focus the next element - await Task.Delay(50); + await Task.Delay(50, TestContext.Current.CancellationToken); // Assert - Assert.False(await suggestBox.GetIsFocused()); - Assert.True(await nextTextBox.GetIsFocused()); + await Assert.That(await suggestBox.GetIsFocused()).IsFalse(); + await Assert.That(await nextTextBox.GetIsFocused()).IsTrue(); recorder.Success(); } - [Fact] + [Test] [Description("Issue 3815")] public async Task AutoSuggestBox_KeysUpAndDown_WrapAround() { @@ -175,7 +173,7 @@ public async Task AutoSuggestBox_KeysUpAndDown_WrapAround() //Act & Assert await suggestBox.MoveKeyboardFocus(); await suggestBox.SendInput(new KeyboardInput("e")); - await Task.Delay(delay); + await Task.Delay(delay, TestContext.Current!.CancellationToken); static int? GetSuggestionCount(AutoSuggestBox autoSuggestBox) { @@ -187,20 +185,22 @@ public async Task AutoSuggestBox_KeysUpAndDown_WrapAround() //Assert that initially the first item is selected int selectedIndex = await suggestionListBox.GetSelectedIndex(); - Assert.Equal(0, selectedIndex); - await Task.Delay(delay); + await Assert.That(selectedIndex).IsEqualTo(0); + await Task.Delay(delay, TestContext.Current.CancellationToken); //Assert that the last item is selected after pressing ArrowUp await suggestBox.SendInput(new KeyboardInput(Key.Up)); - Assert.Equal(itemCount - 1, await suggestionListBox.GetSelectedIndex()); - await Task.Delay(delay); + await Assert.That(await suggestionListBox.GetSelectedIndex()).IsEqualTo(itemCount - 1); + await Task.Delay(delay, TestContext.Current.CancellationToken); //Assert that the first item is selected after pressing ArrowDown await suggestBox.SendInput(new KeyboardInput(Key.Down)); - Assert.Equal(0, await suggestionListBox.GetSelectedIndex()); + await Assert.That(await suggestionListBox.GetSelectedIndex()).IsEqualTo(0); + + recorder.Success(); } - [Fact] + [Test] [Description("Issue 3845")] public async Task AutoSuggestBox_SelectingAnItem_SetsSelectedItem() { @@ -220,12 +220,12 @@ public async Task AutoSuggestBox_SelectingAnItem_SetsSelectedItem() //Assert string? selectedItem = (await suggestBox.GetSelectedItem()) as string; - Assert.Equal("Bananas", selectedItem); + await Assert.That(selectedItem).IsEqualTo("Bananas"); - static void AssertViewModelProperty(AutoSuggestBox autoSuggestBox) + static async Task AssertViewModelProperty(AutoSuggestBox autoSuggestBox) { var viewModel = (AutoSuggestTextBoxWithCollectionViewViewModel)autoSuggestBox.DataContext; - Assert.Equal("Bananas", viewModel.SelectedItem); + await Assert.That(viewModel.SelectedItem).IsEqualTo("Bananas"); } await suggestBox.RemoteExecute(AssertViewModelProperty); @@ -237,11 +237,11 @@ private static async Task AssertExists(IVisualElement suggestionListBox try { _ = await suggestionListBox.GetElement(ElementQuery.PropertyExpression(x => x.Text, text)); - Assert.True(existsOrNotCheck); + await Assert.That(existsOrNotCheck).IsTrue(); } - catch (Exception e) when (e is not TrueException) + catch (Exception e) when (e is not TUnitException) { - Assert.False(existsOrNotCheck); + await Assert.That(existsOrNotCheck).IsFalse(); } } } diff --git a/tests/MaterialDesignThemes.UITests/WPF/Buttons/OutlineButtonTests.cs b/tests/MaterialDesignThemes.UITests/WPF/Buttons/OutlineButtonTests.cs index 1718fcc834..312ab51d28 100644 --- a/tests/MaterialDesignThemes.UITests/WPF/Buttons/OutlineButtonTests.cs +++ b/tests/MaterialDesignThemes.UITests/WPF/Buttons/OutlineButtonTests.cs @@ -4,11 +4,7 @@ namespace MaterialDesignThemes.UITests.WPF.Buttons; public class OutlineButtonTests : TestBase { - public OutlineButtonTests(ITestOutputHelper output) - : base(output) - { } - - [Fact] + [Test] public async Task OutlinedButton_UsesThemeColorForBorder() { await using var recorder = new TestRecorder(App); @@ -24,13 +20,13 @@ public async Task OutlinedButton_UsesThemeColorForBorder() Color? internalBorderColor = await internalBorder.GetBorderBrushColor(); //Assert - Assert.Equal(midColor, borderColor); - Assert.Equal(midColor, internalBorderColor); + await Assert.That(borderColor).IsEqualTo(midColor); + await Assert.That(internalBorderColor).IsEqualTo(midColor); recorder.Success(); } - [Fact] + [Test] public async Task OutlinedButton_BorderCanBeOverridden() { await using var recorder = new TestRecorder(App); @@ -50,13 +46,13 @@ public async Task OutlinedButton_BorderCanBeOverridden() Color? borderBrush = await internalBorder.GetBorderBrushColor(); //Assert - Assert.Equal(new Thickness(5), borderThickness); - Assert.Equal(Colors.Red, borderBrush); + await Assert.That(borderThickness).IsEqualTo(new Thickness(5)); + await Assert.That(borderBrush).IsEqualTo(Colors.Red); recorder.Success(); } - [Fact] + [Test] public async Task OutlinedButton_OnMouseOver_UsesThemeBrush() { await using var recorder = new TestRecorder(App); @@ -74,7 +70,7 @@ await Wait.For(async () => SolidColorBrush? internalBorderBackground = (await internalBorder.GetBackground()) as SolidColorBrush; //Assert - Assert.Equal(midColor, internalBorderBackground?.Color); + await Assert.That(internalBorderBackground?.Color).IsEqualTo(midColor); }); recorder.Success(); diff --git a/tests/MaterialDesignThemes.UITests/WPF/Buttons/RaisedButtonTests.cs b/tests/MaterialDesignThemes.UITests/WPF/Buttons/RaisedButtonTests.cs index c0ed522aec..39c7b3ea7a 100644 --- a/tests/MaterialDesignThemes.UITests/WPF/Buttons/RaisedButtonTests.cs +++ b/tests/MaterialDesignThemes.UITests/WPF/Buttons/RaisedButtonTests.cs @@ -4,11 +4,7 @@ namespace MaterialDesignThemes.UITests.WPF.Buttons; public class RaisedButtonTests : TestBase { - public RaisedButtonTests(ITestOutputHelper output) - : base(output) - { } - - [Fact] + [Test] public async Task OnLoad_ThemeBrushesSet() { await using var recorder = new TestRecorder(App); @@ -21,7 +17,7 @@ public async Task OnLoad_ThemeBrushesSet() Color? color = await button.GetBackgroundColor(); //Assert - Assert.Equal(midColor, color); + await Assert.That(color).IsEqualTo(midColor); recorder.Success(); } diff --git a/tests/MaterialDesignThemes.UITests/WPF/Cards/ElevatedCardTests.cs b/tests/MaterialDesignThemes.UITests/WPF/Cards/ElevatedCardTests.cs index f30f158a9e..1187395aee 100644 --- a/tests/MaterialDesignThemes.UITests/WPF/Cards/ElevatedCardTests.cs +++ b/tests/MaterialDesignThemes.UITests/WPF/Cards/ElevatedCardTests.cs @@ -1,12 +1,11 @@ -namespace MaterialDesignThemes.UITests.WPF.Cards; + + +namespace MaterialDesignThemes.UITests.WPF.Cards; public class ElevatedCardTests : TestBase { - public ElevatedCardTests(ITestOutputHelper output) - : base(output) - { } - [Fact] + [Test] public async Task ElevatedCard_UniformCornerRadiusApplied_AppliesCornerRadiusOnBorder() { await using var recorder = new TestRecorder(App); @@ -20,10 +19,10 @@ public async Task ElevatedCard_UniformCornerRadiusApplied_AppliesCornerRadiusOnB CornerRadius? internalBorderCornerRadius = await internalBorder.GetCornerRadius(); //Assert - Assert.Equal(5, internalBorderCornerRadius.Value.TopLeft); - Assert.Equal(5, internalBorderCornerRadius.Value.TopRight); - Assert.Equal(5, internalBorderCornerRadius.Value.BottomRight); - Assert.Equal(5, internalBorderCornerRadius.Value.BottomLeft); + await Assert.That(internalBorderCornerRadius.Value.TopLeft).IsEqualTo(5); + await Assert.That(internalBorderCornerRadius.Value.TopRight).IsEqualTo(5); + await Assert.That(internalBorderCornerRadius.Value.BottomRight).IsEqualTo(5); + await Assert.That(internalBorderCornerRadius.Value.BottomLeft).IsEqualTo(5); recorder.Success(); } diff --git a/tests/MaterialDesignThemes.UITests/WPF/Cards/OutlinedCardTests.cs b/tests/MaterialDesignThemes.UITests/WPF/Cards/OutlinedCardTests.cs index 424cbaf138..15da509acc 100644 --- a/tests/MaterialDesignThemes.UITests/WPF/Cards/OutlinedCardTests.cs +++ b/tests/MaterialDesignThemes.UITests/WPF/Cards/OutlinedCardTests.cs @@ -4,11 +4,7 @@ namespace MaterialDesignThemes.UITests.WPF.Cards; public class OutlinedCardTests : TestBase { - public OutlinedCardTests(ITestOutputHelper output) - : base(output) - { } - - [Fact] + [Test] public async Task OutlinedCard_UsesThemeColorForBorder() { await using var recorder = new TestRecorder(App); @@ -23,12 +19,12 @@ public async Task OutlinedCard_UsesThemeColorForBorder() Color? internalBorderColor = await internalBorder.GetBorderBrushColor(); //Assert - Assert.Equal(dividerColor, internalBorderColor); + await Assert.That(internalBorderColor).IsEqualTo(dividerColor); recorder.Success(); } - [Fact] + [Test] public async Task OutlinedCard_UniformCornerRadiusApplied_AppliesCornerRadiusOnBorder() { await using var recorder = new TestRecorder(App); @@ -42,10 +38,10 @@ public async Task OutlinedCard_UniformCornerRadiusApplied_AppliesCornerRadiusOnB CornerRadius? internalBorderCornerRadius = await internalBorder.GetCornerRadius(); //Assert - Assert.Equal(5, internalBorderCornerRadius.Value.TopLeft); - Assert.Equal(5, internalBorderCornerRadius.Value.TopRight); - Assert.Equal(5, internalBorderCornerRadius.Value.BottomRight); - Assert.Equal(5, internalBorderCornerRadius.Value.BottomLeft); + await Assert.That(internalBorderCornerRadius.Value.TopLeft).IsEqualTo(5); + await Assert.That(internalBorderCornerRadius.Value.TopRight).IsEqualTo(5); + await Assert.That(internalBorderCornerRadius.Value.BottomRight).IsEqualTo(5); + await Assert.That(internalBorderCornerRadius.Value.BottomLeft).IsEqualTo(5); recorder.Success(); } diff --git a/tests/MaterialDesignThemes.UITests/WPF/ColorPickerTests.cs b/tests/MaterialDesignThemes.UITests/WPF/ColorPickerTests.cs index 57805e8a1c..922a0b5cd8 100644 --- a/tests/MaterialDesignThemes.UITests/WPF/ColorPickerTests.cs +++ b/tests/MaterialDesignThemes.UITests/WPF/ColorPickerTests.cs @@ -5,12 +5,7 @@ namespace MaterialDesignThemes.UITests.WPF; public class ColorPickerTests : TestBase { - public ColorPickerTests(ITestOutputHelper output) - : base(output) - { - } - - [Fact] + [Test] public async Task OnLostFocusIfSelectedTimeIsNull_DatePartWillBeToday() { await using var recorder = new TestRecorder(App); @@ -29,12 +24,12 @@ public async Task OnLostFocusIfSelectedTimeIsNull_DatePartWillBeToday() await thumb.SendInput(MouseInput.MoveRelative(xOffset: -5, yOffset: -10)); await thumb.SendInput(MouseInput.LeftDown()); await thumb.SendInput(MouseInput.MoveRelative(yOffset: 25)); - await Task.Delay(100); + await Task.Delay(100, TestContext.Current!.CancellationToken); await thumb.SendInput(MouseInput.LeftUp()); double currentBrightness = (await colorPicker.GetColor()).ToHsb().Brightness; - Assert.True(currentBrightness < lastBrightness, $"Brightness {currentBrightness} is not less than {lastBrightness}"); + await Assert.That(currentBrightness).IsLessThan(lastBrightness); recorder.Success(); } diff --git a/tests/MaterialDesignThemes.UITests/WPF/ColorZones/ColorZoneTests.cs b/tests/MaterialDesignThemes.UITests/WPF/ColorZones/ColorZoneTests.cs index 6422947496..bc8dca69ca 100644 --- a/tests/MaterialDesignThemes.UITests/WPF/ColorZones/ColorZoneTests.cs +++ b/tests/MaterialDesignThemes.UITests/WPF/ColorZones/ColorZoneTests.cs @@ -1,26 +1,21 @@ using System.Windows.Media; + namespace MaterialDesignThemes.UITests.WPF.ColorZones; public class ColorZoneTests : TestBase { - public ColorZoneTests(ITestOutputHelper output) - : base(output) - { - - } - - [Theory] - [InlineData(ColorZoneMode.Standard, "MaterialDesign.Brush.Background", "MaterialDesign.Brush.Foreground")] - [InlineData(ColorZoneMode.Inverted, "MaterialDesign.Brush.Foreground", "MaterialDesign.Brush.Background")] - [InlineData(ColorZoneMode.PrimaryLight, "MaterialDesign.Brush.Primary.Light", "MaterialDesign.Brush.Primary.Light.Foreground")] - [InlineData(ColorZoneMode.PrimaryMid, "MaterialDesign.Brush.Primary", "MaterialDesign.Brush.Primary.Foreground")] - [InlineData(ColorZoneMode.PrimaryDark, "MaterialDesign.Brush.Primary.Dark", "MaterialDesign.Brush.Primary.Dark.Foreground")] - [InlineData(ColorZoneMode.SecondaryLight, "MaterialDesign.Brush.Secondary.Light", "MaterialDesign.Brush.Secondary.Light.Foreground")] - [InlineData(ColorZoneMode.SecondaryMid, "MaterialDesign.Brush.Secondary", "MaterialDesign.Brush.Secondary.Foreground")] - [InlineData(ColorZoneMode.SecondaryDark, "MaterialDesign.Brush.Secondary.Dark", "MaterialDesign.Brush.Secondary.Dark.Foreground")] - [InlineData(ColorZoneMode.Light, "MaterialDesign.Brush.ColorZone.LightBackground", "MaterialDesign.Brush.ColorZone.LightForeground")] - [InlineData(ColorZoneMode.Dark, "MaterialDesign.Brush.ColorZone.DarkBackground", "MaterialDesign.Brush.ColorZone.DarkForeground")] + [Test] + [Arguments(ColorZoneMode.Standard, "MaterialDesign.Brush.Background", "MaterialDesign.Brush.Foreground")] + [Arguments(ColorZoneMode.Inverted, "MaterialDesign.Brush.Foreground", "MaterialDesign.Brush.Background")] + [Arguments(ColorZoneMode.PrimaryLight, "MaterialDesign.Brush.Primary.Light", "MaterialDesign.Brush.Primary.Light.Foreground")] + [Arguments(ColorZoneMode.PrimaryMid, "MaterialDesign.Brush.Primary", "MaterialDesign.Brush.Primary.Foreground")] + [Arguments(ColorZoneMode.PrimaryDark, "MaterialDesign.Brush.Primary.Dark", "MaterialDesign.Brush.Primary.Dark.Foreground")] + [Arguments(ColorZoneMode.SecondaryLight, "MaterialDesign.Brush.Secondary.Light", "MaterialDesign.Brush.Secondary.Light.Foreground")] + [Arguments(ColorZoneMode.SecondaryMid, "MaterialDesign.Brush.Secondary", "MaterialDesign.Brush.Secondary.Foreground")] + [Arguments(ColorZoneMode.SecondaryDark, "MaterialDesign.Brush.Secondary.Dark", "MaterialDesign.Brush.Secondary.Dark.Foreground")] + [Arguments(ColorZoneMode.Light, "MaterialDesign.Brush.ColorZone.LightBackground", "MaterialDesign.Brush.ColorZone.LightForeground")] + [Arguments(ColorZoneMode.Dark, "MaterialDesign.Brush.ColorZone.DarkBackground", "MaterialDesign.Brush.ColorZone.DarkForeground")] public async Task Mode_SetsThemeColors(ColorZoneMode mode, string backgroundBrush, string foregroundBrush) { await using var recorder = new TestRecorder(App); @@ -31,8 +26,8 @@ public async Task Mode_SetsThemeColors(ColorZoneMode mode, string backgroundBrus Color background = await GetThemeColor(backgroundBrush); Color foreground = await GetThemeColor(foregroundBrush); - Assert.Equal(background, await colorZone.GetBackgroundColor()); - Assert.Equal(foreground, await colorZone.GetForegroundColor()); + await Assert.That(await colorZone.GetBackgroundColor()).IsEqualTo(background); + await Assert.That(await colorZone.GetForegroundColor()).IsEqualTo(foreground); recorder.Success(); } diff --git a/tests/MaterialDesignThemes.UITests/WPF/ComboBoxes/ComboBoxTests.cs b/tests/MaterialDesignThemes.UITests/WPF/ComboBoxes/ComboBoxTests.cs index d081596312..1510cf2b05 100644 --- a/tests/MaterialDesignThemes.UITests/WPF/ComboBoxes/ComboBoxTests.cs +++ b/tests/MaterialDesignThemes.UITests/WPF/ComboBoxes/ComboBoxTests.cs @@ -5,12 +5,7 @@ namespace MaterialDesignThemes.UITests.WPF.ComboBoxes; public class ComboBoxTests : TestBase { - public ComboBoxTests(ITestOutputHelper output) - : base(output) - { - } - - [Fact] + [Test] [Description("Pull Request 2192")] public async Task OnComboBoxHelperTextFontSize_ChangesHelperTextFontSize() { @@ -26,11 +21,11 @@ public async Task OnComboBoxHelperTextFontSize_ChangesHelperTextFontSize() double fontSize = await helpTextBlock.GetFontSize(); - Assert.Equal(20, fontSize); + await Assert.That(fontSize).IsEqualTo(20); recorder.Success(); } - [Fact] + [Test] [Description("Pull Request 2192")] public async Task OnFilledComboBoxHelperTextFontSize_ChangesHelperTextFontSize() { @@ -47,11 +42,11 @@ public async Task OnFilledComboBoxHelperTextFontSize_ChangesHelperTextFontSize() double fontSize = await helpTextBlock.GetFontSize(); - Assert.Equal(20, fontSize); + await Assert.That(fontSize).IsEqualTo(20); recorder.Success(); } - [Fact] + [Test] [Description("Issue 2495")] public async Task OnComboBox_WithClearButton_ClearsSelection() { @@ -74,23 +69,23 @@ public async Task OnComboBox_WithClearButton_ClearsSelection() int? selectedIndex = await comboBox.GetSelectedIndex(); object? text = await comboBox.GetText(); - Assert.True(selectedIndex >= 0); - Assert.NotNull(text); + await Assert.That(selectedIndex >= 0).IsTrue(); + await Assert.That(text).IsNotNull(); await clearButton.LeftClick(); await Wait.For(async () => { text = await comboBox.GetText(); - Assert.Null(text); + await Assert.That(text).IsNull(); selectedIndex = await comboBox.GetSelectedIndex(); - Assert.False(selectedIndex >= 0); + await Assert.That(selectedIndex >= 0).IsFalse(); }); recorder.Success(); } - [Fact] + [Test] [Description("Issue 2690")] public async Task OnEditableComboBox_WithDefaultContextMenu_ShowsCutCopyPaste() { @@ -108,7 +103,7 @@ public async Task OnEditableComboBox_WithDefaultContextMenu_ShowsCutCopyPaste() await comboBox.RightClick(); IVisualElement? contextMenu = await comboBox.GetContextMenu(); - Assert.True(contextMenu is not null, "No context menu set on the ComboBox"); + await Assert.That(contextMenu).IsNotNull().Because("No context menu set on the ComboBox"); await Wait.For(async () => await contextMenu!.GetIsVisible()); await AssertMenu("Cut"); await AssertMenu("Copy"); @@ -119,11 +114,11 @@ public async Task OnEditableComboBox_WithDefaultContextMenu_ShowsCutCopyPaste() async Task AssertMenu(string menuHeader) { var menuItem = await contextMenu!.GetElement(ElementQuery.PropertyExpression(x => x.Header, menuHeader)); - Assert.True(menuItem is not null, $"{menuHeader} menu item not found"); + await Assert.That(menuItem).IsNotNull().Because($"{menuHeader} menu item not found"); } } - [Fact] + [Test] [Description("Issue 2713")] public async Task OnEditableComboBox_ClickInTextArea_FocusesTextBox() { @@ -147,7 +142,7 @@ public async Task OnEditableComboBox_ClickInTextArea_FocusesTextBox() // Open the ComboBox initially await comboBox.LeftClick(Position.RightCenter); - await Task.Delay(50); // Allow a little time for the drop-down to open (and property to change) + await Task.Delay(50, TestContext.Current!.CancellationToken); // Allow a little time for the drop-down to open (and property to change) bool wasOpenAfterClickOnToggleButton = await comboBox.GetIsDropDownOpen(); // Focus (i.e. click) another element @@ -155,29 +150,29 @@ public async Task OnEditableComboBox_ClickInTextArea_FocusesTextBox() // Click the editable TextBox of the ComboBox await editableTextBox.LeftClick(); - await Task.Delay(50); // Allow a little time for the drop-down to open (and property to change) + await Task.Delay(50, TestContext.Current.CancellationToken); // Allow a little time for the drop-down to open (and property to change) bool wasOpenAfterClickOnEditableTextBox = await comboBox.GetIsDropDownOpen(); bool textBoxHasFocus = await editableTextBox.GetIsFocused(); bool textBoxHasKeyboardFocus = await editableTextBox.GetIsKeyboardFocused(); - Assert.True(wasOpenAfterClickOnToggleButton, "ComboBox should have opened drop down when clicking the toggle button"); - Assert.False(wasOpenAfterClickOnEditableTextBox, "ComboBox should not have opened drop down when clicking the editable TextBox"); - Assert.True(textBoxHasFocus, "Editable TextBox should have focus"); - Assert.True(textBoxHasKeyboardFocus, "Editable TextBox should have keyboard focus"); + await Assert.That(wasOpenAfterClickOnToggleButton).IsTrue().Because("ComboBox should have opened drop down when clicking the toggle button"); + await Assert.That(wasOpenAfterClickOnEditableTextBox).IsFalse().Because("ComboBox should not have opened drop down when clicking the editable ait wTextBox"); + await Assert.That(textBoxHasFocus).IsTrue().Because("Editable TextBox should have focus"); + await Assert.That(textBoxHasKeyboardFocus).IsTrue().Because("Editable TextBox should have keyboard focus"); recorder.Success(); } - [Theory] - [InlineData("MaterialDesignFloatingHintComboBox", null)] - [InlineData("MaterialDesignFloatingHintComboBox", 5)] - [InlineData("MaterialDesignFloatingHintComboBox", 20)] - [InlineData("MaterialDesignFilledComboBox", null)] - [InlineData("MaterialDesignFilledComboBox", 5)] - [InlineData("MaterialDesignFilledComboBox", 20)] - [InlineData("MaterialDesignOutlinedComboBox", null)] - [InlineData("MaterialDesignOutlinedComboBox", 5)] - [InlineData("MaterialDesignOutlinedComboBox", 20)] + [Test] + [Arguments("MaterialDesignFloatingHintComboBox", null)] + [Arguments("MaterialDesignFloatingHintComboBox", 5)] + [Arguments("MaterialDesignFloatingHintComboBox", 20)] + [Arguments("MaterialDesignFilledComboBox", null)] + [Arguments("MaterialDesignFilledComboBox", 5)] + [Arguments("MaterialDesignFilledComboBox", 20)] + [Arguments("MaterialDesignOutlinedComboBox", null)] + [Arguments("MaterialDesignOutlinedComboBox", 5)] + [Arguments("MaterialDesignOutlinedComboBox", 20)] public async Task ComboBox_WithHintAndHelperText_RespectsPadding(string styleName, int? padding) { await using var recorder = new TestRecorder(App); @@ -203,22 +198,22 @@ public async Task ComboBox_WithHintAndHelperText_RespectsPadding(string styleNam Rect? hintCoordinates = await hint.GetCoordinates(); Rect? helperTextCoordinates = await helperText.GetCoordinates(); - Assert.InRange(Math.Abs(contentHostCoordinates.Value.Left - hintCoordinates.Value.Left), 0, tolerance); - Assert.InRange(Math.Abs(contentHostCoordinates.Value.Left - helperTextCoordinates.Value.Left), 0, tolerance); + await Assert.That(Math.Abs(contentHostCoordinates.Value.Left - hintCoordinates.Value.Left)).IsCloseTo(0, tolerance); + await Assert.That(Math.Abs(contentHostCoordinates.Value.Left - helperTextCoordinates.Value.Left)).IsCloseTo(0, tolerance); recorder.Success(); } - [Theory] - [InlineData("MaterialDesignFloatingHintComboBox", null)] - [InlineData("MaterialDesignFloatingHintComboBox", 5)] - [InlineData("MaterialDesignFloatingHintComboBox", 20)] - [InlineData("MaterialDesignFilledComboBox", null)] - [InlineData("MaterialDesignFilledComboBox", 5)] - [InlineData("MaterialDesignFilledComboBox", 20)] - [InlineData("MaterialDesignOutlinedComboBox", null)] - [InlineData("MaterialDesignOutlinedComboBox", 5)] - [InlineData("MaterialDesignOutlinedComboBox", 20)] + [Test] + [Arguments("MaterialDesignFloatingHintComboBox", null)] + [Arguments("MaterialDesignFloatingHintComboBox", 5)] + [Arguments("MaterialDesignFloatingHintComboBox", 20)] + [Arguments("MaterialDesignFilledComboBox", null)] + [Arguments("MaterialDesignFilledComboBox", 5)] + [Arguments("MaterialDesignFilledComboBox", 20)] + [Arguments("MaterialDesignOutlinedComboBox", null)] + [Arguments("MaterialDesignOutlinedComboBox", 5)] + [Arguments("MaterialDesignOutlinedComboBox", 20)] public async Task ComboBox_WithHintAndValidationError_RespectsPadding(string styleName, int? padding) { await using var recorder = new TestRecorder(App); @@ -252,17 +247,17 @@ public async Task ComboBox_WithHintAndValidationError_RespectsPadding(string sty Rect? hintCoordinates = await hint.GetCoordinates(); Rect? errorViewerCoordinates = await errorViewer.GetCoordinates(); - Assert.InRange(Math.Abs(contentHostCoordinates.Value.Left - hintCoordinates.Value.Left), 0, tolerance); - Assert.InRange(Math.Abs(contentHostCoordinates.Value.Left - errorViewerCoordinates.Value.Left), 0, tolerance); + await Assert.That(Math.Abs(contentHostCoordinates.Value.Left - hintCoordinates.Value.Left)).IsCloseTo(0, tolerance); + await Assert.That(Math.Abs(contentHostCoordinates.Value.Left - errorViewerCoordinates.Value.Left)).IsCloseTo(0, tolerance); recorder.Success(); } - [Theory] - [InlineData(HorizontalAlignment.Left)] - [InlineData(HorizontalAlignment.Right)] - [InlineData(HorizontalAlignment.Center)] - [InlineData(HorizontalAlignment.Stretch)] + [Test] + [Arguments(HorizontalAlignment.Left)] + [Arguments(HorizontalAlignment.Right)] + [Arguments(HorizontalAlignment.Center)] + [Arguments(HorizontalAlignment.Stretch)] [Description("Issue 3433")] public async Task ComboBox_WithHorizontalContentAlignment_RespectsAlignment(HorizontalAlignment alignment) { @@ -278,15 +273,15 @@ public async Task ComboBox_WithHorizontalContentAlignment_RespectsAlignment(Hori var comboBox = await stackPanel.GetElement("/ComboBox"); var selectedItemPresenter = await comboBox.GetElement("contentPresenter"); - Assert.Equal(alignment, await selectedItemPresenter.GetHorizontalAlignment()); + await Assert.That(await selectedItemPresenter.GetHorizontalAlignment()).IsEqualTo(alignment); recorder.Success(); } - [Theory] - [InlineData("MaterialDesignFloatingHintComboBox", 0, 0, 0, 1)] - [InlineData("MaterialDesignFilledComboBox", 0, 0, 0, 1)] - [InlineData("MaterialDesignOutlinedComboBox", 2, 2, 2, 2)] + [Test] + [Arguments("MaterialDesignFloatingHintComboBox", 0, 0, 0, 1)] + [Arguments("MaterialDesignFilledComboBox", 0, 0, 0, 1)] + [Arguments("MaterialDesignOutlinedComboBox", 2, 2, 2, 2)] [Description("Issue 3623")] public async Task ComboBox_BorderShouldDependOnAppliedStyle(string style, double left, double top, double right, double bottom) { @@ -305,7 +300,7 @@ public async Task ComboBox_BorderShouldDependOnAppliedStyle(string style, double await comboBox.LeftClick(); Thickness thickness = await border.GetBorderThickness(); - Assert.Equal(new Thickness(left, top, right, bottom), thickness); + await Assert.That(thickness).IsEqualTo(new Thickness(left, top, right, bottom)); recorder.Success(); } diff --git a/tests/MaterialDesignThemes.UITests/WPF/ContentControls/ContentControlTests.cs b/tests/MaterialDesignThemes.UITests/WPF/ContentControls/ContentControlTests.cs index b1e8b97c56..5350a69079 100644 --- a/tests/MaterialDesignThemes.UITests/WPF/ContentControls/ContentControlTests.cs +++ b/tests/MaterialDesignThemes.UITests/WPF/ContentControls/ContentControlTests.cs @@ -1,16 +1,11 @@ using System.ComponentModel; + namespace MaterialDesignThemes.UITests.WPF.ContentControls; public class ContentControlTests : TestBase { - public ContentControlTests(ITestOutputHelper output) - : base(output) - { - } - - - [Fact] + [Test] [Description("Issue 2510")] public async Task ClearButton_InsideOfControlTemplate_CanStillClearContent() { @@ -34,10 +29,10 @@ public async Task ClearButton_InsideOfControlTemplate_CanStillClearContent() await clearButton.LeftClick(); //Assert - Assert.Equal("Some Text", initial); + await Assert.That(initial).IsEqualTo("Some Text"); await Wait.For(async () => { - Assert.True(string.IsNullOrEmpty(await textBox.GetText())); + await Assert.That(await textBox.GetText()).IsNullOrEmpty(); }); recorder.Success(); diff --git a/tests/MaterialDesignThemes.UITests/WPF/DatePickers/DatePickerTests.cs b/tests/MaterialDesignThemes.UITests/WPF/DatePickers/DatePickerTests.cs index c4255d5c8d..f5a210c7b0 100644 --- a/tests/MaterialDesignThemes.UITests/WPF/DatePickers/DatePickerTests.cs +++ b/tests/MaterialDesignThemes.UITests/WPF/DatePickers/DatePickerTests.cs @@ -3,16 +3,12 @@ using System.Windows.Media; using MaterialDesignThemes.UITests.WPF.TextBoxes; + namespace MaterialDesignThemes.UITests.WPF.DatePickers; public class DatePickerTests : TestBase { - public DatePickerTests(ITestOutputHelper output) - : base(output) - { - } - - [Fact] + [Test] [Description("Pull Request 2192")] public async Task OnDatePickerHelperTextFontSize_ChangesHelperTextFontSize() { @@ -28,11 +24,11 @@ public async Task OnDatePickerHelperTextFontSize_ChangesHelperTextFontSize() double fontSize = await helpTextBlock.GetFontSize(); - Assert.Equal(20, fontSize); + await Assert.That(fontSize).IsEqualTo(20); recorder.Success(); } - [Fact] + [Test] [Description("Issue 2495")] public async Task OnDatePicker_WithClearButton_ClearsSelectedDate() { @@ -48,20 +44,20 @@ public async Task OnDatePicker_WithClearButton_ClearsSelectedDate() DateTime? selectedDate = await datePicker.GetSelectedDate(); - Assert.NotNull(selectedDate); + await Assert.That(selectedDate).IsNotNull(); await clearButton.LeftClick(); await Wait.For(async () => { selectedDate = await datePicker.GetSelectedDate(); - Assert.Null(selectedDate); + await Assert.That(selectedDate).IsNull(); }); recorder.Success(); } - [Fact] + [Test] [Description("Issue 3369")] public async Task OnDatePicker_WithClearButton_ClearsSelectedUncommittedText() { @@ -78,19 +74,19 @@ public async Task OnDatePicker_WithClearButton_ClearsSelectedUncommittedText() var clearButton = await datePicker.GetElement