diff --git a/.github/workflows/build_artifacts.yml b/.github/workflows/build_artifacts.yml index 09e1baf9ce..cd6148a7a9 100644 --- a/.github/workflows/build_artifacts.yml +++ b/.github/workflows/build_artifacts.yml @@ -48,7 +48,7 @@ jobs: - name: Test timeout-minutes: 20 - run: dotnet test ${{ env.solution }} --configuration ${{ inputs.build-configuration }} --no-build --blame-crash --logger GitHubActions + run: dotnet test ${{ env.solution }} --configuration ${{ inputs.build-configuration }} --no-build - name: Upload Screenshots if: ${{ always() }} diff --git a/Directory.packages.props b/Directory.packages.props index 35cec88399..3dc3a40120 100644 --- a/Directory.packages.props +++ b/Directory.packages.props @@ -4,12 +4,11 @@ true - - + @@ -21,7 +20,7 @@ - + @@ -32,9 +31,11 @@ + - + + diff --git a/global.json b/global.json index bb62055921..c461cbf6c0 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,9 @@ { - "sdk": { - "version": "10.0.102", - "rollForward": "latestMinor" - } + "sdk": { + "version": "10.0.102", + "rollForward": "latestMinor" + }, + "test": { + "runner": "Microsoft.Testing.Platform" + } } diff --git a/tests/MaterialColorUtilities.Tests/HctTests.cs b/tests/MaterialColorUtilities.Tests/HctTests.cs index 0cd4ed5539..6869be7432 100644 --- a/tests/MaterialColorUtilities.Tests/HctTests.cs +++ b/tests/MaterialColorUtilities.Tests/HctTests.cs @@ -3,7 +3,7 @@ public sealed class HctTests { [Test] - [Skip("Takes a long time to run")] + [Explicit] //Takes a long time to run [DisplayName("HCT preserves original color for all opaque ARGB values")] public async Task Hct_Preserves_Original_Color_For_All_Opaque_ARGB() { diff --git a/tests/MaterialColorUtilities.Tests/MaterialColorUtilities.Tests.csproj b/tests/MaterialColorUtilities.Tests/MaterialColorUtilities.Tests.csproj index 0c99ed5703..04f252e323 100644 --- a/tests/MaterialColorUtilities.Tests/MaterialColorUtilities.Tests.csproj +++ b/tests/MaterialColorUtilities.Tests/MaterialColorUtilities.Tests.csproj @@ -2,11 +2,7 @@ net8.0-windows;net10.0-windows - MaterialColorUtilities.Tests - MaterialColorUtilities.Tests Exe - true - true true enable enable @@ -18,16 +14,11 @@ - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - diff --git a/tests/MaterialDesignColors.Wpf.Tests/MaterialDesignColors.Wpf.Tests.csproj b/tests/MaterialDesignColors.Wpf.Tests/MaterialDesignColors.Wpf.Tests.csproj index 0dd149338f..feabcc869b 100644 --- a/tests/MaterialDesignColors.Wpf.Tests/MaterialDesignColors.Wpf.Tests.csproj +++ b/tests/MaterialDesignColors.Wpf.Tests/MaterialDesignColors.Wpf.Tests.csproj @@ -1,12 +1,8 @@ - + net472;net8.0-windows;net10.0-windows - MaterialDesignColors.Wpf.Tests - MaterialDesignColors.Wpf.Tests - true Exe - true @@ -24,11 +20,7 @@ - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - \ No newline at end of file + diff --git a/tests/MaterialDesignColors.Wpf.Tests/ModuleInitializerAttribute.cs b/tests/MaterialDesignColors.Wpf.Tests/ModuleInitializerAttribute.cs new file mode 100644 index 0000000000..543c7dfe54 --- /dev/null +++ b/tests/MaterialDesignColors.Wpf.Tests/ModuleInitializerAttribute.cs @@ -0,0 +1,8 @@ +#if NET472 +namespace System.Runtime.CompilerServices; + +[AttributeUsage(AttributeTargets.Method, Inherited = false)] +internal sealed class ModuleInitializerAttribute : Attribute +{ +} +#endif diff --git a/tests/MaterialDesignThemes.UITests/AllStyles.cs b/tests/MaterialDesignThemes.UITests/AllStyles.cs index 5d3c6c0f01..cf78a95deb 100644 --- a/tests/MaterialDesignThemes.UITests/AllStyles.cs +++ b/tests/MaterialDesignThemes.UITests/AllStyles.cs @@ -32,8 +32,6 @@ public class AllStyles : TestBase [Arguments("TreeView", "MaterialDesignTreeView")] public async Task LoadStyleInIsolation_CanBeLoaded(string controlName, string styleName) { - await using var recorder = new TestRecorder(App); - string applicationResourceXaml = $$""" true $(NoWarn);CA1707 true - true Exe - true - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - @@ -32,4 +26,4 @@ - \ No newline at end of file + diff --git a/tests/MaterialDesignThemes.UITests/TUnit/IsCloseToExtensions.cs b/tests/MaterialDesignThemes.UITests/TUnit/IsCloseToExtensions.cs index 1ae6934500..e70a7fc67a 100644 --- a/tests/MaterialDesignThemes.UITests/TUnit/IsCloseToExtensions.cs +++ b/tests/MaterialDesignThemes.UITests/TUnit/IsCloseToExtensions.cs @@ -1,51 +1,72 @@ using System.Numerics; using System.Runtime.CompilerServices; -using TUnit.Assertions.AssertConditions; -using TUnit.Assertions.AssertConditions.Interfaces; -using TUnit.Assertions.AssertionBuilders; +using TUnit.Assertions.Core; 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) + public static IsCloseToAssertion IsCloseTo( + this IAssertionSource source, double expected, double precision, + [CallerArgumentExpression(nameof(expected))] string? expectedExpression = null, + [CallerArgumentExpression(nameof(precision))] string? precisionExpression = null) { - var assertionBuilder = valueSource.RegisterAssertion(new IsCloseToCondition(expected, precision) - , [doNotPopulateThisValue1, doNotPopulateThisValue2]); - - return new IsCloseToWrapper(assertionBuilder); + source.Context.ExpressionBuilder.Append(".IsCloseTo("); + source.Context.ExpressionBuilder.Append(expectedExpression); + source.Context.ExpressionBuilder.Append(", "); + source.Context.ExpressionBuilder.Append(precisionExpression); + source.Context.ExpressionBuilder.Append(')'); + return new IsCloseToAssertion(source.Context, expected, precision); } - public static IsCloseToWrapper IsCloseTo(this IValueSource valueSource, float expected, float precision, [CallerArgumentExpression(nameof(expected))] string? doNotPopulateThisValue1 = null, [CallerArgumentExpression(nameof(precision))] string? doNotPopulateThisValue2 = null) + public static IsCloseToAssertion IsCloseTo( + this IAssertionSource source, float expected, float precision, + [CallerArgumentExpression(nameof(expected))] string? expectedExpression = null, + [CallerArgumentExpression(nameof(precision))] string? precisionExpression = null) { - var assertionBuilder = valueSource.RegisterAssertion(new IsCloseToCondition(expected, precision) - , [doNotPopulateThisValue1, doNotPopulateThisValue2]); - - return new IsCloseToWrapper(assertionBuilder); + source.Context.ExpressionBuilder.Append(".IsCloseTo("); + source.Context.ExpressionBuilder.Append(expectedExpression); + source.Context.ExpressionBuilder.Append(", "); + source.Context.ExpressionBuilder.Append(precisionExpression); + source.Context.ExpressionBuilder.Append(')'); + return new IsCloseToAssertion(source.Context, expected, precision); } } -public class IsCloseToWrapper(InvokableAssertionBuilder invokableAssertionBuilder) - : InvokableValueAssertionBuilder(invokableAssertionBuilder); - -file class IsCloseToCondition(TActual expected, TActual tolerance) : BaseAssertCondition - where TActual : - IFloatingPoint, - INumberBase +public class IsCloseToAssertion(AssertionContext context, TValue expected, TValue precision) : Assertion(context) + where TValue : IFloatingPoint, INumberBase { - protected override string GetExpectation() => $"to be within {tolerance} of {expected}"; + protected override string GetExpectation() + { + DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new(15, 1); + defaultInterpolatedStringHandler.AppendLiteral("to be within "); + defaultInterpolatedStringHandler.AppendFormatted($"\"{precision}\""); + defaultInterpolatedStringHandler.AppendLiteral(" of "); + defaultInterpolatedStringHandler.AppendFormatted($"\"{expected}\""); + return defaultInterpolatedStringHandler.ToStringAndClear(); + } - protected override ValueTask GetResult( - TActual? actualValue, Exception? exception, - AssertionMetadata assertionMetadata - ) + protected override Task CheckAsync(EvaluationMetadata metadata) { - if(actualValue is null) - return AssertionResult.Fail("received null"); + TValue? actualValue = metadata.Value; + Exception? exception = metadata.Exception; + if (exception != null) + { + return Task.FromResult(AssertionResult.Failed("threw " + exception.GetType().FullName)); + } + if (actualValue is null) + { + return Task.FromResult(AssertionResult.Failed($"found ")); + } + + TValue difference = actualValue - expected; + TValue absoluteDifference = TValue.Abs(difference); + bool isInRange = absoluteDifference <= precision; - TActual difference = actualValue - expected; - TActual absoluteDifference = TActual.Abs(difference); - bool isInRange = absoluteDifference <= tolerance; - return AssertionResult.FailIf(!isInRange, $"received {actualValue}"); + if (isInRange) + { + return Task.FromResult(AssertionResult.Passed); + } + return Task.FromResult(AssertionResult.Failed($"found {actualValue}")); } } diff --git a/tests/MaterialDesignThemes.UITests/TestBase.cs b/tests/MaterialDesignThemes.UITests/TestBase.cs index 4a705022ea..93e6ccae1c 100644 --- a/tests/MaterialDesignThemes.UITests/TestBase.cs +++ b/tests/MaterialDesignThemes.UITests/TestBase.cs @@ -2,6 +2,9 @@ using System.Windows.Media; using MaterialDesignThemes.UITests; using MaterialDesignThemes.Wpf.Internal; +using Microsoft.VisualStudio.TestPlatform.ObjectModel; +using Microsoft.VisualStudio.TestPlatform.Utilities; +using TUnit.Core; using TUnit.Core.Interfaces; [assembly: ParallelLimiter] @@ -26,13 +29,16 @@ public record SingleParallelLimit : IParallelLimit public int Limit => 1; } -public abstract class TestBase() +public abstract class TestBase { - protected bool AttachedDebuggerToRemoteProcess { get; set; } = true; + public bool AttachedDebuggerToRemoteProcess { get; set; } = true; protected static TextWriter Output => TestContext.Current?.OutputWriter ?? throw new InvalidOperationException("Could not find output writer"); [NotNull] - protected IApp? App { get; set; } + public IApp? App { get; set; } + + [NotNull] + public TestRecorder? Recorder { get; set; } protected async Task GetThemeColor(string name) { @@ -56,9 +62,9 @@ protected async Task LoadUserControl(Type userControlType) return await App.CreateWindowWithUserControl(userControlType); } - [Before(Test)] - public async ValueTask InitializeAsync() => - App = await XamlTest.App.StartRemote(new AppOptions + public Task StartApp() + { + return XamlTest.App.StartRemote(new AppOptions { #if !DEBUG MinimizeOtherWindows = !System.Diagnostics.Debugger.IsAttached, @@ -66,7 +72,5 @@ public async ValueTask InitializeAsync() => AllowVisualStudioDebuggerAttach = AttachedDebuggerToRemoteProcess, LogMessage = Output.WriteLine }); - - [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 bf6945b564..faac37b3eb 100644 --- a/tests/MaterialDesignThemes.UITests/WPF/AutoSuggestBoxes/AutoSuggestTextBoxTests.cs +++ b/tests/MaterialDesignThemes.UITests/WPF/AutoSuggestBoxes/AutoSuggestTextBoxTests.cs @@ -14,8 +14,6 @@ public AutoSuggestBoxTests() [Test] public async Task CanFilterItems_WithSuggestionsAndDisplayMember_FiltersSuggestions() { - await using var recorder = new TestRecorder(App); - //Arrange IVisualElement suggestBox = (await LoadUserControl()).As(); IVisualElement popup = await suggestBox.GetElement(); @@ -38,15 +36,11 @@ public async Task CanFilterItems_WithSuggestionsAndDisplayMember_FiltersSuggesti await AssertExists(suggestionListBox, "Apples", false); await AssertExists(suggestionListBox, "Mtn Dew", false); await AssertExists(suggestionListBox, "Orange", false); - - recorder.Success(); } [Test] public async Task CanChoiceItem_FromTheSuggestions_AssertTheTextUpdated() { - await using var recorder = new TestRecorder(App); - //Arrange IVisualElement suggestBox = (await LoadUserControl()).As(); IVisualElement popup = await suggestBox.GetElement(); @@ -69,7 +63,7 @@ await Wait.For(async () => lastHeight = currentHeight; if (!rv) { - await Task.Delay(100, TestContext.Current!.CancellationToken); + await Task.Delay(100, TestContext.Current!.Execution.CancellationToken); } return rv; }); @@ -80,20 +74,16 @@ await Wait.For(async () => await bananas.LeftClick(); // Wait for the text to be updated - await Task.Delay(50, TestContext.Current!.CancellationToken); + await Task.Delay(50, TestContext.Current!.Execution.CancellationToken); var suggestBoxText = await suggestBox.GetText(); //Validate that the current text is the same as the selected item await Assert.That(suggestBoxText).IsEqualTo("Bananas"); - - recorder.Success(); } [Test] public async Task CanFilterItems_WithCollectionView_FiltersSuggestions() { - await using var recorder = new TestRecorder(App); - //Arrange IVisualElement userControl = await LoadUserControl(); IVisualElement suggestBox = await userControl.GetElement(); @@ -117,16 +107,12 @@ public async Task CanFilterItems_WithCollectionView_FiltersSuggestions() await AssertExists(suggestionListBox, "Apples", false); await AssertExists(suggestionListBox, "Mtn Dew", false); await AssertExists(suggestionListBox, "Orange", false); - - recorder.Success(); } [Test] [Description("Issue 3761")] public async Task AutoSuggestBox_MovesFocusToNextElement_WhenPopupIsClosed() { - await using var recorder = new TestRecorder(App); - // Arrange string xaml = """ @@ -142,27 +128,23 @@ public async Task AutoSuggestBox_MovesFocusToNextElement_WhenPopupIsClosed() // Act await suggestBox.MoveKeyboardFocus(); - await Task.Delay(50, TestContext.Current!.CancellationToken); + await Task.Delay(50, TestContext.Current!.Execution.CancellationToken); await suggestBox.SendInput(new KeyboardInput("B")); // Open the popup - await Task.Delay(50, TestContext.Current.CancellationToken); + await Task.Delay(50, TestContext.Current.Execution.CancellationToken); await suggestBox.SendInput(new KeyboardInput(Key.Escape)); // Close the popup - await Task.Delay(50, TestContext.Current.CancellationToken); + await Task.Delay(50, TestContext.Current.Execution.CancellationToken); await suggestBox.SendInput(new KeyboardInput(Key.Tab)); // Press TAB to focus the next element - await Task.Delay(50, TestContext.Current.CancellationToken); + await Task.Delay(50, TestContext.Current.Execution.CancellationToken); // Assert await Assert.That(await suggestBox.GetIsFocused()).IsFalse(); await Assert.That(await nextTextBox.GetIsFocused()).IsTrue(); - - recorder.Success(); } [Test] [Description("Issue 3815")] public async Task AutoSuggestBox_KeysUpAndDown_WrapAround() { - await using var recorder = new TestRecorder(App); - //Arrange IVisualElement suggestBox = (await LoadUserControl()).As(); IVisualElement popup = await suggestBox.GetElement(); @@ -173,7 +155,7 @@ public async Task AutoSuggestBox_KeysUpAndDown_WrapAround() //Act & Assert await suggestBox.MoveKeyboardFocus(); await suggestBox.SendInput(new KeyboardInput("e")); - await Task.Delay(delay, TestContext.Current!.CancellationToken); + await Task.Delay(delay, TestContext.Current!.Execution.CancellationToken); static int? GetSuggestionCount(AutoSuggestBox autoSuggestBox) { @@ -186,26 +168,22 @@ public async Task AutoSuggestBox_KeysUpAndDown_WrapAround() //Assert that initially the first item is selected int selectedIndex = await suggestionListBox.GetSelectedIndex(); await Assert.That(selectedIndex).IsEqualTo(0); - await Task.Delay(delay, TestContext.Current.CancellationToken); + await Task.Delay(delay, TestContext.Current.Execution.CancellationToken); //Assert that the last item is selected after pressing ArrowUp await suggestBox.SendInput(new KeyboardInput(Key.Up)); await Assert.That(await suggestionListBox.GetSelectedIndex()).IsEqualTo(itemCount - 1); - await Task.Delay(delay, TestContext.Current.CancellationToken); + await Task.Delay(delay, TestContext.Current.Execution.CancellationToken); //Assert that the first item is selected after pressing ArrowDown await suggestBox.SendInput(new KeyboardInput(Key.Down)); await Assert.That(await suggestionListBox.GetSelectedIndex()).IsEqualTo(0); - - recorder.Success(); } [Test] [Description("Issue 3845")] public async Task AutoSuggestBox_SelectingAnItem_SetsSelectedItem() { - await using var recorder = new TestRecorder(App); - //Arrange IVisualElement userControl = await LoadUserControl(); IVisualElement suggestBox = await userControl.GetElement(); @@ -228,15 +206,11 @@ static async Task AssertViewModelProperty(AutoSuggestBox autoSuggestBox) await Assert.That(viewModel.SelectedItem).IsEqualTo("Bananas"); } await suggestBox.RemoteExecute(AssertViewModelProperty); - - recorder.Success(); } [Test] public async Task AutoSuggestBox_ClickingButtonInInteractiveItemTemplate_DoesNotSelectOrClosePopup() { - await using var recorder = new TestRecorder(App); - // Arrange IVisualElement suggestBox = (await LoadUserControl()).As(); IVisualElement popup = await suggestBox.GetElement(); @@ -245,7 +219,7 @@ public async Task AutoSuggestBox_ClickingButtonInInteractiveItemTemplate_DoesNot // Act await suggestBox.MoveKeyboardFocus(); await suggestBox.SendInput(new KeyboardInput("a")); - await Task.Delay(500, TestContext.Current!.CancellationToken); + await Task.Delay(500, TestContext.Current!.Execution.CancellationToken); // Find the button in the first suggestion item var thirdListBoxItem = await suggestionListBox.GetElement("/ListBoxItem[2]"); @@ -253,7 +227,7 @@ public async Task AutoSuggestBox_ClickingButtonInInteractiveItemTemplate_DoesNot // Click the button await button.LeftClick(); - await Task.Delay(500, TestContext.Current!.CancellationToken); + await Task.Delay(500, TestContext.Current!.Execution.CancellationToken); // Assert await Assert.That(await suggestBox.GetIsSuggestionOpen()).IsTrue(); @@ -267,14 +241,11 @@ static async Task AssertViewModelProperty(AutoSuggestBox autoSuggestBox) await Assert.That(thirdItem.Count).IsEqualTo(1); } await suggestBox.RemoteExecute(AssertViewModelProperty); - recorder.Success(); } [Test] public async Task AutoSuggestBox_ClickingButtonForcingNonInteractive_SelectsItemAndClosesPopup() { - await using var recorder = new TestRecorder(App); - // Arrange IVisualElement suggestBox = (await LoadUserControl()).As(); IVisualElement popup = await suggestBox.GetElement(); @@ -283,7 +254,7 @@ public async Task AutoSuggestBox_ClickingButtonForcingNonInteractive_SelectsItem // Act await suggestBox.MoveKeyboardFocus(); await suggestBox.SendInput(new KeyboardInput("a")); - await Task.Delay(500, TestContext.Current!.CancellationToken); + await Task.Delay(500, TestContext.Current!.Execution.CancellationToken); // Find the button in the first suggestion item var thirdListBoxItem = await suggestionListBox.GetElement("/ListBoxItem[2]"); @@ -295,19 +266,15 @@ static void SetNonInteractive(Button button) // Click the button await button.LeftClick(); - await Task.Delay(500, TestContext.Current!.CancellationToken); + await Task.Delay(500, TestContext.Current!.Execution.CancellationToken); // Assert await Assert.That(await suggestBox.GetIsSuggestionOpen()).IsFalse(); - - recorder.Success(); } [Test] public async Task AutoSuggestBox_ClickingTextblockThatIsInteractive_DoesNotSelectOrClosePopup() { - await using var recorder = new TestRecorder(App); - // Arrange IVisualElement suggestBox = (await LoadUserControl()).As(); IVisualElement popup = await suggestBox.GetElement(); @@ -316,7 +283,7 @@ public async Task AutoSuggestBox_ClickingTextblockThatIsInteractive_DoesNotSelec // Act await suggestBox.MoveKeyboardFocus(); await suggestBox.SendInput(new KeyboardInput("a")); - await Task.Delay(500, TestContext.Current!.CancellationToken); + await Task.Delay(500, TestContext.Current!.Execution.CancellationToken); // Find the button in the first suggestion item var thirdListBoxItem = await suggestionListBox.GetElement("/ListBoxItem[2]"); @@ -328,7 +295,7 @@ static void SetInteractive(TextBlock textBlock) // Click the button await textBlock.LeftClick(); - await Task.Delay(500, TestContext.Current!.CancellationToken); + await Task.Delay(500, TestContext.Current!.Execution.CancellationToken); // Assert await Assert.That(await suggestBox.GetIsSuggestionOpen()).IsTrue(); @@ -336,8 +303,6 @@ static void SetInteractive(TextBlock textBlock) // The list box item should selected because the TextBlock does not handle the click int selectedIndex = await suggestionListBox.GetSelectedIndex(); await Assert.That(selectedIndex).IsEqualTo(2); - - recorder.Success(); } private static async Task AssertExists(IVisualElement suggestionListBox, string text, bool existsOrNotCheck = true) diff --git a/tests/MaterialDesignThemes.UITests/WPF/Buttons/OutlineButtonTests.cs b/tests/MaterialDesignThemes.UITests/WPF/Buttons/OutlineButtonTests.cs index 312ab51d28..9158740a13 100644 --- a/tests/MaterialDesignThemes.UITests/WPF/Buttons/OutlineButtonTests.cs +++ b/tests/MaterialDesignThemes.UITests/WPF/Buttons/OutlineButtonTests.cs @@ -7,8 +7,6 @@ public class OutlineButtonTests : TestBase [Test] public async Task OutlinedButton_UsesThemeColorForBorder() { - await using var recorder = new TestRecorder(App); - //Arrange IVisualElement