diff --git a/eng/cake/dotnet.cake b/eng/cake/dotnet.cake index 630842987ba3..d78ddde04143 100644 --- a/eng/cake/dotnet.cake +++ b/eng/cake/dotnet.cake @@ -490,6 +490,8 @@ Task("VS") Error("!!!!BUILD TASKS FAILED: !!!!!"); } + UseLocalNuGetCacheFolder(); + StartVisualStudioForDotNet6(); }); @@ -568,6 +570,23 @@ void SetDotNetEnvironmentVariables() SetEnvironmentVariable("MSBuildDebugEngine", "1"); } +void UseLocalNuGetCacheFolder(bool reset = false) +{ + var temp = Context.Environment.GetSpecialPath(SpecialPath.LocalTemp); + var packages = temp.Combine("Microsoft.Maui.Cache/NuGet/packages"); + + EnsureDirectoryExists(packages); + + CleanDirectories(packages.FullPath + "/microsoft.maui.*"); + CleanDirectories(packages.FullPath + "/microsoft.aspnetcore.*"); + + if (reset) + CleanDirectories(packages.FullPath); + + SetEnvironmentVariable("RestorePackagesPath", packages.FullPath); + SetEnvironmentVariable("NUGET_PACKAGES", packages.FullPath); +} + void StartVisualStudioForDotNet6() { string sln = Argument("sln", null); diff --git a/src/Controls/src/Core/Compatibility/Handlers/Android/FrameRenderer.cs b/src/Controls/src/Core/Compatibility/Handlers/Android/FrameRenderer.cs index 3d141d78ba99..7d5191eeb766 100644 --- a/src/Controls/src/Core/Compatibility/Handlers/Android/FrameRenderer.cs +++ b/src/Controls/src/Core/Compatibility/Handlers/Android/FrameRenderer.cs @@ -4,6 +4,7 @@ using Android.Graphics; using Android.Graphics.Drawables; using Android.Views; +using Android.Views.Animations; using AndroidX.CardView.Widget; using AndroidX.Core.View; using Microsoft.Maui.Controls.Platform; @@ -52,7 +53,6 @@ public static IPropertyMapper Mapper public static CommandMapper CommandMapper = new CommandMapper(ViewRenderer.VisualElementRendererCommandMapper); - float _defaultElevation = -1f; float _defaultCornerRadius = -1f; @@ -68,6 +68,8 @@ public static CommandMapper CommandMapper public event EventHandler? ElementChanged; public event EventHandler? ElementPropertyChanged; + const double LegacyMinimumFrameSize = 20; + public FrameRenderer(Context context) : this(context, Mapper) { } @@ -96,17 +98,28 @@ protected Frame? Element } } - Size IViewHandler.GetDesiredSize(double widthMeasureSpec, double heightMeasureSpec) + Size IViewHandler.GetDesiredSize(double widthConstraint, double heightConstraint) { - double minWidth = 20; - if (Primitives.Dimension.IsExplicitSet(widthMeasureSpec) && !double.IsInfinity(widthMeasureSpec)) - minWidth = widthMeasureSpec; + var virtualView = (this as IViewHandler)?.VirtualView; + if (virtualView is null) + { + return Size.Zero; + } + + var minWidth = virtualView.MinimumWidth; + var minHeight = virtualView.MinimumHeight; - double minHeight = 20; - if (Primitives.Dimension.IsExplicitSet(widthMeasureSpec) && !double.IsInfinity(heightMeasureSpec)) - minHeight = heightMeasureSpec; + if (!Primitives.Dimension.IsExplicitSet(minWidth)) + { + minWidth = LegacyMinimumFrameSize; + } + + if (!Primitives.Dimension.IsExplicitSet(minHeight)) + { + minHeight = LegacyMinimumFrameSize; + } - return VisualElementRenderer.GetDesiredSize(this, widthMeasureSpec, heightMeasureSpec, + return VisualElementRenderer.GetDesiredSize(this, widthConstraint, heightConstraint, new Size(minWidth, minHeight)); } diff --git a/src/Controls/src/Core/Compatibility/Handlers/Shell/iOS/ShellSectionRootRenderer.cs b/src/Controls/src/Core/Compatibility/Handlers/Shell/iOS/ShellSectionRootRenderer.cs index 3196afc56722..364dd85fee9b 100644 --- a/src/Controls/src/Core/Compatibility/Handlers/Shell/iOS/ShellSectionRootRenderer.cs +++ b/src/Controls/src/Core/Compatibility/Handlers/Shell/iOS/ShellSectionRootRenderer.cs @@ -255,7 +255,7 @@ protected virtual void LoadRenderers() if (item == currentItem) { - _containerArea.AddSubview(renderer.PlatformView); + _containerArea.AddSubview(renderer.ViewController.View); _currentContent = currentItem; _currentIndex = i; } diff --git a/src/Controls/tests/DeviceTests/ControlsHandlerTestBase.cs b/src/Controls/tests/DeviceTests/ControlsHandlerTestBase.cs index 6174844a4a62..7617c5270044 100644 --- a/src/Controls/tests/DeviceTests/ControlsHandlerTestBase.cs +++ b/src/Controls/tests/DeviceTests/ControlsHandlerTestBase.cs @@ -41,26 +41,8 @@ protected override MauiAppBuilder ConfigureBuilder(MauiAppBuilder mauiAppBuilder return mauiAppBuilder.ConfigureTestBuilder(); } - protected void SetupShellHandlers(IMauiHandlersCollection handlers) - { - handlers.TryAddHandler(typeof(Controls.Shell), typeof(ShellHandler)); - handlers.TryAddHandler(); - handlers.TryAddHandler(); - handlers.TryAddHandler(); - handlers.TryAddHandler(); - handlers.TryAddHandler(typeof(Toolbar), typeof(ToolbarHandler)); - handlers.TryAddHandler(typeof(MenuBar), typeof(MenuBarHandler)); - handlers.TryAddHandler(typeof(MenuBarItem), typeof(MenuBarItemHandler)); - handlers.TryAddHandler(typeof(MenuFlyoutItem), typeof(MenuFlyoutItemHandler)); - handlers.TryAddHandler(typeof(MenuFlyoutSubItem), typeof(MenuFlyoutSubItemHandler)); - handlers.TryAddHandler(); - -#if WINDOWS - handlers.TryAddHandler(typeof(ShellItem), typeof(ShellItemHandler)); - handlers.TryAddHandler(typeof(ShellSection), typeof(ShellSectionHandler)); - handlers.TryAddHandler(typeof(ShellContent), typeof(ShellContentHandler)); -#endif - } + protected void SetupShellHandlers(IMauiHandlersCollection handlers) => + handlers.SetupShellHandlers(); protected THandler CreateHandler(IElement view) where THandler : IElementHandler, new() @@ -99,6 +81,29 @@ protected Task GetValueAsync(IElement view, Func(CreateWindowForContent(view), handler => + { + action(); + return Task.CompletedTask; + }); + } + protected Task CreateHandlerAndAddToWindow(IElement view, Action action) where THandler : class, IElementHandler { @@ -117,23 +122,10 @@ protected Task CreateHandlerAndAddToWindow(IElement view, Func { - IWindow window = null; + IWindow window = CreateWindowForContent(view); var application = mauiContext.Services.GetService(); - if (view is IWindow w) - { - window = w; - } - else if (view is Page page) - { - window = new Controls.Window(page); - } - else - { - window = new Controls.Window(new ContentPage() { Content = (View)view }); - } - if (application is ApplicationStub appStub) { appStub.SetWindow((Window)window); @@ -150,6 +142,9 @@ await SetupWindowForTests(window, async () => { IView content = window.Content; + if (content is FlyoutPage fp) + content = fp.Detail; + if (content is IPageContainer pc) { content = pc.CurrentPage; @@ -180,6 +175,8 @@ await SetupWindowForTests(window, async () => await action((THandler)window.Content.Handler); else if (window.Content is ContentPage cp && typeof(THandler).IsAssignableFrom(cp.Content.Handler.GetType())) await action((THandler)cp.Content.Handler); + else if (typeof(THandler).IsAssignableFrom(typeof(WindowHandler))) + throw new Exception($"Use IWindowHandler instead of WindowHandler for CreateHandlerAndAddToWindow"); else throw new Exception($"I can't work with {typeof(THandler)}"); diff --git a/src/Controls/tests/DeviceTests/Elements/Entry/EntryTests.iOS.cs b/src/Controls/tests/DeviceTests/Elements/Entry/EntryTests.iOS.cs index e6612ac553c3..d9725e5f9a0d 100644 --- a/src/Controls/tests/DeviceTests/Elements/Entry/EntryTests.iOS.cs +++ b/src/Controls/tests/DeviceTests/Elements/Entry/EntryTests.iOS.cs @@ -1,6 +1,11 @@ using System.Threading.Tasks; +using Microsoft.Maui.Controls; +using Microsoft.Maui.DeviceTests.TestCases; using Microsoft.Maui.Handlers; +using Microsoft.Maui.Hosting; +using Microsoft.Maui.Platform; using UIKit; +using Xunit; namespace Microsoft.Maui.DeviceTests { @@ -36,5 +41,56 @@ int GetPlatformSelectionLength(EntryHandler entryHandler) return -1; } + + [Category(TestCategory.Entry)] + [Collection(ControlsHandlerTestBase.RunInNewWindowCollection)] + public partial class EntryTestsWithWindow : ControlsHandlerTestBase + { + [Theory] + [ClassData(typeof(ControlsPageTypesTestCases))] + public async Task NextMovesToNextEntry(string page) + { + EnsureHandlerCreated(builder => + { + ControlsPageTypesTestCases.Setup(builder); + builder.ConfigureMauiHandlers(handlers => + { + handlers.AddHandler(typeof(Entry), typeof(EntryHandler)); + }); + }); + + var entry1 = new Entry + { + Text = "Entry 1", + ReturnType = ReturnType.Next + }; + + var entry2 = new Entry + { + Text = "Entry 2", + ReturnType = ReturnType.Next + }; + + ContentPage contentPage = new ContentPage() + { + Content = new VerticalStackLayout() + { + entry1, + entry2 + } + }; + + Page rootPage = ControlsPageTypesTestCases.CreatePageType(page, contentPage); + Page hostPage = new ContentPage(); + + await CreateHandlerAndAddToWindow(hostPage, async () => + { + await hostPage.Navigation.PushModalAsync(rootPage); + KeyboardAutoManager.GoToNextResponderOrResign(entry1.ToPlatform()); + await AssertionExtensions.Wait(() => entry2.IsFocused); + Assert.True(entry2.IsFocused); + }); + } + } } -} +} \ No newline at end of file diff --git a/src/Controls/tests/DeviceTests/Elements/Frame/FrameHandlerTest.Android.cs b/src/Controls/tests/DeviceTests/Elements/Frame/FrameHandlerTest.Android.cs index 587891f74cf4..f05babfdc875 100644 --- a/src/Controls/tests/DeviceTests/Elements/Frame/FrameHandlerTest.Android.cs +++ b/src/Controls/tests/DeviceTests/Elements/Frame/FrameHandlerTest.Android.cs @@ -1,4 +1,8 @@ using System.Threading.Tasks; +using Java.Lang; +using Microsoft.Maui.Controls; +using Xunit; +using Xunit.Sdk; namespace Microsoft.Maui.DeviceTests { @@ -21,5 +25,23 @@ public override Task ContainerViewRemainsIfShadowMapperRunsAgain() // https://github.com/dotnet/maui/pull/12218 return Task.CompletedTask; } + + public override async Task ReturnsNonEmptyNativeBoundingBox(int size) + { + // Frames have a legacy hard-coded minimum size of 20x20 + var expectedSize = Math.Max(20, size); + var expectedBounds = new Graphics.Rect(0, 0, expectedSize, expectedSize); + + var view = new Frame() + { + HeightRequest = size, + WidthRequest = size + }; + + var nativeBoundingBox = await GetValueAsync(view, handler => GetBoundingBox(handler)); + Assert.NotEqual(nativeBoundingBox, Graphics.Rect.Zero); + + AssertWithinTolerance(expectedBounds.Size, nativeBoundingBox.Size); + } } } diff --git a/src/Controls/tests/DeviceTests/Elements/Frame/FrameTests.cs b/src/Controls/tests/DeviceTests/Elements/Frame/FrameTests.cs index b6d53fd92f4d..23bfd0e4366a 100644 --- a/src/Controls/tests/DeviceTests/Elements/Frame/FrameTests.cs +++ b/src/Controls/tests/DeviceTests/Elements/Frame/FrameTests.cs @@ -91,30 +91,7 @@ public async Task FrameWithEntryMeasuresCorrectly() } }; - var layoutFrame = - await InvokeOnMainThreadAsync(() => - layout.ToPlatform(MauiContext).AttachAndRun(async () => - { - var size = (layout as IView).Measure(double.PositiveInfinity, double.PositiveInfinity); - (layout as IView).Arrange(new Graphics.Rect(0, 0, size.Width, size.Height)); - - await OnFrameSetToNotEmpty(layout); - await OnFrameSetToNotEmpty(frame); - - // verify that the PlatformView was measured - var frameControlSize = (frame.Handler as IPlatformViewHandler).PlatformView.GetBoundingBox(); - Assert.True(frameControlSize.Width > 0); - Assert.True(frameControlSize.Width > 0); - - // if the control sits inside a container make sure that also measured - var containerControlSize = frame.ToPlatform().GetBoundingBox(); - Assert.True(frameControlSize.Width > 0); - Assert.True(frameControlSize.Width > 0); - - return layout.Frame; - - }) - ); + var layoutFrame = await LayoutFrame(layout, frame, double.PositiveInfinity, double.PositiveInfinity); Assert.True(entry.Width > 0); Assert.True(entry.Height > 0); @@ -187,5 +164,92 @@ await InvokeOnMainThreadAsync(() => platformView.AssertContainsColor(expectedColor); }); } + + [Fact(DisplayName = "Frame Respects minimum height/width")] + public async Task FrameRespectsMinimums() + { + SetupBuilder(); + + var content = new Button { Text = "Hey", WidthRequest = 50, HeightRequest = 50 }; + + var frame = new Frame() + { + Content = content, + MinimumHeightRequest = 100, + MinimumWidthRequest = 100, + VerticalOptions = LayoutOptions.Start, + HorizontalOptions = LayoutOptions.Start + }; + + var layout = new StackLayout() + { + Children = + { + frame + } + }; + + var layoutFrame = await LayoutFrame(layout, frame, 500, 500); + + Assert.True(100 <= layoutFrame.Height); + Assert.True(100 <= layoutFrame.Width); + } + + [Fact] + public async Task FrameDoesNotInterpretConstraintsAsMinimums() + { + SetupBuilder(); + + var content = new Button { Text = "Hey", WidthRequest = 50, HeightRequest = 50 }; + + var frame = new Frame() + { + Content = content, + MinimumHeightRequest = 100, + MinimumWidthRequest = 100, + VerticalOptions = LayoutOptions.Start, + HorizontalOptions = LayoutOptions.Start + }; + + var layout = new StackLayout() + { + Children = + { + frame + } + }; + + var layoutFrame = await LayoutFrame(layout, frame, 500, 500); + + Assert.True(500 > layoutFrame.Width); + Assert.True(500 > layoutFrame.Height); + } + + async Task LayoutFrame(Layout layout, Frame frame, double measureWidth, double measureHeight) + { + return await InvokeOnMainThreadAsync(() => + layout.ToPlatform(MauiContext).AttachAndRun(async () => + { + var size = (layout as IView).Measure(measureWidth, measureHeight); + (layout as IView).Arrange(new Graphics.Rect(0, 0, size.Width, size.Height)); + + await OnFrameSetToNotEmpty(layout); + await OnFrameSetToNotEmpty(frame); + + // verify that the PlatformView was measured + var frameControlSize = (frame.Handler as IPlatformViewHandler).PlatformView.GetBoundingBox(); + Assert.True(frameControlSize.Width > 0); + Assert.True(frameControlSize.Width > 0); + + // if the control sits inside a container make sure that also measured + var containerControlSize = frame.ToPlatform().GetBoundingBox(); + Assert.True(frameControlSize.Width > 0); + Assert.True(frameControlSize.Width > 0); + + return layout.Frame; + + }) + ); + } } } diff --git a/src/Controls/tests/DeviceTests/Extensions.cs b/src/Controls/tests/DeviceTests/Extensions.cs index ef609a204bc2..b20b0b9bbd59 100644 --- a/src/Controls/tests/DeviceTests/Extensions.cs +++ b/src/Controls/tests/DeviceTests/Extensions.cs @@ -1,6 +1,18 @@ using System; using System.Threading.Tasks; using Microsoft.Maui.Controls; +using Microsoft.Maui.Controls.Handlers; +using Microsoft.Maui.Controls.Hosting; +using Microsoft.Maui.Devices; +using Microsoft.Maui.DeviceTests.Stubs; +using Microsoft.Maui.Graphics; +using Microsoft.Maui.Handlers; +using Microsoft.Maui.Hosting; +using Microsoft.Maui.Platform; +using Xunit; +#if ANDROID || IOS || MACCATALYST +using ShellHandler = Microsoft.Maui.Controls.Handlers.Compatibility.ShellRenderer; +#endif namespace Microsoft.Maui.DeviceTests { @@ -8,6 +20,32 @@ public static class Extensions { public static Task Wait(this Image image, int timeout = 1000) => AssertionExtensions.Wait(() => !image.IsLoading, timeout); + + public static void SetupShellHandlers(this MauiAppBuilder builder) + { + builder.ConfigureMauiHandlers(SetupShellHandlers); + } + + public static void SetupShellHandlers(this IMauiHandlersCollection handlers) + { + handlers.TryAddHandler(typeof(Controls.Shell), typeof(ShellHandler)); + handlers.TryAddHandler(); + handlers.TryAddHandler(); + handlers.TryAddHandler(); + handlers.TryAddHandler(); + handlers.TryAddHandler(typeof(Toolbar), typeof(ToolbarHandler)); + handlers.TryAddHandler(typeof(MenuBar), typeof(MenuBarHandler)); + handlers.TryAddHandler(typeof(MenuBarItem), typeof(MenuBarItemHandler)); + handlers.TryAddHandler(typeof(MenuFlyoutItem), typeof(MenuFlyoutItemHandler)); + handlers.TryAddHandler(typeof(MenuFlyoutSubItem), typeof(MenuFlyoutSubItemHandler)); + handlers.TryAddHandler(); + +#if WINDOWS + handlers.TryAddHandler(typeof(ShellItem), typeof(ShellItemHandler)); + handlers.TryAddHandler(typeof(ShellSection), typeof(ShellSectionHandler)); + handlers.TryAddHandler(typeof(ShellContent), typeof(ShellContentHandler)); +#endif + } } } diff --git a/src/Controls/tests/DeviceTests/TestCases/ControlsPageTypesTestCases.cs b/src/Controls/tests/DeviceTests/TestCases/ControlsPageTypesTestCases.cs new file mode 100644 index 000000000000..0e6de1d421bb --- /dev/null +++ b/src/Controls/tests/DeviceTests/TestCases/ControlsPageTypesTestCases.cs @@ -0,0 +1,77 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.Maui.Controls; +using Microsoft.Maui.Controls.Handlers.Compatibility; +using Microsoft.Maui.DeviceTests.Stubs; +using Microsoft.Maui.Handlers; +using Microsoft.Maui.Hosting; + +#if IOS || MACCATALYST +using FlyoutViewHandler = Microsoft.Maui.Controls.Handlers.Compatibility.PhoneFlyoutPageRenderer; +#endif + +namespace Microsoft.Maui.DeviceTests.TestCases +{ + public class ControlsPageTypesTestCases : IEnumerable + { + private readonly List _data = new() + { + new object[] { nameof(FlyoutPage) }, + new object[] { nameof(TabbedPage) }, + new object[] { nameof(ContentPage) }, + new object[] { nameof(Shell) }, + new object[] { nameof(NavigationPage) }, + }; + + public IEnumerator GetEnumerator() => _data.GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + + public static Page CreatePageType(string name, Page content) + { + switch (name) + { + case nameof(FlyoutPage): + content.Title = content.Title ?? "Detail Title"; + return new FlyoutPage() { Flyout = new ContentPage() { Title = "title" }, Detail = content }; + case nameof(TabbedPage): + return new TabbedPage() { Children = { content } }; + case nameof(ContentPage): + return content; + case nameof(Shell): + return new Shell() { CurrentItem = (ContentPage)content }; + case nameof(NavigationPage): + return new NavigationPage(content); + } + + throw new Exception($"{name} not found"); + } + + public static void Setup(MauiAppBuilder builder) + { + builder.ConfigureMauiHandlers(handlers => + { + handlers.SetupShellHandlers(); + + handlers.AddHandler(typeof(Controls.Label), typeof(LabelHandler)); + handlers.AddHandler(typeof(Controls.Toolbar), typeof(ToolbarHandler)); + handlers.AddHandler(typeof(FlyoutPage), typeof(FlyoutViewHandler)); +#if IOS || MACCATALYST + handlers.AddHandler(typeof(TabbedPage), typeof(TabbedRenderer)); + handlers.AddHandler(typeof(NavigationPage), typeof(NavigationRenderer)); +#else + handlers.AddHandler(typeof(TabbedPage), typeof(TabbedViewHandler)); + handlers.AddHandler(typeof(NavigationPage), typeof(NavigationViewHandler)); +#endif + handlers.AddHandler(); + handlers.AddHandler(); + }); + } + } +} \ No newline at end of file diff --git a/src/Core/tests/DeviceTests.Shared/HandlerTests/HandlerTestBaseOfT.Tests.cs b/src/Core/tests/DeviceTests.Shared/HandlerTests/HandlerTestBaseOfT.Tests.cs index 8e21d4bc0fbc..2bd0060b9b3f 100644 --- a/src/Core/tests/DeviceTests.Shared/HandlerTests/HandlerTestBaseOfT.Tests.cs +++ b/src/Core/tests/DeviceTests.Shared/HandlerTests/HandlerTestBaseOfT.Tests.cs @@ -8,6 +8,7 @@ using Microsoft.Maui.Hosting; using Microsoft.Maui.Media; using Xunit; +using Xunit.Sdk; namespace Microsoft.Maui.DeviceTests { @@ -244,7 +245,7 @@ public async Task ReturnsNonEmptyPlatformViewBounds(int size) Assert.NotEqual(platformViewBounds, new Graphics.Rect()); } - [Theory(DisplayName = "Native View Bounding Box are not empty" + [Theory(DisplayName = "Native View Bounding Box is not empty" #if WINDOWS , Skip = "https://github.com/dotnet/maui/issues/9054" #endif @@ -252,7 +253,7 @@ public async Task ReturnsNonEmptyPlatformViewBounds(int size) [InlineData(1)] [InlineData(100)] [InlineData(1000)] - public async Task ReturnsNonEmptyNativeBoundingBounds(int size) + public virtual async Task ReturnsNonEmptyNativeBoundingBox(int size) { var view = new TStub() { @@ -261,8 +262,7 @@ public async Task ReturnsNonEmptyNativeBoundingBounds(int size) }; var nativeBoundingBox = await GetValueAsync(view, handler => GetBoundingBox(handler)); - Assert.NotEqual(nativeBoundingBox, new Graphics.Rect()); - + Assert.NotEqual(nativeBoundingBox, Graphics.Rect.Zero); // Currently there's an issue with label/progress where they don't set the frame size to // the explicit Width and Height values set @@ -290,21 +290,29 @@ public async Task ReturnsNonEmptyNativeBoundingBounds(int size) #endif else if (view is IProgress) { - if (!CloseEnough(size, nativeBoundingBox.Size.Width)) - Assert.Equal(new Size(size, size), nativeBoundingBox.Size); + AssertWithinTolerance(size, nativeBoundingBox.Size.Width); } else { - if (!CloseEnough(size, nativeBoundingBox.Size.Height) || !CloseEnough(size, nativeBoundingBox.Size.Width)) - Assert.Equal(new Size(size, size), nativeBoundingBox.Size); + var expectedSize = new Size(size, size); + AssertWithinTolerance(expectedSize, nativeBoundingBox.Size); } + } - bool CloseEnough(double value1, double value2) + protected void AssertWithinTolerance(double expected, double actual, double tolerance = 0.2, string message = "Value was not within tolerance.") + { + var diff = System.Math.Abs(expected - actual); + if (diff > tolerance) { - return System.Math.Abs(value2 - value1) < 0.2; + throw new XunitException($"{message} Expected: {expected}; Actual: {actual}; Tolerance {tolerance}"); } } + protected void AssertWithinTolerance(Graphics.Size expected, Graphics.Size actual, double tolerance = 0.2) + { + AssertWithinTolerance(expected.Height, actual.Height, tolerance, "Height was not within tolerance."); + AssertWithinTolerance(expected.Width, actual.Width, tolerance, "Width was not within tolerance."); + } [Theory(DisplayName = "Native View Transforms are not empty" #if IOS diff --git a/src/Workload/Microsoft.Maui.Sdk/Sdk/BundledVersions.in.targets b/src/Workload/Microsoft.Maui.Sdk/Sdk/BundledVersions.in.targets index fb492322aea2..84b2ce27bef0 100644 --- a/src/Workload/Microsoft.Maui.Sdk/Sdk/BundledVersions.in.targets +++ b/src/Workload/Microsoft.Maui.Sdk/Sdk/BundledVersions.in.targets @@ -4,6 +4,13 @@ @VERSION@ @TFM@ $(MauiWorkloadVersion) + + + true