From 4e05295f52861eff9329c7ef4ed192a9999eca0f Mon Sep 17 00:00:00 2001 From: Shane Neuville Date: Wed, 29 Jan 2025 10:08:03 -0600 Subject: [PATCH 1/2] Fix logging and some async paths --- .../Controls.Sample.Sandbox/MainPage.xaml.cs | 2 +- .../DeviceTests/Controls.DeviceTests.csproj | 1 + .../DeviceTests/ControlsHandlerTestBase.cs | 10 +- .../Elements/Shell/ShellTabBarTests.cs | 7 +- .../src/Hosting/ServiceProviderExtensions.cs | 7 ++ .../HandlerTests/HandlerTestBasement.cs | 8 ++ .../DeviceTests.Shared/Stubs/ContextStub.cs | 24 ++++ .../Handlers/Image/ImageHandlerTests.cs | 8 +- .../FontImageSourceServiceTests.Android.cs | 4 +- .../FontImageSourceServiceTests.iOS.cs | 4 +- .../DeviceTests/Tests/Accelerometer_Tests.cs | 6 +- .../DeviceTests/Tests/AppActions_Tests.cs | 2 +- .../DeviceTests/Tests/Barometer_Shared.cs | 6 +- .../test/DeviceTests/Tests/Compass_Tests.cs | 6 +- .../DeviceTests/Tests/Connectivity_Tests.cs | 2 +- .../test/DeviceTests/Tests/Contacts_Tests.cs | 2 +- .../DeviceTests/Tests/FileSystem_Tests.cs | 4 +- .../DeviceTests/Tests/Flashlight_Tests.cs | 2 +- .../DeviceTests/Tests/Geolocation_Tests.cs | 14 +-- .../test/DeviceTests/Tests/Gyroscope_Tests.cs | 6 +- .../test/DeviceTests/Tests/Launcher_Tests.cs | 20 ++-- .../DeviceTests/Tests/Magnetometer_Tests.cs | 6 +- .../test/DeviceTests/Tests/Maps_Tests.cs | 12 +- .../DeviceTests/Tests/Permissions_Tests.cs | 16 +-- .../DeviceTests/Tests/Screenshot_Tests.cs | 4 +- .../test/DeviceTests/Tests/Share_Tests.cs | 14 +-- .../Tests/WebAuthenticator_Tests.cs | 4 +- .../AppHostBuilderExtensions.cs | 8 +- .../TestUtils.DeviceTests.Runners.csproj | 1 + .../AssertionExtensions.Android.cs | 86 +++++++------- .../DeviceTests/AssertionExtensions.iOS.cs | 112 +++++++++++------- 31 files changed, 246 insertions(+), 162 deletions(-) diff --git a/src/Controls/samples/Controls.Sample.Sandbox/MainPage.xaml.cs b/src/Controls/samples/Controls.Sample.Sandbox/MainPage.xaml.cs index 6e467ed53a97..b7744fa262ea 100644 --- a/src/Controls/samples/Controls.Sample.Sandbox/MainPage.xaml.cs +++ b/src/Controls/samples/Controls.Sample.Sandbox/MainPage.xaml.cs @@ -6,4 +6,4 @@ public MainPage() { InitializeComponent(); } -} +} \ No newline at end of file diff --git a/src/Controls/tests/DeviceTests/Controls.DeviceTests.csproj b/src/Controls/tests/DeviceTests/Controls.DeviceTests.csproj index 84cd5c8d3f47..1e9336edda67 100644 --- a/src/Controls/tests/DeviceTests/Controls.DeviceTests.csproj +++ b/src/Controls/tests/DeviceTests/Controls.DeviceTests.csproj @@ -23,6 +23,7 @@ + diff --git a/src/Controls/tests/DeviceTests/ControlsHandlerTestBase.cs b/src/Controls/tests/DeviceTests/ControlsHandlerTestBase.cs index 68b0b1948c74..43c95dbd73fa 100644 --- a/src/Controls/tests/DeviceTests/ControlsHandlerTestBase.cs +++ b/src/Controls/tests/DeviceTests/ControlsHandlerTestBase.cs @@ -4,6 +4,7 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; using Microsoft.Maui.Controls; using Microsoft.Maui.Controls.Handlers; using Microsoft.Maui.DeviceTests.Stubs; @@ -146,8 +147,11 @@ protected Task CreateHandlerAndAddToWindow(IElement view, Func { + TestRunnerLogger.LogDebug($"Starting InvokeOnMainThreadAsync"); IWindow window = CreateWindowForContent(view); var application = mauiContext.Services.GetService(); @@ -162,10 +166,13 @@ protected Task CreateHandlerAndAddToWindow(IElement view, Func(window, async () => { + TestRunnerLogger.LogDebug($"Window Setup For Tests"); IView content = window.Content; if (content is FlyoutPage fp) @@ -249,9 +256,9 @@ void OnBatchCommitted(object sender, Controls.Internals.EventArg else throw new Exception($"I can't work with {typeof(THandler)}"); + TestRunnerLogger.LogDebug($"Running Test"); await action(handler).WaitAsync(timeOut.Value); - #if !WINDOWS bool isActivated = controlsWindow?.IsActivated ?? false; bool isDestroyed = controlsWindow?.IsDestroyed ?? false; @@ -268,6 +275,7 @@ void OnBatchCommitted(object sender, Controls.Internals.EventArg finally { _takeOverMainContentSempahore.Release(); + TestRunnerLogger.LogDebug($"Finished Running Test"); } }); } diff --git a/src/Controls/tests/DeviceTests/Elements/Shell/ShellTabBarTests.cs b/src/Controls/tests/DeviceTests/Elements/Shell/ShellTabBarTests.cs index 203c71208019..d4cfa59d26f0 100644 --- a/src/Controls/tests/DeviceTests/Elements/Shell/ShellTabBarTests.cs +++ b/src/Controls/tests/DeviceTests/Elements/Shell/ShellTabBarTests.cs @@ -6,6 +6,7 @@ using Microsoft.Maui.Controls; using Microsoft.Maui.Graphics; using Xunit; +using Microsoft.Extensions.Logging; #if ANDROID || IOS || MACCATALYST using ShellHandler = Microsoft.Maui.Controls.Handlers.Compatibility.ShellRenderer; @@ -100,7 +101,7 @@ async Task RunShellTabBarTests(Action setup, Func runTest) Route = "Tab1", Title = "Tab1", Content = new ContentPage(), - Icon = "white.png" + Icon = "white_tab.png" }; var unselectedContent = new ShellContent() @@ -108,7 +109,7 @@ async Task RunShellTabBarTests(Action setup, Func runTest) Route = "Tab2", Title = "Tab2", Content = new ContentPage(), - Icon = "white.png" + Icon = "white_tab.png" }; var unselectedContent_2 = new ShellContent() @@ -116,7 +117,7 @@ async Task RunShellTabBarTests(Action setup, Func runTest) Route = "Tab3", Title = "Tab3", Content = new ContentPage(), - Icon = "white.png" + Icon = "white_tab.png" }; var shell = await CreateShellAsync((shell) => diff --git a/src/Core/src/Hosting/ServiceProviderExtensions.cs b/src/Core/src/Hosting/ServiceProviderExtensions.cs index db1d3ffea29f..8669065f1587 100644 --- a/src/Core/src/Hosting/ServiceProviderExtensions.cs +++ b/src/Core/src/Hosting/ServiceProviderExtensions.cs @@ -2,6 +2,7 @@ using System; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; namespace Microsoft.Maui { @@ -10,6 +11,9 @@ internal static class ServiceProviderExtensions internal static ILogger? CreateLogger(this IMauiContext context) => context.Services.CreateLogger(); + internal static ILogger CreateLogger(this IMauiContext context, Type type) => + context.Services.GetService()?.CreateLogger(type) ?? NullLogger.Instance; + internal static ILogger? CreateLogger(this IServiceProvider services) => services.GetService>(); @@ -18,5 +22,8 @@ internal static class ServiceProviderExtensions internal static ILogger? CreateLogger(this IServiceProvider services, string loggerName) => services.GetService()?.CreateLogger(loggerName); + + internal static ILogger CreateLogger(this IServiceProvider services, Type type) => + services.GetService()?.CreateLogger(type) ?? NullLogger.Instance; } } \ No newline at end of file diff --git a/src/Core/tests/DeviceTests.Shared/HandlerTests/HandlerTestBasement.cs b/src/Core/tests/DeviceTests.Shared/HandlerTests/HandlerTestBasement.cs index 85b99c18f044..37615075c265 100644 --- a/src/Core/tests/DeviceTests.Shared/HandlerTests/HandlerTestBasement.cs +++ b/src/Core/tests/DeviceTests.Shared/HandlerTests/HandlerTestBasement.cs @@ -2,6 +2,9 @@ using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using Microsoft.Maui; using Microsoft.Maui.DeviceTests.ImageAnalysis; using Microsoft.Maui.DeviceTests.Stubs; using Microsoft.Maui.Dispatching; @@ -46,12 +49,17 @@ public void EnsureHandlerCreated(Action additionalCreationAction appBuilder = ConfigureBuilder(appBuilder); additionalCreationActions?.Invoke(appBuilder); + appBuilder.Services.TryAdd(ServiceDescriptor.Singleton()); + appBuilder.Services.TryAdd(ServiceDescriptor.Singleton(typeof(ILogger<>), typeof(NullLogger<>))); + _mauiApp = appBuilder.Build(); _servicesProvider = _mauiApp.Services; _mauiContext = new ContextStub(_servicesProvider); } + protected ILogger TestRunnerLogger => MauiContext.CreateLogger(this.GetType()); + protected virtual MauiAppBuilder ConfigureBuilder(MauiAppBuilder mauiAppBuilder) { return mauiAppBuilder; diff --git a/src/Core/tests/DeviceTests.Shared/Stubs/ContextStub.cs b/src/Core/tests/DeviceTests.Shared/Stubs/ContextStub.cs index 2d4220cde2ed..73c6b4ed1e00 100644 --- a/src/Core/tests/DeviceTests.Shared/Stubs/ContextStub.cs +++ b/src/Core/tests/DeviceTests.Shared/Stubs/ContextStub.cs @@ -1,6 +1,9 @@ using System; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Maui.Animations; +using Microsoft.Maui.Controls; using Microsoft.Maui.Dispatching; using Microsoft.Maui.TestUtils.DeviceTests.Runners; @@ -70,6 +73,27 @@ public object GetService(Type serviceType) if (serviceType == typeof(IDispatcher)) return _services.GetService(serviceType) ?? TestDispatcher.Current; + if (serviceType.IsGenericType && serviceType.GetGenericTypeDefinition() == typeof(ILogger<>) || + serviceType == typeof(ILogger) || + serviceType == typeof(ILoggerFactory)) + { + // This verifies that the test itself hasn't registered a logger + // if the test itself has registered a logger than return that because the logger is under tests + var registeredLogger = _services.GetService(serviceType); + var registeredLoggerType = registeredLogger.GetType(); + + if (registeredLogger is NullLoggerFactory) + { + return TestServices.Services.GetService(serviceType) ?? registeredLogger; + } + + if (registeredLogger is NullLogger || + registeredLoggerType.IsGenericType && registeredLoggerType.GetGenericTypeDefinition() == typeof(NullLogger<>)) + { + return TestServices.Services.GetService(serviceType) ?? registeredLogger; + } + } + return _services.GetService(serviceType); } diff --git a/src/Core/tests/DeviceTests/Handlers/Image/ImageHandlerTests.cs b/src/Core/tests/DeviceTests/Handlers/Image/ImageHandlerTests.cs index abc81299cef7..168ff22c24fa 100644 --- a/src/Core/tests/DeviceTests/Handlers/Image/ImageHandlerTests.cs +++ b/src/Core/tests/DeviceTests/Handlers/Image/ImageHandlerTests.cs @@ -399,7 +399,7 @@ await InvokeOnMainThreadAsync(async () => #if ANDROID Assert.Equal(GetDrawableId("red"), platformImage); #elif IOS || MACCATALYST - platformImage.AssertContainsColor(Colors.Red.ToPlatform()); + await platformImage.AssertContainsColor(Colors.Red.ToPlatform()).ConfigureAwait(false); #endif }); } @@ -441,7 +441,7 @@ await InvokeOnMainThreadAsync(async () => #if ANDROID Assert.Equal(GetDrawableId("blue"), platformImage); #elif IOS || MACCATALYST - platformImage.AssertContainsColor(Colors.Blue.ToPlatform()); + await platformImage.AssertContainsColor(Colors.Blue.ToPlatform()).ConfigureAwait(false); #endif }); } @@ -463,7 +463,7 @@ public async Task ImageLoadSequenceIsCorrectWithChecks() platformImage.Color.IsEquivalent(Colors.Blue.ToPlatform()); #elif IOS || MACCATALYST var platformImage = Assert.IsType(events[0].Value); - platformImage.AssertContainsColor(Colors.Blue.ToPlatform()); + await platformImage.AssertContainsColor(Colors.Blue.ToPlatform()).ConfigureAwait(false); #endif } @@ -484,7 +484,7 @@ public async Task InterruptingLoadCancelsAndStartsOverWithChecks() platformImage.Color.IsEquivalent(Colors.Red.ToPlatform()); #elif IOS || MACCATALYST var platformImage = Assert.IsType(events[0].Value); - platformImage.AssertContainsColor(Colors.Red.ToPlatform()); + await platformImage.AssertContainsColor(Colors.Red.ToPlatform()).ConfigureAwait(false); #endif } diff --git a/src/Core/tests/DeviceTests/Services/ImageSource/FontImageSourceServiceTests.Android.cs b/src/Core/tests/DeviceTests/Services/ImageSource/FontImageSourceServiceTests.Android.cs index b8257a216588..44dec675ba6e 100644 --- a/src/Core/tests/DeviceTests/Services/ImageSource/FontImageSourceServiceTests.Android.cs +++ b/src/Core/tests/DeviceTests/Services/ImageSource/FontImageSourceServiceTests.Android.cs @@ -53,7 +53,7 @@ public async Task GetDrawableAsync(string colorHex) var bitmap = bitmapDrawable.Bitmap; - bitmap.AssertContainsColor(expectedColor.ToPlatform()); + await bitmap.AssertContainsColor(expectedColor.ToPlatform()).ConfigureAwait(false); } [Theory] @@ -92,7 +92,7 @@ public async Task GetDrawableAsyncWithCustomFont() var bitmap = bitmapDrawable.Bitmap; - bitmap.AssertContainsColor(Colors.Red.ToPlatform()); + await bitmap.AssertContainsColor(Colors.Red.ToPlatform()).ConfigureAwait(false); } } } \ No newline at end of file diff --git a/src/Core/tests/DeviceTests/Services/ImageSource/FontImageSourceServiceTests.iOS.cs b/src/Core/tests/DeviceTests/Services/ImageSource/FontImageSourceServiceTests.iOS.cs index cbd911a00f13..b9cc2d9e7552 100644 --- a/src/Core/tests/DeviceTests/Services/ImageSource/FontImageSourceServiceTests.iOS.cs +++ b/src/Core/tests/DeviceTests/Services/ImageSource/FontImageSourceServiceTests.iOS.cs @@ -52,7 +52,7 @@ public async Task GetImageAsync(string colorHex) var uiimage = Assert.IsType(drawable.Value); - uiimage.AssertContainsColor(expectedColor.ToPlatform()); + await uiimage.AssertContainsColor(expectedColor.ToPlatform()).ConfigureAwait(false); } [Fact] @@ -80,7 +80,7 @@ public async Task GetImageAsyncWithCustomFont() var uiimage = Assert.IsType(drawable.Value); - uiimage.AssertContainsColor(Colors.Red.ToPlatform()); + await uiimage.AssertContainsColor(Colors.Red.ToPlatform()).ConfigureAwait(false); } } } \ No newline at end of file diff --git a/src/Essentials/test/DeviceTests/Tests/Accelerometer_Tests.cs b/src/Essentials/test/DeviceTests/Tests/Accelerometer_Tests.cs index 89fa51d79c09..4589b91c6a0c 100644 --- a/src/Essentials/test/DeviceTests/Tests/Accelerometer_Tests.cs +++ b/src/Essentials/test/DeviceTests/Tests/Accelerometer_Tests.cs @@ -24,7 +24,7 @@ public async Task Monitor(SensorSpeed sensorSpeed) if (!HardwareSupport.HasAccelerometer) return; - var tcs = new TaskCompletionSource(); + var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); Accelerometer.ReadingChanged += Accelerometer_ReadingChanged; Accelerometer.Start(sensorSpeed); @@ -48,7 +48,7 @@ public async Task IsMonitoring(SensorSpeed sensorSpeed) if (!HardwareSupport.HasAccelerometer) return; - var tcs = new TaskCompletionSource(); + var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); Accelerometer.ReadingChanged += Accelerometer_ReadingChanged; Accelerometer.Start(sensorSpeed); @@ -72,7 +72,7 @@ public async Task Stop_Monitor(SensorSpeed sensorSpeed) if (!HardwareSupport.HasAccelerometer) return; - var tcs = new TaskCompletionSource(); + var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); Accelerometer.ReadingChanged += Accelerometer_ReadingChanged; Accelerometer.Start(sensorSpeed); diff --git a/src/Essentials/test/DeviceTests/Tests/AppActions_Tests.cs b/src/Essentials/test/DeviceTests/Tests/AppActions_Tests.cs index bd360d2ac51d..d12072c36217 100644 --- a/src/Essentials/test/DeviceTests/Tests/AppActions_Tests.cs +++ b/src/Essentials/test/DeviceTests/Tests/AppActions_Tests.cs @@ -37,7 +37,7 @@ public async Task GetSetItems() await AppActions.SetAsync(actions); - var get = await AppActions.GetAsync(); + var get = await AppActions.GetAsync().ConfigureAwait(false); Assert.Contains(get, a => a.Id == "TEST1"); } diff --git a/src/Essentials/test/DeviceTests/Tests/Barometer_Shared.cs b/src/Essentials/test/DeviceTests/Tests/Barometer_Shared.cs index 301e89488d6d..afe95ab78c3e 100644 --- a/src/Essentials/test/DeviceTests/Tests/Barometer_Shared.cs +++ b/src/Essentials/test/DeviceTests/Tests/Barometer_Shared.cs @@ -19,7 +19,7 @@ public async Task Monitor() if (!HardwareSupport.HasBarometer) return; - var tcs = new TaskCompletionSource(); + var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); Barometer.ReadingChanged += Barometer_ReadingChanged; void Barometer_ReadingChanged(object sender, BarometerChangedEventArgs e) @@ -43,7 +43,7 @@ public async Task IsMonitoring() if (!HardwareSupport.HasBarometer) return; - var tcs = new TaskCompletionSource(); + var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); Barometer.ReadingChanged += Barometer_ReadingChanged; void Barometer_ReadingChanged(object sender, BarometerChangedEventArgs e) { @@ -66,7 +66,7 @@ public async Task Stop_Monitor() if (!HardwareSupport.HasBarometer) return; - var tcs = new TaskCompletionSource(); + var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); Barometer.ReadingChanged += Barometer_ReadingChanged; void Barometer_ReadingChanged(object sender, BarometerChangedEventArgs e) { diff --git a/src/Essentials/test/DeviceTests/Tests/Compass_Tests.cs b/src/Essentials/test/DeviceTests/Tests/Compass_Tests.cs index 6b2ae63df57f..0f03774ce207 100644 --- a/src/Essentials/test/DeviceTests/Tests/Compass_Tests.cs +++ b/src/Essentials/test/DeviceTests/Tests/Compass_Tests.cs @@ -24,7 +24,7 @@ public async Task Monitor(SensorSpeed sensorSpeed) if (!HardwareSupport.HasCompass) return; - var tcs = new TaskCompletionSource(); + var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); Compass.ReadingChanged += Compass_ReadingChanged; void Compass_ReadingChanged(object sender, CompassChangedEventArgs e) @@ -49,7 +49,7 @@ public async Task IsMonitoring(SensorSpeed sensorSpeed) if (!HardwareSupport.HasCompass) return; - var tcs = new TaskCompletionSource(); + var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); Compass.ReadingChanged += Compass_ReadingChanged; void Compass_ReadingChanged(object sender, CompassChangedEventArgs e) { @@ -73,7 +73,7 @@ public async Task Stop_Monitor(SensorSpeed sensorSpeed) if (!HardwareSupport.HasCompass) return; - var tcs = new TaskCompletionSource(); + var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); Compass.ReadingChanged += Compass_ReadingChanged; void Compass_ReadingChanged(object sender, CompassChangedEventArgs e) { diff --git a/src/Essentials/test/DeviceTests/Tests/Connectivity_Tests.cs b/src/Essentials/test/DeviceTests/Tests/Connectivity_Tests.cs index 7fbc1bd22020..de7cfb8b874a 100644 --- a/src/Essentials/test/DeviceTests/Tests/Connectivity_Tests.cs +++ b/src/Essentials/test/DeviceTests/Tests/Connectivity_Tests.cs @@ -44,7 +44,7 @@ public async Task Test() { var current = Connectivity.Current.NetworkAccess; - var thread = await Task.Run(() => Connectivity.Current.NetworkAccess); + var thread = await Task.Run(() => Connectivity.Current.NetworkAccess).ConfigureAwait(false); Assert.Equal(current, thread); } diff --git a/src/Essentials/test/DeviceTests/Tests/Contacts_Tests.cs b/src/Essentials/test/DeviceTests/Tests/Contacts_Tests.cs index 9c533c78edfc..062a47c31e1e 100644 --- a/src/Essentials/test/DeviceTests/Tests/Contacts_Tests.cs +++ b/src/Essentials/test/DeviceTests/Tests/Contacts_Tests.cs @@ -19,7 +19,7 @@ public async Task GetAll() { await MainThread.InvokeOnMainThreadAsync(async () => { - await Permissions.RequestAsync(); + await Permissions.RequestAsync().ConfigureAwait(false); }); var list = new List(); diff --git a/src/Essentials/test/DeviceTests/Tests/FileSystem_Tests.cs b/src/Essentials/test/DeviceTests/Tests/FileSystem_Tests.cs index 375af6c7ca2f..dd79527ad590 100644 --- a/src/Essentials/test/DeviceTests/Tests/FileSystem_Tests.cs +++ b/src/Essentials/test/DeviceTests/Tests/FileSystem_Tests.cs @@ -33,7 +33,7 @@ public async Task OpenAppPackageFileAsync_Can_Load_File(string filename, string Assert.NotNull(stream); using var reader = new StreamReader(stream); - var text = await reader.ReadToEndAsync(); + var text = await reader.ReadToEndAsync().ConfigureAwait(false); Assert.Equal(contents, text); } @@ -41,7 +41,7 @@ public async Task OpenAppPackageFileAsync_Can_Load_File(string filename, string [Fact] public async Task OpenAppPackageFileAsync_Throws_If_File_Is_Not_Found() { - await Assert.ThrowsAsync(() => FileSystem.OpenAppPackageFileAsync("MissingFile.txt")); + await Assert.ThrowsAsync(() => FileSystem.OpenAppPackageFileAsync("MissingFile.txt")).ConfigureAwait(false); } } } diff --git a/src/Essentials/test/DeviceTests/Tests/Flashlight_Tests.cs b/src/Essentials/test/DeviceTests/Tests/Flashlight_Tests.cs index 58aa43e861ac..6b986c542f88 100644 --- a/src/Essentials/test/DeviceTests/Tests/Flashlight_Tests.cs +++ b/src/Essentials/test/DeviceTests/Tests/Flashlight_Tests.cs @@ -32,7 +32,7 @@ public Task Turn_On_Off(bool oldCameraApi) return Utils.OnMainThread(async () => { await Flashlight.TurnOnAsync(); - await Flashlight.TurnOffAsync(); + await Flashlight.TurnOffAsync().ConfigureAwait(false); }); } } diff --git a/src/Essentials/test/DeviceTests/Tests/Geolocation_Tests.cs b/src/Essentials/test/DeviceTests/Tests/Geolocation_Tests.cs index f95e4560038a..48871f4ff161 100644 --- a/src/Essentials/test/DeviceTests/Tests/Geolocation_Tests.cs +++ b/src/Essentials/test/DeviceTests/Tests/Geolocation_Tests.cs @@ -17,10 +17,10 @@ public async Task Get_LastKnownLocation_Is_Something() { await MainThread.InvokeOnMainThreadAsync(async () => { - await Permissions.RequestAsync(); + await Permissions.RequestAsync().ConfigureAwait(false); }); - var location = await Geolocation.GetLastKnownLocationAsync(); + var location = await Geolocation.GetLastKnownLocationAsync().ConfigureAwait(false); Assert.NotNull(location); @@ -42,10 +42,10 @@ public async Task Get_Location_Is_Something() { await MainThread.InvokeOnMainThreadAsync(async () => { - await Permissions.RequestAsync(); + await Permissions.RequestAsync().ConfigureAwait(false); }); - var location = await Geolocation.GetLocationAsync(); + var location = await Geolocation.GetLocationAsync().ConfigureAwait(false); Assert.NotNull(location); @@ -67,12 +67,12 @@ public async Task Get_Location_With_Request_Is_Something() { await MainThread.InvokeOnMainThreadAsync(async () => { - await Permissions.RequestAsync(); + await Permissions.RequestAsync().ConfigureAwait(false); }); var request = new GeolocationRequest(GeolocationAccuracy.Best); request.RequestFullAccuracy = true; - var location = await Geolocation.GetLocationAsync(request); + var location = await Geolocation.GetLocationAsync(request).ConfigureAwait(false); Assert.NotNull(location); @@ -95,7 +95,7 @@ public async Task Geolocation_IsListeningForeground() { await MainThread.InvokeOnMainThreadAsync(async () => { - await Permissions.RequestAsync(); + await Permissions.RequestAsync().ConfigureAwait(false); }); var request = new GeolocationListeningRequest(GeolocationAccuracy.Best); diff --git a/src/Essentials/test/DeviceTests/Tests/Gyroscope_Tests.cs b/src/Essentials/test/DeviceTests/Tests/Gyroscope_Tests.cs index 40080e8120e9..19265ee8b1dd 100644 --- a/src/Essentials/test/DeviceTests/Tests/Gyroscope_Tests.cs +++ b/src/Essentials/test/DeviceTests/Tests/Gyroscope_Tests.cs @@ -24,7 +24,7 @@ public async Task Monitor(SensorSpeed sensorSpeed) if (!HardwareSupport.HasGyroscope) return; - var tcs = new TaskCompletionSource(); + var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); Gyroscope.ReadingChanged += Gyroscope_ReadingChanged; Gyroscope.Start(sensorSpeed); @@ -48,7 +48,7 @@ public async Task IsMonitoring(SensorSpeed sensorSpeed) if (!HardwareSupport.HasGyroscope) return; - var tcs = new TaskCompletionSource(); + var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); Gyroscope.ReadingChanged += Gyroscope_ReadingChanged; Gyroscope.Start(sensorSpeed); @@ -72,7 +72,7 @@ public async Task Stop_Monitor(SensorSpeed sensorSpeed) if (!HardwareSupport.HasGyroscope) return; - var tcs = new TaskCompletionSource(); + var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); Gyroscope.ReadingChanged += Gyroscope_ReadingChanged; Gyroscope.Start(sensorSpeed); diff --git a/src/Essentials/test/DeviceTests/Tests/Launcher_Tests.cs b/src/Essentials/test/DeviceTests/Tests/Launcher_Tests.cs index 8836b0463784..742e53d1088d 100644 --- a/src/Essentials/test/DeviceTests/Tests/Launcher_Tests.cs +++ b/src/Essentials/test/DeviceTests/Tests/Launcher_Tests.cs @@ -72,12 +72,12 @@ public async Task CanOpen(string uri) #if __IOS__ if (DeviceInfo.DeviceType == DeviceType.Virtual && (uri.Contains("tel:", StringComparison.Ordinal) || uri.Contains("mailto:", StringComparison.Ordinal))) { - Assert.False(await Launcher.CanOpenAsync(uri)); + Assert.False(await Launcher.CanOpenAsync(uri).ConfigureAwait(false)); return; } #endif - Assert.True(await Launcher.CanOpenAsync(uri)); + Assert.True(await Launcher.CanOpenAsync(uri)).ConfigureAwait(false); } [Theory] @@ -109,13 +109,13 @@ public async Task CanOpenUri(string uri) #if __IOS__ if (DeviceInfo.DeviceType == DeviceType.Virtual && (uri.Contains("tel:", StringComparison.Ordinal) || uri.Contains("mailto:", StringComparison.Ordinal))) { - Assert.False(await Launcher.CanOpenAsync(new Uri(uri))); + Assert.False(await Launcher.CanOpenAsync(new Uri(uri)).ConfigureAwait(false)); return; } #endif - Assert.True(await Launcher.CanOpenAsync(new Uri(uri))); + Assert.True(await Launcher.CanOpenAsync(new Uri(uri)).ConfigureAwait(false)); } #if __IOS__ @@ -133,21 +133,21 @@ public void GetNativeUrl(string uri, string expected) [InlineData("Not Valid Uri")] public async Task InvalidUri(string uri) { - await Assert.ThrowsAsync(() => Launcher.CanOpenAsync(uri)); + await Assert.ThrowsAsync(() => Launcher.CanOpenAsync(uri)).ConfigureAwait(false); } [Theory] [InlineData("ms-invalidurifortest:abc")] public async Task CanNotOpenUri(string uri) { - Assert.False(await Launcher.CanOpenAsync(new Uri(uri))); + Assert.False(await Launcher.CanOpenAsync(new Uri(uri)).ConfigureAwait(false)); } [Theory] [InlineData("ms-invalidurifortest:abc")] public async Task CanNotOpen(string uri) { - Assert.False(await Launcher.CanOpenAsync(uri)); + Assert.False(await Launcher.CanOpenAsync(uri).ConfigureAwait(false)); } [Theory] @@ -164,12 +164,12 @@ public async Task TryOpen(string uri) #if __IOS__ if (DeviceInfo.DeviceType == DeviceType.Virtual && (uri.Contains("tel:", StringComparison.Ordinal) || uri.Contains("mailto:", StringComparison.Ordinal))) { - Assert.False(await Launcher.TryOpenAsync(uri)); + Assert.False(await Launcher.TryOpenAsync(uri).ConfigureAwait(false)); return; } #endif - Assert.True(await Launcher.TryOpenAsync(uri)); + Assert.True(await Launcher.TryOpenAsync(uri).ConfigureAwait(false)); } [Theory] @@ -177,7 +177,7 @@ public async Task TryOpen(string uri) [Trait(Traits.InteractionType, Traits.InteractionTypes.Human)] public async Task CanNotTryOpen(string uri) { - Assert.False(await Launcher.TryOpenAsync(new Uri(uri))); + Assert.False(await Launcher.TryOpenAsync(new Uri(uri)).ConfigureAwait(false)); } } } diff --git a/src/Essentials/test/DeviceTests/Tests/Magnetometer_Tests.cs b/src/Essentials/test/DeviceTests/Tests/Magnetometer_Tests.cs index f02dda3162f8..2183209e150c 100644 --- a/src/Essentials/test/DeviceTests/Tests/Magnetometer_Tests.cs +++ b/src/Essentials/test/DeviceTests/Tests/Magnetometer_Tests.cs @@ -24,7 +24,7 @@ public async Task Monitor(SensorSpeed sensorSpeed) if (!HardwareSupport.HasMagnetometer) return; - var tcs = new TaskCompletionSource(); + var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); Magnetometer.ReadingChanged += Magnetometer_ReadingChanged; Magnetometer.Start(sensorSpeed); @@ -48,7 +48,7 @@ public async Task IsMonitoring(SensorSpeed sensorSpeed) if (!HardwareSupport.HasMagnetometer) return; - var tcs = new TaskCompletionSource(); + var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); Magnetometer.ReadingChanged += Magnetometer_ReadingChanged; Magnetometer.Start(sensorSpeed); @@ -72,7 +72,7 @@ public async Task Stop_Monitor(SensorSpeed sensorSpeed) if (!HardwareSupport.HasMagnetometer) return; - var tcs = new TaskCompletionSource(); + var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); Magnetometer.ReadingChanged += Magnetometer_ReadingChanged; Magnetometer.Start(sensorSpeed); diff --git a/src/Essentials/test/DeviceTests/Tests/Maps_Tests.cs b/src/Essentials/test/DeviceTests/Tests/Maps_Tests.cs index a1664a7b9f74..d9edce246a9a 100644 --- a/src/Essentials/test/DeviceTests/Tests/Maps_Tests.cs +++ b/src/Essentials/test/DeviceTests/Tests/Maps_Tests.cs @@ -17,7 +17,7 @@ public class Maps_Tests [Trait(Traits.InteractionType, Traits.InteractionTypes.Human)] public async Task LaunchMap_CoordinatesDisplayCorrectPlace() { - await Map.OpenAsync(testLatitude, testLongitude, new MapLaunchOptions { Name = mapName }); + await Map.OpenAsync(testLatitude, testLongitude, new MapLaunchOptions { Name = mapName }).ConfigureAwait(false); } [Fact] @@ -31,28 +31,28 @@ public async Task LaunchMap_PlacemarkDisplayCorrectPlace() Thoroughfare = "Microsoft Building 25", Locality = "Redmond" }; - await Map.OpenAsync(placemark, new MapLaunchOptions { Name = mapName }); + await Map.OpenAsync(placemark, new MapLaunchOptions { Name = mapName }).ConfigureAwait(false); } [Fact] public async Task LaunchMap_NullLocation() { Location location = null; - await Assert.ThrowsAsync(() => Map.OpenAsync(location)); + await Assert.ThrowsAsync(() => Map.OpenAsync(location)).ConfigureAwait(false); } [Fact] public async Task LaunchMap_NullOptionsLocation() { var location = new Location(testLatitude, testLongitude); - await Assert.ThrowsAsync(() => Map.OpenAsync(location, null)); + await Assert.ThrowsAsync(() => Map.OpenAsync(location, null)).ConfigureAwait(false); } [Fact] public async Task LaunchMap_NullPlacemark() { Placemark location = null; - await Assert.ThrowsAsync(() => Map.OpenAsync(location)); + await Assert.ThrowsAsync(() => Map.OpenAsync(location)).ConfigureAwait(false); } [Fact] @@ -65,7 +65,7 @@ public async Task LaunchMap_NullOptionsPlacemark() Thoroughfare = "Microsoft Building 25", Locality = "Redmond" }; - await Assert.ThrowsAsync(() => Map.OpenAsync(placemark, null)); + await Assert.ThrowsAsync(() => Map.OpenAsync(placemark, null)).ConfigureAwait(false); } } } diff --git a/src/Essentials/test/DeviceTests/Tests/Permissions_Tests.cs b/src/Essentials/test/DeviceTests/Tests/Permissions_Tests.cs index 615aae993237..da41c2eb4367 100644 --- a/src/Essentials/test/DeviceTests/Tests/Permissions_Tests.cs +++ b/src/Essentials/test/DeviceTests/Tests/Permissions_Tests.cs @@ -40,10 +40,10 @@ internal async Task Check_Status(string permission, PermissionStatus expectedSta switch (permission) { case "Battery": - status = await Permissions.CheckStatusAsync(); + status = await Permissions.CheckStatusAsync().ConfigureAwait(false); break; case "NetworkState": - status = await Permissions.CheckStatusAsync(); + status = await Permissions.CheckStatusAsync().ConfigureAwait(false); break; } @@ -59,10 +59,10 @@ internal async Task Request(string permission, PermissionStatus expectedStatus) switch (permission) { case "Battery": - status = await Permissions.RequestAsync(); + status = await Permissions.RequestAsync().ConfigureAwait(false); break; case "NetworkState": - status = await Permissions.RequestAsync(); + status = await Permissions.RequestAsync().ConfigureAwait(false); break; } @@ -75,8 +75,8 @@ public async Task Request_NotMainThread() { await Task.Run(async () => { - await Assert.ThrowsAsync(async () => await Permissions.RequestAsync()); - }); + await Assert.ThrowsAsync(async () => await Permissions.RequestAsync()).ConfigureAwait(false); + }).ConfigureAwait(false); } [Fact @@ -91,7 +91,7 @@ public async Task StorageAndroid13AlwaysGranted() var status = await Permissions.CheckStatusAsync(); Assert.Equal(PermissionStatus.Granted, status); - status = await Permissions.CheckStatusAsync(); + status = await Permissions.CheckStatusAsync().ConfigureAwait(false); Assert.Equal(PermissionStatus.Granted, status); } else // Android < API 33, we didn't request these, so status denied @@ -99,7 +99,7 @@ public async Task StorageAndroid13AlwaysGranted() var status = await Permissions.CheckStatusAsync(); Assert.Equal(PermissionStatus.Denied, status); - status = await Permissions.CheckStatusAsync(); + status = await Permissions.CheckStatusAsync().ConfigureAwait(false); Assert.Equal(PermissionStatus.Denied, status); } } diff --git a/src/Essentials/test/DeviceTests/Tests/Screenshot_Tests.cs b/src/Essentials/test/DeviceTests/Tests/Screenshot_Tests.cs index c3b59e53e38c..f8a8408ab033 100644 --- a/src/Essentials/test/DeviceTests/Tests/Screenshot_Tests.cs +++ b/src/Essentials/test/DeviceTests/Tests/Screenshot_Tests.cs @@ -19,7 +19,7 @@ public Task GetPngScreenshot() await Task.Delay(100); IScreenshotResult mediaFile = await Screenshot.CaptureAsync(); - var png = await mediaFile.OpenReadAsync(ScreenshotFormat.Png); + var png = await mediaFile.OpenReadAsync(ScreenshotFormat.Png).ConfigureAwait(false); Assert.True(png.Length > 0); }); @@ -33,7 +33,7 @@ public Task GetJpegScreenshot() await Task.Delay(100); IScreenshotResult mediaFile = await Screenshot.CaptureAsync(); - var png = await mediaFile.OpenReadAsync(ScreenshotFormat.Jpeg); + var png = await mediaFile.OpenReadAsync(ScreenshotFormat.Jpeg).ConfigureAwait(false); Assert.True(png.Length > 0); }); diff --git a/src/Essentials/test/DeviceTests/Tests/Share_Tests.cs b/src/Essentials/test/DeviceTests/Tests/Share_Tests.cs index 20437eb63be4..b9a3783a62ad 100644 --- a/src/Essentials/test/DeviceTests/Tests/Share_Tests.cs +++ b/src/Essentials/test/DeviceTests/Tests/Share_Tests.cs @@ -17,14 +17,14 @@ public async Task Share_ShareTextRequestWithInvalidTextAndUri() Text = null, Uri = null }; - await Assert.ThrowsAsync(() => Share.RequestAsync(request)); + await Assert.ThrowsAsync(() => Share.RequestAsync(request)).ConfigureAwait(false); } [Fact] public async Task Share_NullShareTextRequest() { ShareTextRequest request = null; - await Assert.ThrowsAsync(() => Share.RequestAsync(request)); + await Assert.ThrowsAsync(() => Share.RequestAsync(request)).ConfigureAwait(false); } [Fact] @@ -34,14 +34,14 @@ public async Task Share_ShareFileRequestWithInvalidFile() { File = null }; - await Assert.ThrowsAsync(() => Share.RequestAsync(request)); + await Assert.ThrowsAsync(() => Share.RequestAsync(request)).ConfigureAwait(false); } [Fact] public async Task Share_NullShareFileRequest() { ShareFileRequest request = null; - await Assert.ThrowsAsync(() => Share.RequestAsync(request)); + await Assert.ThrowsAsync(() => Share.RequestAsync(request)).ConfigureAwait(false); } [Fact] @@ -51,7 +51,7 @@ public async Task Share_ShareMultipleFilesRequestWithEmptyFilesList() { Files = new List() }; - await Assert.ThrowsAsync(() => Share.RequestAsync(request)); + await Assert.ThrowsAsync(() => Share.RequestAsync(request)).ConfigureAwait(false); } [Fact] @@ -61,14 +61,14 @@ public async Task Share_ShareMultipleFilesRequestWithInvalidFilesList() { Files = new List() { null } }; - await Assert.ThrowsAsync(() => Share.RequestAsync(request)); + await Assert.ThrowsAsync(() => Share.RequestAsync(request)).ConfigureAwait(false); } [Fact] public async Task Share_NullShareMultipleFilesRequest() { ShareMultipleFilesRequest request = null; - await Assert.ThrowsAsync(() => Share.RequestAsync(request)); + await Assert.ThrowsAsync(() => Share.RequestAsync(request)).ConfigureAwait(false); } [Fact] diff --git a/src/Essentials/test/DeviceTests/Tests/WebAuthenticator_Tests.cs b/src/Essentials/test/DeviceTests/Tests/WebAuthenticator_Tests.cs index 645d636bd2ee..f8fae1805eb1 100644 --- a/src/Essentials/test/DeviceTests/Tests/WebAuthenticator_Tests.cs +++ b/src/Essentials/test/DeviceTests/Tests/WebAuthenticator_Tests.cs @@ -30,7 +30,7 @@ public async Task Redirect(string urlBase, string callbackScheme, string accessT #if WINDOWS var exception = await Assert.ThrowsAsync(async () => await authenticationTask); #else - var r = await authenticationTask; + var r = await authenticationTask.ConfigureAwait(false); Assert.Equal(accessToken, r?.AccessToken); Assert.Equal(refreshToken, r?.RefreshToken); Assert.NotNull(r?.ExpiresIn); @@ -60,7 +60,7 @@ public async Task RedirectWithResponseDecoder(string urlBase, string callbackSch #if WINDOWS var exception = await Assert.ThrowsAsync(async () => await authenticationTask); #else - var r = await authenticationTask; + var r = await authenticationTask.ConfigureAwait(false); Assert.Equal(accessToken, r?.AccessToken); Assert.Equal(refreshToken, r?.RefreshToken); Assert.NotNull(r?.ExpiresIn); diff --git a/src/TestUtils/src/DeviceTests.Runners/AppHostBuilderExtensions.cs b/src/TestUtils/src/DeviceTests.Runners/AppHostBuilderExtensions.cs index b66e18cb1c8b..ae758eb13081 100644 --- a/src/TestUtils/src/DeviceTests.Runners/AppHostBuilderExtensions.cs +++ b/src/TestUtils/src/DeviceTests.Runners/AppHostBuilderExtensions.cs @@ -1,10 +1,13 @@ #nullable enable +using System; +using System.Diagnostics; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Maui.Controls.Hosting; using Microsoft.Maui.Hosting; using Microsoft.Maui.TestUtils.DeviceTests.Runners.HeadlessRunner; using Microsoft.Maui.TestUtils.DeviceTests.Runners.VisualRunner; +using Microsoft.Extensions.Logging.Console; namespace Microsoft.Maui.TestUtils.DeviceTests.Runners { @@ -13,7 +16,8 @@ public static class AppHostBuilderExtensions public static MauiAppBuilder ConfigureTests(this MauiAppBuilder appHostBuilder, TestOptions options) { appHostBuilder.Services.AddSingleton(options); - + appHostBuilder.Logging.AddConsole(); + // appHostBuilder.Logging.SetMinimumLevel(LogLevel.Debug); return appHostBuilder; } @@ -36,6 +40,8 @@ public static MauiAppBuilder UseHeadlessRunner(this MauiAppBuilder appHostBuilde svc.GetRequiredService())); #endif + appHostBuilder.Logging.AddConsole(); + return appHostBuilder; } diff --git a/src/TestUtils/src/DeviceTests.Runners/TestUtils.DeviceTests.Runners.csproj b/src/TestUtils/src/DeviceTests.Runners/TestUtils.DeviceTests.Runners.csproj index 55cae5c70af0..58300da095ad 100644 --- a/src/TestUtils/src/DeviceTests.Runners/TestUtils.DeviceTests.Runners.csproj +++ b/src/TestUtils/src/DeviceTests.Runners/TestUtils.DeviceTests.Runners.csproj @@ -22,6 +22,7 @@ + diff --git a/src/TestUtils/src/DeviceTests/AssertionExtensions.Android.cs b/src/TestUtils/src/DeviceTests/AssertionExtensions.Android.cs index 1a29d235f04f..9072379ffc73 100644 --- a/src/TestUtils/src/DeviceTests/AssertionExtensions.Android.cs +++ b/src/TestUtils/src/DeviceTests/AssertionExtensions.Android.cs @@ -445,51 +445,57 @@ public static Bitmap AssertColorAtTopRight(this Bitmap bitmap, AColor expectedCo } public static Task AssertContainsColor(this Bitmap bitmap, Graphics.Color expectedColor, Func? withinRectModifier = null, double? tolerance = null) - => Task.FromResult(bitmap.AssertContainsColor(expectedColor.ToPlatform(), tolerance: tolerance)); + => bitmap.AssertContainsColor(expectedColor.ToPlatform(), tolerance: tolerance); public static Task AssertDoesNotContainColor(this Bitmap bitmap, Graphics.Color unexpectedColor, Func? withinRectModifier = null) - => Task.FromResult(bitmap.AssertDoesNotContainColor(unexpectedColor.ToPlatform())); + => bitmap.AssertDoesNotContainColor(unexpectedColor.ToPlatform()); - public static Bitmap AssertContainsColor(this Bitmap bitmap, AColor expectedColor, Func? withinRectModifier = null, double? tolerance = null) + public static Task AssertContainsColor(this Bitmap bitmap, AColor expectedColor, Func? withinRectModifier = null, double? tolerance = null) { - var imageRect = new Graphics.RectF(0, 0, bitmap.Width, bitmap.Height); + return Task.Run(() => + { + var imageRect = new Graphics.RectF(0, 0, bitmap.Width, bitmap.Height); - if (withinRectModifier is not null) - imageRect = withinRectModifier.Invoke(imageRect); + if (withinRectModifier is not null) + imageRect = withinRectModifier.Invoke(imageRect); - for (int x = (int)imageRect.X; x < (int)imageRect.Width; x++) - { - for (int y = (int)imageRect.Y; y < (int)imageRect.Height; y++) + for (int x = (int)imageRect.X; x < (int)imageRect.Width; x++) { - if (bitmap.ColorAtPoint(x, y, true).IsEquivalent(expectedColor)) + for (int y = (int)imageRect.Y; y < (int)imageRect.Height; y++) { - return bitmap; + if (bitmap.ColorAtPoint(x, y, true).IsEquivalent(expectedColor)) + { + return bitmap; + } } } - } - throw new XunitException(CreateColorError(bitmap, $"Color {expectedColor} not found.")); + throw new XunitException(CreateColorError(bitmap, $"Color {expectedColor} not found.")); + }); } - public static Bitmap AssertDoesNotContainColor(this Bitmap bitmap, AColor unexpectedColor, Func? withinRectModifier = null) + public static Task AssertDoesNotContainColor(this Bitmap bitmap, AColor unexpectedColor, Func? withinRectModifier = null) { - var imageRect = new Graphics.RectF(0, 0, bitmap.Width, bitmap.Height); + return Task.Run(() => + { + var imageRect = new Graphics.RectF(0, 0, bitmap.Width, bitmap.Height); - if (withinRectModifier is not null) - imageRect = withinRectModifier.Invoke(imageRect); + if (withinRectModifier is not null) + imageRect = withinRectModifier.Invoke(imageRect); - for (int x = (int)imageRect.X; x < (int)imageRect.Width; x++) - { - for (int y = (int)imageRect.Y; y < (int)imageRect.Height; y++) + for (int x = (int)imageRect.X; x < (int)imageRect.Width; x++) { - if (bitmap.ColorAtPoint(x, y, true).IsEquivalent(unexpectedColor)) + for (int y = (int)imageRect.Y; y < (int)imageRect.Height; y++) { - throw new XunitException(CreateColorError(bitmap, $"Color {unexpectedColor} was found at point {x}, {y}.")); + if (bitmap.ColorAtPoint(x, y, true).IsEquivalent(unexpectedColor)) + { + throw new XunitException(CreateColorError(bitmap, $"Color {unexpectedColor} was found at point {x}, {y}.")); + } } } - } - return bitmap; + return bitmap; + }); } public static Task AssertContainsColor(this AView view, Graphics.Color expectedColor, IMauiContext mauiContext, double? tolerance = null) => @@ -500,26 +506,26 @@ public static Task AssertDoesNotContainColor(this AView view, Graphics.C public static async Task AssertContainsColor(this AView view, AColor expectedColor, IMauiContext mauiContext, double? tolerance = null) { - var bitmap = await view.ToBitmap(mauiContext); - return AssertContainsColor(bitmap, expectedColor, tolerance: tolerance); + var bitmap = await view.ToBitmap(mauiContext).ConfigureAwait(false); + return await AssertContainsColor(bitmap, expectedColor, tolerance: tolerance).ConfigureAwait(false); } public static async Task AssertDoesNotContainColor(this AView view, AColor unexpectedColor, IMauiContext mauiContext) { - var bitmap = await view.ToBitmap(mauiContext); - return AssertDoesNotContainColor(bitmap, unexpectedColor); + var bitmap = await view.ToBitmap(mauiContext).ConfigureAwait(false); + return await AssertDoesNotContainColor(bitmap, unexpectedColor).ConfigureAwait(false); } public static async Task AssertColorAtPointAsync(this AView view, AColor expectedColor, int x, int y, IMauiContext mauiContext) { - var bitmap = await view.ToBitmap(mauiContext); + var bitmap = await view.ToBitmap(mauiContext).ConfigureAwait(false); return bitmap.AssertColorAtPoint(expectedColor, x, y); } public static async Task AssertColorsAtPointsAsync(this AView view, Graphics.Color[] colors, Graphics.Point[] points, IMauiContext mauiContext) { var density = mauiContext.Context.GetDisplayDensity(); - var bitmap = await view.ToBitmap(mauiContext); + var bitmap = await view.ToBitmap(mauiContext).ConfigureAwait(false); for (int i = 0; i < points.Length; i++) { @@ -531,31 +537,31 @@ public static async Task AssertColorsAtPointsAsync(this AView view, Grap public static async Task AssertColorAtCenterAsync(this AView view, AColor expectedColor, IMauiContext mauiContext) { - var bitmap = await view.ToBitmap(mauiContext); + var bitmap = await view.ToBitmap(mauiContext).ConfigureAwait(false); return bitmap.AssertColorAtCenter(expectedColor); } public static async Task AssertColorAtBottomLeft(this AView view, AColor expectedColor, IMauiContext mauiContext) { - var bitmap = await view.ToBitmap(mauiContext); + var bitmap = await view.ToBitmap(mauiContext).ConfigureAwait(false); return bitmap.AssertColorAtBottomLeft(expectedColor); } public static async Task AssertColorAtBottomRight(this AView view, AColor expectedColor, IMauiContext mauiContext) { - var bitmap = await view.ToBitmap(mauiContext); + var bitmap = await view.ToBitmap(mauiContext).ConfigureAwait(false); return bitmap.AssertColorAtBottomRight(expectedColor); } public static async Task AssertColorAtTopLeft(this AView view, AColor expectedColor, IMauiContext mauiContext) { - var bitmap = await view.ToBitmap(mauiContext); + var bitmap = await view.ToBitmap(mauiContext).ConfigureAwait(false); return bitmap.AssertColorAtTopLeft(expectedColor); } public static async Task AssertColorAtTopRight(this AView view, AColor expectedColor, IMauiContext mauiContext) { - var bitmap = await view.ToBitmap(mauiContext); + var bitmap = await view.ToBitmap(mauiContext).ConfigureAwait(false); return bitmap.AssertColorAtTopRight(expectedColor); } @@ -605,7 +611,7 @@ public static Task AssertNotEqualAsync(this Bitmap bitmap, Bitmap other) public static async Task ThrowScreenshot(this AView view, IMauiContext mauiContext, string? message = null, Exception? ex = null) { - var bitmap = await view.ToBitmap(mauiContext); + var bitmap = await view.ToBitmap(mauiContext).ConfigureAwait(false); if (ex is null) throw new XunitException(CreateScreenshotError(bitmap, message ?? "There was an error.")); else @@ -661,9 +667,9 @@ static async Task AssertTabItemTextColor( throw new Exception("Unable to locate Tab Item Text Container"); if (hasColor) - await navItemView.AssertContainsColor(expectedColor.ToPlatform(), mauiContext); + await navItemView.AssertContainsColor(expectedColor.ToPlatform(), mauiContext).ConfigureAwait(false); else - await navItemView.AssertDoesNotContainColor(expectedColor.ToPlatform(), mauiContext); + await navItemView.AssertDoesNotContainColor(expectedColor.ToPlatform(), mauiContext).ConfigureAwait(false); } static async Task AssertTabItemIconColor( @@ -676,9 +682,9 @@ static async Task AssertTabItemIconColor( throw new Exception("Unable to locate Tab Item Icon Container"); if (hasColor) - await navItemView.AssertContainsColor(expectedColor.ToPlatform(), mauiContext); + await navItemView.AssertContainsColor(expectedColor.ToPlatform(), mauiContext).ConfigureAwait(false); else - await navItemView.AssertDoesNotContainColor(expectedColor.ToPlatform(), mauiContext); + await navItemView.AssertDoesNotContainColor(expectedColor.ToPlatform(), mauiContext).ConfigureAwait(false); } static public Task AssertTabItemIconDoesNotContainColor( diff --git a/src/TestUtils/src/DeviceTests/AssertionExtensions.iOS.cs b/src/TestUtils/src/DeviceTests/AssertionExtensions.iOS.cs index 3198239437a5..76240468fea5 100644 --- a/src/TestUtils/src/DeviceTests/AssertionExtensions.iOS.cs +++ b/src/TestUtils/src/DeviceTests/AssertionExtensions.iOS.cs @@ -4,6 +4,7 @@ using CoreAnimation; using CoreGraphics; using Foundation; +using Microsoft.Extensions.Logging; using Microsoft.Maui.Graphics; using Microsoft.Maui.Platform; using UIKit; @@ -17,12 +18,12 @@ public static partial class AssertionExtensions { public static async Task WaitForKeyboardToShow(this UIView view, int timeout = 1000) { - await AssertEventually(() => KeyboardAutoManagerScroll.IsKeyboardShowing, timeout: timeout, message: $"Timed out waiting for {view} to show keyboard"); + await AssertEventually(() => KeyboardAutoManagerScroll.IsKeyboardShowing, timeout: timeout, message: $"Timed out waiting for {view} to show keyboard").ConfigureAwait(false); } public static async Task WaitForKeyboardToHide(this UIView view, int timeout = 1000) { - await AssertEventually(() => !KeyboardAutoManagerScroll.IsKeyboardShowing, timeout: timeout, message: $"Timed out waiting for {view} to hide keyboard"); + await AssertEventually(() => !KeyboardAutoManagerScroll.IsKeyboardShowing, timeout: timeout, message: $"Timed out waiting for {view} to hide keyboard").ConfigureAwait(false); } public static Task SendValueToKeyboard(this UIView view, char value, int timeout = 1000) @@ -37,12 +38,12 @@ public static Task SendKeyboardReturnType(this UIView view, ReturnType returnTyp public static async Task WaitForFocused(this UIView view, int timeout = 1000) { - await AssertEventually(view.IsFocused, timeout: timeout, message: $"Timed out waiting for {view} to become focused"); + await AssertEventually(view.IsFocused, timeout: timeout, message: $"Timed out waiting for {view} to become focused").ConfigureAwait(false); } public static async Task WaitForUnFocused(this UIView view, int timeout = 1000) { - await AssertEventually(() => !view.IsFocused(), timeout: timeout, message: $"Timed out waiting for {view} to become unfocused"); + await AssertEventually(() => !view.IsFocused(), timeout: timeout, message: $"Timed out waiting for {view} to become unfocused").ConfigureAwait(false); } static bool IsFocused(this UIView view) => view.Focused || view.IsFirstResponder; @@ -206,10 +207,11 @@ public static UIView FindContentView() public static Task ToBitmap(this UIView view, IMauiContext mauiContext) { + var logger = mauiContext.CreateLogger(nameof(ToBitmap)); + logger?.LogDebug("Start"); if (view.Superview is WrapperView wrapper) view = wrapper; - var imageRect = new CGRect(0, 0, view.Frame.Width, view.Frame.Height); if (view.Frame.Width == 0 && view.Frame.Height == 0) @@ -228,6 +230,7 @@ public static Task ToBitmap(this UIView view, IMauiContext mauiContext) var image = UIGraphics.GetImageFromCurrentImageContext(); UIGraphics.EndImageContext(); + logger?.LogDebug($"Finish: {image.Size}"); return Task.FromResult(image); } @@ -317,13 +320,13 @@ public static UIImage AssertColorAtTopRight(this UIImage bitmap, UIColor expecte public static async Task AssertColorAtPointAsync(this UIView view, UIColor expectedColor, int x, int y, IMauiContext mauiContext) { - var bitmap = await view.ToBitmap(mauiContext); + var bitmap = await view.ToBitmap(mauiContext).ConfigureAwait(false); return bitmap.AssertColorAtPoint(expectedColor, x, y); } public static async Task AssertColorsAtPointsAsync(this UIView view, Graphics.Color[] colors, Graphics.Point[] points, IMauiContext mauiContext) { - var bitmap = await view.ToBitmap(mauiContext); + var bitmap = await view.ToBitmap(mauiContext).ConfigureAwait(false); for (int i = 0; i < points.Length; i++) { @@ -335,44 +338,52 @@ public static async Task AssertColorsAtPointsAsync(this UIView view, Gr public static async Task AssertColorAtCenterAsync(this UIView view, UIColor expectedColor, IMauiContext mauiContext) { - var bitmap = await view.ToBitmap(mauiContext); + var bitmap = await view.ToBitmap(mauiContext).ConfigureAwait(false); return bitmap.AssertColorAtCenter(expectedColor); } public static async Task AssertColorAtBottomLeft(this UIView view, UIColor expectedColor, IMauiContext mauiContext) { - var bitmap = await view.ToBitmap(mauiContext); + var bitmap = await view.ToBitmap(mauiContext).ConfigureAwait(false); return bitmap.AssertColorAtBottomLeft(expectedColor); } public static async Task AssertColorAtBottomRight(this UIView view, UIColor expectedColor, IMauiContext mauiContext) { - var bitmap = await view.ToBitmap(mauiContext); + var bitmap = await view.ToBitmap(mauiContext).ConfigureAwait(false); return bitmap.AssertColorAtBottomRight(expectedColor); } public static async Task AssertColorAtTopLeft(this UIView view, UIColor expectedColor, IMauiContext mauiContext) { - var bitmap = await view.ToBitmap(mauiContext); + var bitmap = await view.ToBitmap(mauiContext).ConfigureAwait(false); return bitmap.AssertColorAtTopLeft(expectedColor); } public static async Task AssertColorAtTopRight(this UIView view, UIColor expectedColor, IMauiContext mauiContext) { - var bitmap = await view.ToBitmap(mauiContext); + var bitmap = await view.ToBitmap(mauiContext).ConfigureAwait(false); return bitmap.AssertColorAtTopRight(expectedColor); } public static async Task AssertContainsColor(this UIView view, UIColor expectedColor, IMauiContext mauiContext, double? tolerance = null) { - var bitmap = await view.ToBitmap(mauiContext); - return bitmap.AssertContainsColor(expectedColor, tolerance: tolerance); + var logger = mauiContext.CreateLogger(nameof(AssertContainsColor)); + logger?.LogDebug("Start"); + var bitmap = await view.ToBitmap(mauiContext).ConfigureAwait(false); + var result = await bitmap.AssertContainsColor(expectedColor, tolerance: tolerance).ConfigureAwait(false); + logger?.LogDebug("Finish"); + return result; } public static async Task AssertDoesNotContainColor(this UIView view, UIColor unexpectedColor, IMauiContext mauiContext) { - var bitmap = await view.ToBitmap(mauiContext); - return bitmap.AssertDoesNotContainColor(unexpectedColor); + var logger = mauiContext.CreateLogger(nameof(AssertDoesNotContainColor)); + logger?.LogDebug("Start"); + var bitmap = await view.ToBitmap(mauiContext).ConfigureAwait(false); + var result = await bitmap.AssertDoesNotContainColor(unexpectedColor, logger: logger).ConfigureAwait(false); + logger?.LogDebug("Finish"); + return result; } public static Task AssertContainsColor(this UIView view, Microsoft.Maui.Graphics.Color expectedColor, IMauiContext mauiContext, double? tolerance = null) => @@ -382,48 +393,54 @@ public static Task AssertDoesNotContainColor(this UIView view, Microsof AssertDoesNotContainColor(view, unexpectedColor.ToPlatform(), mauiContext); public static Task AssertContainsColor(this UIImage image, Graphics.Color expectedColor, Func? withinRectModifier = null, double? tolerance = null) - => Task.FromResult(image.AssertContainsColor(expectedColor.ToPlatform(), withinRectModifier, tolerance: tolerance)); + => image.AssertContainsColor(expectedColor.ToPlatform(), withinRectModifier, tolerance: tolerance); - public static UIImage AssertContainsColor(this UIImage bitmap, UIColor expectedColor, Func? withinRectModifier = null, double? tolerance = null) + public static Task AssertContainsColor(this UIImage bitmap, UIColor expectedColor, Func? withinRectModifier = null, double? tolerance = null) { - var imageRect = new Graphics.RectF(0, 0, (float)bitmap.Size.Width.Value, (float)bitmap.Size.Height.Value); + return Task.Run(() => + { + var imageRect = new Graphics.RectF(0, 0, (float)bitmap.Size.Width.Value, (float)bitmap.Size.Height.Value); - if (withinRectModifier is not null) - imageRect = withinRectModifier.Invoke(imageRect); + if (withinRectModifier is not null) + imageRect = withinRectModifier.Invoke(imageRect); - for (int x = (int)imageRect.X; x < (int)imageRect.Width; x++) - { - for (int y = (int)imageRect.Y; y < (int)imageRect.Height; y++) + for (int x = (int)imageRect.X; x < (int)imageRect.Width; x++) { - if (ColorComparison.ARGBEquivalent(bitmap.ColorAtPoint(x, y), expectedColor, tolerance)) + for (int y = (int)imageRect.Y; y < (int)imageRect.Height; y++) { - return bitmap; + if (ColorComparison.ARGBEquivalent(bitmap.ColorAtPoint(x, y), expectedColor, tolerance)) + { + return bitmap; + } } } - } - throw new XunitException(CreateColorError(bitmap, $"Color {expectedColor} not found.")); + throw new XunitException(CreateColorError(bitmap, $"Color {expectedColor} not found.")); + }); } - public static UIImage AssertDoesNotContainColor(this UIImage bitmap, UIColor unexpectedColor, Func? withinRectModifier = null) + public static Task AssertDoesNotContainColor(this UIImage bitmap, UIColor unexpectedColor, Func? withinRectModifier = null, ILogger? logger = null) { - var imageRect = new Graphics.RectF(0, 0, (float)bitmap.Size.Width.Value, (float)bitmap.Size.Height.Value); + return Task.Run(() => + { + var imageRect = new Graphics.RectF(0, 0, (float)bitmap.Size.Width.Value, (float)bitmap.Size.Height.Value); - if (withinRectModifier is not null) - imageRect = withinRectModifier.Invoke(imageRect); + if (withinRectModifier is not null) + imageRect = withinRectModifier.Invoke(imageRect); - for (int x = (int)imageRect.X; x < (int)imageRect.Width; x++) - { - for (int y = (int)imageRect.Y; y < (int)imageRect.Height; y++) + for (int x = (int)imageRect.X; x < (int)imageRect.Width; x++) { - if (ColorComparison.ARGBEquivalent(bitmap.ColorAtPoint(x, y), unexpectedColor)) + for (int y = (int)imageRect.Y; y < (int)imageRect.Height; y++) { - throw new XunitException(CreateColorError(bitmap, $"Color {unexpectedColor} was found at point {x}, {y}.")); + if (ColorComparison.ARGBEquivalent(bitmap.ColorAtPoint(x, y), unexpectedColor)) + { + throw new XunitException(CreateColorError(bitmap, $"Color {unexpectedColor} was found at point {x}, {y}.")); + } } } - } - return bitmap; + return bitmap; + }); } @@ -457,7 +474,7 @@ bool IsMatching() public static async Task ThrowScreenshot(this UIView view, IMauiContext mauiContext, string? message = null, Exception? ex = null) { - var bitmap = await view.ToBitmap(mauiContext); + var bitmap = await view.ToBitmap(mauiContext).ConfigureAwait(false); if (ex is null) throw new XunitException(CreateScreenshotError(bitmap, message ?? "There was an error.")); else @@ -805,29 +822,34 @@ static async Task AssertTabItemTextColor( if (hasColor) { - await tabBarItemView.AssertContainsColor(expectedColor, mauiContext, 0.1); + await tabBarItemView.AssertContainsColor(expectedColor, mauiContext, 0.1).ConfigureAwait(false); } else { - await tabBarItemView.AssertDoesNotContainColor(expectedColor, mauiContext); + await tabBarItemView.AssertDoesNotContainColor(expectedColor, mauiContext).ConfigureAwait(false); } } static async Task AssertTabItemIconColor( this UITabBar navigationView, string tabText, Color expectedColor, bool hasColor, IMauiContext mauiContext) - { + { + var logger = mauiContext.CreateLogger(nameof(AssertTabItemIconColor)); + logger?.LogDebug("Start"); var tabBarItemView = GetTabItemView(navigationView, tabText).FindDescendantView(); + if (tabBarItemView is null) throw new Exception($"Unable to locate Tab Item Icon Container: {tabText}"); + logger?.LogDebug("Retrieved GetTabItemView"); + if (hasColor) { - await tabBarItemView.AssertContainsColor(expectedColor, mauiContext); + await tabBarItemView.AssertContainsColor(expectedColor, mauiContext).ConfigureAwait(false); } else { - await tabBarItemView.AssertDoesNotContainColor(expectedColor, mauiContext); + await tabBarItemView.AssertDoesNotContainColor(expectedColor, mauiContext).ConfigureAwait(false); } } From 645a809608157926f2036e3ed0f5c9b20f3aeeca Mon Sep 17 00:00:00 2001 From: Shane Neuville Date: Wed, 29 Jan 2025 11:51:49 -0600 Subject: [PATCH 2/2] - fixed --- src/Essentials/test/DeviceTests/Tests/Launcher_Tests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Essentials/test/DeviceTests/Tests/Launcher_Tests.cs b/src/Essentials/test/DeviceTests/Tests/Launcher_Tests.cs index 742e53d1088d..692ad22eafd8 100644 --- a/src/Essentials/test/DeviceTests/Tests/Launcher_Tests.cs +++ b/src/Essentials/test/DeviceTests/Tests/Launcher_Tests.cs @@ -77,7 +77,7 @@ public async Task CanOpen(string uri) } #endif - Assert.True(await Launcher.CanOpenAsync(uri)).ConfigureAwait(false); + Assert.True(await Launcher.CanOpenAsync(uri).ConfigureAwait(false)); } [Theory]