diff --git a/.github/workflows/dotnet-build.yml b/.github/workflows/dotnet-build.yml index 3333df3bb4..b03536fd2e 100644 --- a/.github/workflows/dotnet-build.yml +++ b/.github/workflows/dotnet-build.yml @@ -212,24 +212,24 @@ jobs: - name: Run CommunityToolkit Analyzers UnitTests run: | cd ${{ env.PathToCommunityToolkitAnalyzersUnitTestProjectDirectory }} - dotnet run -c Release --results-directory "${{ runner.temp }}" --coverage --coverage-output "${{ runner.temp }}/ut-analyzers.cobertura.xml" --coverage-output-format cobertura --report-xunit + dotnet test -c Release --report-gh -report-xunit-trx --report-xunit-trx-filename "ut-analyzers.trx" --results-directory "${{ runner.temp }}" --coverage --coverage-output "${{ runner.temp }}/ut-analyzers.cobertura.xml" --coverage-output-format cobertura - name: Run CommunityToolkit Source Generators UnitTests if: runner.os == 'Windows' run: | cd ${{ env.PathToCommunityToolkitSourceGeneratorsUnitTestDirectory }} - dotnet run -c Release --results-directory "${{ runner.temp }}" --coverage --coverage-output "${{ runner.temp }}/ut-sourcegenerators.cobertura.xml" --coverage-output-format cobertura --report-xunit + dotnet test -c Release --report-gh -report-xunit-trx --report-xunit-trx-filename "ut-sourcegenerators.trx" --results-directory "${{ runner.temp }}" --coverage --coverage-output "${{ runner.temp }}/ut-sourcegenerators.cobertura.xml" --coverage-output-format cobertura - name: Run CommunityToolkit MediaElement Source Generators UnitTests if: runner.os == 'Windows' run: | cd ${{ env.PathToCommunityToolkitMediaElementSourceGeneratorsUnitTestDirectory }} - dotnet run -c Release --results-directory "${{ runner.temp }}" --coverage --coverage-output "${{ runner.temp }}/ut-mediaelement-sourcegenerators.cobertura.xml" --coverage-output-format cobertura --report-xunit + dotnet test -c Release --report-gh -report-xunit-trx --report-xunit-trx-filename "ut-mediaelement-sourcegenerators.trx" --results-directory "${{ runner.temp }}" --coverage --coverage-output "${{ runner.temp }}/ut-mediaelement-sourcegenerators.cobertura.xml" --coverage-output-format cobertura - name: Run CommunityToolkit UnitTests run: | cd ${{ env.PathToCommunityToolkitUnitTestProjectDirectory }} - dotnet run -c Release --results-directory "${{ runner.temp }}" --coverage --coverage-output "${{ runner.temp }}/ut.cobertura.xml" --coverage-output-format cobertura --report-xunit + dotnet test -c Release --report-gh -report-xunit-trx --report-xunit-trx-filename "ut.trx" --results-directory "${{ runner.temp }}" --coverage --coverage-output "${{ runner.temp }}/ut.cobertura.xml" --coverage-output-format cobertura - name: Create code coverage report if: ${{ runner.os == 'Windows' && (success() || failure()) }} diff --git a/Directory.Build.props b/Directory.Build.props index 552b161d37..9a7d5c666a 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -141,10 +141,30 @@ https://docs.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitati xUnit1041: Fixture arguments to test classes must have fixture sources xUnit1042: The member referenced by the MemberData attribute returns untyped data rows xUnit1043: Constructors on classes derived from FactAttribute must be public when used on test methods + xUnit1044: Avoid using TheoryData type arguments that are not serializable + xUnit1046: Avoid using TheoryDataRow arguments that are not serializable xUnit1048: Avoid using 'async void' for test methods as it is deprecated in xUnit.net v3 xUnit1049: Do not use 'async void' for test methods as it is no longer supported xUnit1050: The class referenced by the ClassData attribute returns untyped data rows xUnit1051: Calls to methods which accept CancellationToken should use TestContext.Current.CancellationToken + xUnit1052: Avoid using 'TheoryData<...>' with types that implement 'ITheoryDataRow' + xUnit1053: The static member used as theory data must be statically initialized + xUnit1054: Properties used for conditional skipping must be public, static, and return bool + xUnit1055: Conditional skipping cannot set both SkipUnless and SkipWhen + xUnit1056: Type must have a single public non-static constructor + xUnit1057: Type must be public or internal + xUnit1058: Generic collection definitions are not supported in Native AOT + xUnit1059: Test classes may not be decorated with ICollectionFixture<> + xUnit1060: Cultured test methods must have at least one culture + xUnit1061: Fact methods cannot be generic + xUnit1062: Theory methods cannot be generic in Native AOT + xUnit1063: Test class cannot be an open generic type + xUnit1064: Theory parameter cannot use params modifier in Native AOT + xUnit1065: MemberData method is ambiguous + xUnit1066: MemberData parameter cannot use params modifier in Native AOT + xUnit1067: There is no matching MemberData method argument + xUnit1068: MemberData cannot point to an open generic type + xUnit1069: Test methods with a Timeout should reference TestContext.Current.CancellationToken xUnit2000: Constants and literals should be the expected argument xUnit2001: Do not use invalid equality check xUnit2002: Do not use null check on value type @@ -178,9 +198,16 @@ https://docs.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitati xUnit2030: Do not use Assert.NotEmpty to check if a value exists in a collection xUnit2031: Do not use Where clause with Assert.Single xUnit2032: Type assertions based on 'assignable from' are confusingly named + xUnit2033: Use the assertion return value instead of re-deriving it xUnit3000: Classes which cross AppDomain boundaries must derive directly or indirectly from LongLivedMarshalByRefObject xUnit3001: Classes that are marked as serializable (or created by the test framework at runtime) must have a public parameterless constructor xUnit3002: Classes which are JSON serializable should not be tested for their concrete type + xUnit3003: Classes which extend FactAttribute (directly or indirectly) should provide a public constructor for source information + xUnit3004: Type must implement appropriate interface + xUnit3005: Type must have an appropriate non-obsolete public constructor + xUnit3006: Test case implementation must be serializable + xUnit3007: Test case implementation might not be serializable + xUnit1045 + xUnit1047 ("might not be serializable") are intentionally excluded: they flag every TheoryData, TheoryData, etc. used to test converters and behaviors, which cannot be resolved without suppressing the diagnostic XC0045: Binding: Property not found XC0103: Consider attributing the markup extension with [RequireService] or [AcceptEmptyServiceProvider] if it doesn't require any XC0618: Property, Property setter or BindableProperty "BackgroundColor" is deprecated @@ -194,9 +221,9 @@ https://docs.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitati CsWinRT1028,CsWinRT1030, MVVMTK0001,MVVMTK0002,MVVMTK0003,MVVMTK0009,MVVMTK0010,MVVMTK0011,MVVMTK0012,MVVMTK0013,MVVMTK0017,MVVMTK0018,MVVMTK0019,MVVMTK0020,MVVMTK0023,MVVMTK0024,MVVMTK0032,MVVMTK0033,MVVMTK0034,MVVMTK0035,MVVMTK0036,MVVMTK0039,MVVMTK0042,MVVMTK0049,MVVMTK0050,MVVMTK0052,MVVMTK0053,MVVMTK0054,MVVMTK0055,MVVMTK0056, NU1900,NU1901,NU1902,NU1903,NU1904,NU1905, - xUnit1000,xUnit1001,xUnit1002,xUnit1003,xUnit1004,xUnit1005,xUnit1006,xUnit1007,xUnit1008,xUnit1009,xUnit1010,xUnit1011,xUnit1012,xUnit1013,xUnit1014,xUnit1015,xUnit1016,xUnit1017,xUnit1018,xUnit1019,xUnit1020,xUnit1021,xUnit1022,xUnit1023,xUnit1024,xUnit1025,xUnit1026,xUnit1027,xUnit1028,xUnit1029,xUnit1030,xUnit1031,xUnit1032,xUnit1033,xUnit1034,xUnit1035,xUnit1036,xUnit1037,xUnit1038,xUnit1039,xUnit1040,xUnit1041,xUnit1042,xUnit1043,xUnit1048,xUnit1049,xUnit1050,xUnit1051, - xUnit2000,xUnit2001,xUnit2002,xUnit2003,xUnit2004,xUnit2005,xUnit2006,xUnit2007,xUnit2008,xUnit2009,xUnit2010,xUnit2011,xUnit2012,xUnit2013,xUnit2014,xUnit2015,xUnit2016,xUnit2017,xUnit2018,xUnit2019,xUnit2020,xUnit2021,xUnit2022,xUnit2023,xUnit2024,xUnit2025,xUnit2026,xUnit2027,xUnit2028,xUnit2029,xUnit2030,xUnit2031,xUnit2032, - xUnit3000,xUnit3001,xUnit3002, + xUnit1000,xUnit1001,xUnit1002,xUnit1003,xUnit1004,xUnit1005,xUnit1006,xUnit1007,xUnit1008,xUnit1009,xUnit1010,xUnit1011,xUnit1012,xUnit1013,xUnit1014,xUnit1015,xUnit1016,xUnit1017,xUnit1018,xUnit1019,xUnit1020,xUnit1021,xUnit1022,xUnit1023,xUnit1024,xUnit1025,xUnit1026,xUnit1027,xUnit1028,xUnit1029,xUnit1030,xUnit1031,xUnit1032,xUnit1033,xUnit1034,xUnit1035,xUnit1036,xUnit1037,xUnit1038,xUnit1039,xUnit1040,xUnit1041,xUnit1042,xUnit1043,xUnit1044,xUnit1046,xUnit1048,xUnit1049,xUnit1050,xUnit1051,xUnit1052,xUnit1053,xUnit1054,xUnit1055,xUnit1056,xUnit1057,xUnit1058,xUnit1059,xUnit1060,xUnit1061,xUnit1062,xUnit1063,xUnit1064,xUnit1065,xUnit1066,xUnit1067,xUnit1068,xUnit1069, + xUnit2000,xUnit2001,xUnit2002,xUnit2003,xUnit2004,xUnit2005,xUnit2006,xUnit2007,xUnit2008,xUnit2009,xUnit2010,xUnit2011,xUnit2012,xUnit2013,xUnit2014,xUnit2015,xUnit2016,xUnit2017,xUnit2018,xUnit2019,xUnit2020,xUnit2021,xUnit2022,xUnit2023,xUnit2024,xUnit2025,xUnit2026,xUnit2027,xUnit2028,xUnit2029,xUnit2030,xUnit2031,xUnit2032,xUnit2033, + xUnit3000,xUnit3001,xUnit3002,xUnit3003,xUnit3004,xUnit3005,xUnit3006,xUnit3007, XC0045,XC0103,XC0618, IL2001,IL2002,IL2003,IL2004,IL2005,IL2006,IL2007,IL2008,IL2009, IL2010,IL2011,IL2012,IL2013,IL2014,IL2015,IL2016,IL2017,IL2018,IL2019, diff --git a/global.json b/global.json index d46d21e50b..df32a2e39c 100644 --- a/global.json +++ b/global.json @@ -3,5 +3,8 @@ "version": "10.0.100", "rollForward": "latestFeature", "allowPrerelease": false + }, + "test": { + "runner": "Microsoft.Testing.Platform" } } diff --git a/src/CommunityToolkit.Maui.Analyzers.UnitTests/CommunityToolkit.Maui.Analyzers.UnitTests.csproj b/src/CommunityToolkit.Maui.Analyzers.UnitTests/CommunityToolkit.Maui.Analyzers.UnitTests.csproj index d8cc168303..83f29eb216 100644 --- a/src/CommunityToolkit.Maui.Analyzers.UnitTests/CommunityToolkit.Maui.Analyzers.UnitTests.csproj +++ b/src/CommunityToolkit.Maui.Analyzers.UnitTests/CommunityToolkit.Maui.Analyzers.UnitTests.csproj @@ -9,6 +9,7 @@ true Exe CommunityToolkit.Maui.Analyzers.UnitTests + true @@ -19,17 +20,13 @@ - - + + + + - - - - - - diff --git a/src/CommunityToolkit.Maui.Core/CommunityToolkit.Maui.Core.csproj b/src/CommunityToolkit.Maui.Core/CommunityToolkit.Maui.Core.csproj index 365578de60..46938e4f45 100644 --- a/src/CommunityToolkit.Maui.Core/CommunityToolkit.Maui.Core.csproj +++ b/src/CommunityToolkit.Maui.Core/CommunityToolkit.Maui.Core.csproj @@ -66,7 +66,7 @@ - + diff --git a/src/CommunityToolkit.Maui.MediaElement.SourceGenerators.UnitTests/CommunityToolkit.Maui.MediaElement.SourceGenerators.UnitTests.csproj b/src/CommunityToolkit.Maui.MediaElement.SourceGenerators.UnitTests/CommunityToolkit.Maui.MediaElement.SourceGenerators.UnitTests.csproj index 2a2ada503b..b4beda4060 100644 --- a/src/CommunityToolkit.Maui.MediaElement.SourceGenerators.UnitTests/CommunityToolkit.Maui.MediaElement.SourceGenerators.UnitTests.csproj +++ b/src/CommunityToolkit.Maui.MediaElement.SourceGenerators.UnitTests/CommunityToolkit.Maui.MediaElement.SourceGenerators.UnitTests.csproj @@ -8,6 +8,7 @@ true Exe CommunityToolkit.Maui.MediaElement.SourceGenerators.UnitTests + true @@ -18,19 +19,15 @@ - - + + + + - - - - - - diff --git a/src/CommunityToolkit.Maui.SourceGenerators.UnitTests/CommunityToolkit.Maui.SourceGenerators.UnitTests.csproj b/src/CommunityToolkit.Maui.SourceGenerators.UnitTests/CommunityToolkit.Maui.SourceGenerators.UnitTests.csproj index 32332dda2c..b177a42b9a 100644 --- a/src/CommunityToolkit.Maui.SourceGenerators.UnitTests/CommunityToolkit.Maui.SourceGenerators.UnitTests.csproj +++ b/src/CommunityToolkit.Maui.SourceGenerators.UnitTests/CommunityToolkit.Maui.SourceGenerators.UnitTests.csproj @@ -8,6 +8,7 @@ true Exe CommunityToolkit.Maui.SourceGenerators.UnitTests + true @@ -18,19 +19,15 @@ - + + + - - - - - - diff --git a/src/CommunityToolkit.Maui.UnitTests/Alerts/SnackbarTests.cs b/src/CommunityToolkit.Maui.UnitTests/Alerts/SnackbarTests.cs index d873bd64c6..4188afd058 100644 --- a/src/CommunityToolkit.Maui.UnitTests/Alerts/SnackbarTests.cs +++ b/src/CommunityToolkit.Maui.UnitTests/Alerts/SnackbarTests.cs @@ -46,7 +46,7 @@ public async Task SnackbarShow_CancellationTokenExpires() [Fact(Timeout = (int)TestDuration.Short)] public async Task SnackbarShow_CancellationTokenCanceled() { - var cts = new CancellationTokenSource(); + using var cts = CancellationTokenSource.CreateLinkedTokenSource(TestContext.Current.CancellationToken); await Assert.ThrowsAsync(() => { @@ -69,7 +69,7 @@ public async Task SnackbarDismiss_CancellationTokenExpires() [Fact(Timeout = (int)TestDuration.Short)] public async Task SnackbarDismiss_CancellationTokenCanceled() { - var cts = new CancellationTokenSource(); + using var cts = CancellationTokenSource.CreateLinkedTokenSource(TestContext.Current.CancellationToken); await Assert.ThrowsAsync(() => { @@ -176,7 +176,7 @@ public void SnackbarMake_NewSnackbarCreatedWithValidProperties() [Fact(Timeout = (int)TestDuration.Short)] public async Task SnackbarShow_CancellationTokenCancelled_ReceiveException() { - using var cancellationTokenSource = new CancellationTokenSource(); + using var cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(TestContext.Current.CancellationToken); cancellationTokenSource.Cancel(); @@ -186,7 +186,7 @@ public async Task SnackbarShow_CancellationTokenCancelled_ReceiveException() [Fact(Timeout = (int)TestDuration.Short)] public async Task SnackbarDismiss_CancellationTokenCancelled_ReceiveException() { - using var cancellationTokenSource = new CancellationTokenSource(); + using var cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(TestContext.Current.CancellationToken); cancellationTokenSource.Cancel(); @@ -196,14 +196,14 @@ public async Task SnackbarDismiss_CancellationTokenCancelled_ReceiveException() [Fact(Timeout = (int)TestDuration.Short)] public async Task SnackbarShow_CancellationTokenNotCancelled_NotReceiveException() { - using var cancellationTokenSource = new CancellationTokenSource(); + using var cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(TestContext.Current.CancellationToken); await snackbar.Invoking(x => x.Show(cancellationTokenSource.Token)).Should().NotThrowAsync(); } [Fact(Timeout = (int)TestDuration.Short)] public async Task SnackbarDismiss_CancellationTokenNotCancelled_NotReceiveException() { - using var cancellationTokenSource = new CancellationTokenSource(); + using var cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(TestContext.Current.CancellationToken); await snackbar.Invoking(x => x.Dismiss(cancellationTokenSource.Token)).Should().NotThrowAsync(); } diff --git a/src/CommunityToolkit.Maui.UnitTests/Alerts/ToastTests.cs b/src/CommunityToolkit.Maui.UnitTests/Alerts/ToastTests.cs index 90e32e007d..c37294fa73 100644 --- a/src/CommunityToolkit.Maui.UnitTests/Alerts/ToastTests.cs +++ b/src/CommunityToolkit.Maui.UnitTests/Alerts/ToastTests.cs @@ -29,7 +29,7 @@ public async Task ToastShow_CancellationTokenExpires() [Fact(Timeout = (int)TestDuration.Short)] public async Task ToastShow_CancellationTokenCanceled() { - var cts = new CancellationTokenSource(); + using var cts = CancellationTokenSource.CreateLinkedTokenSource(TestContext.Current.CancellationToken); await Assert.ThrowsAsync(() => { @@ -52,7 +52,7 @@ public async Task ToastDismiss_CancellationTokenExpires() [Fact(Timeout = (int)TestDuration.Short)] public async Task ToastDismiss_CancellationTokenCanceled() { - var cts = new CancellationTokenSource(); + using var cts = CancellationTokenSource.CreateLinkedTokenSource(TestContext.Current.CancellationToken); await Assert.ThrowsAsync(() => { @@ -82,35 +82,31 @@ public void ToastMake_NewToastCreatedWithValidProperties() [Fact(Timeout = (int)TestDuration.Short)] public async Task ToastShow_CancellationTokenCancelled_ReceiveException() { - var cancellationTokenSource = new CancellationTokenSource(); + using var cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(TestContext.Current.CancellationToken); cancellationTokenSource.Cancel(); await toast.Invoking(x => x.Show(cancellationTokenSource.Token)).Should().ThrowExactlyAsync(); - cancellationTokenSource.Dispose(); } [Fact(Timeout = (int)TestDuration.Short)] public async Task ToastDismiss_CancellationTokenCancelled_ReceiveException() { - var cancellationTokenSource = new CancellationTokenSource(); + using var cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(TestContext.Current.CancellationToken); cancellationTokenSource.Cancel(); await toast.Invoking(x => x.Dismiss(cancellationTokenSource.Token)).Should().ThrowExactlyAsync(); - cancellationTokenSource.Dispose(); } [Fact(Timeout = (int)TestDuration.Short)] public async Task ToastShow_CancellationTokenNotCancelled_NotReceiveException() { - var cancellationTokenSource = new CancellationTokenSource(); + using var cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(TestContext.Current.CancellationToken); await toast.Invoking(x => x.Show(cancellationTokenSource.Token)).Should().NotThrowAsync(); - cancellationTokenSource.Dispose(); } [Fact(Timeout = (int)TestDuration.Short)] public async Task ToastDismiss_CancellationTokenNotCancelled_NotReceiveException() { - var cancellationTokenSource = new CancellationTokenSource(); + using var cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(TestContext.Current.CancellationToken); await toast.Invoking(x => x.Dismiss(cancellationTokenSource.Token)).Should().NotThrowAsync(); - cancellationTokenSource.Dispose(); } [Fact(Timeout = (int)TestDuration.Short)] diff --git a/src/CommunityToolkit.Maui.UnitTests/Animations/FadeAnimationTests.cs b/src/CommunityToolkit.Maui.UnitTests/Animations/FadeAnimationTests.cs index 2d10acb793..85fe360194 100644 --- a/src/CommunityToolkit.Maui.UnitTests/Animations/FadeAnimationTests.cs +++ b/src/CommunityToolkit.Maui.UnitTests/Animations/FadeAnimationTests.cs @@ -22,7 +22,7 @@ public async Task AnimateShouldThrowWithNullView() public async Task CancellationTokenCanceled() { FadeAnimation animation = new(); - var cts = new CancellationTokenSource(); + using var cts = CancellationTokenSource.CreateLinkedTokenSource(TestContext.Current.CancellationToken); var label = new Label { diff --git a/src/CommunityToolkit.Maui.UnitTests/Behaviors/AnimationBehaviorTests.cs b/src/CommunityToolkit.Maui.UnitTests/Behaviors/AnimationBehaviorTests.cs index 5fe311d09f..ab48ec2d22 100644 --- a/src/CommunityToolkit.Maui.UnitTests/Behaviors/AnimationBehaviorTests.cs +++ b/src/CommunityToolkit.Maui.UnitTests/Behaviors/AnimationBehaviorTests.cs @@ -108,8 +108,8 @@ public async Task AnimateCommandStartsAnimation() behavior.AnimateCommand.Execute(TestContext.Current.CancellationToken); - await animationStartedTcs.Task; - await animationEndedTcs.Task; + await animationStartedTcs.Task.WaitAsync(TestContext.Current.CancellationToken); + await animationEndedTcs.Task.WaitAsync(TestContext.Current.CancellationToken); animationEnded.Should().BeTrue(); animationStarted.Should().BeTrue(); diff --git a/src/CommunityToolkit.Maui.UnitTests/Behaviors/BaseBehaviorTest.cs b/src/CommunityToolkit.Maui.UnitTests/Behaviors/BaseBehaviorTest.cs index be40a7a032..f3e702cd39 100644 --- a/src/CommunityToolkit.Maui.UnitTests/Behaviors/BaseBehaviorTest.cs +++ b/src/CommunityToolkit.Maui.UnitTests/Behaviors/BaseBehaviorTest.cs @@ -36,8 +36,8 @@ public void VerifyBindingContextNotAutomaticallySetWhenViewAttached() view.Behaviors.Add((Behavior)behavior); - Assert.Single(view.Behaviors); - Assert.Null(view.Behaviors[0].BindingContext); + var attachedBehavior = Assert.Single(view.Behaviors); + Assert.Null(attachedBehavior.BindingContext); } [Fact] diff --git a/src/CommunityToolkit.Maui.UnitTests/Behaviors/EmailValidationBehaviorTests.cs b/src/CommunityToolkit.Maui.UnitTests/Behaviors/EmailValidationBehaviorTests.cs index 3d97dd8898..696d3d1b98 100644 --- a/src/CommunityToolkit.Maui.UnitTests/Behaviors/EmailValidationBehaviorTests.cs +++ b/src/CommunityToolkit.Maui.UnitTests/Behaviors/EmailValidationBehaviorTests.cs @@ -279,7 +279,7 @@ public async Task ForceValidateCancellationTokenCanceled() { // Arrange var behavior = new EmailValidationBehavior(); - var cts = new CancellationTokenSource(TimeSpan.FromMilliseconds(1)); + using var cts = CancellationTokenSource.CreateLinkedTokenSource(TestContext.Current.CancellationToken); var entry = new Entry { diff --git a/src/CommunityToolkit.Maui.UnitTests/Behaviors/GestureManagerTests.cs b/src/CommunityToolkit.Maui.UnitTests/Behaviors/GestureManagerTests.cs index 034dae33d8..a61e0c5c66 100644 --- a/src/CommunityToolkit.Maui.UnitTests/Behaviors/GestureManagerTests.cs +++ b/src/CommunityToolkit.Maui.UnitTests/Behaviors/GestureManagerTests.cs @@ -107,8 +107,7 @@ public async Task HandleLongPress_ShouldRaiseLongPressCompleted() // Act var gestureManager = new GestureManager(); - var token = new CancellationTokenSource().Token; - await gestureManager.HandleLongPress(touchBehavior, token); + await gestureManager.HandleLongPress(touchBehavior, TestContext.Current.CancellationToken); // Assert Assert.True(longPressCompletedRaised); diff --git a/src/CommunityToolkit.Maui.UnitTests/Behaviors/MultiValidationBehaviorTests.cs b/src/CommunityToolkit.Maui.UnitTests/Behaviors/MultiValidationBehaviorTests.cs index 047d5bfa92..6d8d1f3d43 100644 --- a/src/CommunityToolkit.Maui.UnitTests/Behaviors/MultiValidationBehaviorTests.cs +++ b/src/CommunityToolkit.Maui.UnitTests/Behaviors/MultiValidationBehaviorTests.cs @@ -97,7 +97,7 @@ public async Task ForceValidateCancellationTokenExpired() public async Task ForceValidateCancellationTokenCanceled() { // Arrange - var cts = new CancellationTokenSource(TimeSpan.FromMilliseconds(1)); + using var cts = CancellationTokenSource.CreateLinkedTokenSource(TestContext.Current.CancellationToken); var characterValidationBehavior = new CharactersValidationBehavior(); var requiredStringValidationBehavior = new RequiredStringValidationBehavior(); diff --git a/src/CommunityToolkit.Maui.UnitTests/Behaviors/ProgressBarAnimationBehaviorTests.cs b/src/CommunityToolkit.Maui.UnitTests/Behaviors/ProgressBarAnimationBehaviorTests.cs index 21c47f82b4..10ceeb8135 100644 --- a/src/CommunityToolkit.Maui.UnitTests/Behaviors/ProgressBarAnimationBehaviorTests.cs +++ b/src/CommunityToolkit.Maui.UnitTests/Behaviors/ProgressBarAnimationBehaviorTests.cs @@ -38,9 +38,9 @@ public async Task ValidPropertiesTests(double progress, uint length, Easing easi progressBarAnimationBehavior.Easing = easing; progressBarAnimationBehavior.Progress = progress; - if (progressBar.Progress != progress) + if (Math.Abs(progressBar.Progress - progress) > 0.01) { - await progressBarAnimationCompletedTcs.Task; + await progressBarAnimationCompletedTcs.Task.WaitAsync(TestContext.Current.CancellationToken); } Assert.Equal(progress, progressBar.Progress); diff --git a/src/CommunityToolkit.Maui.UnitTests/Behaviors/TouchBehaviorTests.cs b/src/CommunityToolkit.Maui.UnitTests/Behaviors/TouchBehaviorTests.cs index 98768e1446..a4bccdb108 100644 --- a/src/CommunityToolkit.Maui.UnitTests/Behaviors/TouchBehaviorTests.cs +++ b/src/CommunityToolkit.Maui.UnitTests/Behaviors/TouchBehaviorTests.cs @@ -389,7 +389,7 @@ public async Task TestRaiseLongPressCompleted() touchBehavior.LongPressCompleted += HandleLongPressCompleted; touchBehavior.RaiseLongPressCompleted(); - hasLongPressCompleted = await longPressCompletedTCS.Task; + hasLongPressCompleted = await longPressCompletedTCS.Task.WaitAsync(TestContext.Current.CancellationToken); Assert.True(hasLongPressCompleted); @@ -414,7 +414,7 @@ public async Task TestRaiseEvent() Assert.False(hasTouchCompleted); touchBehavior.RaiseTouchGestureCompleted(); - hasTouchCompleted = await touchCompletedTCS.Task; + hasTouchCompleted = await touchCompletedTCS.Task.WaitAsync(TestContext.Current.CancellationToken); Assert.True(hasTouchCompleted); @@ -443,14 +443,14 @@ public async Task TestRaiseInteractionStatusChangedEvent() Assert.Equal(firstInteractionResult, finalInteractionResult); touchBehavior.HandleUserInteraction(TouchInteractionStatus.Started); - firstInteractionResult = await interactionStatusChangedCompletedTCS.Task; + firstInteractionResult = await interactionStatusChangedCompletedTCS.Task.WaitAsync(TestContext.Current.CancellationToken); Assert.Equal(TouchInteractionStatus.Started, firstInteractionResult); Assert.Equal(firstInteractionResult, touchBehavior.CurrentInteractionStatus); interactionStatusChangedCompletedTCS = new TaskCompletionSource(); touchBehavior.HandleUserInteraction(TouchInteractionStatus.Completed); - finalInteractionResult = await interactionStatusChangedCompletedTCS.Task; + finalInteractionResult = await interactionStatusChangedCompletedTCS.Task.WaitAsync(TestContext.Current.CancellationToken); Assert.Equal(TouchInteractionStatus.Completed, finalInteractionResult); Assert.Equal(finalInteractionResult, touchBehavior.CurrentInteractionStatus); @@ -480,14 +480,14 @@ public async Task TestRaiseHoverStatusChangedEvent() Assert.Equal(firstHoverStatusResult, finalHoverStatusResult); touchBehavior.HandleHover(HoverStatus.Entered); - firstHoverStatusResult = await hoverStatusChangedTCS.Task; + firstHoverStatusResult = await hoverStatusChangedTCS.Task.WaitAsync(TestContext.Current.CancellationToken); Assert.Equal(HoverStatus.Entered, firstHoverStatusResult); Assert.Equal(firstHoverStatusResult, touchBehavior.CurrentHoverStatus); hoverStatusChangedTCS = new TaskCompletionSource(); touchBehavior.HandleHover(HoverStatus.Exited); - finalHoverStatusResult = await hoverStatusChangedTCS.Task; + finalHoverStatusResult = await hoverStatusChangedTCS.Task.WaitAsync(TestContext.Current.CancellationToken); Assert.Equal(HoverStatus.Exited, finalHoverStatusResult); Assert.Equal(finalHoverStatusResult, touchBehavior.CurrentHoverStatus); @@ -517,14 +517,14 @@ public async Task TestRaiseHoverStateChangedEvent() Assert.Equal(firstHoverStateResult, finalHoverStateResult); touchBehavior.HandleHover(HoverStatus.Entered); - firstHoverStateResult = await hoverStateChangedTCS.Task; + firstHoverStateResult = await hoverStateChangedTCS.Task.WaitAsync(TestContext.Current.CancellationToken); Assert.Equal(HoverState.Hovered, firstHoverStateResult); Assert.Equal(firstHoverStateResult, touchBehavior.CurrentHoverState); hoverStateChangedTCS = new TaskCompletionSource(); touchBehavior.HandleHover(HoverStatus.Exited); - finalHoverStateResult = await hoverStateChangedTCS.Task; + finalHoverStateResult = await hoverStateChangedTCS.Task.WaitAsync(TestContext.Current.CancellationToken); Assert.Equal(HoverState.Default, finalHoverStateResult); Assert.Equal(finalHoverStateResult, touchBehavior.CurrentHoverState); @@ -558,13 +558,13 @@ public async Task TestRaiseTouchGestureCompletedEvent() Assert.Null(completedTouchGestureCompletedCommandParameter); touchBehavior.HandleTouch(TouchStatus.Started); - startedTouchStateChanged = await touchStateChangedTCS.Task; + startedTouchStateChanged = await touchStateChangedTCS.Task.WaitAsync(TestContext.Current.CancellationToken); Assert.Equal(TouchState.Pressed, startedTouchStateChanged); touchStateChangedTCS = new TaskCompletionSource(); touchBehavior.HandleTouch(TouchStatus.Completed); - completedTouchGestureCompletedCommandParameter = await touchGestureCompletedTCS.Task; - completedTouchStateChanged = await touchStateChangedTCS.Task; + completedTouchGestureCompletedCommandParameter = await touchGestureCompletedTCS.Task.WaitAsync(TestContext.Current.CancellationToken); + completedTouchStateChanged = await touchStateChangedTCS.Task.WaitAsync(TestContext.Current.CancellationToken); Assert.Equal(commandParameter, completedTouchGestureCompletedCommandParameter); Assert.Equal(completedTouchGestureCompletedCommandParameter, touchBehavior.CommandParameter); @@ -574,12 +574,12 @@ public async Task TestRaiseTouchGestureCompletedEvent() touchStateChangedTCS = new TaskCompletionSource(); touchBehavior.HandleTouch(TouchStatus.Started); - await touchStateChangedTCS.Task; + await touchStateChangedTCS.Task.WaitAsync(TestContext.Current.CancellationToken); touchStateChangedTCS = new TaskCompletionSource(); touchBehavior.HandleTouch(TouchStatus.Canceled); - canceledTouchStateChanged = await touchStateChangedTCS.Task; + canceledTouchStateChanged = await touchStateChangedTCS.Task.WaitAsync(TestContext.Current.CancellationToken); Assert.Equal(TouchStatus.Canceled, touchBehavior.CurrentTouchStatus); Assert.Equal(TouchState.Default, canceledTouchStateChanged); @@ -622,8 +622,8 @@ public async Task TestRaiseLongPressCompletedEvent() Assert.Null(longPressCompletedCommandParameter); touchBehavior.RaiseLongPressCompleted(); - await longPressCommandTCS.Task; - raiseLongPressCompletedCommandParameter = await longPressCompletedTCS.Task; + await longPressCommandTCS.Task.WaitAsync(TestContext.Current.CancellationToken); + raiseLongPressCompletedCommandParameter = await longPressCompletedTCS.Task.WaitAsync(TestContext.Current.CancellationToken); Assert.Equal(longPressCompletedParameter, raiseLongPressCompletedCommandParameter); @@ -631,8 +631,8 @@ public async Task TestRaiseLongPressCompletedEvent() longPressCommandTCS = new TaskCompletionSource(); touchBehavior.HandleTouch(TouchStatus.Started); - longPressCompletedCommandParameter = await longPressCompletedTCS.Task; - await longPressCommandTCS.Task; + longPressCompletedCommandParameter = await longPressCompletedTCS.Task.WaitAsync(TestContext.Current.CancellationToken); + await longPressCommandTCS.Task.WaitAsync(TestContext.Current.CancellationToken); touchBehavior.HandleTouch(TouchStatus.Completed); Assert.Equal(longPressCompletedParameter, longPressCompletedCommandParameter); @@ -643,8 +643,8 @@ public async Task TestRaiseLongPressCompletedEvent() touchBehavior.HandleUserInteraction(TouchInteractionStatus.Started); touchBehavior.HandleTouch(TouchStatus.Started); - longPressCanceledTouchGestureCompletedCommandParameter = await longPressCompletedTCS.Task; - await longPressCommandTCS.Task; + longPressCanceledTouchGestureCompletedCommandParameter = await longPressCompletedTCS.Task.WaitAsync(TestContext.Current.CancellationToken); + await longPressCommandTCS.Task.WaitAsync(TestContext.Current.CancellationToken); touchBehavior.HandleTouch(TouchStatus.Canceled); Assert.Equal(longPressCompletedParameter, longPressCanceledTouchGestureCompletedCommandParameter); @@ -678,25 +678,25 @@ public async Task VerifyIsToggledChangesState() touchStatusChangedTCS = new TaskCompletionSource(); touchBehavior.HandleTouch(TouchStatus.Started); - touchStatus = await touchStatusChangedTCS.Task; + touchStatus = await touchStatusChangedTCS.Task.WaitAsync(TestContext.Current.CancellationToken); Assert.Equal(TouchStatus.Started, touchStatus); touchStatusChangedTCS = new TaskCompletionSource(); touchBehavior.HandleTouch(TouchStatus.Completed); - touchStatus = await touchStatusChangedTCS.Task; + touchStatus = await touchStatusChangedTCS.Task.WaitAsync(TestContext.Current.CancellationToken); Assert.Equal(TouchStatus.Completed, touchStatus); touchStatusChangedTCS = new TaskCompletionSource(); touchBehavior.HandleTouch(TouchStatus.Started); - touchStatus = await touchStatusChangedTCS.Task; + touchStatus = await touchStatusChangedTCS.Task.WaitAsync(TestContext.Current.CancellationToken); Assert.Equal(TouchStatus.Started, touchStatus); touchStatusChangedTCS = new TaskCompletionSource(); touchBehavior.HandleTouch(TouchStatus.Completed); - touchStatus = await touchStatusChangedTCS.Task; + touchStatus = await touchStatusChangedTCS.Task.WaitAsync(TestContext.Current.CancellationToken); Assert.Equal(TouchStatus.Completed, touchStatus); @@ -778,8 +778,8 @@ public async Task RaiseTouchGestureCompletedWhenElementIsNull() AttachTouchBehaviorToVisualElement(view); touchBehavior.RaiseTouchGestureCompleted(); - var touchCompletedResult = await touchCompletedTCS.Task; - var commandResult = await touchCommandTCS.Task; + var touchCompletedResult = await touchCompletedTCS.Task.WaitAsync(TestContext.Current.CancellationToken); + var commandResult = await touchCommandTCS.Task.WaitAsync(TestContext.Current.CancellationToken); Assert.Equal(touchGestureCompletedParameter, touchCompletedResult); Assert.True(commandResult); @@ -820,8 +820,8 @@ public async Task RaiseLongPressCompletedWhenElementIsNull() AttachTouchBehaviorToVisualElement(view); touchBehavior.RaiseLongPressCompleted(); - var longPressCompletedResult = await longPressCompletedTCS.Task; - var longPressCommandResult = await longPressCommandTCS.Task; + var longPressCompletedResult = await longPressCompletedTCS.Task.WaitAsync(TestContext.Current.CancellationToken); + var longPressCommandResult = await longPressCommandTCS.Task.WaitAsync(TestContext.Current.CancellationToken); // Event fires and LongPressCommand executes when Element is not null Assert.Equal(longPressCompletedParameter, longPressCompletedResult); diff --git a/src/CommunityToolkit.Maui.UnitTests/Behaviors/UserStoppedTypingBehaviorTests.cs b/src/CommunityToolkit.Maui.UnitTests/Behaviors/UserStoppedTypingBehaviorTests.cs index 7635f0d943..d75f1aaf3e 100644 --- a/src/CommunityToolkit.Maui.UnitTests/Behaviors/UserStoppedTypingBehaviorTests.cs +++ b/src/CommunityToolkit.Maui.UnitTests/Behaviors/UserStoppedTypingBehaviorTests.cs @@ -21,7 +21,7 @@ public async Task ShouldExecuteCommandWhenTimeThresholdHasExpired() // act entry.Text = "1"; - await commandTCS.Task; + await commandTCS.Task.WaitAsync(TestContext.Current.CancellationToken); // assert Assert.True(commandHasBeenExecuted); @@ -41,7 +41,7 @@ public async Task ShouldExecuteCommandWithSpecificParameterWhenSpecified() // act entry.Text = "1"; - await commandTCS.Task; + await commandTCS.Task.WaitAsync(TestContext.Current.CancellationToken); // assert Assert.True(commandHasBeenExecuted); @@ -66,7 +66,7 @@ public async Task ShouldNotExecuteCommandBeforeTimeThresholdHasExpired() Assert.False(commandHasBeenExecuted); // act - await commandTCS.Task; + await commandTCS.Task.WaitAsync(TestContext.Current.CancellationToken); Assert.True(commandHasBeenExecuted); } @@ -90,7 +90,7 @@ public async Task ShouldOnlyExecuteCommandOnceWhenTextChangedHasOccurredMultiple entry.Text = "12"; entry.Text = "123"; entry.Text = "1234"; - await commandTCS.Task; + await commandTCS.Task.WaitAsync(TestContext.Current.CancellationToken); // assert Assert.Equal(1, timesExecuted); @@ -108,7 +108,7 @@ public async Task ShouldDismissKeyboardWhenTimeThresholdHasExpired() entry.Focus(); entry.Text = "1"; - await unfocusTCS.Task; + await unfocusTCS.Task.WaitAsync(TestContext.Current.CancellationToken); // assert Assert.False(entry.IsFocused); @@ -137,7 +137,7 @@ public async Task ShouldExecuteCommandWhenMinimumLengthThresholdHasBeenReached() entry.Text = "1"; entry.Text = "12"; entry.Text = "123"; - await commandTCS.Task; + await commandTCS.Task.WaitAsync(TestContext.Current.CancellationToken); // assert Assert.True(commandHasBeenExecuted); @@ -162,14 +162,14 @@ public async Task ShouldNotExecuteCommandWhenMinimumLengthThresholdHasNotBeenRea // act entry.Focus(); entry.Text = "1"; - await focusTCS.Task; + await focusTCS.Task.WaitAsync(TestContext.Current.CancellationToken); // assert Assert.False(commandHasBeenExecuted); // act entry.Text = "123"; - await commandTCS.Task; + await commandTCS.Task.WaitAsync(TestContext.Current.CancellationToken); // assert Assert.True(commandHasBeenExecuted); @@ -196,14 +196,14 @@ public async Task ShouldNotDismissKeyboardWhenMinimumLengthThresholdHasNotBeenRe entry.Focus(); entry.Text = "1"; - await focusTCS.Task; + await focusTCS.Task.WaitAsync(TestContext.Current.CancellationToken); // assert Assert.True(entry.IsFocused); // act entry.Text = "123"; - await unfocusTCS.Task; + await unfocusTCS.Task.WaitAsync(TestContext.Current.CancellationToken); // assert Assert.False(entry.IsFocused); @@ -235,7 +235,7 @@ public async Task ShouldExecuteCommandImmediatelyWhenMinimumLengthThresholdHasNo // act entry.Text = "1"; - await commandTCS.Task; + await commandTCS.Task.WaitAsync(TestContext.Current.CancellationToken); // assert Assert.True(commandHasBeenExecuted); diff --git a/src/CommunityToolkit.Maui.UnitTests/CommunityToolkit.Maui.UnitTests.csproj b/src/CommunityToolkit.Maui.UnitTests/CommunityToolkit.Maui.UnitTests.csproj index dc7711ec30..0a8aca09d5 100644 --- a/src/CommunityToolkit.Maui.UnitTests/CommunityToolkit.Maui.UnitTests.csproj +++ b/src/CommunityToolkit.Maui.UnitTests/CommunityToolkit.Maui.UnitTests.csproj @@ -4,15 +4,16 @@ $(NetVersion) Exe CommunityToolkit.Maui.UnitTests + true - - - + + + diff --git a/src/CommunityToolkit.Maui.UnitTests/Converters/ImageResourceConverterTests.cs b/src/CommunityToolkit.Maui.UnitTests/Converters/ImageResourceConverterTests.cs index 940fd1d6ad..99e8c16d67 100644 --- a/src/CommunityToolkit.Maui.UnitTests/Converters/ImageResourceConverterTests.cs +++ b/src/CommunityToolkit.Maui.UnitTests/Converters/ImageResourceConverterTests.cs @@ -52,7 +52,7 @@ public async Task ImageResourceConverter_CancellationTokenExpired() public async Task ImageResourceConverter_CancellationTokenCancelled() { const string resourceToLoad = "CommunityToolkit.Maui.UnitTests.Resources.dotnet-bot.png"; - var cts = new CancellationTokenSource(); + using var cts = CancellationTokenSource.CreateLinkedTokenSource(TestContext.Current.CancellationToken); var imageResourceConverter = new ImageResourceConverter(); diff --git a/src/CommunityToolkit.Maui.UnitTests/Extensions/BackgroundColorToTests.cs b/src/CommunityToolkit.Maui.UnitTests/Extensions/BackgroundColorToTests.cs index f0c8200a6e..1ddc456961 100644 --- a/src/CommunityToolkit.Maui.UnitTests/Extensions/BackgroundColorToTests.cs +++ b/src/CommunityToolkit.Maui.UnitTests/Extensions/BackgroundColorToTests.cs @@ -39,7 +39,7 @@ public async Task BackgroundColorTo_CancellationTokenExpired() [Fact(Timeout = (int)TestDuration.Short)] public async Task BackgroundColorTo_CancellationTokenCanceled() { - var cts = new CancellationTokenSource(); + using var cts = CancellationTokenSource.CreateLinkedTokenSource(TestContext.Current.CancellationToken); VisualElement element = new Label { BackgroundColor = Colors.Blue }; element.EnableAnimations(); diff --git a/src/CommunityToolkit.Maui.UnitTests/Extensions/DispatcherExtensionsTests.cs b/src/CommunityToolkit.Maui.UnitTests/Extensions/DispatcherExtensionsTests.cs index 3f6c811cf7..f3fb1044e9 100644 --- a/src/CommunityToolkit.Maui.UnitTests/Extensions/DispatcherExtensionsTests.cs +++ b/src/CommunityToolkit.Maui.UnitTests/Extensions/DispatcherExtensionsTests.cs @@ -107,7 +107,7 @@ public async Task DispatchIfRequiredAsync_TokenAlreadyCancelled_ThrowsOperationC { var dispatcher = new ConfigurableMockDispatcher(isDispatchRequired); var wasActionExecuted = false; - using var cts = new CancellationTokenSource(); + using var cts = CancellationTokenSource.CreateLinkedTokenSource(TestContext.Current.CancellationToken); await cts.CancelAsync(); await Assert.ThrowsAsync(() => ToolkitDispatcherExtensions.DispatchIfRequiredAsync(dispatcher, () => wasActionExecuted = true, cts.Token)); @@ -198,7 +198,7 @@ public async Task DispatchIfRequiredAsync_TokenCancelledBeforeQueuedActionExecut { var dispatcher = new ConfigurableMockDispatcher(isDispatchRequired: true, executeDispatchedActionsImmediately: false); var wasActionExecuted = false; - using var cts = new CancellationTokenSource(); + using var cts = CancellationTokenSource.CreateLinkedTokenSource(TestContext.Current.CancellationToken); var dispatchTask = ToolkitDispatcherExtensions.DispatchIfRequiredAsync(dispatcher, () => wasActionExecuted = true, cts.Token); @@ -214,7 +214,7 @@ public async Task DispatchIfRequiredAsync_TokenCancelledWhileActionQueued_Cancel { var dispatcher = new ConfigurableMockDispatcher(isDispatchRequired: true, executeDispatchedActionsImmediately: false); var wasActionExecuted = false; - using var cts = new CancellationTokenSource(); + using var cts = CancellationTokenSource.CreateLinkedTokenSource(TestContext.Current.CancellationToken); var dispatchTask = ToolkitDispatcherExtensions.DispatchIfRequiredAsync(dispatcher, () => wasActionExecuted = true, cts.Token); diff --git a/src/CommunityToolkit.Maui.UnitTests/Extensions/NavigatedFromEventArgsExtensionsTests.cs b/src/CommunityToolkit.Maui.UnitTests/Extensions/NavigatedFromEventArgsExtensionsTests.cs index 704bbe178f..2aa263af87 100644 --- a/src/CommunityToolkit.Maui.UnitTests/Extensions/NavigatedFromEventArgsExtensionsTests.cs +++ b/src/CommunityToolkit.Maui.UnitTests/Extensions/NavigatedFromEventArgsExtensionsTests.cs @@ -29,7 +29,7 @@ public async Task NavigatedFromEventArgsExtensions_IsDestinationPageACommunityTo // Act await mainPage.Navigation.PushAsync(shellContentPage); await popupService.ShowPopupAsync(shell, null, shellParameters, TestContext.Current.CancellationToken); - var isDestinationPageACommunityToolkitPopupPage = await isDestinationPageACommunityToolkitPopupPageTCS.Task; + var isDestinationPageACommunityToolkitPopupPage = await isDestinationPageACommunityToolkitPopupPageTCS.Task.WaitAsync(TestContext.Current.CancellationToken); // Assert Assert.True(isDestinationPageACommunityToolkitPopupPage); @@ -59,7 +59,7 @@ public async Task NavigatedFromEventArgsExtensions_IsDestinationPageACommunityTo await mainPage.Navigation.PushAsync(shellContentPage); //push a new content page on top to make sure the navigation handler doesn't think we're navigating to a popup page await mainPage.Navigation.PushAsync(newShellContentPage); - var isDestinationPageACommunityToolkitPopupPage = await isDestinationPageACommunityToolkitPopupPageTCS.Task; + var isDestinationPageACommunityToolkitPopupPage = await isDestinationPageACommunityToolkitPopupPageTCS.Task.WaitAsync(TestContext.Current.CancellationToken); // Assert Assert.False(isDestinationPageACommunityToolkitPopupPage); diff --git a/src/CommunityToolkit.Maui.UnitTests/Extensions/NavigatedToEventArgsExtensionsTests.cs b/src/CommunityToolkit.Maui.UnitTests/Extensions/NavigatedToEventArgsExtensionsTests.cs index c464c746c4..5243c7a0b7 100644 --- a/src/CommunityToolkit.Maui.UnitTests/Extensions/NavigatedToEventArgsExtensionsTests.cs +++ b/src/CommunityToolkit.Maui.UnitTests/Extensions/NavigatedToEventArgsExtensionsTests.cs @@ -29,7 +29,7 @@ public async Task NavigatedToEventArgsExtensions_WasPreviousPageACommunityToolki // Act await mainPage.Navigation.PushAsync(shellContentPage); await popupService.ShowPopupAsync(shell, null, shellParameters, TestContext.Current.CancellationToken); - var wasPreviousPageACommunityToolkitPopupPage = await wasPreviousPageACommunityToolkitPopupPageTCS.Task; + var wasPreviousPageACommunityToolkitPopupPage = await wasPreviousPageACommunityToolkitPopupPageTCS.Task.WaitAsync(TestContext.Current.CancellationToken); // Assert Assert.True(wasPreviousPageACommunityToolkitPopupPage); @@ -58,7 +58,7 @@ public async Task NavigatedToEventArgsExtensions_WasPreviousPageACommunityToolki // Act await mainPage.Navigation.PushAsync(shellContentPage); - var wasPreviousPageACommunityToolkitPopupPage = await wasPreviousPageACommunityToolkitPopupPageTCS.Task; + var wasPreviousPageACommunityToolkitPopupPage = await wasPreviousPageACommunityToolkitPopupPageTCS.Task.WaitAsync(TestContext.Current.CancellationToken); // Assert Assert.False(wasPreviousPageACommunityToolkitPopupPage); diff --git a/src/CommunityToolkit.Maui.UnitTests/Extensions/NavigatingFromEventArgsExtensionsTests.cs b/src/CommunityToolkit.Maui.UnitTests/Extensions/NavigatingFromEventArgsExtensionsTests.cs index 3530b49297..863a423652 100644 --- a/src/CommunityToolkit.Maui.UnitTests/Extensions/NavigatingFromEventArgsExtensionsTests.cs +++ b/src/CommunityToolkit.Maui.UnitTests/Extensions/NavigatingFromEventArgsExtensionsTests.cs @@ -27,7 +27,7 @@ public async Task NavigatingFromEventArgsExtensions_IsDestinationPageACommunityT // Act await mainPage.Navigation.PushAsync(shellContentPage); await popupService.ShowPopupAsync(shell, null, shellParameters, TestContext.Current.CancellationToken); - bool? isDestinationPageACommunityToolkitPopupPage = await isDestinationPageACommunityToolkitPopupPageTCS.Task; + bool? isDestinationPageACommunityToolkitPopupPage = await isDestinationPageACommunityToolkitPopupPageTCS.Task.WaitAsync(TestContext.Current.CancellationToken); // Assert Assert.True(isDestinationPageACommunityToolkitPopupPage); @@ -59,7 +59,7 @@ public async Task NavigatingFromEventArgsExtensions_IsDestinationPageACommunityT // Act await mainPage.Navigation.PushAsync(shellContentPage); await mainPage.Navigation.PushAsync(anotherShellContentPage); - bool? isDestinationPageACommunityToolkitPopupPage = await isDestinationPageACommunityToolkitPopupPageTCS.Task; + bool? isDestinationPageACommunityToolkitPopupPage = await isDestinationPageACommunityToolkitPopupPageTCS.Task.WaitAsync(TestContext.Current.CancellationToken); // Assert Assert.False(isDestinationPageACommunityToolkitPopupPage); diff --git a/src/CommunityToolkit.Maui.UnitTests/Extensions/PopupExtensionsTests.cs b/src/CommunityToolkit.Maui.UnitTests/Extensions/PopupExtensionsTests.cs index 68bbc63bc6..70b592c559 100644 --- a/src/CommunityToolkit.Maui.UnitTests/Extensions/PopupExtensionsTests.cs +++ b/src/CommunityToolkit.Maui.UnitTests/Extensions/PopupExtensionsTests.cs @@ -36,7 +36,7 @@ public PopupExtensionsTests() public async Task ClosePopup_TokenExpired_ShouldThrowOperationCancelledException() { // Arrange - var cts = new CancellationTokenSource(); + using var cts = CancellationTokenSource.CreateLinkedTokenSource(TestContext.Current.CancellationToken); // Act await cts.CancelAsync(); @@ -183,8 +183,8 @@ public async Task ShowPopupAsync_WithPopupType_ShowsPopupAndClosesPopup() navigation.ShowPopup(selfClosingPopup); // Assert - Assert.Single(navigation.ModalStack); - Assert.IsType(navigation.ModalStack[0]); + var modalPage = Assert.Single(navigation.ModalStack); + Assert.IsType(modalPage); // Act await navigation.ClosePopupAsync(TestContext.Current.CancellationToken); @@ -209,8 +209,8 @@ public async Task ShowPopupAsync_Shell_WithPopupType_ShowsPopupAndClosesPopup() shell.ShowPopup(new Popup()); // Assert - Assert.Single(shellNavigation.ModalStack); - Assert.IsType(shellNavigation.ModalStack[0]); + var modalPage = Assert.Single(shellNavigation.ModalStack); + Assert.IsType(modalPage); // Act await navigation.ClosePopupAsync(TestContext.Current.CancellationToken); @@ -229,8 +229,8 @@ public void ShowPopupAsync_WithViewType_ShowsPopup() navigation.ShowPopup(view); // Assert - Assert.Single(navigation.ModalStack); - Assert.IsType(navigation.ModalStack[0]); + var modalPage = Assert.Single(navigation.ModalStack); + Assert.IsType(modalPage); } [Fact] @@ -275,8 +275,8 @@ public void ShowPopupAsync_Shell_WithViewType_ShowsPopup() shell.ShowPopup(viewWithQueryable, shellParameters: shellParameters); // Assert - Assert.Single(shellNavigation.ModalStack); - Assert.IsType(shellNavigation.ModalStack[0]); + var modalPage = Assert.Single(shellNavigation.ModalStack); + Assert.IsType(modalPage); Assert.Equal(shellParameterBackgroundColorValue, viewWithQueryable.BackgroundColor); Assert.Equal(shellParameterViewModelTextValue, viewWithQueryable.BindingContext.Text); } @@ -844,7 +844,7 @@ public async Task ShowPopupAsync_CancellationTokenCanceled() { // Arrange var selfClosingPopup = ServiceProvider.GetRequiredService() ?? throw new InvalidOperationException(); - var cts = new CancellationTokenSource(TimeSpan.FromMilliseconds(1)); + using var cts = CancellationTokenSource.CreateLinkedTokenSource(TestContext.Current.CancellationToken); // Act await cts.CancelAsync(); // Ensure CancellationToken has expired @@ -866,7 +866,7 @@ public async Task ShowPopupAsync_Shell_CancellationTokenCanceled() var shellNavigation = Shell.Current.Navigation; var selfClosingPopup = ServiceProvider.GetRequiredService() ?? throw new InvalidOperationException(); - var cts = new CancellationTokenSource(TimeSpan.FromMilliseconds(1)); + using var cts = CancellationTokenSource.CreateLinkedTokenSource(TestContext.Current.CancellationToken); // Act await cts.CancelAsync(); @@ -881,7 +881,7 @@ public async Task ShowPopupAsyncWithView_CancellationTokenCanceled() { // Arrange var view = new Grid(); - var cts = new CancellationTokenSource(TimeSpan.FromMilliseconds(1)); + using var cts = CancellationTokenSource.CreateLinkedTokenSource(TestContext.Current.CancellationToken); // Act await cts.CancelAsync(); // Ensure CancellationToken has expired @@ -903,7 +903,7 @@ public async Task ShowPopupAsyncWithView_Shell_CancellationTokenCanceled() var shellNavigation = Shell.Current.Navigation; var view = new ViewWithIQueryAttributable(new ViewModelWithIQueryAttributable()); - var cts = new CancellationTokenSource(TimeSpan.FromMilliseconds(1)); + using var cts = CancellationTokenSource.CreateLinkedTokenSource(TestContext.Current.CancellationToken); // Act await cts.CancelAsync(); @@ -1228,7 +1228,7 @@ public async Task ShowPopupAsync_ReferenceTypeShouldReturnNull_WhenPopupTapGestu { } - var popupClosedResult = await popupClosedTCS.Task; + var popupClosedResult = await popupClosedTCS.Task.WaitAsync(TestContext.Current.CancellationToken); var showPopupResult = await showPopupTask; // Assert @@ -1269,7 +1269,7 @@ public async Task ShowPopupAsync_Shell_ReferenceTypeShouldReturnNull_WhenPopupTa { } - var popupClosedResult = await popupClosedTCS.Task; + var popupClosedResult = await popupClosedTCS.Task.WaitAsync(TestContext.Current.CancellationToken); var showPopupResult = await showPopupTask; // Assert @@ -1303,7 +1303,7 @@ public async Task ShowPopupAsync_NullableValueTypeShouldReturnResult_WhenPopupIs { } - var popupClosedResult = await popupClosedTCS.Task; + var popupClosedResult = await popupClosedTCS.Task.WaitAsync(TestContext.Current.CancellationToken); var showPopupResult = await showPopupTask; // Assert @@ -1344,7 +1344,7 @@ public async Task ShowPopupAsync_Shell_NullableValueTypeShouldReturnResult_WhenP { } - var popupClosedResult = await popupClosedTCS.Task; + var popupClosedResult = await popupClosedTCS.Task.WaitAsync(TestContext.Current.CancellationToken); var showPopupResult = await showPopupTask; // Assert @@ -1378,7 +1378,7 @@ public async Task ShowPopupAsync_ValueTypeShouldReturnResult_WhenPopupIsClosedBy { } - var popupClosedResult = await popupClosedTCS.Task; + var popupClosedResult = await popupClosedTCS.Task.WaitAsync(TestContext.Current.CancellationToken); var showPopupResult = await showPopupTask; // Assert @@ -1420,7 +1420,7 @@ public async Task ShowPopupAsync_Shell_ValueTypeShouldReturnResult_WhenPopupIsCl { } - var popupClosedResult = await popupClosedTCS.Task; + var popupClosedResult = await popupClosedTCS.Task.WaitAsync(TestContext.Current.CancellationToken); var showPopupResult = await showPopupTask; // Assert @@ -1449,8 +1449,8 @@ public async Task ClosePopupAsync_ShouldClosePopupUsingNavigationAndReturnResult page.ShowPopup(new MockPopup()); // Assert - Assert.Single(page.Navigation.ModalStack); - Assert.IsType(page.Navigation.ModalStack[0]); + var modalPage = Assert.Single(page.Navigation.ModalStack); + Assert.IsType(modalPage); // Act var popupResult = await page.ClosePopupAsync(TestContext.Current.CancellationToken); @@ -1473,8 +1473,8 @@ public async Task ClosePopupAsync_ShouldClosePopupUsingPageAndReturnResult() page.ShowPopup(new MockPopup()); // Assert - Assert.Single(page.Navigation.ModalStack); - Assert.IsType(page.Navigation.ModalStack[0]); + var modalPage = Assert.Single(page.Navigation.ModalStack); + Assert.IsType(modalPage); // Act var popupResult = await page.ClosePopupAsync(page, TestContext.Current.CancellationToken); @@ -1498,8 +1498,8 @@ public async Task ClosePopupAsyncT_ShouldClosePopupUsingNavigationAndReturnResul page.ShowPopup(new Popup()); // Assert - Assert.Single(page.Navigation.ModalStack); - Assert.IsType(page.Navigation.ModalStack[0]); + var modalPage = Assert.Single(page.Navigation.ModalStack); + Assert.IsType(modalPage); // Act var popupResult = await page.ClosePopupAsync(expectedResult, TestContext.Current.CancellationToken); @@ -1525,8 +1525,8 @@ public async Task ClosePopupAsyncT_ShouldClosePopupUsingPageAndReturnResult() page.ShowPopup(new MockPopup()); // Assert - Assert.Single(page.Navigation.ModalStack); - Assert.IsType(page.Navigation.ModalStack[0]); + var modalPage = Assert.Single(page.Navigation.ModalStack); + Assert.IsType(modalPage); // Act var popupResult = await page.ClosePopupAsync(expectedResult, TestContext.Current.CancellationToken); @@ -1553,8 +1553,8 @@ public async Task ShowPopupAsync_TaskShouldCompleteWhenCloseAsyncIsCalled() showPopupAsyncTask = page.ShowPopupAsync(new MockPopup(), token: TestContext.Current.CancellationToken); // Assert - Assert.Single(page.Navigation.ModalStack); - Assert.IsType(page.Navigation.ModalStack[0]); + var modalPage = Assert.Single(page.Navigation.ModalStack); + Assert.IsType(modalPage); // Act var popupResult = await page.ClosePopupAsync(expectedResult, TestContext.Current.CancellationToken); @@ -1579,6 +1579,7 @@ public void ShowPopup_INavigation_SemaphoreReleasedAfterDisplay_AllowsAdditional Assert.Single(navigation.ModalStack); // Act - The second ShowPopup can only display if the semaphore was released after the first push + TestContext.Current.CancellationToken.ThrowIfCancellationRequested(); navigation.ShowPopup(new Grid()); // Assert @@ -1633,6 +1634,7 @@ public void ShowPopup_Shell_SemaphoreReleasedAfterDisplay_NullParameters_AllowsA Assert.Single(shellNavigation.ModalStack); // Act - The second display proves the semaphore was released by the null-parameters branch + TestContext.Current.CancellationToken.ThrowIfCancellationRequested(); shell.ShowPopup(new Popup()); // Assert @@ -1662,6 +1664,7 @@ public void ShowPopup_Shell_SemaphoreReleasedAfterDisplay_WithParameters_AllowsA Assert.Single(shellNavigation.ModalStack); // Act - The second display proves the semaphore was released by the with-parameters branch + TestContext.Current.CancellationToken.ThrowIfCancellationRequested(); shell.ShowPopup(secondView, PopupOptions.Empty, shellParameters); // Assert @@ -1672,7 +1675,7 @@ public void ShowPopup_Shell_SemaphoreReleasedAfterDisplay_WithParameters_AllowsA public async Task ShowPopupAsync_INavigation_SemaphoreReleasedAfterCancellation_AllowsSubsequentPopup() { // Arrange - var cts = new CancellationTokenSource(); + using var cts = CancellationTokenSource.CreateLinkedTokenSource(TestContext.Current.CancellationToken); await cts.CancelAsync(); // Act - A canceled token forces ShowPopupAsync to throw; the semaphore must not be leaked @@ -1701,7 +1704,7 @@ public async Task ShowPopupAsync_Shell_SemaphoreReleasedAfterCancellation_WithPa var shellNavigation = Shell.Current.Navigation; var view = new ViewWithIQueryAttributable(new ViewModelWithIQueryAttributable()); - var cts = new CancellationTokenSource(); + using var cts = CancellationTokenSource.CreateLinkedTokenSource(TestContext.Current.CancellationToken); await cts.CancelAsync(); // Act - A canceled token forces ShowPopupAsync to throw; the semaphore must not be leaked @@ -1730,7 +1733,7 @@ public async Task ShowPopupAsync_Shell_SemaphoreReleasedAfterCancellation_NullPa var shellNavigation = Shell.Current.Navigation; var view = new ViewWithIQueryAttributable(new ViewModelWithIQueryAttributable()); - var cts = new CancellationTokenSource(); + using var cts = CancellationTokenSource.CreateLinkedTokenSource(TestContext.Current.CancellationToken); await cts.CancelAsync(); // Act - A canceled token (with null shellParameters) forces ShowPopupAsync to throw; the semaphore must not be leaked diff --git a/src/CommunityToolkit.Maui.UnitTests/Extensions/TextColorToTests.cs b/src/CommunityToolkit.Maui.UnitTests/Extensions/TextColorToTests.cs index 910120b1af..c29d7829bc 100644 --- a/src/CommunityToolkit.Maui.UnitTests/Extensions/TextColorToTests.cs +++ b/src/CommunityToolkit.Maui.UnitTests/Extensions/TextColorToTests.cs @@ -42,7 +42,7 @@ public async Task TextColorTo_CancellationTokenExpired() [Fact(Timeout = (int)TestDuration.Short)] public async Task TextColorTo_CancellationTokenCanceled() { - var cts = new CancellationTokenSource(); + using var cts = CancellationTokenSource.CreateLinkedTokenSource(TestContext.Current.CancellationToken); var label = new Label { TextColor = Colors.Blue }; label.EnableAnimations(); diff --git a/src/CommunityToolkit.Maui.UnitTests/GlobalUsings.cs b/src/CommunityToolkit.Maui.UnitTests/GlobalUsings.cs index 7e3a20db63..d7d7d992dc 100644 --- a/src/CommunityToolkit.Maui.UnitTests/GlobalUsings.cs +++ b/src/CommunityToolkit.Maui.UnitTests/GlobalUsings.cs @@ -1,3 +1,6 @@ using Xunit; +using Xunit.Sdk; +using Xunit.v3; -[assembly: CollectionBehavior(CollectionBehavior.CollectionPerAssembly, DisableTestParallelization = true, MaxParallelThreads = 1)] \ No newline at end of file +[assembly: CollectionBehavior(CollectionBehavior.CollectionPerAssembly)] +[assembly: Parallelization(Mode = ParallelMode.None, MaxThreads = 1)] \ No newline at end of file diff --git a/src/CommunityToolkit.Maui.UnitTests/ImageSources/GravatarImageSource/GravatarImageSourceTests.cs b/src/CommunityToolkit.Maui.UnitTests/ImageSources/GravatarImageSource/GravatarImageSourceTests.cs index acd8fc289a..51edb10f0c 100644 --- a/src/CommunityToolkit.Maui.UnitTests/ImageSources/GravatarImageSource/GravatarImageSourceTests.cs +++ b/src/CommunityToolkit.Maui.UnitTests/ImageSources/GravatarImageSource/GravatarImageSourceTests.cs @@ -335,16 +335,15 @@ public void TestDataPackage() [Fact(Timeout = (int)TestDuration.Short)] public async Task TestDefaultStream() { - CancellationTokenSource cts = new(); var gravatarImageSource = new GravatarImageSource(); - await using var stream = await gravatarImageSource.Stream(cts.Token); + await using var stream = await gravatarImageSource.Stream(TestContext.Current.CancellationToken); stream.Should().NotBeNull(); } [Fact(Timeout = (int)TestDuration.Short)] public async Task TestDefaultStreamCanceled() { - CancellationTokenSource cts = new(); + using var cts = CancellationTokenSource.CreateLinkedTokenSource(TestContext.Current.CancellationToken); var gravatarImageSource = new GravatarImageSource(); cts.Cancel(); Stream stream = await gravatarImageSource.Stream(cts.Token); diff --git a/src/CommunityToolkit.Maui.UnitTests/Layouts/StateContainerTests.cs b/src/CommunityToolkit.Maui.UnitTests/Layouts/StateContainerTests.cs index 6d7f8f8347..ae6f8173b7 100644 --- a/src/CommunityToolkit.Maui.UnitTests/Layouts/StateContainerTests.cs +++ b/src/CommunityToolkit.Maui.UnitTests/Layouts/StateContainerTests.cs @@ -126,7 +126,7 @@ public async Task StateContainer_CancellationTokenExpired() [Fact(Timeout = (int)TestDuration.Short)] public async Task StateContainer_CancellationTokenCanceled() { - var cts = new CancellationTokenSource(TimeSpan.FromMilliseconds(1)); + using var cts = CancellationTokenSource.CreateLinkedTokenSource(TestContext.Current.CancellationToken); layout.EnableAnimations(); foreach (var child in layout.Children) @@ -542,58 +542,51 @@ public void Controller_ThrowsStateContainerExceptionOnDuplicateStateKey() public void Controller_SwitchesToStateFromContentSuccess() { controller.SwitchToState(StateKey.Loading); - var state = controller.GetLayout().Children[0]; + var state = Assert.IsType