From cf4d13472c963076cbc8d80f083cd59c07f97832 Mon Sep 17 00:00:00 2001 From: Oleksii Sokol Date: Tue, 7 May 2024 15:09:00 +0300 Subject: [PATCH 1/7] fixed crash with Change Aspect Clicked --- .../Pages/Views/MediaElement/MediaElementPage.xaml.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/CommunityToolkit.Maui.Sample/Pages/Views/MediaElement/MediaElementPage.xaml.cs b/samples/CommunityToolkit.Maui.Sample/Pages/Views/MediaElement/MediaElementPage.xaml.cs index 0908e8bd8..f1c2ef005 100644 --- a/samples/CommunityToolkit.Maui.Sample/Pages/Views/MediaElement/MediaElementPage.xaml.cs +++ b/samples/CommunityToolkit.Maui.Sample/Pages/Views/MediaElement/MediaElementPage.xaml.cs @@ -198,7 +198,7 @@ async void ChangeAspectClicked(Object sender, EventArgs e) "Cancel", null, Aspect.AspectFit.ToString(), Aspect.AspectFill.ToString(), Aspect.Fill.ToString()); - if (resultAspect.Equals("Cancel")) + if (resultAspect is null || resultAspect.Equals("Cancel")) { return; } From 0ce8cf298456993f76164115fd24249fcce0ead3 Mon Sep 17 00:00:00 2001 From: Oleksii Sokol Date: Tue, 7 May 2024 15:41:38 +0300 Subject: [PATCH 2/7] updated Microsoft.Maui.Controls package version --- .../CommunityToolkit.Maui.Sample.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/samples/CommunityToolkit.Maui.Sample/CommunityToolkit.Maui.Sample.csproj b/samples/CommunityToolkit.Maui.Sample/CommunityToolkit.Maui.Sample.csproj index 28fbd2749..524fbbc86 100644 --- a/samples/CommunityToolkit.Maui.Sample/CommunityToolkit.Maui.Sample.csproj +++ b/samples/CommunityToolkit.Maui.Sample/CommunityToolkit.Maui.Sample.csproj @@ -51,8 +51,8 @@ - - + + From 0e9d7a1353703f60d483a7403a4176a53048ef2a Mon Sep 17 00:00:00 2001 From: Oleksii Sokol Date: Thu, 9 May 2024 12:44:04 +0300 Subject: [PATCH 3/7] updated MauiPackageVersion --- Directory.Build.props | 2 +- .../CommunityToolkit.Maui.Sample.csproj | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index 5d3a1861f..430f44d86 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -2,7 +2,7 @@ net8.0 - 8.0.14 + 8.0.21 latest enable enable diff --git a/samples/CommunityToolkit.Maui.Sample/CommunityToolkit.Maui.Sample.csproj b/samples/CommunityToolkit.Maui.Sample/CommunityToolkit.Maui.Sample.csproj index 524fbbc86..7c5f539d8 100644 --- a/samples/CommunityToolkit.Maui.Sample/CommunityToolkit.Maui.Sample.csproj +++ b/samples/CommunityToolkit.Maui.Sample/CommunityToolkit.Maui.Sample.csproj @@ -1,4 +1,4 @@ - + $(NetVersion)-ios;$(NetVersion)-android;$(NetVersion)-maccatalyst @@ -51,7 +51,7 @@ - + From 6f5103e062499f9d5d098cd6b8e4086ce3396ef2 Mon Sep 17 00:00:00 2001 From: Brandon Minnick <13558917+brminnick@users.noreply.github.com> Date: Fri, 14 Jun 2024 16:09:24 +0200 Subject: [PATCH 4/7] Use reflection to assign `Application. _systemResources` --- .../BaseHandlerTest.cs | 2 +- .../Mocks/MockApplication.cs | 43 +++++++++++++++---- .../Mocks/MockResourcesProvider.cs | 39 +++++++++++++++++ 3 files changed, 75 insertions(+), 9 deletions(-) create mode 100644 src/CommunityToolkit.Maui.UnitTests/Mocks/MockResourcesProvider.cs diff --git a/src/CommunityToolkit.Maui.UnitTests/BaseHandlerTest.cs b/src/CommunityToolkit.Maui.UnitTests/BaseHandlerTest.cs index 578ba9fb7..270dc5a87 100644 --- a/src/CommunityToolkit.Maui.UnitTests/BaseHandlerTest.cs +++ b/src/CommunityToolkit.Maui.UnitTests/BaseHandlerTest.cs @@ -13,7 +13,7 @@ protected BaseHandlerTest() protected IServiceProvider ServiceProvider { get; } - protected static TElementHandler CreateElementHandler(Microsoft.Maui.IElement view, bool hasMauiContext = true) + protected static TElementHandler CreateElementHandler(IElement view, bool hasMauiContext = true) where TElementHandler : IElementHandler, new() { var mockElementHandler = new TElementHandler(); diff --git a/src/CommunityToolkit.Maui.UnitTests/Mocks/MockApplication.cs b/src/CommunityToolkit.Maui.UnitTests/Mocks/MockApplication.cs index 08706b960..7eae23128 100644 --- a/src/CommunityToolkit.Maui.UnitTests/Mocks/MockApplication.cs +++ b/src/CommunityToolkit.Maui.UnitTests/Mocks/MockApplication.cs @@ -1,21 +1,48 @@ -using Microsoft.Maui.Handlers; +using System.Reflection; +using Microsoft.Maui.Controls.Internals; +using Microsoft.Maui.Handlers; namespace CommunityToolkit.Maui.UnitTests.Mocks; -class MockApplication(IServiceProvider serviceProvider) : Application, IPlatformApplication +class MockApplication : Application, IPlatformApplication { public new Application? Current = null; - public IServiceProvider Services { get; } = serviceProvider; + public IServiceProvider Services { get; } public IApplication Application => this; -} -// Inspired by https://github.com/dotnet/maui/blob/main/src/Controls/tests/Core.UnitTests/TestClasses/ApplicationHandlerStub.cs -class ApplicationHandlerStub : ElementHandler -{ - public ApplicationHandlerStub() : base(Mapper) +#pragma warning disable CS0612 // Type or member is obsolete + public MockApplication(IServiceProvider serviceProvider) +#pragma warning restore CS0612 // Type or member is obsolete + { + Services = serviceProvider; + + InitializeSystemResources(new MockResourcesProvider()); + } +#pragma warning disable CS0612 // Type or member is obsolete + void InitializeSystemResources(ISystemResourcesProvider resourcesProvider) +#pragma warning restore CS0612 // Type or member is obsolete { + const string privateFieldName = "_systemResources"; + + if (typeof(Application).GetField(privateFieldName, BindingFlags.NonPublic | BindingFlags.Instance) is not FieldInfo systemResourcesFieldInfo) + { + throw new InvalidOperationException($"Unable to access {privateFieldName}"); + } + + // .NET MAUI's SystemResources initialization: https://github.com/dotnet/maui/blob/79695fbb7ba6517a334c795ecf0a1d6358ef309a/src/Controls/src/Core/Application/Application.cs#L42-L49 + systemResourcesFieldInfo.SetValue(this, new Lazy(() => + { + var systemResources = resourcesProvider.GetSystemResources(); + systemResources.ValuesChanged += OnParentResourcesChanged; + return systemResources; + })); + } +} +// Inspired by https://github.com/dotnet/maui/blob/main/src/Controls/tests/Core.UnitTests/TestClasses/ApplicationHandlerStub.cs +class ApplicationHandlerStub() : ElementHandler(Mapper) +{ public static IPropertyMapper Mapper = new PropertyMapper(ElementMapper); protected override object CreatePlatformElement() diff --git a/src/CommunityToolkit.Maui.UnitTests/Mocks/MockResourcesProvider.cs b/src/CommunityToolkit.Maui.UnitTests/Mocks/MockResourcesProvider.cs new file mode 100644 index 000000000..7929b4816 --- /dev/null +++ b/src/CommunityToolkit.Maui.UnitTests/Mocks/MockResourcesProvider.cs @@ -0,0 +1,39 @@ +using Microsoft.Maui.Controls.Internals; +namespace CommunityToolkit.Maui.UnitTests.Mocks; + +// Inspired by https://github.com/dotnet/maui/blob/79695fbb7ba6517a334c795ecf0a1d6358ef309a/src/Controls/Foldable/test/MockPlatformServices.cs#L145-L176 + +#pragma warning disable CS0612 // Type or member is obsolete +class MockResourcesProvider : ISystemResourcesProvider +#pragma warning restore CS0612 // Type or member is obsolete +{ + public IResourceDictionary GetSystemResources() + { + var dictionary = new ResourceDictionary(); + + Style style = new Style(typeof(Label)); + dictionary[Device.Styles.BodyStyleKey] = style; + + style = new Style(typeof(Label)); + style.Setters.Add(Label.FontSizeProperty, 50); + dictionary[Device.Styles.TitleStyleKey] = style; + + style = new Style(typeof(Label)); + style.Setters.Add(Label.FontSizeProperty, 40); + dictionary[Device.Styles.SubtitleStyleKey] = style; + + style = new Style(typeof(Label)); + style.Setters.Add(Label.FontSizeProperty, 30); + dictionary[Device.Styles.CaptionStyleKey] = style; + + style = new Style(typeof(Label)); + style.Setters.Add(Label.FontSizeProperty, 20); + dictionary[Device.Styles.ListItemTextStyleKey] = style; + + style = new Style(typeof(Label)); + style.Setters.Add(Label.FontSizeProperty, 10); + dictionary[Device.Styles.ListItemDetailTextStyleKey] = style; + + return dictionary; + } +} \ No newline at end of file From 9bcb6e710f0a8bf352525671dba85a660a6a00b2 Mon Sep 17 00:00:00 2001 From: Brandon Minnick <13558917+brminnick@users.noreply.github.com> Date: Fri, 14 Jun 2024 17:32:37 +0200 Subject: [PATCH 5/7] Remove Reflection --- .../Mocks/MockApplication.cs | 24 ++------------- .../Mocks/MockResourcesProvider.cs | 30 ++----------------- 2 files changed, 4 insertions(+), 50 deletions(-) diff --git a/src/CommunityToolkit.Maui.UnitTests/Mocks/MockApplication.cs b/src/CommunityToolkit.Maui.UnitTests/Mocks/MockApplication.cs index 7eae23128..ba854ab24 100644 --- a/src/CommunityToolkit.Maui.UnitTests/Mocks/MockApplication.cs +++ b/src/CommunityToolkit.Maui.UnitTests/Mocks/MockApplication.cs @@ -15,28 +15,8 @@ public MockApplication(IServiceProvider serviceProvider) #pragma warning restore CS0612 // Type or member is obsolete { Services = serviceProvider; - - InitializeSystemResources(new MockResourcesProvider()); - } -#pragma warning disable CS0612 // Type or member is obsolete - void InitializeSystemResources(ISystemResourcesProvider resourcesProvider) -#pragma warning restore CS0612 // Type or member is obsolete - { - const string privateFieldName = "_systemResources"; - - if (typeof(Application).GetField(privateFieldName, BindingFlags.NonPublic | BindingFlags.Instance) is not FieldInfo systemResourcesFieldInfo) - { - throw new InvalidOperationException($"Unable to access {privateFieldName}"); - } - - // .NET MAUI's SystemResources initialization: https://github.com/dotnet/maui/blob/79695fbb7ba6517a334c795ecf0a1d6358ef309a/src/Controls/src/Core/Application/Application.cs#L42-L49 - systemResourcesFieldInfo.SetValue(this, new Lazy(() => - { - var systemResources = resourcesProvider.GetSystemResources(); - systemResources.ValuesChanged += OnParentResourcesChanged; - return systemResources; - })); - + + DependencyService.Register(); } } diff --git a/src/CommunityToolkit.Maui.UnitTests/Mocks/MockResourcesProvider.cs b/src/CommunityToolkit.Maui.UnitTests/Mocks/MockResourcesProvider.cs index 7929b4816..9d738515a 100644 --- a/src/CommunityToolkit.Maui.UnitTests/Mocks/MockResourcesProvider.cs +++ b/src/CommunityToolkit.Maui.UnitTests/Mocks/MockResourcesProvider.cs @@ -7,33 +7,7 @@ namespace CommunityToolkit.Maui.UnitTests.Mocks; class MockResourcesProvider : ISystemResourcesProvider #pragma warning restore CS0612 // Type or member is obsolete { - public IResourceDictionary GetSystemResources() - { - var dictionary = new ResourceDictionary(); + readonly ResourceDictionary dictionary = new(); - Style style = new Style(typeof(Label)); - dictionary[Device.Styles.BodyStyleKey] = style; - - style = new Style(typeof(Label)); - style.Setters.Add(Label.FontSizeProperty, 50); - dictionary[Device.Styles.TitleStyleKey] = style; - - style = new Style(typeof(Label)); - style.Setters.Add(Label.FontSizeProperty, 40); - dictionary[Device.Styles.SubtitleStyleKey] = style; - - style = new Style(typeof(Label)); - style.Setters.Add(Label.FontSizeProperty, 30); - dictionary[Device.Styles.CaptionStyleKey] = style; - - style = new Style(typeof(Label)); - style.Setters.Add(Label.FontSizeProperty, 20); - dictionary[Device.Styles.ListItemTextStyleKey] = style; - - style = new Style(typeof(Label)); - style.Setters.Add(Label.FontSizeProperty, 10); - dictionary[Device.Styles.ListItemDetailTextStyleKey] = style; - - return dictionary; - } + public IResourceDictionary GetSystemResources() => dictionary; } \ No newline at end of file From abfa6b62e5bf02576476f94e55ed05c04f9efd0f Mon Sep 17 00:00:00 2001 From: Brandon Minnick <13558917+brminnick@users.noreply.github.com> Date: Fri, 14 Jun 2024 17:33:15 +0200 Subject: [PATCH 6/7] Use `MockApplication` --- .../Essentials/AppThemeTests.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/CommunityToolkit.Maui.UnitTests/Essentials/AppThemeTests.cs b/src/CommunityToolkit.Maui.UnitTests/Essentials/AppThemeTests.cs index 75454d249..9e4397dde 100644 --- a/src/CommunityToolkit.Maui.UnitTests/Essentials/AppThemeTests.cs +++ b/src/CommunityToolkit.Maui.UnitTests/Essentials/AppThemeTests.cs @@ -4,7 +4,7 @@ namespace CommunityToolkit.Maui.UnitTests.Essentials; -public class AppThemeTests : BaseTest +public class AppThemeTests : BaseHandlerTest { readonly MockAppInfo mockAppInfo; readonly Application app; @@ -12,7 +12,7 @@ public class AppThemeTests : BaseTest public AppThemeTests() { AppInfo.SetCurrent(mockAppInfo = new() { RequestedTheme = AppTheme.Light }); - Application.Current = app = new Application(); + Application.Current = app = new MockApplication(ServiceProvider); } [Fact] @@ -113,6 +113,11 @@ public void AppThemeResourceUpdatesLabelText() void SetAppTheme(AppTheme theme) { + app.RequestedThemeChanged += (sender, args) => + { + var temp = DateTime.Now; + }; + mockAppInfo.RequestedTheme = theme; ((IApplication)app).ThemeChanged(); } From b583d21303ea75ea46e8e54753fbf2831fbe50cc Mon Sep 17 00:00:00 2001 From: Brandon Minnick <13558917+brminnick@users.noreply.github.com> Date: Thu, 20 Jun 2024 13:53:46 -0700 Subject: [PATCH 7/7] Fix Unit Tests --- .../BaseTest.cs | 6 +++ .../Essentials/AppThemeTests.cs | 39 ++++++++++++------- .../Mocks/MockApplication.cs | 8 ++-- .../AppThemeResourceExtension.shared.cs | 29 +++++++------- 4 files changed, 50 insertions(+), 32 deletions(-) diff --git a/src/CommunityToolkit.Maui.UnitTests/BaseTest.cs b/src/CommunityToolkit.Maui.UnitTests/BaseTest.cs index af9ddcfd6..7f291210d 100644 --- a/src/CommunityToolkit.Maui.UnitTests/BaseTest.cs +++ b/src/CommunityToolkit.Maui.UnitTests/BaseTest.cs @@ -18,8 +18,14 @@ protected enum TestDuration protected BaseTest() { + CompatibilityCheck.UseCompatibility(); + defaultCulture = Thread.CurrentThread.CurrentCulture; defaultUiCulture = Thread.CurrentThread.CurrentUICulture; + + DeviceDisplay.SetCurrent(null); + DeviceInfo.SetCurrent(null); + AppInfo.SetCurrent(null); DispatcherProvider.SetCurrent(new MockDispatcherProvider()); DeviceDisplay.SetCurrent(null); diff --git a/src/CommunityToolkit.Maui.UnitTests/Essentials/AppThemeTests.cs b/src/CommunityToolkit.Maui.UnitTests/Essentials/AppThemeTests.cs index 9e4397dde..fa2ae2087 100644 --- a/src/CommunityToolkit.Maui.UnitTests/Essentials/AppThemeTests.cs +++ b/src/CommunityToolkit.Maui.UnitTests/Essentials/AppThemeTests.cs @@ -11,8 +11,14 @@ public class AppThemeTests : BaseHandlerTest public AppThemeTests() { - AppInfo.SetCurrent(mockAppInfo = new() { RequestedTheme = AppTheme.Light }); - Application.Current = app = new MockApplication(ServiceProvider); + const AppTheme initialAppTheme = AppTheme.Light; + AppInfo.SetCurrent(mockAppInfo = new() { RequestedTheme = initialAppTheme }); + + Application.Current = app = new Application(); + + SetAppTheme(initialAppTheme); + + Assert.Equal(initialAppTheme, app.PlatformAppTheme); } [Fact] @@ -28,10 +34,12 @@ public void AppThemeColorUsesCorrectColorForTheme() { Text = "Green on Light, Red on Dark" }; - label.SetAppThemeColor(Label.TextColorProperty, color); - Application.Current = null; + app.MainPage = new ContentPage + { + Content = label + }; Assert.Equal(Colors.Green, label.TextColor); @@ -56,7 +64,10 @@ public void AppThemeColorUsesDefaultColorWhenDarkColorNotSet() label.SetAppThemeColor(Label.TextColorProperty, color); - Application.Current = null; + app.MainPage = new ContentPage + { + Content = label + }; Assert.Equal(Colors.Green, label.TextColor); @@ -81,7 +92,10 @@ public void AppThemeColorUsesDefaultColorWhenLightColorNotSet() label.SetAppThemeColor(Label.TextColorProperty, color); - Application.Current = null; + app.MainPage = new ContentPage + { + Content = label + }; Assert.Equal(Colors.Blue, label.TextColor); @@ -103,7 +117,11 @@ public void AppThemeResourceUpdatesLabelText() label.SetAppTheme(Label.TextProperty, resource); - Application.Current = null; + app.MainPage = new ContentPage + { + Content = label + }; + Assert.Equal("Light Theme", label.Text); SetAppTheme(AppTheme.Dark); @@ -111,13 +129,8 @@ public void AppThemeResourceUpdatesLabelText() Assert.Equal("Dark Theme", label.Text); } - void SetAppTheme(AppTheme theme) + void SetAppTheme(in AppTheme theme) { - app.RequestedThemeChanged += (sender, args) => - { - var temp = DateTime.Now; - }; - mockAppInfo.RequestedTheme = theme; ((IApplication)app).ThemeChanged(); } diff --git a/src/CommunityToolkit.Maui.UnitTests/Mocks/MockApplication.cs b/src/CommunityToolkit.Maui.UnitTests/Mocks/MockApplication.cs index ba854ab24..919276b6c 100644 --- a/src/CommunityToolkit.Maui.UnitTests/Mocks/MockApplication.cs +++ b/src/CommunityToolkit.Maui.UnitTests/Mocks/MockApplication.cs @@ -6,18 +6,16 @@ namespace CommunityToolkit.Maui.UnitTests.Mocks; class MockApplication : Application, IPlatformApplication { - public new Application? Current = null; - public IServiceProvider Services { get; } - public IApplication Application => this; - #pragma warning disable CS0612 // Type or member is obsolete public MockApplication(IServiceProvider serviceProvider) #pragma warning restore CS0612 // Type or member is obsolete { Services = serviceProvider; - DependencyService.Register(); } + + public IApplication Application => this; + public IServiceProvider Services { get; } } // Inspired by https://github.com/dotnet/maui/blob/main/src/Controls/tests/Core.UnitTests/TestClasses/ApplicationHandlerStub.cs diff --git a/src/CommunityToolkit.Maui/Extensions/AppThemeResourceExtension.shared.cs b/src/CommunityToolkit.Maui/Extensions/AppThemeResourceExtension.shared.cs index 692b8e574..8b1ecf466 100644 --- a/src/CommunityToolkit.Maui/Extensions/AppThemeResourceExtension.shared.cs +++ b/src/CommunityToolkit.Maui/Extensions/AppThemeResourceExtension.shared.cs @@ -17,7 +17,7 @@ public sealed class AppThemeResourceExtension : IMarkupExtension /// Thrown if does no implement . public BindingBase ProvideValue(IServiceProvider serviceProvider) { - ArgumentNullException.ThrowIfNull(serviceProvider, nameof(serviceProvider)); + ArgumentNullException.ThrowIfNull(serviceProvider); if (Key is null) { @@ -35,19 +35,20 @@ public BindingBase ProvideValue(IServiceProvider serviceProvider) var xmlLineInfo = serviceProvider.GetService(typeof(IXmlLineInfoProvider)) is IXmlLineInfoProvider xmlLineInfoProvider ? xmlLineInfoProvider.XmlLineInfo : null; throw new XamlParseException($"Resource not found for key {Key}", xmlLineInfo); } - else if (resource is AppThemeColor color) + + switch (resource) { - return color.GetBinding(); - } - else if (resource is AppThemeObject themeResource) - { - return themeResource.GetBinding(); - } - else - { - var xmlLineInfo = serviceProvider.GetService(typeof(IXmlLineInfoProvider)) is IXmlLineInfoProvider xmlLineInfoProvider ? xmlLineInfoProvider.XmlLineInfo : null; - throw new XamlParseException($"Resource found for key {Key} is not of type {nameof(AppThemeColor)} or {nameof(AppThemeObject)}", xmlLineInfo); + case AppThemeColor color: + return color.GetBinding(); + case AppThemeObject themeResource: + return themeResource.GetBinding(); + default: + { + var xmlLineInfo = serviceProvider.GetService(typeof(IXmlLineInfoProvider)) is IXmlLineInfoProvider xmlLineInfoProvider ? xmlLineInfoProvider.XmlLineInfo : null; + throw new XamlParseException($"Resource found for key {Key} is not of type {nameof(AppThemeColor)} or {nameof(AppThemeObject)}", xmlLineInfo); + } } + } static bool TryGetResource(string key, IEnumerable parentObjects, out object? resource, out ResourceDictionary? resourceDictionary) @@ -57,8 +58,8 @@ static bool TryGetResource(string key, IEnumerable parentObjects, out ob foreach (var parentObject in parentObjects) { - ResourceDictionary? resDict = parentObject is IResourcesProvider resoiurceProvider && resoiurceProvider.IsResourcesCreated - ? resoiurceProvider.Resources + var resDict = parentObject is IResourcesProvider { IsResourcesCreated: true } resourcesProvider + ? resourcesProvider.Resources : parentObject as ResourceDictionary; if (resDict is null) {