From 3f4d36590595cf176514ebbb9f7504f3f9eed561 Mon Sep 17 00:00:00 2001 From: Matthew Leibowitz Date: Fri, 7 Jun 2024 01:45:38 +0800 Subject: [PATCH 01/41] Size and SizeF should not throw on NaN --- src/Graphics/src/Graphics/Size.cs | 67 ++++++++-------------------- src/Graphics/src/Graphics/SizeF.cs | 71 +++++++++--------------------- 2 files changed, 38 insertions(+), 100 deletions(-) diff --git a/src/Graphics/src/Graphics/Size.cs b/src/Graphics/src/Graphics/Size.cs index 9b3aa45dace1..17265ef2ba2a 100644 --- a/src/Graphics/src/Graphics/Size.cs +++ b/src/Graphics/src/Graphics/Size.cs @@ -10,93 +10,62 @@ namespace Microsoft.Maui.Graphics [TypeConverter(typeof(Converters.SizeTypeConverter))] public partial struct Size { - double _width; - double _height; - public static readonly Size Zero; public Size(double size = 0) { - if (double.IsNaN(size)) - throw new ArgumentException("NaN is not a valid value for size"); - _width = size; - _height = size; + Width = size; + Height = size; } public Size(double width, double height) { - if (double.IsNaN(width)) - throw new ArgumentException("NaN is not a valid value for width"); - if (double.IsNaN(height)) - throw new ArgumentException("NaN is not a valid value for height"); - _width = width; - _height = height; + Width = width; + Height = height; } public Size(Vector2 vector) { - if (float.IsNaN(vector.X)) - throw new ArgumentException("NaN is not a valid value for X"); - if (float.IsNaN(vector.Y)) - throw new ArgumentException("NaN is not a valid value for Y"); - _width = vector.X; - _height = vector.Y; + Width = vector.X; + Height = vector.Y; } - public bool IsZero => _width == 0 && _height == 0; + public bool IsZero => Width == 0 && Height == 0; [DefaultValue(0d)] - public double Width - { - get => _width; - set - { - if (double.IsNaN(value)) - throw new ArgumentException("NaN is not a valid value for Width"); - _width = value; - } - } + public double Width { get; set; } [DefaultValue(0d)] - public double Height - { - get => _height; - set - { - if (double.IsNaN(value)) - throw new ArgumentException("NaN is not a valid value for Height"); - _height = value; - } - } + public double Height { get; set; } public static Size operator +(Size s1, Size s2) { - return new Size(s1._width + s2._width, s1._height + s2._height); + return new Size(s1.Width + s2.Width, s1.Height + s2.Height); } public static Size operator -(Size s1, Size s2) { - return new Size(s1._width - s2._width, s1._height - s2._height); + return new Size(s1.Width - s2.Width, s1.Height - s2.Height); } public static Size operator *(Size s1, double value) { - return new Size(s1._width * value, s1._height * value); + return new Size(s1.Width * value, s1.Height * value); } public static Size operator /(Size s1, double value) { - return new Size(s1._width / value, s1._height / value); + return new Size(s1.Width / value, s1.Height / value); } public static bool operator ==(Size s1, Size s2) { - return s1._width == s2._width && s1._height == s2._height; + return s1.Width == s2.Width && s1.Height == s2.Height; } public static bool operator !=(Size s1, Size s2) { - return s1._width != s2._width || s1._height != s2._height; + return s1.Width != s2.Width || s1.Height != s2.Height; } public static explicit operator Point(Size size) @@ -106,7 +75,7 @@ public static explicit operator Point(Size size) public bool Equals(Size other) { - return _width.Equals(other._width) && _height.Equals(other._height); + return Width.Equals(other.Width) && Height.Equals(other.Height); } public override bool Equals(object obj) @@ -120,13 +89,13 @@ public override int GetHashCode() { unchecked { - return (_width.GetHashCode() * 397) ^ _height.GetHashCode(); + return (Width.GetHashCode() * 397) ^ Height.GetHashCode(); } } public override string ToString() { - return string.Format("{{Width={0} Height={1}}}", _width.ToString(CultureInfo.InvariantCulture), _height.ToString(CultureInfo.InvariantCulture)); + return string.Format("{{Width={0} Height={1}}}", Width.ToString(CultureInfo.InvariantCulture), Height.ToString(CultureInfo.InvariantCulture)); } public void Deconstruct(out double width, out double height) diff --git a/src/Graphics/src/Graphics/SizeF.cs b/src/Graphics/src/Graphics/SizeF.cs index d032288c28c9..21fa69fb9aa9 100644 --- a/src/Graphics/src/Graphics/SizeF.cs +++ b/src/Graphics/src/Graphics/SizeF.cs @@ -10,64 +10,33 @@ namespace Microsoft.Maui.Graphics [TypeConverter(typeof(Converters.SizeFTypeConverter))] public partial struct SizeF { - float _width; - float _height; - public static readonly SizeF Zero; public SizeF(float size = 0) { - if (float.IsNaN(size)) - throw new ArgumentException("NaN is not a valid value for size"); - _width = size; - _height = size; + Width = size; + Height = size; } public SizeF(float width, float height) { - if (float.IsNaN(width)) - throw new ArgumentException("NaN is not a valid value for width"); - if (float.IsNaN(height)) - throw new ArgumentException("NaN is not a valid value for height"); - _width = width; - _height = height; + Width = width; + Height = height; } public SizeF(Vector2 vector) { - if (float.IsNaN(vector.X)) - throw new ArgumentException("NaN is not a valid value for X"); - if (float.IsNaN(vector.Y)) - throw new ArgumentException("NaN is not a valid value for Y"); - _width = vector.X; - _height = vector.Y; + Width = vector.X; + Height = vector.Y; } - public bool IsZero => _width == 0 && _height == 0; + public bool IsZero => Width == 0 && Height == 0; - [DefaultValue(0d)] - public float Width - { - get => _width; - set - { - if (float.IsNaN(value)) - throw new ArgumentException("NaN is not a valid value for Width"); - _width = value; - } - } + [DefaultValue(0f)] + public float Width { get; set; } - [DefaultValue(0d)] - public float Height - { - get => _height; - set - { - if (float.IsNaN(value)) - throw new ArgumentException("NaN is not a valid value for Height"); - _height = value; - } - } + [DefaultValue(0f)] + public float Height { get; set; } public SizeF TransformNormalBy(in Matrix3x2 transform) { @@ -76,32 +45,32 @@ public SizeF TransformNormalBy(in Matrix3x2 transform) public static SizeF operator +(SizeF s1, SizeF s2) { - return new SizeF(s1._width + s2._width, s1._height + s2._height); + return new SizeF(s1.Width + s2.Width, s1.Height + s2.Height); } public static SizeF operator -(SizeF s1, SizeF s2) { - return new SizeF(s1._width - s2._width, s1._height - s2._height); + return new SizeF(s1.Width - s2.Width, s1.Height - s2.Height); } public static SizeF operator *(SizeF s1, float value) { - return new SizeF(s1._width * value, s1._height * value); + return new SizeF(s1.Width * value, s1.Height * value); } public static SizeF operator /(SizeF s1, float value) { - return new SizeF(s1._width / value, s1._height / value); + return new SizeF(s1.Width / value, s1.Height / value); } public static bool operator ==(SizeF s1, SizeF s2) { - return s1._width == s2._width && s1._height == s2._height; + return s1.Width == s2.Width && s1.Height == s2.Height; } public static bool operator !=(SizeF s1, SizeF s2) { - return s1._width != s2._width || s1._height != s2._height; + return s1.Width != s2.Width || s1.Height != s2.Height; } public static explicit operator PointF(SizeF size) @@ -121,7 +90,7 @@ public static explicit operator SizeF(Vector2 size) public bool Equals(SizeF other) { - return _width.Equals(other._width) && _height.Equals(other._height); + return Width.Equals(other.Width) && Height.Equals(other.Height); } public override bool Equals(object obj) @@ -135,13 +104,13 @@ public override int GetHashCode() { unchecked { - return (_width.GetHashCode() * 397) ^ _height.GetHashCode(); + return (Width.GetHashCode() * 397) ^ Height.GetHashCode(); } } public override string ToString() { - return string.Format("{{Width={0} Height={1}}}", _width.ToString(CultureInfo.InvariantCulture), _height.ToString(CultureInfo.InvariantCulture)); + return string.Format("{{Width={0} Height={1}}}", Width.ToString(CultureInfo.InvariantCulture), Height.ToString(CultureInfo.InvariantCulture)); } public void Deconstruct(out float width, out float height) From 83d55ad0756e3238585fb97e5fe7f0c4e5e517f3 Mon Sep 17 00:00:00 2001 From: Shane Neuville Date: Sun, 9 Jun 2024 11:18:57 -0500 Subject: [PATCH 02/41] Fix Release Versioning --- eng/Versions.props | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/eng/Versions.props b/eng/Versions.props index 10dfe1deabee..05542fff637d 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -6,10 +6,11 @@ 0 60 8.0.100 + servicing true - true + true release -$(PreReleaseVersionLabel) -$(PreReleaseVersionLabel).$(PreReleaseVersionIteration) From df0d35311e68ca17fc37b429170fc280ddacb29e Mon Sep 17 00:00:00 2001 From: MartyIX <203266+MartyIX@users.noreply.github.com> Date: Wed, 12 Jun 2024 09:58:22 +0200 Subject: [PATCH 03/41] Upgrade from 1.5.1 to 1.5.4 --- eng/Versions.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eng/Versions.props b/eng/Versions.props index 0183e3e48eba..922ed2da6856 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -60,7 +60,7 @@ 8.0.0 - 1.5.240311000 + 1.5.240607001 10.0.22621.756 1.2.0 From b01e16389d30a6b894e2dc964320b7d7350b5d7b Mon Sep 17 00:00:00 2001 From: Jakub Florkowski <42434498+kubaflo@users.noreply.github.com> Date: Wed, 12 Jun 2024 20:21:33 +0200 Subject: [PATCH 04/41] SwipeView Fix #22580 (#22741) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Javier Suárez --- .../src/Core/SwipeView/SwipeView.Mapper.cs | 39 +++++++++++++++++++ .../Xaml/Hosting/AppHostBuilderExtensions.cs | 1 + 2 files changed, 40 insertions(+) create mode 100644 src/Controls/src/Core/SwipeView/SwipeView.Mapper.cs diff --git a/src/Controls/src/Core/SwipeView/SwipeView.Mapper.cs b/src/Controls/src/Core/SwipeView/SwipeView.Mapper.cs new file mode 100644 index 000000000000..1b1f918451d6 --- /dev/null +++ b/src/Controls/src/Core/SwipeView/SwipeView.Mapper.cs @@ -0,0 +1,39 @@ +using System; +using Microsoft.Maui.Controls.Compatibility; + +namespace Microsoft.Maui.Controls +{ + public partial class SwipeView + { + [Obsolete("Use SwipeViewHandler.Mapper instead.")] + internal static IPropertyMapper ControlsSwipeMapper = + new ControlsMapper(SwipeViewHandler.Mapper); + + internal static new void RemapForControls() + { + // Adjusted the mapping to preserve SwipeView.Entry legacy behavior + SwipeViewHandler.Mapper.AppendToMapping(nameof(Background), MapBackground); + } + + static void MapBackground(ISwipeViewHandler handler, SwipeView swipeView) + { + if (swipeView.Content is not null) + { + var contentBackgroundIsNull = Brush.IsNullOrEmpty(swipeView.Content.Background); + var contentBackgroundColorIsNull = swipeView.Content.BackgroundColor == null; + + if (contentBackgroundIsNull && contentBackgroundColorIsNull) + { + if (!Brush.IsNullOrEmpty(swipeView.Background)) + { + swipeView.Content.Background = swipeView.Background; + } + else if (swipeView.BackgroundColor != null) + { + swipeView.Content.BackgroundColor = swipeView.BackgroundColor; + } + } + } + } + } +} diff --git a/src/Controls/src/Xaml/Hosting/AppHostBuilderExtensions.cs b/src/Controls/src/Xaml/Hosting/AppHostBuilderExtensions.cs index 50eeb913fc75..c7a02e335a49 100644 --- a/src/Controls/src/Xaml/Hosting/AppHostBuilderExtensions.cs +++ b/src/Controls/src/Xaml/Hosting/AppHostBuilderExtensions.cs @@ -242,6 +242,7 @@ internal static MauiAppBuilder RemapForControls(this MauiAppBuilder builder) Window.RemapForControls(); Editor.RemapForControls(); Entry.RemapForControls(); + SwipeView.RemapForControls(); Picker.RemapForControls(); SearchBar.RemapForControls(); TabbedPage.RemapForControls(); From 8497dee9be3929c51d65a644bc1bdd110af78455 Mon Sep 17 00:00:00 2001 From: redth Date: Thu, 13 Jun 2024 09:49:33 -0700 Subject: [PATCH 05/41] Update vscode extension recommendations --- .vscode/extensions.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 4930f5b8a0c4..45d0d17ffd51 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -1,7 +1,7 @@ { "recommendations": [ - "ms-dotnettools.csharp", - "ms-vscode.mono-debug", - "visualstudioexptteam.vscodeintellicode", + "ms-dotnettools.vscodeintellicode-csharp", + "ms-dotnettools.dotnet-maui", + "github.copilot-chat" ] } \ No newline at end of file From 79695fbb7ba6517a334c795ecf0a1d6358ef309a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Rozs=C3=ADval?= Date: Fri, 14 Jun 2024 00:01:57 +0200 Subject: [PATCH 06/41] [XC] Fix SimplifyTypeExtensionVisitor (#23043) * Add test * Fix the visitor --- .../src/Xaml/SimplifyTypeExtensionVisitor.cs | 24 ++++--- .../Xaml.UnitTests/Issues/Maui21757_2.xaml | 20 ++++++ .../Xaml.UnitTests/Issues/Maui21757_2.xaml.cs | 70 +++++++++++++++++++ 3 files changed, 105 insertions(+), 9 deletions(-) create mode 100644 src/Controls/tests/Xaml.UnitTests/Issues/Maui21757_2.xaml create mode 100644 src/Controls/tests/Xaml.UnitTests/Issues/Maui21757_2.xaml.cs diff --git a/src/Controls/src/Xaml/SimplifyTypeExtensionVisitor.cs b/src/Controls/src/Xaml/SimplifyTypeExtensionVisitor.cs index 02a5139de95b..491b13c35074 100644 --- a/src/Controls/src/Xaml/SimplifyTypeExtensionVisitor.cs +++ b/src/Controls/src/Xaml/SimplifyTypeExtensionVisitor.cs @@ -55,16 +55,22 @@ static bool IsTargetTypePropertyOfMauiType(INode parentNode, XmlName propertyNam static bool IsTypeExtension(ElementNode node, out ValueNode typeNameValueNode) { - XmlName typeNameXmlName = new("", "TypeName"); - - if (node.XmlType.Name == nameof(TypeExtension) - && node.XmlType.NamespaceUri == XamlParser.X2009Uri - && node.Properties.ContainsKey(typeNameXmlName) - && node.Properties[typeNameXmlName] is ValueNode valueNode - && valueNode.Value is string) + if (node.XmlType.Name == nameof(TypeExtension) && node.XmlType.NamespaceUri == XamlParser.X2009Uri) { - typeNameValueNode = valueNode; - return true; + XmlName typeNameXmlName = new("", "TypeName"); + if (node.Properties.ContainsKey(typeNameXmlName) + && node.Properties[typeNameXmlName] is ValueNode { Value: string } propertyValueNode) + { + typeNameValueNode = propertyValueNode; + return true; + } + + if (node.CollectionItems.Count == 1 + && node.CollectionItems[0] is ValueNode { Value: string } collectionValueNode) + { + typeNameValueNode = collectionValueNode; + return true; + } } typeNameValueNode = null; diff --git a/src/Controls/tests/Xaml.UnitTests/Issues/Maui21757_2.xaml b/src/Controls/tests/Xaml.UnitTests/Issues/Maui21757_2.xaml new file mode 100644 index 000000000000..849a660a0f38 --- /dev/null +++ b/src/Controls/tests/Xaml.UnitTests/Issues/Maui21757_2.xaml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Controls/tests/Xaml.UnitTests/Issues/Maui21757_2.xaml.cs b/src/Controls/tests/Xaml.UnitTests/Issues/Maui21757_2.xaml.cs new file mode 100644 index 000000000000..d964e36f1b87 --- /dev/null +++ b/src/Controls/tests/Xaml.UnitTests/Issues/Maui21757_2.xaml.cs @@ -0,0 +1,70 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Globalization; +using System.Linq; +using Microsoft.Maui.ApplicationModel; +using Microsoft.Maui.Controls.Core.UnitTests; +using Microsoft.Maui.Controls.Shapes; +using Microsoft.Maui.Devices; +using Microsoft.Maui.Dispatching; + +using Microsoft.Maui.Graphics; +using Microsoft.Maui.UnitTests; +using NUnit.Framework; + +namespace Microsoft.Maui.Controls.Xaml.UnitTests; + +[XamlCompilation(XamlCompilationOptions.Skip)] +public partial class Maui21757_2 +{ + public Maui21757_2() + { + InitializeComponent(); + } + + public Maui21757_2(bool useCompiledXaml) + { + //this stub will be replaced at compile time + } + + [TestFixture] + class Test + { + [SetUp] + public void Setup() + { + Application.SetCurrentApplication(new MockApplication()); + DispatcherProvider.SetCurrent(new DispatcherProviderStub()); + } + + [TearDown] public void TearDown() => AppInfo.SetCurrent(null); + + [Test] + public void TypeLiteralAndXTypeCanBeUsedInterchangeably() + { + Assert.DoesNotThrow(() => MockCompiler.Compile(typeof(Maui21757_2))); + } + } +} + +public class ViewModelMainPage21757_2 +{ + public List TestList { get; set; } + + public ViewModelMainPage21757_2() + { + TestList = new List() + { + new ViewModelTest21757_2() { TestValue = 0 }, + new ViewModelTest21757_2() { TestValue = 1 }, + new ViewModelTest21757_2() { TestValue = 2 }, + new ViewModelTest21757_2() { TestValue = 3 } + }; + } +} + +public class ViewModelTest21757_2 +{ + public int TestValue { get; set; } +} \ No newline at end of file From 3143629c3c607b148ea199b7d67705ed8991edc6 Mon Sep 17 00:00:00 2001 From: Shane Neuville Date: Sat, 15 Jun 2024 07:23:21 -0500 Subject: [PATCH 07/41] Add SR6 to issue template (#23071) --- .github/ISSUE_TEMPLATE/bug-report.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/ISSUE_TEMPLATE/bug-report.yml b/.github/ISSUE_TEMPLATE/bug-report.yml index ba8454f62a00..da107f057221 100644 --- a/.github/ISSUE_TEMPLATE/bug-report.yml +++ b/.github/ISSUE_TEMPLATE/bug-report.yml @@ -49,6 +49,7 @@ body: - 9.0.0-preview.3.10457 - 9.0.0-preview.2.10293 - 9.0.0-preview.1.9973 + - 8.0.60 SR6 - 8.0.40 SR5 - 8.0.21 SR4.1 - 8.0.20 SR4 @@ -111,6 +112,7 @@ body: - 8.0.20 SR4 - 8.0.21 SR4.1 - 8.0.40 SR5 + - 8.0.60 SR6 - 9.0.0-preview.1.9973 - 9.0.0-preview.2.10293 - 9.0.0-preview.3.10457 From 4fabb3eb2eef4a1c81664f9696e25c1cd434ae93 Mon Sep 17 00:00:00 2001 From: Matthew Leibowitz Date: Mon, 17 Jun 2024 21:29:43 +0800 Subject: [PATCH 08/41] Make sure the main branch is using .NET 8 SDK (#23077) * Make sure the main branch is using .NET 8 SDK The main branch needs to use the .NET 8 SDK because we are building the .NET 7 TFMs as well. The .NET 9 SDK does not support .NET 7 TFMs anymore. * no previews! --- global.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/global.json b/global.json index 2b3c65d222ba..d05a39062b91 100644 --- a/global.json +++ b/global.json @@ -6,5 +6,8 @@ "MSBuild.Sdk.Extras": "3.0.44", "Microsoft.Build.NoTargets": "3.7.0", "Microsoft.DotNet.Arcade.Sdk": "8.0.0-beta.24310.5" + }, + "sdk": { + "allowPrerelease": false } } From b998447d1d72b460664aa8cae94f2f58bda62ff7 Mon Sep 17 00:00:00 2001 From: Shane Neuville Date: Mon, 17 Jun 2024 14:33:54 -0500 Subject: [PATCH 09/41] Setup preview versioning for SR6.1 --- eng/Versions.props | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/eng/Versions.props b/eng/Versions.props index 05542fff637d..a0fb11dc710f 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -1,16 +1,16 @@ - 8.0.60 + 8.0.61 8 0 - 60 + 61 8.0.100 - servicing + ci.net8 true - true + false release -$(PreReleaseVersionLabel) -$(PreReleaseVersionLabel).$(PreReleaseVersionIteration) From 05116cff93d782b743074c3d0b264e744d998a05 Mon Sep 17 00:00:00 2001 From: redth Date: Mon, 17 Jun 2024 15:50:27 -0400 Subject: [PATCH 10/41] Remove compat appium tests Since we're moving in a different direction for moving these over in #22635 these projects (and the Issue11853 test, since it's in the other PR) can be deleted. --- Microsoft.Maui.sln | 7 - ...ntrolGallery.Android.Appium.UITests.csproj | 43 ----- .../PlatformSpecificSampleTest.cs | 16 -- .../AppiumServerHelper.cs | 33 ---- ...ontrolGallery.Shared.Appium.UITests.csproj | 36 ---- .../Shared.Appium.UITests/GalleryQueries.cs | 30 --- .../Shared.Appium.UITests/IssuesUITest.cs | 63 ------- .../TestContextSetupFixture.cs | 17 -- .../test/Shared.Appium.UITests/TestDevice.cs | 10 - .../Tests/Issues/Issue11853.cs | 32 ---- .../test/Shared.Appium.UITests/UITest.cs | 169 ----------------- .../test/Shared.Appium.UITests/UITestBase.cs | 175 ------------------ .../Shared.Appium.UITests/UITestCategories.cs | 68 ------- .../UITestContextBase.cs | 91 --------- .../Shared.Appium.UITests/UITestExtensions.cs | 90 --------- .../UITestIgnoreAttributes.cs | 112 ----------- .../VisualTestContext.cs | 11 -- .../ControlGallery.iOS.Appium.UITests.csproj | 39 ---- .../PlatformSpecificSampleTest.cs | 16 -- 19 files changed, 1058 deletions(-) delete mode 100644 src/Compatibility/ControlGallery/test/Android.Appium.UITests/ControlGallery.Android.Appium.UITests.csproj delete mode 100644 src/Compatibility/ControlGallery/test/Android.Appium.UITests/PlatformSpecificSampleTest.cs delete mode 100644 src/Compatibility/ControlGallery/test/Shared.Appium.UITests/AppiumServerHelper.cs delete mode 100644 src/Compatibility/ControlGallery/test/Shared.Appium.UITests/ControlGallery.Shared.Appium.UITests.csproj delete mode 100644 src/Compatibility/ControlGallery/test/Shared.Appium.UITests/GalleryQueries.cs delete mode 100644 src/Compatibility/ControlGallery/test/Shared.Appium.UITests/IssuesUITest.cs delete mode 100644 src/Compatibility/ControlGallery/test/Shared.Appium.UITests/TestContextSetupFixture.cs delete mode 100644 src/Compatibility/ControlGallery/test/Shared.Appium.UITests/TestDevice.cs delete mode 100644 src/Compatibility/ControlGallery/test/Shared.Appium.UITests/Tests/Issues/Issue11853.cs delete mode 100644 src/Compatibility/ControlGallery/test/Shared.Appium.UITests/UITest.cs delete mode 100644 src/Compatibility/ControlGallery/test/Shared.Appium.UITests/UITestBase.cs delete mode 100644 src/Compatibility/ControlGallery/test/Shared.Appium.UITests/UITestCategories.cs delete mode 100644 src/Compatibility/ControlGallery/test/Shared.Appium.UITests/UITestContextBase.cs delete mode 100644 src/Compatibility/ControlGallery/test/Shared.Appium.UITests/UITestExtensions.cs delete mode 100644 src/Compatibility/ControlGallery/test/Shared.Appium.UITests/UITestIgnoreAttributes.cs delete mode 100644 src/Compatibility/ControlGallery/test/Shared.Appium.UITests/VisualTestContext.cs delete mode 100644 src/Compatibility/ControlGallery/test/iOS.Appium.UITests/ControlGallery.iOS.Appium.UITests.csproj delete mode 100644 src/Compatibility/ControlGallery/test/iOS.Appium.UITests/PlatformSpecificSampleTest.cs diff --git a/Microsoft.Maui.sln b/Microsoft.Maui.sln index 934382686cc2..3152be870542 100644 --- a/Microsoft.Maui.sln +++ b/Microsoft.Maui.sln @@ -257,8 +257,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ControlGallery.Android.Appi EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ControlGallery.iOS.Appium.UITests", "src\Compatibility\ControlGallery\test\iOS.Appium.UITests\ControlGallery.iOS.Appium.UITests.csproj", "{5923B35B-EA24-4B86-A384-9DAF9F2AFD56}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ControlGallery.Shared.Appium.UITests", "src\Compatibility\ControlGallery\test\Shared.Appium.UITests\ControlGallery.Shared.Appium.UITests.csproj", "{07D8D4B5-C89D-4BE3-A14A-17668358587C}" -EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{6730CE13-8567-4DC8-B2AF-B12C39818825}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Compatibility.Core.UnitTests", "src\Compatibility\Core\tests\Compatibility.UnitTests\Compatibility.Core.UnitTests.csproj", "{9F3DD0E7-8A71-4BA8-A3E6-690DC5A9F3D7}" @@ -668,10 +666,6 @@ Global {5923B35B-EA24-4B86-A384-9DAF9F2AFD56}.Debug|Any CPU.Build.0 = Debug|Any CPU {5923B35B-EA24-4B86-A384-9DAF9F2AFD56}.Release|Any CPU.ActiveCfg = Release|Any CPU {5923B35B-EA24-4B86-A384-9DAF9F2AFD56}.Release|Any CPU.Build.0 = Release|Any CPU - {07D8D4B5-C89D-4BE3-A14A-17668358587C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {07D8D4B5-C89D-4BE3-A14A-17668358587C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {07D8D4B5-C89D-4BE3-A14A-17668358587C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {07D8D4B5-C89D-4BE3-A14A-17668358587C}.Release|Any CPU.Build.0 = Release|Any CPU {9F3DD0E7-8A71-4BA8-A3E6-690DC5A9F3D7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {9F3DD0E7-8A71-4BA8-A3E6-690DC5A9F3D7}.Debug|Any CPU.Build.0 = Debug|Any CPU {9F3DD0E7-8A71-4BA8-A3E6-690DC5A9F3D7}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -819,7 +813,6 @@ Global {8050448A-E08F-4972-9B47-16042A5DFE82} = {7AC28763-9C68-4BF9-A1BA-25CBFFD2D15C} {F748974F-A8E4-4659-801C-804B739D6326} = {DDBA9144-36FC-429E-99E1-2A64825434C1} {5923B35B-EA24-4B86-A384-9DAF9F2AFD56} = {DDBA9144-36FC-429E-99E1-2A64825434C1} - {07D8D4B5-C89D-4BE3-A14A-17668358587C} = {DDBA9144-36FC-429E-99E1-2A64825434C1} {6730CE13-8567-4DC8-B2AF-B12C39818825} = {123AA89E-1638-4E0E-B828-B8F9F9F906A2} {9F3DD0E7-8A71-4BA8-A3E6-690DC5A9F3D7} = {6730CE13-8567-4DC8-B2AF-B12C39818825} {199777D4-0EA9-4AAB-82A0-0B53D4BA9E4B} = {25D0D27A-C5FE-443D-8B65-D6C987F4A80E} diff --git a/src/Compatibility/ControlGallery/test/Android.Appium.UITests/ControlGallery.Android.Appium.UITests.csproj b/src/Compatibility/ControlGallery/test/Android.Appium.UITests/ControlGallery.Android.Appium.UITests.csproj deleted file mode 100644 index 5d66c158ad15..000000000000 --- a/src/Compatibility/ControlGallery/test/Android.Appium.UITests/ControlGallery.Android.Appium.UITests.csproj +++ /dev/null @@ -1,43 +0,0 @@ - - - - $(_MauiDotNetTfm) - enable - enable - true - UITests - $(DefineConstants);ANDROID - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/Compatibility/ControlGallery/test/Android.Appium.UITests/PlatformSpecificSampleTest.cs b/src/Compatibility/ControlGallery/test/Android.Appium.UITests/PlatformSpecificSampleTest.cs deleted file mode 100644 index 98435f47f3e8..000000000000 --- a/src/Compatibility/ControlGallery/test/Android.Appium.UITests/PlatformSpecificSampleTest.cs +++ /dev/null @@ -1,16 +0,0 @@ -using NUnit.Framework; - -namespace UITests; - -public class PlatformSpecificSampleTest : UITest -{ - public PlatformSpecificSampleTest(TestDevice testDevice) : base(testDevice) - { - } - - [Test] - public void SampleTest() - { - Driver?.GetScreenshot().SaveAsFile($"{nameof(SampleTest)}.png"); - } -} \ No newline at end of file diff --git a/src/Compatibility/ControlGallery/test/Shared.Appium.UITests/AppiumServerHelper.cs b/src/Compatibility/ControlGallery/test/Shared.Appium.UITests/AppiumServerHelper.cs deleted file mode 100644 index 6165a3e9a341..000000000000 --- a/src/Compatibility/ControlGallery/test/Shared.Appium.UITests/AppiumServerHelper.cs +++ /dev/null @@ -1,33 +0,0 @@ -using OpenQA.Selenium.Appium.Service; - -namespace UITests; - -public static class AppiumServerHelper -{ - static AppiumLocalService? AppiumLocalService; - - public const string DefaultHostAddress = "127.0.0.1"; - public const int DefaultHostPort = 4723; - - public static void StartAppiumLocalServer(string host = DefaultHostAddress, - int port = DefaultHostPort) - { - if (AppiumLocalService is not null) - { - return; - } - - var builder = new AppiumServiceBuilder() - .WithIPAddress(host) - .UsingPort(port); - - // Start the server with the builder - AppiumLocalService = builder.Build(); - AppiumLocalService.Start(); - } - - public static void DisposeAppiumLocalServer() - { - AppiumLocalService?.Dispose(); - } -} \ No newline at end of file diff --git a/src/Compatibility/ControlGallery/test/Shared.Appium.UITests/ControlGallery.Shared.Appium.UITests.csproj b/src/Compatibility/ControlGallery/test/Shared.Appium.UITests/ControlGallery.Shared.Appium.UITests.csproj deleted file mode 100644 index 4515e8ece37e..000000000000 --- a/src/Compatibility/ControlGallery/test/Shared.Appium.UITests/ControlGallery.Shared.Appium.UITests.csproj +++ /dev/null @@ -1,36 +0,0 @@ - - - - $(_MauiDotNetTfm) - False - False - UITests - - - - - - - - - - - - - - - - - - $(DefineConstants);ANDROID - - - - $(DefineConstants);IOS;IOSUITEST - - - - $(DefineConstants);WINDOWS;WINTEST - - - \ No newline at end of file diff --git a/src/Compatibility/ControlGallery/test/Shared.Appium.UITests/GalleryQueries.cs b/src/Compatibility/ControlGallery/test/Shared.Appium.UITests/GalleryQueries.cs deleted file mode 100644 index 889551735add..000000000000 --- a/src/Compatibility/ControlGallery/test/Shared.Appium.UITests/GalleryQueries.cs +++ /dev/null @@ -1,30 +0,0 @@ -namespace UITests -{ - internal static class GalleryQueries - { - public const string ActivityIndicatorGallery = "ActivityIndicator Gallery"; - public const string BoxViewGallery = "BoxView Gallery"; - public const string ButtonGallery = "Button Gallery"; - public const string CheckBoxGallery = "CheckBox Gallery"; - public const string CollectionViewGallery = "CollectionView Gallery"; - public const string CarouselViewGallery = "CarouselView Gallery"; - public const string DatePickerGallery = "DatePicker Gallery"; - public const string EditorGallery = "Editor Gallery"; - public const string EntryGallery = "Entry Gallery"; - public const string FrameGallery = "Frame Gallery"; - public const string ImageGallery = "Image Gallery"; - public const string ImageButtonGallery = "Image Button Gallery"; - public const string LabelGallery = "Label Gallery"; - public const string ListViewGallery = "ListView Gallery"; - public const string PickerGallery = "Picker Gallery"; - public const string ProgressBarGallery = "ProgressBar Gallery"; - public const string RadioButtonGallery = "RadioButton Core Gallery"; - public const string ScrollViewGallery = "ScrollView Gallery"; - public const string SearchBarGallery = "SearchBar Gallery"; - public const string SliderGallery = "Slider Gallery"; - public const string StepperGallery = "Stepper Gallery"; - public const string SwitchGallery = "Switch Gallery"; - public const string TimePickerGallery = "TimePicker Gallery"; - public const string WebViewGallery = "WebView Gallery"; - } -} \ No newline at end of file diff --git a/src/Compatibility/ControlGallery/test/Shared.Appium.UITests/IssuesUITest.cs b/src/Compatibility/ControlGallery/test/Shared.Appium.UITests/IssuesUITest.cs deleted file mode 100644 index b8931ebf2c4e..000000000000 --- a/src/Compatibility/ControlGallery/test/Shared.Appium.UITests/IssuesUITest.cs +++ /dev/null @@ -1,63 +0,0 @@ -using NUnit.Framework; -using UITest.Appium; - -namespace UITests -{ - public abstract class IssuesUITest : UITest - { - public IssuesUITest(TestDevice device) : base(device) { } - - protected override void FixtureSetup() - { - int retries = 0; - while (true) - { - try - { - base.FixtureSetup(); - NavigateToIssue(Issue); - break; - } - catch (Exception e) - { - TestContext.Error.WriteLine($">>>>> {DateTime.Now} The FixtureSetup threw an exception. Attempt {retries}/{SetupMaxRetries}.{Environment.NewLine}Exception details: {e}"); - if (retries++ < SetupMaxRetries) - { - Reset(); - } - else - { - throw; - } - } - } - } - - protected override void FixtureTeardown() - { - base.FixtureTeardown(); - try - { - this.Back(); - RunningApp.Tap("GoBackToGalleriesButton"); - } - catch (Exception e) - { - var name = TestContext.CurrentContext.Test.MethodName ?? TestContext.CurrentContext.Test.Name; - TestContext.Error.WriteLine($">>>>> {DateTime.Now} The FixtureTeardown threw an exception during {name}.{Environment.NewLine}Exception details: {e}"); - } - } - - public abstract string Issue { get; } - - private void NavigateToIssue(string issue) - { - RunningApp.NavigateToIssues(); - - RunningApp.EnterText("SearchBarGo", issue); - - RunningApp.WaitForElement("SearchButton"); - RunningApp.Tap("SearchButton"); - } - } -} \ No newline at end of file diff --git a/src/Compatibility/ControlGallery/test/Shared.Appium.UITests/TestContextSetupFixture.cs b/src/Compatibility/ControlGallery/test/Shared.Appium.UITests/TestContextSetupFixture.cs deleted file mode 100644 index b8631bc9026f..000000000000 --- a/src/Compatibility/ControlGallery/test/Shared.Appium.UITests/TestContextSetupFixture.cs +++ /dev/null @@ -1,17 +0,0 @@ -using UITest.Appium; - -// SetupFixture runs once for all tests under the same namespace, if placed outside the namespace it will run once for all tests in the assembly -namespace UITests -{ - public class TestContextSetupFixture : UITestContextSetupFixture - { - AppiumServerContext? _appiumServerContext; - - public override void Initialize() - { - _appiumServerContext = new AppiumServerContext(); - _appiumServerContext.CreateAndStartServer(); - _serverContext = _appiumServerContext; - } - } -} \ No newline at end of file diff --git a/src/Compatibility/ControlGallery/test/Shared.Appium.UITests/TestDevice.cs b/src/Compatibility/ControlGallery/test/Shared.Appium.UITests/TestDevice.cs deleted file mode 100644 index bb0f09240ac1..000000000000 --- a/src/Compatibility/ControlGallery/test/Shared.Appium.UITests/TestDevice.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace UITests -{ - public enum TestDevice - { - Windows, - Android, - iOS, - Mac - } -} \ No newline at end of file diff --git a/src/Compatibility/ControlGallery/test/Shared.Appium.UITests/Tests/Issues/Issue11853.cs b/src/Compatibility/ControlGallery/test/Shared.Appium.UITests/Tests/Issues/Issue11853.cs deleted file mode 100644 index 1aa0f8291d18..000000000000 --- a/src/Compatibility/ControlGallery/test/Shared.Appium.UITests/Tests/Issues/Issue11853.cs +++ /dev/null @@ -1,32 +0,0 @@ -#if IOS -using NUnit.Framework; -using UITest.Appium; - -namespace UITests -{ - public class Issue11853 : IssuesUITest - { - const string Run = "Run"; - - public Issue11853(TestDevice testDevice) : base(testDevice) - { - } - - public override string Issue => "[Bug][iOS] Concurrent issue leading to crash in SemaphoreSlim.Release in ObservableItemsSource"; - - [Test] - [Category(UITestCategories.CollectionView)] - public void JustWhalingAwayOnTheCollectionViewWithAddsAndClearsShouldNotCrash() - { - RunningApp.WaitForElement(Run); - RunningApp.Tap(Run); - Task.Delay(5000).Wait(); - RunningApp.Tap(Run); - Task.Delay(5000).Wait(); - - // If we can still find the button, then we didn't crash - RunningApp.WaitForElement(Run); - } - } -} -#endif \ No newline at end of file diff --git a/src/Compatibility/ControlGallery/test/Shared.Appium.UITests/UITest.cs b/src/Compatibility/ControlGallery/test/Shared.Appium.UITests/UITest.cs deleted file mode 100644 index 000c987a0acb..000000000000 --- a/src/Compatibility/ControlGallery/test/Shared.Appium.UITests/UITest.cs +++ /dev/null @@ -1,169 +0,0 @@ -using NUnit.Framework; -using UITest.Core; -using VisualTestUtils; -using VisualTestUtils.MagickNet; - -namespace UITests -{ -#if ANDROID - [TestFixture(TestDevice.Android)] -#elif IOSUITEST - [TestFixture(TestDevice.iOS)] -#elif MACUITEST - [TestFixture(TestDevice.Mac)] -#elif WINTEST - [TestFixture(TestDevice.Windows)] -#else - [TestFixture(TestDevice.iOS)] - [TestFixture(TestDevice.Mac)] - [TestFixture(TestDevice.Windows)] - [TestFixture(TestDevice.Android)] -#endif - public abstract class UITest : UITestBase - { - protected const int SetupMaxRetries = 1; - readonly VisualRegressionTester _visualRegressionTester; - readonly IImageEditorFactory _imageEditorFactory; - readonly VisualTestContext _visualTestContext; - - protected UITest(TestDevice testDevice) : base(testDevice) - { - string? ciArtifactsDirectory = Environment.GetEnvironmentVariable("BUILD_ARTIFACTSTAGINGDIRECTORY"); - if (ciArtifactsDirectory != null) - ciArtifactsDirectory = Path.Combine(ciArtifactsDirectory, "Controls.TestCases.Shared.Tests"); - - string assemblyDirectory = Path.GetDirectoryName(System.AppDomain.CurrentDomain.BaseDirectory)!; - string projectRootDirectory = Path.GetFullPath(Path.Combine(assemblyDirectory, "..", "..", "..")); - _visualRegressionTester = new VisualRegressionTester(testRootDirectory: projectRootDirectory, - visualComparer: new MagickNetVisualComparer(), - visualDiffGenerator: new MagickNetVisualDiffGenerator(), - ciArtifactsDirectory: ciArtifactsDirectory); - - _imageEditorFactory = new MagickNetImageEditorFactory(); - _visualTestContext = new VisualTestContext(); - } - - public override IConfig GetTestConfig() - { - IConfig config = new Config(); - config.SetProperty("AppId", "com.microsoft.mauicompatibilitygallery"); - - switch (_testDevice) - { - case TestDevice.Android: - config.SetProperty("DeviceName", Environment.GetEnvironmentVariable("DEVICE_SKIN") ?? ""); - config.SetProperty("PlatformVersion", Environment.GetEnvironmentVariable("PLATFORM_VERSION") ?? ""); - config.SetProperty("Udid", Environment.GetEnvironmentVariable("DEVICE_UDID") ?? ""); - break; - case TestDevice.iOS: - config.SetProperty("DeviceName", Environment.GetEnvironmentVariable("DEVICE_NAME") ?? "iPhone X"); - config.SetProperty("PlatformVersion", Environment.GetEnvironmentVariable("PLATFORM_VERSION") ?? "17.0"); - config.SetProperty("Udid", Environment.GetEnvironmentVariable("DEVICE_UDID") ?? ""); - break; - } - - return config; - } - - public void VerifyScreenshot(string? name = null) - { - string deviceName = GetTestConfig().GetProperty("DeviceName") ?? string.Empty; - // Remove the XHarness suffix if present - deviceName = deviceName.Replace(" - created by XHarness", "", StringComparison.Ordinal); - - /* - Determine the environmentName, used as the directory name for visual testing snaphots. Here are the rules/conventions: - - Names are lower case, no spaces. - - By default, the name matches the platform (android, ios, windows, or mac). - - Each platform has a default device (or set of devices) - if the snapshot matches the default no suffix is needed (e.g. just ios). - - If tests are run on secondary devices that produce different snapshots, the device name is used as suffix (e.g. ios-iphonex). - - If tests are run on secondary devices with multiple OS versions that produce different snapshots, both device name and os version are - used as a suffix (e.g. ios-iphonex-16_4). We don't have any cases of this today but may eventually. The device name comes first here, - before os version, because most visual testing differences come from different sceen size (a device thing), not OS version differences, - but both can happen. - */ - string environmentName = string.Empty; - - switch (_testDevice) - { - case TestDevice.Android: - if (deviceName == "Nexus 5X") - { - environmentName = "android"; - } - else - { - Assert.Fail($"Android visual tests should be run on an Nexus 5X (API 30) emulator image, but the current device is '{deviceName}'. Follow the steps on the MAUI UI testing wiki."); - } - break; - - case TestDevice.iOS: - if (deviceName == "iPhone Xs (iOS 17.2)") - { - environmentName = "ios"; - } - else if (deviceName == "iPhone X (iOS 16.4)") - { - environmentName = "ios-iphonex"; - } - else - { - Assert.Fail($"iOS visual tests should be run on iPhone Xs (iOS 17.2) or iPhone X (iOS 16.4) simulator images, but the current device is '{deviceName}'. Follow the steps on the MAUI UI testing wiki."); - } - break; - - case TestDevice.Windows: - environmentName = "windows"; - break; - - case TestDevice.Mac: - // For now, ignore visual tests on Mac Catalyst since the Appium screenshot on Mac (unlike Windows) - // is of the entire screen, not just the app. Later when xharness relay support is in place to - // send a message to the MAUI app to get the screenshot, we can use that to just screenshot - // the app. - Assert.Ignore("MacCatalyst isn't supported yet for visual tests"); - break; - - default: - throw new NotImplementedException($"Unknown device type {_testDevice}"); - } - - name ??= TestContext.CurrentContext.Test.MethodName ?? TestContext.CurrentContext.Test.Name; - - byte[] screenshotPngBytes = RunningApp.Screenshot() ?? throw new InvalidOperationException("Failed to get screenshot"); - - var actualImage = new ImageSnapshot(screenshotPngBytes, ImageSnapshotFormat.PNG); - - // For Android and iOS, crop off the OS status bar at the top since it's not part of the - // app itself and contains the time, which always changes. For WinUI, crop off the title - // bar at the top as it varies slightly based on OS theme and is also not part of the app. - int cropFromTop = _testDevice switch - { - TestDevice.Android => 60, - TestDevice.iOS => environmentName == "ios-iphonex" ? 90 : 110, - TestDevice.Windows => 32, - _ => 0, - }; - - // For Android also crop the 3 button nav from the bottom, since it's not part of the - // app itself and the button color can vary (the buttons change clear briefly when tapped) - int cropFromBottom = _testDevice switch - { - TestDevice.Android => 125, - _ => 0, - }; - - if (cropFromTop > 0 || cropFromBottom > 0) - { - IImageEditor imageEditor = _imageEditorFactory.CreateImageEditor(actualImage); - (int width, int height) = imageEditor.GetSize(); - - imageEditor.Crop(0, cropFromTop, width, height - cropFromTop - cropFromBottom); - - actualImage = imageEditor.GetUpdatedImage(); - } - - _visualRegressionTester.VerifyMatchesSnapshot(name!, actualImage, environmentName: environmentName, testContext: _visualTestContext); - } - } -} \ No newline at end of file diff --git a/src/Compatibility/ControlGallery/test/Shared.Appium.UITests/UITestBase.cs b/src/Compatibility/ControlGallery/test/Shared.Appium.UITests/UITestBase.cs deleted file mode 100644 index 936e5a1f7780..000000000000 --- a/src/Compatibility/ControlGallery/test/Shared.Appium.UITests/UITestBase.cs +++ /dev/null @@ -1,175 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using NUnit.Framework; -using NUnit.Framework.Interfaces; -using UITest.Core; - -namespace UITests -{ - public abstract class UITestBase : UITestContextBase - { - public UITestBase(TestDevice testDevice) - : base(testDevice) - { - } - - [SetUp] - public void RecordTestSetup() - { - var name = TestContext.CurrentContext.Test.MethodName ?? TestContext.CurrentContext.Test.Name; - TestContext.Progress.WriteLine($">>>>> {DateTime.Now} {name} Start"); - } - - [TearDown] - public void RecordTestTeardown() - { - var name = TestContext.CurrentContext.Test.MethodName ?? TestContext.CurrentContext.Test.Name; - TestContext.Progress.WriteLine($">>>>> {DateTime.Now} {name} Stop"); - } - - protected virtual void FixtureSetup() - { - var name = TestContext.CurrentContext.Test.MethodName ?? TestContext.CurrentContext.Test.Name; - TestContext.Progress.WriteLine($">>>>> {DateTime.Now} {nameof(FixtureSetup)} for {name}"); - } - - protected virtual void FixtureTeardown() - { - var name = TestContext.CurrentContext.Test.MethodName ?? TestContext.CurrentContext.Test.Name; - TestContext.Progress.WriteLine($">>>>> {DateTime.Now} {nameof(FixtureTeardown)} for {name}"); - } - - [TearDown] - public void UITestBaseTearDown() - { - if (App.AppState == ApplicationState.NotRunning) - { - SaveDeviceDiagnosticInfo(); - - Reset(); - FixtureSetup(); - - // Assert.Fail will immediately exit the test which is desirable as the app is not - // running anymore so we can't capture any UI structures or any screenshots - Assert.Fail("The app was expected to be running still, investigate as possible crash"); - } - - var testOutcome = TestContext.CurrentContext.Result.Outcome; - if (testOutcome == ResultState.Error || - testOutcome == ResultState.Failure) - { - SaveDeviceDiagnosticInfo(); - SaveUIDiagnosticInfo(); - } - } - - [OneTimeSetUp] - public void OneTimeSetup() - { - InitialSetup(UITestContextSetupFixture.ServerContext); - try - { - FixtureSetup(); - } - catch - { - SaveDeviceDiagnosticInfo(); - SaveUIDiagnosticInfo(); - throw; - } - } - - [OneTimeTearDown] - public void OneTimeTearDown() - { - var outcome = TestContext.CurrentContext.Result.Outcome; - - // We only care about setup failures as regular test failures will already do logging - if (outcome.Status == ResultState.SetUpFailure.Status && - outcome.Site == ResultState.SetUpFailure.Site) - { - SaveDeviceDiagnosticInfo(); - SaveUIDiagnosticInfo(); - } - - FixtureTeardown(); - } - - void SaveDeviceDiagnosticInfo([CallerMemberName] string? note = null) - { - var types = App.GetLogTypes().ToArray(); - TestContext.Progress.WriteLine($">>>>> {DateTime.Now} Log types: {string.Join(", ", types)}"); - - foreach (var logType in new[] { "logcat" }) - { - if (!types.Contains(logType, StringComparer.InvariantCultureIgnoreCase)) - continue; - - var logsPath = GetGeneratedFilePath($"AppLogs-{logType}.log", note); - if (logsPath is not null) - { - var entries = App.GetLogEntries(logType); - File.WriteAllLines(logsPath, entries); - - AddTestAttachment(logsPath, Path.GetFileName(logsPath)); - } - } - } - - void SaveUIDiagnosticInfo([CallerMemberName] string? note = null) - { - var screenshotPath = GetGeneratedFilePath("ScreenShot.png", note); - if (screenshotPath is not null) - { - _ = RunningApp.Screenshot(screenshotPath); - - AddTestAttachment(screenshotPath, Path.GetFileName(screenshotPath)); - } - - var pageSourcePath = GetGeneratedFilePath("PageSource.txt", note); - if (pageSourcePath is not null) - { - File.WriteAllText(pageSourcePath, App.ElementTree); - - AddTestAttachment(pageSourcePath, Path.GetFileName(pageSourcePath)); - } - } - - string? GetGeneratedFilePath(string filename, string? note = null) - { - // App could be null if UITestContext was not able to connect to the test process (e.g. port already in use etc...) - if (UITestContext is null) - return null; - - if (string.IsNullOrEmpty(note)) - note = "-"; - else - note = $"-{note}-"; - - filename = $"{Path.GetFileNameWithoutExtension(filename)}-{Guid.NewGuid().ToString("N")}{Path.GetExtension(filename)}"; - - var logDir = - Path.GetDirectoryName(Environment.GetEnvironmentVariable("APPIUM_LOG_FILE") ?? - Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location))!; - - var name = - TestContext.CurrentContext.Test.MethodName ?? - TestContext.CurrentContext.Test.Name; - - return Path.Combine(logDir, $"{name}-{_testDevice}{note}{filename}"); - } - - void AddTestAttachment(string filePath, string? description = null) - { - try - { - TestContext.AddTestAttachment(filePath, description); - } - catch (FileNotFoundException e) when (e.Message == "Test attachment file path could not be found.") - { - // Add the file path to better troubleshoot when these errors occur - throw new FileNotFoundException($"Test attachment file path could not be found: '{filePath}' {description}", e); - } - } - } -} \ No newline at end of file diff --git a/src/Compatibility/ControlGallery/test/Shared.Appium.UITests/UITestCategories.cs b/src/Compatibility/ControlGallery/test/Shared.Appium.UITests/UITestCategories.cs deleted file mode 100644 index aa8c41a63837..000000000000 --- a/src/Compatibility/ControlGallery/test/Shared.Appium.UITests/UITestCategories.cs +++ /dev/null @@ -1,68 +0,0 @@ -namespace UITests -{ - internal static class UITestCategories - { - public const string ViewBaseTests = "ViewBaseTests"; - public const string ActionSheet = "ActionSheet"; - public const string ActivityIndicator = "ActivityIndicator"; - public const string Animation = "Animation"; - public const string AutomationId = "AutomationID"; - public const string BoxView = "BoxView"; - public const string Button = "Button"; - public const string CarouselView = "CarouselView"; - public const string Cells = "Cells"; - public const string CheckBox = "CheckBox"; - public const string CollectionView = "CollectionView"; - public const string ContextActions = "ContextActions"; - public const string DatePicker = "DatePicker"; - public const string DragAndDrop = "DragAndDrop"; - public const string DisplayAlert = "DisplayAlert"; - public const string Editor = "Editor"; - public const string Entry = "Entry"; - public const string Frame = "Frame"; - public const string Image = "Image"; - public const string ImageButton = "ImageButton"; - public const string Label = "Label"; - public const string Layout = "Layout"; - public const string ListView = "ListView"; - public const string UwpIgnore = "UwpIgnore"; - public const string LifeCycle = "Lifecycle"; - public const string FlyoutPage = "FlyoutPage"; - public const string Picker = "Picker"; - public const string ProgressBar = "ProgressBar"; - public const string RequiresInternetConnection = "RequiresInternetConnection"; - public const string RootGallery = "RootGallery"; - public const string ScrollView = "ScrollView"; - public const string SearchBar = "SearchBar"; - public const string Slider = "Slider"; - public const string Stepper = "Stepper"; - public const string Switch = "Switch"; - public const string SwipeView = "SwipeView"; - public const string TableView = "TableView"; - public const string TimePicker = "TimePicker"; - public const string ToolbarItem = "ToolbarItem"; - public const string WebView = "WebView"; - public const string Maps = "Maps"; - public const string InputTransparent = "InputTransparent"; - public const string IsEnabled = "IsEnabled"; - public const string Gestures = "Gestures"; - public const string Navigation = "Navigation"; - public const string Effects = "Effects"; - public const string Focus = "Focus"; - public const string ManualReview = "ManualReview"; - public const string Performance = "Performance"; - public const string AppLinks = "AppLinks"; - public const string Shell = "Shell"; - public const string TabbedPage = "TabbedPage"; - public const string CustomHandlers = "CustomHandlers"; - public const string Page = "Page"; - public const string RefreshView = "RefreshView"; - public const string TitleView = "TitleView"; - public const string DisplayPrompt = "DisplayPrompt"; - public const string IndicatorView = "IndicatorView"; - public const string RadioButton = "RadioButton"; - public const string Shape = "Shape"; - public const string Accessibility = "Accessibility"; - public const string Brush = "Brush"; - } -} diff --git a/src/Compatibility/ControlGallery/test/Shared.Appium.UITests/UITestContextBase.cs b/src/Compatibility/ControlGallery/test/Shared.Appium.UITests/UITestContextBase.cs deleted file mode 100644 index 68f0a129e5dd..000000000000 --- a/src/Compatibility/ControlGallery/test/Shared.Appium.UITests/UITestContextBase.cs +++ /dev/null @@ -1,91 +0,0 @@ -using OpenQA.Selenium.Appium; -using UITest.Appium; -using UITest.Core; - -namespace UITests -{ - public abstract class UITestContextBase - { - static IUIClientContext? UiTestContext; - IServerContext? _context; - protected TestDevice _testDevice; - - public UITestContextBase(TestDevice testDevice) - { - _testDevice = testDevice; - } - - public static IUIClientContext? UITestContext { get { return UiTestContext; } } - - protected AppiumDriver? Driver - { - get - { - if (App is AppiumApp app) - { - return app.Driver; - } - - return null; - } - } - - public TestDevice Device - { - get - { - return UITestContext == null - ? throw new InvalidOperationException($"Call {nameof(InitialSetup)} before accessing the {nameof(Device)} property.") - : UITestContext.Config.GetProperty("TestDevice"); - } - } - - public IApp App - { - get - { - return UITestContext == null - ? throw new InvalidOperationException($"Call {nameof(InitialSetup)} before accessing the {nameof(App)} property.") - : UITestContext.App; - } - } - - internal IApp RunningApp => App; - - public abstract IConfig GetTestConfig(); - - public void InitialSetup(IServerContext context) - { - _context = context ?? throw new ArgumentNullException(nameof(context)); - InitialSetup(context, false); - } - - public void Reset() - { - if (_context == null) - { - throw new InvalidOperationException($"Cannot {nameof(Reset)} if {nameof(InitialSetup)} has not been called."); - } - - InitialSetup(_context, true); - } - - private void InitialSetup(IServerContext context, bool reset) - { - var testConfig = GetTestConfig(); - testConfig.SetProperty("TestDevice", _testDevice); - - // Check to see if we have a context already from a previous test and re-use it as creating the driver is expensive - if (reset || UiTestContext == null) - { - UiTestContext?.Dispose(); - UiTestContext = context.CreateUIClientContext(testConfig); - } - - if (UiTestContext == null) - { - throw new InvalidOperationException("Failed to get the driver."); - } - } - } -} \ No newline at end of file diff --git a/src/Compatibility/ControlGallery/test/Shared.Appium.UITests/UITestExtensions.cs b/src/Compatibility/ControlGallery/test/Shared.Appium.UITests/UITestExtensions.cs deleted file mode 100644 index c1b1b1461e67..000000000000 --- a/src/Compatibility/ControlGallery/test/Shared.Appium.UITests/UITestExtensions.cs +++ /dev/null @@ -1,90 +0,0 @@ -using NUnit.Framework; -using UITest.Appium; -using UITest.Core; -using System.Drawing; - -namespace UITests -{ - public static class UITestExtensions - { - const string GoToTestButtonId = "GoToTestButton"; - - public static void Back(this UITestContextBase testBase) - { - if (testBase.Device == TestDevice.Android) - { - var query = testBase.App.Query.ByAccessibilityId("Navigate up").First(); - query.Click(); - } - else if (testBase.Device == TestDevice.iOS || testBase.Device == TestDevice.Mac) - { - // Get the first NavigationBar we can find and the first button in it (the back button), index starts at 1 - var queryBy = testBase.App.Query.ByClass("XCUIElementTypeNavigationBar").First().ByClass("XCUIElementTypeButton").First(); - queryBy.Click(); - } - else - { - testBase.RunningApp.FindElement("NavigationViewBackButton").Click(); - } - } - - public static void NavigateToGallery(this IApp app, string page) - { - app.WaitForElement(GoToTestButtonId, "Timed out waiting for Go To Test button to appear", TimeSpan.FromMinutes(2)); - NavigateTo(app, page); - } - - public static void NavigateTo(this IApp app, string text) - { - app.WaitForElement("SearchBar"); - app.ClearText("SearchBar"); - if (!string.IsNullOrWhiteSpace(text)) - { - app.EnterText("SearchBar", text); - } - app.Tap(GoToTestButtonId); - - app.WaitForNoElement(GoToTestButtonId, "Timed out waiting for Go To Test button to disappear", TimeSpan.FromMinutes(1)); - } - - public static void NavigateToIssues(this IApp app) - { - app.WaitForElement(GoToTestButtonId, "Timed out waiting for Go To Test button to appear", TimeSpan.FromMinutes(2)); - - app.WaitForElement("SearchBar"); - app.ClearText("SearchBar"); - - app.Tap(GoToTestButtonId); - app.WaitForElement("TestCasesIssueList"); - } - - public static void IgnoreIfPlatforms(this UITestBase? test, IEnumerable devices, string? message = null) - { - foreach (var device in devices) - { - test?.IgnoreIfPlatform(device, message); - } - } - - public static void IgnoreIfPlatform(this UITestBase? test, TestDevice device, string? message = null) - { - if (test != null && test.Device == device) - { - if (string.IsNullOrEmpty(message)) - Assert.Ignore(); - else - Assert.Ignore(message); - } - } - - public static int CenterX(this Rectangle rect) - { - return rect.X + rect.Width / 2; - } - - public static int CenterY(this Rectangle rect) - { - return rect.Y + rect.Height / 2; - } - } -} \ No newline at end of file diff --git a/src/Compatibility/ControlGallery/test/Shared.Appium.UITests/UITestIgnoreAttributes.cs b/src/Compatibility/ControlGallery/test/Shared.Appium.UITests/UITestIgnoreAttributes.cs deleted file mode 100644 index 4113ca8aaa5e..000000000000 --- a/src/Compatibility/ControlGallery/test/Shared.Appium.UITests/UITestIgnoreAttributes.cs +++ /dev/null @@ -1,112 +0,0 @@ -using NUnit.Framework; - -namespace UITests -{ - public class IgnoredDuringMoveToAppium : IgnoreAttribute - { - public IgnoredDuringMoveToAppium() : base(nameof(IgnoredDuringMoveToAppium)) - { - } - public IgnoredDuringMoveToAppium(string reason) : base(reason) - { - } - } - - public class FailsOnAllPlatforms : IgnoreAttribute - { - public FailsOnAllPlatforms() : base(nameof(FailsOnAndroid)) - { - } - public FailsOnAllPlatforms(string reason) : base(reason) - { - } - } - -#if ANDROID - public class FailsOnAndroid : IgnoreAttribute - { - public FailsOnAndroid() : base(nameof(FailsOnAndroid)) - { - } - public FailsOnAndroid(string reason) : base(reason) - { - } - } -#else - public class FailsOnAndroid : CategoryAttribute - { - public FailsOnAndroid() : base(nameof(FailsOnAndroid)) - { - } - public FailsOnAndroid(string name) : base(name) - { - } - } -#endif - -#if IOS - public class FailsOnIOS : IgnoreAttribute - { - public FailsOnIOS() : base(nameof(FailsOnIOS)) - { - } - public FailsOnIOS(string reason) : base(reason) - { - } - } -#else - public class FailsOnIOS : CategoryAttribute - { - public FailsOnIOS() : base(nameof(FailsOnIOS)) - { - } - public FailsOnIOS(string name) : base(name) - { - } - } -#endif - -#if MACCATALYST - public class FailsOnMac : IgnoreAttribute - { - public FailsOnMac() : base(nameof(FailsOnMac)) - { - } - public FailsOnMac(string reason) : base(reason) - { - } - } -#else - public class FailsOnMac : CategoryAttribute - { - public FailsOnMac() : base(nameof(FailsOnMac)) - { - } - public FailsOnMac(string name) : base(name) - { - } - } -#endif - -#if WINDOWS - public class FailsOnWindows : IgnoreAttribute - { - public FailsOnWindows() : base(nameof(FailsOnWindows)) - { - } - public FailsOnWindows(string reason) : base(reason) - { - } - } -#else - public class FailsOnWindows : CategoryAttribute - { - public FailsOnWindows() : base(nameof(FailsOnWindows)) - { - } - public FailsOnWindows(string name) : base(name) - { - } - } -#endif -} diff --git a/src/Compatibility/ControlGallery/test/Shared.Appium.UITests/VisualTestContext.cs b/src/Compatibility/ControlGallery/test/Shared.Appium.UITests/VisualTestContext.cs deleted file mode 100644 index 38598c27c489..000000000000 --- a/src/Compatibility/ControlGallery/test/Shared.Appium.UITests/VisualTestContext.cs +++ /dev/null @@ -1,11 +0,0 @@ -using NUnit.Framework; -using VisualTestUtils; - -namespace UITests -{ - public class VisualTestContext : ITestContext - { - public void AddTestAttachment(string filePath, string? description = null) => - TestContext.AddTestAttachment(filePath, description); - } -} \ No newline at end of file diff --git a/src/Compatibility/ControlGallery/test/iOS.Appium.UITests/ControlGallery.iOS.Appium.UITests.csproj b/src/Compatibility/ControlGallery/test/iOS.Appium.UITests/ControlGallery.iOS.Appium.UITests.csproj deleted file mode 100644 index 4558c59d5333..000000000000 --- a/src/Compatibility/ControlGallery/test/iOS.Appium.UITests/ControlGallery.iOS.Appium.UITests.csproj +++ /dev/null @@ -1,39 +0,0 @@ - - - - $(_MauiDotNetTfm) - enable - enable - true - UITests - $(DefineConstants);IOS;IOSUITEST - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/Compatibility/ControlGallery/test/iOS.Appium.UITests/PlatformSpecificSampleTest.cs b/src/Compatibility/ControlGallery/test/iOS.Appium.UITests/PlatformSpecificSampleTest.cs deleted file mode 100644 index 98435f47f3e8..000000000000 --- a/src/Compatibility/ControlGallery/test/iOS.Appium.UITests/PlatformSpecificSampleTest.cs +++ /dev/null @@ -1,16 +0,0 @@ -using NUnit.Framework; - -namespace UITests; - -public class PlatformSpecificSampleTest : UITest -{ - public PlatformSpecificSampleTest(TestDevice testDevice) : base(testDevice) - { - } - - [Test] - public void SampleTest() - { - Driver?.GetScreenshot().SaveAsFile($"{nameof(SampleTest)}.png"); - } -} \ No newline at end of file From e653d5d3546618a8579a846bf8b1a0d7e1bfadb7 Mon Sep 17 00:00:00 2001 From: Rui Marinho Date: Tue, 11 Jun 2024 17:00:48 -0700 Subject: [PATCH 11/41] [main] Update arcade and xharness (#22981) * Update arcade * Update dotnet-tools.json * Update xharness # Conflicts: # .config/dotnet-tools.json # eng/Version.Details.xml # eng/Versions.props --- .config/dotnet-tools.json | 2 +- eng/Version.Details.xml | 20 +++++----- eng/Versions.props | 8 ++-- .../job/source-index-stage1.yml | 39 +++++++++++++------ .../templates/job/source-index-stage1.yml | 39 +++++++++++++------ global.json | 4 +- 6 files changed, 71 insertions(+), 41 deletions(-) diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index 022b1d13b0c0..08371f46f87f 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -21,7 +21,7 @@ ] }, "microsoft.dotnet.xharness.cli": { - "version": "9.0.0-prerelease.24277.1", + "version": "9.0.0-prerelease.24311.2", "commands": [ "xharness" ] diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index f5f5dd6ec31d..9b192028500b 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,26 +1,26 @@ - + https://github.com/dotnet/xharness - 914dd73b3622741590db173b5dd6eac1aa9cc553 + 975b330d51119efc4884f7a323784662cbf74391 - + https://github.com/dotnet/xharness - 914dd73b3622741590db173b5dd6eac1aa9cc553 + 975b330d51119efc4884f7a323784662cbf74391 - + https://github.com/dotnet/xharness - 914dd73b3622741590db173b5dd6eac1aa9cc553 + 975b330d51119efc4884f7a323784662cbf74391 - + https://github.com/dotnet/arcade - 67d23f4ba1813b315e7e33c71d18b63475f5c5f8 + 9f6799fdc16ae19b3e9478c55b997a6aab839d09 - + https://github.com/dotnet/arcade - 67d23f4ba1813b315e7e33c71d18b63475f5c5f8 + 9f6799fdc16ae19b3e9478c55b997a6aab839d09 diff --git a/eng/Versions.props b/eng/Versions.props index a0fb11dc710f..dc6e476cfb2a 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -104,16 +104,16 @@ <_HarfBuzzSharpVersion>7.3.0.2 <_SkiaSharpNativeAssetsVersion>0.0.0-commit.7af1d0840a381c0ce7ef2877454a88dbb2949686.1086 7.0.114 - 9.0.0-prerelease.24277.1 - 9.0.0-prerelease.24277.1 - 9.0.0-prerelease.24277.1 + 9.0.0-prerelease.24311.2 + 9.0.0-prerelease.24311.2 + 9.0.0-prerelease.24311.2 0.9.2 1.0.0.16 1.3.0 0.9.0 4.2.3 8.0.3 - 8.0.0-beta.24225.1 + 8.0.0-beta.24310.5 17.6.0 diff --git a/eng/common/templates-official/job/source-index-stage1.yml b/eng/common/templates-official/job/source-index-stage1.yml index f0513aee5b0d..60dfb6b2d1c0 100644 --- a/eng/common/templates-official/job/source-index-stage1.yml +++ b/eng/common/templates-official/job/source-index-stage1.yml @@ -1,6 +1,7 @@ parameters: runAsPublic: false - sourceIndexPackageVersion: 1.0.1-20230228.2 + sourceIndexUploadPackageVersion: 2.0.0-20240502.12 + sourceIndexProcessBinlogPackageVersion: 1.0.1-20240129.2 sourceIndexPackageSource: https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json sourceIndexBuildCommand: powershell -NoLogo -NoProfile -ExecutionPolicy Bypass -Command "eng/common/build.ps1 -restore -build -binarylog -ci" preSteps: [] @@ -14,14 +15,14 @@ jobs: dependsOn: ${{ parameters.dependsOn }} condition: ${{ parameters.condition }} variables: - - name: SourceIndexPackageVersion - value: ${{ parameters.sourceIndexPackageVersion }} + - name: SourceIndexUploadPackageVersion + value: ${{ parameters.sourceIndexUploadPackageVersion }} + - name: SourceIndexProcessBinlogPackageVersion + value: ${{ parameters.sourceIndexProcessBinlogPackageVersion }} - name: SourceIndexPackageSource value: ${{ parameters.sourceIndexPackageSource }} - name: BinlogPath value: ${{ parameters.binlogPath }} - - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - - group: source-dot-net stage1 variables - template: /eng/common/templates-official/variables/pool-providers.yml ${{ if ne(parameters.pool, '') }}: @@ -41,16 +42,16 @@ jobs: - ${{ preStep }} - task: UseDotNet@2 - displayName: Use .NET Core SDK 6 + displayName: Use .NET 8 SDK inputs: packageType: sdk - version: 6.0.x + version: 8.0.x installationPath: $(Agent.TempDirectory)/dotnet workingDirectory: $(Agent.TempDirectory) - script: | - $(Agent.TempDirectory)/dotnet/dotnet tool install BinLogToSln --version $(SourceIndexPackageVersion) --add-source $(SourceIndexPackageSource) --tool-path $(Agent.TempDirectory)/.source-index/tools - $(Agent.TempDirectory)/dotnet/dotnet tool install UploadIndexStage1 --version $(SourceIndexPackageVersion) --add-source $(SourceIndexPackageSource) --tool-path $(Agent.TempDirectory)/.source-index/tools + $(Agent.TempDirectory)/dotnet/dotnet tool install BinLogToSln --version $(sourceIndexProcessBinlogPackageVersion) --add-source $(SourceIndexPackageSource) --tool-path $(Agent.TempDirectory)/.source-index/tools + $(Agent.TempDirectory)/dotnet/dotnet tool install UploadIndexStage1 --version $(sourceIndexUploadPackageVersion) --add-source $(SourceIndexPackageSource) --tool-path $(Agent.TempDirectory)/.source-index/tools displayName: Download Tools # Set working directory to temp directory so 'dotnet' doesn't try to use global.json and use the repo's sdk. workingDirectory: $(Agent.TempDirectory) @@ -62,7 +63,21 @@ jobs: displayName: Process Binlog into indexable sln - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - - script: $(Agent.TempDirectory)/.source-index/tools/UploadIndexStage1 -i .source-index/stage1output -n $(Build.Repository.Name) + - task: AzureCLI@2 + displayName: Get stage 1 auth token + inputs: + azureSubscription: 'SourceDotNet Stage1 Publish' + addSpnToEnvironment: true + scriptType: 'ps' + scriptLocation: 'inlineScript' + inlineScript: | + echo "##vso[task.setvariable variable=ARM_CLIENT_ID;issecret=true]$env:servicePrincipalId" + echo "##vso[task.setvariable variable=ARM_ID_TOKEN;issecret=true]$env:idToken" + echo "##vso[task.setvariable variable=ARM_TENANT_ID;issecret=true]$env:tenantId" + + - script: | + az login --service-principal -u $(ARM_CLIENT_ID) --tenant $(ARM_TENANT_ID) --allow-no-subscriptions --federated-token $(ARM_ID_TOKEN) + displayName: "Login to Azure" + + - script: $(Agent.TempDirectory)/.source-index/tools/UploadIndexStage1 -i .source-index/stage1output -n $(Build.Repository.Name) -s netsourceindexstage1 -b stage1 displayName: Upload stage1 artifacts to source index - env: - BLOB_CONTAINER_URL: $(source-dot-net-stage1-blob-container-url) diff --git a/eng/common/templates/job/source-index-stage1.yml b/eng/common/templates/job/source-index-stage1.yml index b98202aa02d8..0b6bb89dc78a 100644 --- a/eng/common/templates/job/source-index-stage1.yml +++ b/eng/common/templates/job/source-index-stage1.yml @@ -1,6 +1,7 @@ parameters: runAsPublic: false - sourceIndexPackageVersion: 1.0.1-20230228.2 + sourceIndexUploadPackageVersion: 2.0.0-20240502.12 + sourceIndexProcessBinlogPackageVersion: 1.0.1-20240129.2 sourceIndexPackageSource: https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json sourceIndexBuildCommand: powershell -NoLogo -NoProfile -ExecutionPolicy Bypass -Command "eng/common/build.ps1 -restore -build -binarylog -ci" preSteps: [] @@ -14,14 +15,14 @@ jobs: dependsOn: ${{ parameters.dependsOn }} condition: ${{ parameters.condition }} variables: - - name: SourceIndexPackageVersion - value: ${{ parameters.sourceIndexPackageVersion }} + - name: SourceIndexUploadPackageVersion + value: ${{ parameters.sourceIndexUploadPackageVersion }} + - name: SourceIndexProcessBinlogPackageVersion + value: ${{ parameters.sourceIndexProcessBinlogPackageVersion }} - name: SourceIndexPackageSource value: ${{ parameters.sourceIndexPackageSource }} - name: BinlogPath value: ${{ parameters.binlogPath }} - - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - - group: source-dot-net stage1 variables - template: /eng/common/templates/variables/pool-providers.yml ${{ if ne(parameters.pool, '') }}: @@ -40,16 +41,16 @@ jobs: - ${{ preStep }} - task: UseDotNet@2 - displayName: Use .NET Core SDK 6 + displayName: Use .NET 8 SDK inputs: packageType: sdk - version: 6.0.x + version: 8.0.x installationPath: $(Agent.TempDirectory)/dotnet workingDirectory: $(Agent.TempDirectory) - script: | - $(Agent.TempDirectory)/dotnet/dotnet tool install BinLogToSln --version $(SourceIndexPackageVersion) --add-source $(SourceIndexPackageSource) --tool-path $(Agent.TempDirectory)/.source-index/tools - $(Agent.TempDirectory)/dotnet/dotnet tool install UploadIndexStage1 --version $(SourceIndexPackageVersion) --add-source $(SourceIndexPackageSource) --tool-path $(Agent.TempDirectory)/.source-index/tools + $(Agent.TempDirectory)/dotnet/dotnet tool install BinLogToSln --version $(sourceIndexProcessBinlogPackageVersion) --add-source $(SourceIndexPackageSource) --tool-path $(Agent.TempDirectory)/.source-index/tools + $(Agent.TempDirectory)/dotnet/dotnet tool install UploadIndexStage1 --version $(sourceIndexUploadPackageVersion) --add-source $(SourceIndexPackageSource) --tool-path $(Agent.TempDirectory)/.source-index/tools displayName: Download Tools # Set working directory to temp directory so 'dotnet' doesn't try to use global.json and use the repo's sdk. workingDirectory: $(Agent.TempDirectory) @@ -61,7 +62,21 @@ jobs: displayName: Process Binlog into indexable sln - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - - script: $(Agent.TempDirectory)/.source-index/tools/UploadIndexStage1 -i .source-index/stage1output -n $(Build.Repository.Name) + - task: AzureCLI@2 + displayName: Get stage 1 auth token + inputs: + azureSubscription: 'SourceDotNet Stage1 Publish' + addSpnToEnvironment: true + scriptType: 'ps' + scriptLocation: 'inlineScript' + inlineScript: | + echo "##vso[task.setvariable variable=ARM_CLIENT_ID;issecret=true]$env:servicePrincipalId" + echo "##vso[task.setvariable variable=ARM_ID_TOKEN;issecret=true]$env:idToken" + echo "##vso[task.setvariable variable=ARM_TENANT_ID;issecret=true]$env:tenantId" + + - script: | + az login --service-principal -u $(ARM_CLIENT_ID) --tenant $(ARM_TENANT_ID) --allow-no-subscriptions --federated-token $(ARM_ID_TOKEN) + displayName: "Login to Azure" + + - script: $(Agent.TempDirectory)/.source-index/tools/UploadIndexStage1 -i .source-index/stage1output -n $(Build.Repository.Name) -s netsourceindexstage1 -b stage1 displayName: Upload stage1 artifacts to source index - env: - BLOB_CONTAINER_URL: $(source-dot-net-stage1-blob-container-url) diff --git a/global.json b/global.json index b26b64979308..2b3c65d222ba 100644 --- a/global.json +++ b/global.json @@ -1,10 +1,10 @@ { "tools": { - "dotnet": "9.0.100-preview.3.24204.13" + "dotnet": "9.0.100-preview.4.24267.66" }, "msbuild-sdks": { "MSBuild.Sdk.Extras": "3.0.44", "Microsoft.Build.NoTargets": "3.7.0", - "Microsoft.DotNet.Arcade.Sdk": "8.0.0-beta.24225.1" + "Microsoft.DotNet.Arcade.Sdk": "8.0.0-beta.24310.5" } } From 192911a9247e95b81a068fd83457b02c4f4ed444 Mon Sep 17 00:00:00 2001 From: redth Date: Mon, 17 Jun 2024 16:41:46 -0400 Subject: [PATCH 12/41] Remove more references to removed projects --- Microsoft.Maui.sln | 14 -------------- eng/pipelines/ui-tests.yml | 3 +-- 2 files changed, 1 insertion(+), 16 deletions(-) diff --git a/Microsoft.Maui.sln b/Microsoft.Maui.sln index 3152be870542..20687492a3d2 100644 --- a/Microsoft.Maui.sln +++ b/Microsoft.Maui.sln @@ -253,10 +253,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UITest.Appium", "src\TestUt EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UITest.NUnit", "src\TestUtils\src\UITest.NUnit\UITest.NUnit.csproj", "{8050448A-E08F-4972-9B47-16042A5DFE82}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ControlGallery.Android.Appium.UITests", "src\Compatibility\ControlGallery\test\Android.Appium.UITests\ControlGallery.Android.Appium.UITests.csproj", "{F748974F-A8E4-4659-801C-804B739D6326}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ControlGallery.iOS.Appium.UITests", "src\Compatibility\ControlGallery\test\iOS.Appium.UITests\ControlGallery.iOS.Appium.UITests.csproj", "{5923B35B-EA24-4B86-A384-9DAF9F2AFD56}" -EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{6730CE13-8567-4DC8-B2AF-B12C39818825}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Compatibility.Core.UnitTests", "src\Compatibility\Core\tests\Compatibility.UnitTests\Compatibility.Core.UnitTests.csproj", "{9F3DD0E7-8A71-4BA8-A3E6-690DC5A9F3D7}" @@ -658,14 +654,6 @@ Global {8050448A-E08F-4972-9B47-16042A5DFE82}.Debug|Any CPU.Build.0 = Debug|Any CPU {8050448A-E08F-4972-9B47-16042A5DFE82}.Release|Any CPU.ActiveCfg = Release|Any CPU {8050448A-E08F-4972-9B47-16042A5DFE82}.Release|Any CPU.Build.0 = Release|Any CPU - {F748974F-A8E4-4659-801C-804B739D6326}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F748974F-A8E4-4659-801C-804B739D6326}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F748974F-A8E4-4659-801C-804B739D6326}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F748974F-A8E4-4659-801C-804B739D6326}.Release|Any CPU.Build.0 = Release|Any CPU - {5923B35B-EA24-4B86-A384-9DAF9F2AFD56}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {5923B35B-EA24-4B86-A384-9DAF9F2AFD56}.Debug|Any CPU.Build.0 = Debug|Any CPU - {5923B35B-EA24-4B86-A384-9DAF9F2AFD56}.Release|Any CPU.ActiveCfg = Release|Any CPU - {5923B35B-EA24-4B86-A384-9DAF9F2AFD56}.Release|Any CPU.Build.0 = Release|Any CPU {9F3DD0E7-8A71-4BA8-A3E6-690DC5A9F3D7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {9F3DD0E7-8A71-4BA8-A3E6-690DC5A9F3D7}.Debug|Any CPU.Build.0 = Debug|Any CPU {9F3DD0E7-8A71-4BA8-A3E6-690DC5A9F3D7}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -811,8 +799,6 @@ Global {352C2381-1DEC-4487-819D-340D1EA98FBE} = {7AC28763-9C68-4BF9-A1BA-25CBFFD2D15C} {8C8CD467-11F9-4A14-8AF3-047B2CFD19A7} = {7AC28763-9C68-4BF9-A1BA-25CBFFD2D15C} {8050448A-E08F-4972-9B47-16042A5DFE82} = {7AC28763-9C68-4BF9-A1BA-25CBFFD2D15C} - {F748974F-A8E4-4659-801C-804B739D6326} = {DDBA9144-36FC-429E-99E1-2A64825434C1} - {5923B35B-EA24-4B86-A384-9DAF9F2AFD56} = {DDBA9144-36FC-429E-99E1-2A64825434C1} {6730CE13-8567-4DC8-B2AF-B12C39818825} = {123AA89E-1638-4E0E-B828-B8F9F9F906A2} {9F3DD0E7-8A71-4BA8-A3E6-690DC5A9F3D7} = {6730CE13-8567-4DC8-B2AF-B12C39818825} {199777D4-0EA9-4AAB-82A0-0B53D4BA9E4B} = {25D0D27A-C5FE-443D-8B65-D6C987F4A80E} diff --git a/eng/pipelines/ui-tests.yml b/eng/pipelines/ui-tests.yml index 020077868f92..851a0eddc2d4 100644 --- a/eng/pipelines/ui-tests.yml +++ b/eng/pipelines/ui-tests.yml @@ -173,7 +173,6 @@ stages: compatibilityiOSApp: $(System.DefaultWorkingDirectory)/src/Compatibility/ControlGallery/src/iOS/Compatibility.ControlGallery.iOS.csproj compatibilityiOSTestProject: $(System.DefaultWorkingDirectory)/src/Compatibility/ControlGallery/test/iOS.UITests/Compatibility.ControlGallery.iOS.UITests.csproj legacyAndroidApp: $(System.DefaultWorkingDirectory)/src/Compatibility/ControlGallery/src/Android/Compatibility.ControlGallery.Android.csproj - legacyAndroidTestProject: $(System.DefaultWorkingDirectory)/src/Compatibility/ControlGallery/test/Android.Appium.UITests/ControlGallery.Android.Appium.UITests.csproj legacyiOSApp: $(System.DefaultWorkingDirectory)/src/Compatibility/ControlGallery/src/iOS/Compatibility.ControlGallery.iOS.csproj - legacyiOSTestProject: $(System.DefaultWorkingDirectory)/src/Compatibility/ControlGallery/test/iOS.Appium.UITests/ControlGallery.iOS.Appium.UITests.csproj + From 86689ebd04240c01bc4071682524cd883b28e18f Mon Sep 17 00:00:00 2001 From: Mike Corsaro Date: Mon, 17 Jun 2024 14:36:19 -0700 Subject: [PATCH 13/41] Make titlebar button foreground colors use app theme --- src/Core/src/Platform/Windows/MauiWinUIWindow.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Core/src/Platform/Windows/MauiWinUIWindow.cs b/src/Core/src/Platform/Windows/MauiWinUIWindow.cs index 516cac5f12cd..04b61ed61a04 100644 --- a/src/Core/src/Platform/Windows/MauiWinUIWindow.cs +++ b/src/Core/src/Platform/Windows/MauiWinUIWindow.cs @@ -215,7 +215,8 @@ private void SetTileBarButtonColors() titleBar.ButtonBackgroundColor = Colors.Transparent; titleBar.ButtonInactiveBackgroundColor = Colors.Transparent; - titleBar.ButtonForegroundColor = _viewSettings.GetColorValue(ViewManagement.UIColorType.Foreground); + titleBar.ButtonForegroundColor = UI.Xaml.Application.Current.RequestedTheme == UI.Xaml.ApplicationTheme.Dark ? + Colors.White : Colors.Black; } } From ac397e4555ae5a7eba59284a0a9d094ff0ba3e1f Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Mon, 17 Jun 2024 21:52:58 +0000 Subject: [PATCH 14/41] Update dependencies from https://github.com/dotnet/xharness build 20240612.3 (#23088) Microsoft.DotNet.XHarness.CLI , Microsoft.DotNet.XHarness.TestRunners.Common , Microsoft.DotNet.XHarness.TestRunners.Xunit From Version 9.0.0-prerelease.24311.2 -> To Version 9.0.0-prerelease.24312.3 Co-authored-by: dotnet-maestro[bot] --- .config/dotnet-tools.json | 2 +- eng/Version.Details.xml | 12 ++++++------ eng/Versions.props | 6 +++--- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index 08371f46f87f..0dab7bf7fd78 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -21,7 +21,7 @@ ] }, "microsoft.dotnet.xharness.cli": { - "version": "9.0.0-prerelease.24311.2", + "version": "9.0.0-prerelease.24312.3", "commands": [ "xharness" ] diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 9b192028500b..4a57974289af 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,16 +1,16 @@ - + https://github.com/dotnet/xharness - 975b330d51119efc4884f7a323784662cbf74391 + 6ce15319de72ab6d4c3b0f4c40f59300cffc5450 - + https://github.com/dotnet/xharness - 975b330d51119efc4884f7a323784662cbf74391 + 6ce15319de72ab6d4c3b0f4c40f59300cffc5450 - + https://github.com/dotnet/xharness - 975b330d51119efc4884f7a323784662cbf74391 + 6ce15319de72ab6d4c3b0f4c40f59300cffc5450 diff --git a/eng/Versions.props b/eng/Versions.props index 922ed2da6856..b55e89cff6ae 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -104,9 +104,9 @@ <_HarfBuzzSharpVersion>7.3.0.2 <_SkiaSharpNativeAssetsVersion>0.0.0-commit.7af1d0840a381c0ce7ef2877454a88dbb2949686.1086 7.0.114 - 9.0.0-prerelease.24311.2 - 9.0.0-prerelease.24311.2 - 9.0.0-prerelease.24311.2 + 9.0.0-prerelease.24312.3 + 9.0.0-prerelease.24312.3 + 9.0.0-prerelease.24312.3 0.9.2 1.0.0.16 1.3.0 From 3f20f158abc6e6e0a2d7aca61f57bcc696f58034 Mon Sep 17 00:00:00 2001 From: Shane Neuville Date: Mon, 17 Jun 2024 17:18:55 -0500 Subject: [PATCH 15/41] Add additional logging for PopLifeCycle --- .../tests/Core.UnitTests/NavigationPageLifecycleTests.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/Controls/tests/Core.UnitTests/NavigationPageLifecycleTests.cs b/src/Controls/tests/Core.UnitTests/NavigationPageLifecycleTests.cs index 299e15b8e9b1..c2065b8aad00 100644 --- a/src/Controls/tests/Core.UnitTests/NavigationPageLifecycleTests.cs +++ b/src/Controls/tests/Core.UnitTests/NavigationPageLifecycleTests.cs @@ -60,6 +60,7 @@ public async Task PushLifeCycle(bool useMaui) [InlineData(true)] public async Task PopLifeCycle(bool useMaui) { + bool appearingShouldFireOnInitialPage = false; ContentPage initialPage = new ContentPage(); ContentPage pushedPage = new ContentPage(); @@ -82,14 +83,18 @@ void OnInitialPageAppearing(object sender, EventArgs e) _ = new TestWindow(nav); await waitForFirstAppearing.Task; - initialPage.Appearing += (sender, _) - => rootPageFiresAppearingAfterPop = (ContentPage)sender; + initialPage.Appearing += (sender, _) => + { + Assert.True(appearingShouldFireOnInitialPage); + rootPageFiresAppearingAfterPop = (ContentPage)sender; + }; pushedPage.Disappearing += (sender, _) => pageDisappeared = (ContentPage)sender; await nav.PushAsync(pushedPage); Assert.Null(rootPageFiresAppearingAfterPop); + appearingShouldFireOnInitialPage = true; Assert.Null(pageDisappeared); await nav.PopAsync(); From 4a53801a10f8f1af08179b60275f2679af0ff9a9 Mon Sep 17 00:00:00 2001 From: redth Date: Mon, 17 Jun 2024 21:58:59 -0400 Subject: [PATCH 16/41] Remove more legacy pipeline bits --- .../common/ui-tests-legacy-steps.yml | 118 ------------------ eng/pipelines/common/ui-tests.yml | 74 ----------- eng/pipelines/ui-tests.yml | 22 ---- 3 files changed, 214 deletions(-) delete mode 100644 eng/pipelines/common/ui-tests-legacy-steps.yml diff --git a/eng/pipelines/common/ui-tests-legacy-steps.yml b/eng/pipelines/common/ui-tests-legacy-steps.yml deleted file mode 100644 index ecf009a4dc4a..000000000000 --- a/eng/pipelines/common/ui-tests-legacy-steps.yml +++ /dev/null @@ -1,118 +0,0 @@ -parameters: - platform: '' # [ android, ios, windows, catalyst ] - path: '' # path to csproj - device: '' # the xharness device to use - cakeArgs: '' # additional cake args - app: '' #path to app to test - version: '' #the iOS version' - provisionatorChannel: 'latest' - agentPoolAccessToken: '' - targetSample: "dotnet-legacy-controlgallery" - configuration : "Release" - -steps: - - ${{ if eq(parameters.platform, 'ios')}}: - - bash: | - chmod +x $(System.DefaultWorkingDirectory)/eng/scripts/clean-bot.sh - $(System.DefaultWorkingDirectory)/eng/scripts/clean-bot.sh - displayName: 'Clean bot' - continueOnError: true - timeoutInMinutes: 60 - - - template: provision.yml - parameters: - skipProvisioning: ${{ eq(parameters.platform, 'windows') }} - skipAndroidSdks: ${{ ne(parameters.platform, 'android') }} - skipXcode: ${{ or(eq(parameters.platform, 'android'), eq(parameters.platform, 'windows')) }} - provisionatorChannel: ${{ parameters.provisionatorChannel }} - - - task: PowerShell@2 - condition: ne('${{ parameters.platform }}' , 'windows') - inputs: - targetType: 'inline' - script: | - defaults write -g NSAutomaticCapitalizationEnabled -bool false - defaults write -g NSAutomaticTextCompletionEnabled -bool false - defaults write -g NSAutomaticSpellingCorrectionEnabled -bool false - displayName: "Modify defaults" - continueOnError: true - - # AzDO hosted agents default to 1024x768; set something bigger for Windows UI tests - - task: ScreenResolutionUtility@1 - condition: eq('${{ parameters.platform }}' , 'windows') - inputs: - displaySettings: 'specific' - width: '1920' - height: '1080' - displayName: "Set screen resolution" - - - task: UseNode@1 - inputs: - version: "20.3.1" - displayName: "Install node" - - - pwsh: | - $fullLogsDir = Join-Path "$(LogDirectory)" "npm" - ./eng/scripts/appium-install.ps1 -logsDir "$fullLogsDir" - Dir -Recurse $(APPIUM_HOME) | Get-Childitem | Select Fullname - displayName: "Install Appium (Drivers)" - continueOnError: false - retryCountOnTaskFailure: 1 - env: - APPIUM_HOME: $(APPIUM_HOME) - - - pwsh: ./build.ps1 --target=dotnet --configuration="${{ parameters.configuration }}" --verbosity=diagnostic - displayName: 'Install .NET' - retryCountOnTaskFailure: 2 - env: - DOTNET_TOKEN: $(dotnetbuilds-internal-container-read-token) - PRIVATE_BUILD: $(PrivateBuild) - - - pwsh: echo "##vso[task.prependpath]$(DotNet.Dir)" - displayName: 'Add .NET to PATH' - - - pwsh: ./build.ps1 --target=dotnet-buildtasks --configuration="${{ parameters.configuration }}" - displayName: 'Build the MSBuild Tasks' - - - pwsh: ./build.ps1 --target=${{ parameters.targetSample }} --configuration="${{ parameters.configuration }}" --${{ parameters.platform }} --verbosity=diagnostic --usenuget=false - displayName: 'Build the Legacy ControlGallery' - - - bash: | - if [ -f "$HOME/Library/Logs/CoreSimulator/*" ]; then rm -r $HOME/Library/Logs/CoreSimulator/*; fi - if [ -f "$HOME/Library/Logs/DiagnosticReports/*" ]; then rm -r $HOME/Library/Logs/DiagnosticReports/*; fi - displayName: Delete Old Simulator Logs - condition: ${{ eq(parameters.platform, 'ios') }} - continueOnError: true - - - pwsh: ./build.ps1 -Script eng/devices/${{ parameters.platform }}.cake --target=uitest --project="${{ parameters.path }}" --appproject="${{ parameters.app }}" --device="${{ parameters.device }}" --apiversion="${{ parameters.version }}" --configuration="${{ parameters.configuration }}" --results="$(TestResultsDirectory)" --binlog="$(LogDirectory)" ${{ parameters.cakeArgs }} --verbosity=diagnostic - displayName: $(Agent.JobName) - ${{ if ne(parameters.platform, 'android')}}: - retryCountOnTaskFailure: 1 - env: - APPIUM_HOME: $(APPIUM_HOME) - - - bash: | - suffix=$(date +%Y%m%d%H%M%S) - zip -9r "$(LogDirectory)/CoreSimulatorLog_${suffix}.zip" "$HOME/Library/Logs/CoreSimulator/" - zip -9r "$(LogDirectory)/DiagnosticReports_${suffix}.zip" "$HOME/Library/Logs/DiagnosticReports/" - displayName: Zip Simulator Logs - condition: ${{ eq(parameters.platform, 'ios') }} - continueOnError: true - - - task: PublishTestResults@2 - displayName: Publish the $(System.PhaseName) test results - condition: always() - inputs: - testResultsFormat: VSTest - testResultsFiles: '$(TestResultsDirectory)/*.trx' - testRunTitle: '$(System.PhaseName)' - failTaskOnFailedTests: true - - - task: PublishBuildArtifacts@1 - condition: always() - displayName: publish artifacts - - # This must always be placed as the last step in the job - - template: agent-rebooter/mac.v1.yml@yaml-templates - parameters: - AgentPoolAccessToken: ${{ parameters.agentPoolAccessToken }} diff --git a/eng/pipelines/common/ui-tests.yml b/eng/pipelines/common/ui-tests.yml index dff176c43c35..9ae31afb61cb 100644 --- a/eng/pipelines/common/ui-tests.yml +++ b/eng/pipelines/common/ui-tests.yml @@ -5,14 +5,11 @@ parameters: macosPool: { } androidCompatibilityPool: { } iosCompatibilityPool: { } - androidLegacyPool: { } - iosLegacyPool: { } androidApiLevels: [ 30 ] iosVersions: [ 'latest' ] provisionatorChannel: 'latest' agentPoolAccessToken: '' runCompatibilityTests: false - runLegacyTests: true projects: - name: name desc: Human Description @@ -25,10 +22,6 @@ parameters: compatibilityAndroidTestProject: /optional/path/to/android.csproj compatibilityiOSTestProject: /optional/path/to/ios.csproj compatibilityiOSApp: /optional/path/to/app.csproj - legacyAndroidApp: /optional/path/to/app.csproj - legacyAndroidTestProject: /optional/path/to/android.csproj - legacyiOSTestProject: /optional/path/to/ios.csproj - legacyiOSApp: /optional/path/to/app.csproj stages: @@ -217,70 +210,3 @@ stages: device: ios-simulator-64_${{ version }} provisionatorChannel: ${{ parameters.provisionatorChannel }} agentPoolAccessToken: ${{ parameters.agentPoolAccessToken }} - - ${{ if eq(parameters.runLegacyTests, true) }}: - - stage: android_legacy_ui_tests - displayName: Android Legacy UITests - dependsOn: [] - jobs: - - ${{ each project in parameters.projects }}: - - ${{ if ne(project.android, '') }}: - - ${{ each api in parameters.androidApiLevels }}: - - ${{ if not(containsValue(project.androidApiLevelsExclude, api)) }}: - - job: android_legacy_ui_tests_${{ project.name }}_${{ api }} - timeoutInMinutes: 240 - workspace: - clean: all - displayName: ${{ coalesce(project.desc, project.name) }} (API ${{ api }}) - pool: ${{ parameters.androidLegacyPool }} - variables: - REQUIRED_XCODE: $(DEVICETESTS_REQUIRED_XCODE) - APPIUM_HOME: $(System.DefaultWorkingDirectory)/.appium/ - steps: - - template: ui-tests-legacy-steps.yml - parameters: - platform: android - version: ${{ api }} - path: ${{ project.legacyAndroidTestProject }} - app: ${{ project.legacyAndroidApp }} - targetSample: "dotnet-legacy-controlgallery-android" - ${{ if eq(api, 27) }}: - device: android-emulator-32_${{ api }} - ${{ if not(eq(api, 27)) }}: - device: android-emulator-64_${{ api }} - provisionatorChannel: ${{ parameters.provisionatorChannel }} - agentPoolAccessToken: ${{ parameters.agentPoolAccessToken }} - - - stage: ios_legacy_ui_tests - displayName: iOS Legacy UITests - dependsOn: [] - jobs: - - ${{ each project in parameters.projects }}: - - ${{ if ne(project.ios, '') }}: - - ${{ each version in parameters.iosVersions }}: - - ${{ if not(containsValue(project.iosVersionsExclude, version)) }}: - - job: ios_legacy_ui_tests_${{ project.name }}_${{ replace(version, '.', '_') }} - timeoutInMinutes: 240 - workspace: - clean: all - displayName: ${{ coalesce(project.desc, project.name) }} (v${{ version }}) - pool: ${{ parameters.iosLegacyPool }} - variables: - REQUIRED_XCODE: $(DEVICETESTS_REQUIRED_XCODE) - APPIUM_HOME: $(System.DefaultWorkingDirectory)/.appium/ - steps: - - template: ui-tests-legacy-steps.yml - parameters: - platform: ios - ${{ if eq(version, 'latest') }}: - version: 16.4 - ${{ if ne(version, 'latest') }}: - version: ${{ version }} - path: ${{ project.legacyiOSTestProject }} - app: ${{ project.legacyiOSApp }} - targetSample: "dotnet-legacy-controlgallery-ios" - ${{ if eq(version, 'latest') }}: - device: ios-simulator-64 - ${{ if ne(version, 'latest') }}: - device: ios-simulator-64_${{ version }} - provisionatorChannel: ${{ parameters.provisionatorChannel }} - agentPoolAccessToken: ${{ parameters.agentPoolAccessToken }} \ No newline at end of file diff --git a/eng/pipelines/ui-tests.yml b/eng/pipelines/ui-tests.yml index 851a0eddc2d4..7e5f18d85c20 100644 --- a/eng/pipelines/ui-tests.yml +++ b/eng/pipelines/ui-tests.yml @@ -109,24 +109,6 @@ parameters: - macOS.Name -equals Ventura - macOS.Architecture -equals x64 - - name: androidLegacyPool - type: object - default: - name: $(androidTestsVmPool) - vmImage: $(androidTestsVmImage) - demands: - - macOS.Name -equals Ventura - - macOS.Architecture -equals x64 - - - name: iosLegacyPool - type: object - default: - name: $(iosTestsVmPool) - vmImage: $(iosTestsVmImage) - demands: - - macOS.Name -equals Ventura - - macOS.Architecture -equals x64 - resources: repositories: - repository: yaml-templates @@ -145,8 +127,6 @@ stages: macosPool: ${{ parameters.macosPool }} androidCompatibilityPool: ${{ parameters.androidCompatibilityPool }} iosCompatibilityPool: ${{ parameters.iosCompatibilityPool }} - iosLegacyPool: ${{ parameters.iosLegacyPool }} - androidLegacyPool: ${{ parameters.androidLegacyPool }} agentPoolAccessToken: $(AgentPoolAccessToken) ${{ if or(parameters.BuildEverything, and(ne(variables['Build.Reason'], 'PullRequest'), eq(variables['System.TeamProject'], 'devdiv'))) }}: androidApiLevels: [ 30 ] @@ -172,7 +152,5 @@ stages: compatibilityAndroidTestProject: $(System.DefaultWorkingDirectory)/src/Compatibility/ControlGallery/test/Android.UITests/Compatibility.ControlGallery.Android.UITests.csproj compatibilityiOSApp: $(System.DefaultWorkingDirectory)/src/Compatibility/ControlGallery/src/iOS/Compatibility.ControlGallery.iOS.csproj compatibilityiOSTestProject: $(System.DefaultWorkingDirectory)/src/Compatibility/ControlGallery/test/iOS.UITests/Compatibility.ControlGallery.iOS.UITests.csproj - legacyAndroidApp: $(System.DefaultWorkingDirectory)/src/Compatibility/ControlGallery/src/Android/Compatibility.ControlGallery.Android.csproj - legacyiOSApp: $(System.DefaultWorkingDirectory)/src/Compatibility/ControlGallery/src/iOS/Compatibility.ControlGallery.iOS.csproj From 7fad926c0c5130541543376ba75322f510c9b5bb Mon Sep 17 00:00:00 2001 From: Vitaly Knyazev Date: Tue, 18 Jun 2024 16:42:29 +0100 Subject: [PATCH 17/41] [iOS] Fixed NRE after calling ViewCell.ForceUpdateSize (#23094) * [iOS] Fixed NRE after calling ViewCell.ForceUpdateSize * - add test --------- Co-authored-by: Shane Neuville --- src/Controls/src/Core/Cells/Cell.cs | 2 +- .../tests/Core.UnitTests/ListViewTests.cs | 20 +++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/Controls/src/Core/Cells/Cell.cs b/src/Controls/src/Core/Cells/Cell.cs index 2da47d8120ec..c82f661fe2b6 100644 --- a/src/Controls/src/Core/Cells/Cell.cs +++ b/src/Controls/src/Core/Cells/Cell.cs @@ -273,7 +273,7 @@ async void OnForceUpdateSizeRequested() // don't run more than once per 16 milliseconds await Task.Delay(TimeSpan.FromMilliseconds(16)); ForceUpdateSizeRequested?.Invoke(this, null); - Handler.Invoke("ForceUpdateSizeRequested", null); + Handler?.Invoke("ForceUpdateSizeRequested", null); _nextCallToForceUpdateSizeQueued = false; } diff --git a/src/Controls/tests/Core.UnitTests/ListViewTests.cs b/src/Controls/tests/Core.UnitTests/ListViewTests.cs index e1bd22ce486f..78fe5abcbb10 100644 --- a/src/Controls/tests/Core.UnitTests/ListViewTests.cs +++ b/src/Controls/tests/Core.UnitTests/ListViewTests.cs @@ -1649,5 +1649,25 @@ public void DoesNotRetainInRecycleMode() Assert.False(ReferenceEquals(item1, item2)); } + + [Fact] + public void ForceUpdateSizeCalledOnViewCellDoesntCrash() + { + var list = new ListView(){ + HasUnevenRows = true + }; + + list.ItemTemplate = new DataTemplate(() => + { + return new ViewCell { View = new Label() }; + } + ); + + list.ItemsSource = new[] { "Hi" }; + + var element = (ViewCell)list.TemplatedItems[0]; + + element.ForceUpdateSize(); + } } } From 0f6a922aa4017c068878aca8753af206be33ff96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Rozs=C3=ADval?= Date: Tue, 18 Jun 2024 20:17:31 +0200 Subject: [PATCH 18/41] Add x:DataType to the carousel view UI tests (#23113) --- .../Elements/CarouselViewCoreGalleryPage.xaml | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/Controls/tests/TestCases/Elements/CarouselViewCoreGalleryPage.xaml b/src/Controls/tests/TestCases/Elements/CarouselViewCoreGalleryPage.xaml index d8af44621577..4e4debb65818 100644 --- a/src/Controls/tests/TestCases/Elements/CarouselViewCoreGalleryPage.xaml +++ b/src/Controls/tests/TestCases/Elements/CarouselViewCoreGalleryPage.xaml @@ -2,8 +2,10 @@ + Title="CarouselView Core Gallery" + x:DataType="local:CarouselViewModel"> @@ -25,6 +27,7 @@ Grid.Column="0" /> - + diff --git a/src/Controls/tests/TestCases.Mac.Tests/Controls.TestCases.Mac.Tests.csproj b/src/Controls/tests/TestCases.Mac.Tests/Controls.TestCases.Mac.Tests.csproj index 19739d6177d6..408168b2f848 100644 --- a/src/Controls/tests/TestCases.Mac.Tests/Controls.TestCases.Mac.Tests.csproj +++ b/src/Controls/tests/TestCases.Mac.Tests/Controls.TestCases.Mac.Tests.csproj @@ -10,7 +10,7 @@ - + diff --git a/src/Controls/tests/TestCases.WinUI.Tests/Controls.TestCases.WinUI.Tests.csproj b/src/Controls/tests/TestCases.WinUI.Tests/Controls.TestCases.WinUI.Tests.csproj index 935c059d6d57..3279ab0fd0a9 100644 --- a/src/Controls/tests/TestCases.WinUI.Tests/Controls.TestCases.WinUI.Tests.csproj +++ b/src/Controls/tests/TestCases.WinUI.Tests/Controls.TestCases.WinUI.Tests.csproj @@ -10,7 +10,7 @@ - + diff --git a/src/Controls/tests/TestCases.iOS.Tests/Controls.TestCases.iOS.Tests.csproj b/src/Controls/tests/TestCases.iOS.Tests/Controls.TestCases.iOS.Tests.csproj index 8d90bbb080e1..d781e1e9465f 100644 --- a/src/Controls/tests/TestCases.iOS.Tests/Controls.TestCases.iOS.Tests.csproj +++ b/src/Controls/tests/TestCases.iOS.Tests/Controls.TestCases.iOS.Tests.csproj @@ -10,7 +10,7 @@ - + diff --git a/src/TestUtils/src/UITest.Appium/Actions/AppiumLifecycleActions.cs b/src/TestUtils/src/UITest.Appium/Actions/AppiumLifecycleActions.cs index 1132c1943ebe..fd1d13e24037 100644 --- a/src/TestUtils/src/UITest.Appium/Actions/AppiumLifecycleActions.cs +++ b/src/TestUtils/src/UITest.Appium/Actions/AppiumLifecycleActions.cs @@ -55,19 +55,21 @@ CommandResponse LaunchApp(IDictionary parameters) return CommandResponse.FailedEmptyResponse; if (_app.GetTestDevice() == TestDevice.Mac) - { + { _app.Driver.ExecuteScript("macos: activateApp", new Dictionary { { "bundleId", _app.GetAppId() }, }); } - else if (_app.GetTestDevice() == TestDevice.Windows) + else if (_app.Driver is WindowsDriver windowsDriver) { -#pragma warning disable CS0618 // Type or member is obsolete - _app.Driver.LaunchApp(); -#pragma warning restore CS0618 // Type or member is obsolete + // Appium driver removed the LaunchApp method in 5.0.0, so we need to use the executeScript method instead + // Currently the appium-windows-driver reports the following commands as compatible: + // startRecordingScreen,stopRecordingScreen,launchApp,closeApp,deleteFile,deleteFolder, + // click,scroll,clickAndDrag,hover,keys,setClipboard,getClipboard + windowsDriver.ExecuteScript("windows: launchApp", [_app.GetAppId()]); } - else + else { _app.Driver.ActivateApp(_app.GetAppId()); } @@ -127,7 +129,7 @@ CommandResponse CloseApp(IDictionary parameters) } catch (Exception) { - // TODO Pass in logger so we can log these exceptions + // TODO: Pass in logger so we can log these exceptions // Occasionally the app seems to get so locked up it can't // even report back the appstate. In that case, we'll just @@ -143,11 +145,12 @@ CommandResponse CloseApp(IDictionary parameters) { "bundleId", _app.GetAppId() }, }); } - else if (_app.GetTestDevice() == TestDevice.Windows) + else if (_app.Driver is WindowsDriver windowsDriver) { - #pragma warning disable CS0618 // Type or member is obsolete - _app.Driver.CloseApp(); - #pragma warning restore CS0618 // Type or member is obsolete + // This is still here for now, but it looks like it will get removed just like + // LaunchApp was in 5.0.0, in which case we may need to use: + // windowsDriver.ExecuteScript("windows: closeApp", [_app.GetAppId()]); + windowsDriver.CloseApp(); } else { diff --git a/src/TestUtils/src/UITest.Appium/UITest.Appium.csproj b/src/TestUtils/src/UITest.Appium/UITest.Appium.csproj index 3d33c1a996c8..08b934d89b4c 100644 --- a/src/TestUtils/src/UITest.Appium/UITest.Appium.csproj +++ b/src/TestUtils/src/UITest.Appium/UITest.Appium.csproj @@ -7,8 +7,7 @@ - - + From b368e8b9ed3875bd7bfa51a163eb166da5322279 Mon Sep 17 00:00:00 2001 From: Shane Neuville Date: Wed, 19 Jun 2024 07:46:21 -0500 Subject: [PATCH 25/41] Use correct interface type in FrameRenderer (#23124) --- global.json | 3 +++ .../Handlers/Android/FrameRenderer.cs | 2 +- .../Tests/Issues/Issue18526.cs | 26 +++++++++++++++++++ .../tests/TestCases/Issues/Issue18526.xaml | 22 ++++++++++++++++ .../tests/TestCases/Issues/Issue18526.xaml.cs | 14 ++++++++++ 5 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue18526.cs create mode 100644 src/Controls/tests/TestCases/Issues/Issue18526.xaml create mode 100644 src/Controls/tests/TestCases/Issues/Issue18526.xaml.cs diff --git a/global.json b/global.json index 2b3c65d222ba..d05a39062b91 100644 --- a/global.json +++ b/global.json @@ -6,5 +6,8 @@ "MSBuild.Sdk.Extras": "3.0.44", "Microsoft.Build.NoTargets": "3.7.0", "Microsoft.DotNet.Arcade.Sdk": "8.0.0-beta.24310.5" + }, + "sdk": { + "allowPrerelease": false } } diff --git a/src/Controls/src/Core/Compatibility/Handlers/Android/FrameRenderer.cs b/src/Controls/src/Core/Compatibility/Handlers/Android/FrameRenderer.cs index 6cab4f0a2e94..bb64e53baf5b 100644 --- a/src/Controls/src/Core/Compatibility/Handlers/Android/FrameRenderer.cs +++ b/src/Controls/src/Core/Compatibility/Handlers/Android/FrameRenderer.cs @@ -176,7 +176,7 @@ protected override void OnLayout(bool changed, int l, int t, int r, int b) if (Element.Handler is IPlatformViewHandler pvh && - Element is IContentView cv) + Element is ICrossPlatformLayout cv) { pvh.LayoutVirtualView(l, t, r, b, cv.CrossPlatformArrange); } diff --git a/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue18526.cs b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue18526.cs new file mode 100644 index 000000000000..f05e62185871 --- /dev/null +++ b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue18526.cs @@ -0,0 +1,26 @@ +using NUnit.Framework; +using NUnit.Framework.Legacy; +using UITest.Appium; +using UITest.Core; + +namespace Microsoft.Maui.TestCases.Tests.Issues; + +public class Issue18526 : _IssuesUITest +{ + public override string Issue => "Border not rendering inside a frame"; + + public Issue18526(TestDevice device) + : base(device) + { } + + [Test] + [Category(UITestCategories.Frame)] + public void BorderShouldRender() + { + var label = App.WaitForElement("label"); + var size = label.GetRect(); + Assert.That(label.GetText(), Is.EqualTo(".NET MAUI")); + Assert.That(size.Width, Is.GreaterThan(0)); + Assert.That(size.Height, Is.GreaterThan(0)); + } +} \ No newline at end of file diff --git a/src/Controls/tests/TestCases/Issues/Issue18526.xaml b/src/Controls/tests/TestCases/Issues/Issue18526.xaml new file mode 100644 index 000000000000..06979dc3ffe6 --- /dev/null +++ b/src/Controls/tests/TestCases/Issues/Issue18526.xaml @@ -0,0 +1,22 @@ + + + + + + + + \ No newline at end of file diff --git a/src/Controls/tests/TestCases/Issues/Issue18526.xaml.cs b/src/Controls/tests/TestCases/Issues/Issue18526.xaml.cs new file mode 100644 index 000000000000..0b00e6317422 --- /dev/null +++ b/src/Controls/tests/TestCases/Issues/Issue18526.xaml.cs @@ -0,0 +1,14 @@ +using Microsoft.Maui.Controls; +using Microsoft.Maui.Controls.Xaml; + +namespace Maui.Controls.Sample.Issues; + +[Issue(IssueTracker.Github, 18526, "Border not rendering inside a frame", PlatformAffected.All)] + +public partial class Issue18526 : ContentPage +{ + public Issue18526() + { + InitializeComponent(); + } +} \ No newline at end of file From 9f0d6166e62f6cba5e659a957aaa9cb7e71dea48 Mon Sep 17 00:00:00 2001 From: Shane Neuville Date: Wed, 19 Jun 2024 23:08:10 -0500 Subject: [PATCH 26/41] Use correct interface type in FrameRenderer (#23124) (#23146) --- .../Handlers/Android/FrameRenderer.cs | 2 +- .../Tests/Issues/Issue18526.cs | 26 +++++++++++++++++++ .../tests/TestCases/Issues/Issue18526.xaml | 22 ++++++++++++++++ .../tests/TestCases/Issues/Issue18526.xaml.cs | 14 ++++++++++ 4 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue18526.cs create mode 100644 src/Controls/tests/TestCases/Issues/Issue18526.xaml create mode 100644 src/Controls/tests/TestCases/Issues/Issue18526.xaml.cs diff --git a/src/Controls/src/Core/Compatibility/Handlers/Android/FrameRenderer.cs b/src/Controls/src/Core/Compatibility/Handlers/Android/FrameRenderer.cs index 6cab4f0a2e94..bb64e53baf5b 100644 --- a/src/Controls/src/Core/Compatibility/Handlers/Android/FrameRenderer.cs +++ b/src/Controls/src/Core/Compatibility/Handlers/Android/FrameRenderer.cs @@ -176,7 +176,7 @@ protected override void OnLayout(bool changed, int l, int t, int r, int b) if (Element.Handler is IPlatformViewHandler pvh && - Element is IContentView cv) + Element is ICrossPlatformLayout cv) { pvh.LayoutVirtualView(l, t, r, b, cv.CrossPlatformArrange); } diff --git a/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue18526.cs b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue18526.cs new file mode 100644 index 000000000000..f05e62185871 --- /dev/null +++ b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue18526.cs @@ -0,0 +1,26 @@ +using NUnit.Framework; +using NUnit.Framework.Legacy; +using UITest.Appium; +using UITest.Core; + +namespace Microsoft.Maui.TestCases.Tests.Issues; + +public class Issue18526 : _IssuesUITest +{ + public override string Issue => "Border not rendering inside a frame"; + + public Issue18526(TestDevice device) + : base(device) + { } + + [Test] + [Category(UITestCategories.Frame)] + public void BorderShouldRender() + { + var label = App.WaitForElement("label"); + var size = label.GetRect(); + Assert.That(label.GetText(), Is.EqualTo(".NET MAUI")); + Assert.That(size.Width, Is.GreaterThan(0)); + Assert.That(size.Height, Is.GreaterThan(0)); + } +} \ No newline at end of file diff --git a/src/Controls/tests/TestCases/Issues/Issue18526.xaml b/src/Controls/tests/TestCases/Issues/Issue18526.xaml new file mode 100644 index 000000000000..06979dc3ffe6 --- /dev/null +++ b/src/Controls/tests/TestCases/Issues/Issue18526.xaml @@ -0,0 +1,22 @@ + + + + + + + + \ No newline at end of file diff --git a/src/Controls/tests/TestCases/Issues/Issue18526.xaml.cs b/src/Controls/tests/TestCases/Issues/Issue18526.xaml.cs new file mode 100644 index 000000000000..0b00e6317422 --- /dev/null +++ b/src/Controls/tests/TestCases/Issues/Issue18526.xaml.cs @@ -0,0 +1,14 @@ +using Microsoft.Maui.Controls; +using Microsoft.Maui.Controls.Xaml; + +namespace Maui.Controls.Sample.Issues; + +[Issue(IssueTracker.Github, 18526, "Border not rendering inside a frame", PlatformAffected.All)] + +public partial class Issue18526 : ContentPage +{ + public Issue18526() + { + InitializeComponent(); + } +} \ No newline at end of file From a984765999315033592f1256b2bc3a0da9cb2782 Mon Sep 17 00:00:00 2001 From: Matthew Leibowitz Date: Thu, 20 Jun 2024 21:00:28 +0800 Subject: [PATCH 27/41] Squashed commit of the following: (#19629) commit f6c3bfae64a0494762d5c98dbfc975d1231b1d13 Merge: d0b3f84b74 3143629c3c Author: Matthew Leibowitz Date: Mon Jun 17 19:58:40 2024 +0800 Merge remote-tracking branch 'origin/main' into dev/macos-actionsheet commit d0b3f84b74d40bab285b8a8cc3ed5f9cafd01a28 Author: Matthew Leibowitz Date: Tue Jun 11 05:00:38 2024 +0800 Fix the older macOS testing commit 3dc6b4da82b5c03143f921344b0024eb72df293a Author: Matthew Leibowitz Date: Mon Jun 10 23:40:40 2024 +0800 macOS 13 things commit e3e48e4581962266190cde3b91a3b6e5fe1586db Author: Matthew Leibowitz Date: Sat Jun 8 02:15:55 2024 +0800 docs commit 693d79c69652a6cb1a2cec255c88819f55c6f76b Merge: 3dbce49d7f a3c872dfbf Author: Matthew Leibowitz Date: Sat Jun 8 02:08:31 2024 +0800 Merge remote-tracking branch 'origin/main' into dev/macos-actionsheet commit 3dbce49d7f0ecd0fa095ab2e64a043a654c29679 Merge: 17ea9c6fc5 93a1bc49d7 Author: Matthew Leibowitz Date: Sat Jun 8 02:06:16 2024 +0800 Merge remote-tracking branch 'origin/main' into dev/macos-actionsheet commit 17ea9c6fc5d2c6e765754e2348a5d67b10af53c4 Author: Matthew Leibowitz Date: Sat Jun 8 02:05:42 2024 +0800 Fix the tests commit 026da412c5a323956ffdf8b27793596bfafa34f7 Author: Matthew Leibowitz Date: Fri Jun 7 03:56:26 2024 +0800 fixes commit d2b85d52078f32551ce777d7c57660b512f4a425 Author: Matthew Leibowitz Date: Thu Jun 6 23:58:33 2024 +0800 namespaces commit 9fa77cd7ab3180a123cc9cc0b77eb2387181bf2a Merge: 3f9596b976 9d71d3212a Author: Matthew Leibowitz Date: Thu Jun 6 23:57:00 2024 +0800 Merge branch 'main' into dev/macos-actionsheet # Conflicts: # src/Controls/samples/Controls.Sample.UITests/Test.cs # src/Controls/src/Core/Platform/AlertManager/AlertManager.iOS.cs # src/Controls/tests/TestCases.Shared.Tests/Tests/Concepts/AlertsGalleryTests.cs # src/Controls/tests/TestCases/Concepts/AlertsGalleryPage.cs # src/TestUtils/src/UITest.Appium/AppiumCatalystApp.cs # src/TestUtils/src/UITest.Appium/HelperExtensions.cs commit 3f9596b976170023eade99f3e39cdf7946fde523 Author: Matthew Leibowitz Date: Sat Dec 30 09:29:31 2023 +0200 Add some UI tests Done: iOS/macOS/Android. TODO: Windows commit 68c930ffe6cacf8f35d7a1db6aa93500056a4892 Author: Matthew Leibowitz Date: Tue Dec 19 18:15:51 2023 +0200 macOS does not use PopoverPresentationController Fixes #18156 --- src/Controls/src/Core/Page/Page.cs | 2 +- .../Platform/AlertManager/AlertManager.iOS.cs | 9 +- src/Controls/tests/CustomAttributes/Test.cs | 10 ++ .../Tests/Concepts/AlertsGalleryTests.cs | 149 ++++++++++++++++++ .../TestCases/Concepts/AlertsGalleryPage.cs | 96 +++++++++++ .../tests/TestCases/CoreViews/CorePageView.cs | 1 + .../Actions/AppiumAndroidAlertActions.cs | 92 +++++++++++ .../Actions/AppiumAppleAlertActions.cs | 80 ++++++++++ .../Actions/AppiumCatalystAlertActions.cs | 68 ++++++++ .../Actions/AppiumIOSAlertActions.cs | 29 ++++ .../src/UITest.Appium/AppiumAndroidApp.cs | 1 + .../src/UITest.Appium/AppiumCatalystApp.cs | 1 + .../src/UITest.Appium/AppiumIOSApp.cs | 1 + .../src/UITest.Appium/AppiumQuery.cs | 13 ++ .../src/UITest.Appium/HelperExtensions.cs | 87 +++++++++- src/TestUtils/src/UITest.Core/IQuery.cs | 1 + 16 files changed, 632 insertions(+), 8 deletions(-) create mode 100644 src/Controls/tests/TestCases.Shared.Tests/Tests/Concepts/AlertsGalleryTests.cs create mode 100644 src/Controls/tests/TestCases/Concepts/AlertsGalleryPage.cs create mode 100644 src/TestUtils/src/UITest.Appium/Actions/AppiumAndroidAlertActions.cs create mode 100644 src/TestUtils/src/UITest.Appium/Actions/AppiumAppleAlertActions.cs create mode 100644 src/TestUtils/src/UITest.Appium/Actions/AppiumCatalystAlertActions.cs create mode 100644 src/TestUtils/src/UITest.Appium/Actions/AppiumIOSAlertActions.cs diff --git a/src/Controls/src/Core/Page/Page.cs b/src/Controls/src/Core/Page/Page.cs index bc49235eccba..007b91ce6c84 100644 --- a/src/Controls/src/Core/Page/Page.cs +++ b/src/Controls/src/Core/Page/Page.cs @@ -282,7 +282,7 @@ public Task DisplayActionSheet(string title, string cancel, string destr /// Displays a platform action sheet, allowing the application user to choose from several buttons. /// /// Title of the displayed action sheet. Can be to hide the title. - /// Text to be displayed in the 'Cancel' button. Can be null to hide the action. + /// Text to be displayed in the 'Cancel' button. Can be null to hide the cancel action. /// Text to be displayed in the 'Destruct' button. Can be to hide the destructive option. /// The flow direction to be used by the action sheet. /// Text labels for additional buttons. diff --git a/src/Controls/src/Core/Platform/AlertManager/AlertManager.iOS.cs b/src/Controls/src/Core/Platform/AlertManager/AlertManager.iOS.cs index e4323b096bbf..14a8c19e4988 100644 --- a/src/Controls/src/Core/Platform/AlertManager/AlertManager.iOS.cs +++ b/src/Controls/src/Core/Platform/AlertManager/AlertManager.iOS.cs @@ -187,12 +187,15 @@ static void PresentPopUp(Page sender, Window virtualView, UIWindow platformView, presentingWindow = senderPageWindow; } - if (UIDevice.CurrentDevice.UserInterfaceIdiom == UIUserInterfaceIdiom.Pad && arguments != null) + if (UIDevice.CurrentDevice.UserInterfaceIdiom == UIUserInterfaceIdiom.Pad && + arguments is not null && + alert.PopoverPresentationController is not null && + platformView.RootViewController?.View is not null) { var topViewController = GetTopUIViewController(presentingWindow); UIDevice.CurrentDevice.BeginGeneratingDeviceOrientationNotifications(); var observer = NSNotificationCenter.DefaultCenter.AddObserver(UIDevice.OrientationDidChangeNotification, - n => { alert.PopoverPresentationController.SourceRect = topViewController.View.Bounds; }); + n => alert.PopoverPresentationController.SourceRect = topViewController.View.Bounds); arguments.Result.Task.ContinueWith(t => { @@ -216,7 +219,7 @@ static void PresentPopUp(Page sender, Window virtualView, UIWindow platformView, static UIViewController GetTopUIViewController(UIWindow platformWindow) { var topUIViewController = platformWindow.RootViewController; - while (topUIViewController.PresentedViewController is not null) + while (topUIViewController?.PresentedViewController is not null) { topUIViewController = topUIViewController.PresentedViewController; } diff --git a/src/Controls/tests/CustomAttributes/Test.cs b/src/Controls/tests/CustomAttributes/Test.cs index ae46f9c3a975..1eed63091e90 100644 --- a/src/Controls/tests/CustomAttributes/Test.cs +++ b/src/Controls/tests/CustomAttributes/Test.cs @@ -744,6 +744,16 @@ public enum InputTransparency CascadeTransLayoutOverlayWithButton, } + public enum Alerts + { + AlertCancel, + AlertAcceptCancelClickAccept, + AlertAcceptCancelClickCancel, + ActionSheetClickItem, + ActionSheetClickCancel, + ActionSheetClickDestroy, + } + public static class InputTransparencyMatrix { // this is both for color diff and cols diff --git a/src/Controls/tests/TestCases.Shared.Tests/Tests/Concepts/AlertsGalleryTests.cs b/src/Controls/tests/TestCases.Shared.Tests/Tests/Concepts/AlertsGalleryTests.cs new file mode 100644 index 000000000000..5527b2fa9bb6 --- /dev/null +++ b/src/Controls/tests/TestCases.Shared.Tests/Tests/Concepts/AlertsGalleryTests.cs @@ -0,0 +1,149 @@ +using NUnit.Framework; +using NUnit.Framework.Legacy; +using UITest.Appium; +using UITest.Core; + +namespace Microsoft.Maui.TestCases.Tests +{ + public class AlertsGalleryTests : CoreGalleryBasePageTest + { + public AlertsGalleryTests(TestDevice device) + : base(device) + { + } + + protected override void NavigateToGallery() + { + App.NavigateToGallery("Alerts Gallery"); + } + +// TODO: UI testing alert code is not yet implemented on Windows. +#if !WINDOWS + [Test] + public void AlertCancel() + { + var test = Test.Alerts.AlertCancel; + + var remote = new EventViewContainerRemote(UITestContext, test); + remote.GoTo(test.ToString()); + + var textBeforeClick = remote.GetEventLabel().GetText(); + ClassicAssert.AreEqual($"Event: {test} (none)", textBeforeClick); + + remote.TapView(); + + var alert = App.WaitForElement(() => App.GetAlert()); + ClassicAssert.NotNull(alert); + + var alertText = alert.GetAlertText(); + CollectionAssert.Contains(alertText, "Alert Title Here"); + CollectionAssert.Contains(alertText, "Alert Message Here"); + + var buttons = alert.GetAlertButtons(); + CollectionAssert.IsNotEmpty(buttons); + ClassicAssert.True(buttons.Count == 1, $"Expected 1 buttonText, found {buttons.Count}."); + + var cancel = buttons.First(); + ClassicAssert.AreEqual("CANCEL", cancel.GetText()); + + cancel.Click(); + + App.WaitForNoElement(() => App.GetAlert()); + + var textAfterClick = remote.GetEventLabel().GetText(); + ClassicAssert.AreEqual($"Event: {test} (SUCCESS 1)", textAfterClick); + } + + [Test] + [TestCase(Test.Alerts.AlertAcceptCancelClickAccept, "ACCEPT")] + [TestCase(Test.Alerts.AlertAcceptCancelClickCancel, "CANCEL")] + public void AlertAcceptCancel(Test.Alerts test, string buttonText) + { + var remote = new EventViewContainerRemote(UITestContext, test); + remote.GoTo(test.ToString()); + + var textBeforeClick = remote.GetEventLabel().GetText(); + ClassicAssert.AreEqual($"Event: {test} (none)", textBeforeClick); + + remote.TapView(); + + var alert = App.WaitForElement(() => App.GetAlert()); + ClassicAssert.NotNull(alert); + + var alertText = alert.GetAlertText(); + CollectionAssert.Contains(alertText, "Alert Title Here"); + CollectionAssert.Contains(alertText, "Alert Message Here"); + + var buttons = alert.GetAlertButtons() + .Select(b => (Element: b, Text: b.GetText())) + .ToList(); + CollectionAssert.IsNotEmpty(buttons); + ClassicAssert.True(buttons.Count == 2, $"Expected 2 buttons, found {buttons.Count}."); + CollectionAssert.Contains(buttons.Select(b => b.Text), "ACCEPT"); + CollectionAssert.Contains(buttons.Select(b => b.Text), "CANCEL"); + + var button = buttons.Single(b => b.Text == buttonText); + button.Element.Click(); + + App.WaitForNoElement(() => App.GetAlert()); + + var textAfterClick = remote.GetEventLabel().GetText(); + ClassicAssert.AreEqual($"Event: {test} (SUCCESS 1)", textAfterClick); + } + + [Test] + [TestCase(Test.Alerts.ActionSheetClickItem, "ITEM 2")] + [TestCase(Test.Alerts.ActionSheetClickCancel, "CANCEL")] + [TestCase(Test.Alerts.ActionSheetClickDestroy, "DESTROY")] + public void ActionSheetClickItem(Test.Alerts test, string itemText) + { + var remote = new EventViewContainerRemote(UITestContext, test); + remote.GoTo(test.ToString()); + + var textBeforeClick = remote.GetEventLabel().GetText(); + ClassicAssert.AreEqual($"Event: {test} (none)", textBeforeClick); + + remote.TapView(); + + var alert = App.WaitForElement(() => App.GetAlert()); + ClassicAssert.NotNull(alert); + + var alertText = alert.GetAlertText(); + CollectionAssert.Contains(alertText, "Action Sheet Title Here"); + + var buttons = alert.GetAlertButtons() + .Select(b => (Element: b, Text: b.GetText())) + .ToList(); + CollectionAssert.IsNotEmpty(buttons); + ClassicAssert.True(buttons.Count >= 4 && buttons.Count <= 5, $"Expected 4 or 5 buttons, found {buttons.Count}."); + CollectionAssert.Contains(buttons.Select(b => b.Text), "DESTROY"); + CollectionAssert.Contains(buttons.Select(b => b.Text), "ITEM 1"); + CollectionAssert.Contains(buttons.Select(b => b.Text), "ITEM 2"); + CollectionAssert.Contains(buttons.Select(b => b.Text), "ITEM 3"); + + // handle the case where the dismiss button is an actual button + if (buttons.Count == 5) + CollectionAssert.Contains(buttons.Select(b => b.Text), "CANCEL"); + + if (buttons.Count == 4 && itemText == "CANCEL") + { + // handle the case where the dismiss button is a "click outside the popup" + + alert.DismissAlert(); + } + else + { + // handle the case where the dismiss button is an actual button + + var button = buttons.Single(b => b.Text == itemText); + button.Element.Click(); + } + + App.WaitForNoElement(() => App.GetAlert()); + + var textAfterClick = remote.GetEventLabel().GetText(); + ClassicAssert.AreEqual($"Event: {test} (SUCCESS 1)", textAfterClick); + } +#endif + } +} diff --git a/src/Controls/tests/TestCases/Concepts/AlertsGalleryPage.cs b/src/Controls/tests/TestCases/Concepts/AlertsGalleryPage.cs new file mode 100644 index 000000000000..d4756fc656b0 --- /dev/null +++ b/src/Controls/tests/TestCases/Concepts/AlertsGalleryPage.cs @@ -0,0 +1,96 @@ +using System; +using System.Threading.Tasks; +using Microsoft.Maui.Controls; + +namespace Maui.Controls.Sample +{ + internal class AlertsGalleryPage : CoreGalleryBasePage + { + protected override void Build() + { + // ALERTS + + // Test with a single button alert that can be dismissed by tapping the button + Add(Test.Alerts.AlertCancel, async t => + { + await DisplayAlert( + "Alert Title Here", + "Alert Message Here", + "CANCEL"); + t.ReportSuccessEvent(); + }); + + // Test alert with options to Accept or Cancel, Accept is the correct option + Add(Test.Alerts.AlertAcceptCancelClickAccept, async t => + { + var result = await DisplayAlert( + "Alert Title Here", + "Alert Message Here", + "ACCEPT", "CANCEL"); + if (result) + t.ReportSuccessEvent(); + else + t.ReportFailEvent(); + }); + + // Test alert with options to Accept or Cancel, Cancel is the correct option + Add(Test.Alerts.AlertAcceptCancelClickCancel, async t => + { + var result = await DisplayAlert( + "Alert Title Here", + "Alert Message Here", + "ACCEPT", "CANCEL"); + if (result) + t.ReportFailEvent(); + else + t.ReportSuccessEvent(); + }); + + // ACTION SHEETS + + // Test action sheet with items and Cancel, Item 2 is the correct option + Add(Test.Alerts.ActionSheetClickItem, async t => + { + var result = await DisplayActionSheet( + "Action Sheet Title Here", + "CANCEL", "DESTROY", + "ITEM 1", "ITEM 2", "ITEM 3"); + if (result == "ITEM 2") + t.ReportSuccessEvent(); + else + t.ReportFailEvent(); + }); + + // Test action sheet with items and Cancel, Cancel is the correct option + Add(Test.Alerts.ActionSheetClickCancel, async t => + { + var result = await DisplayActionSheet( + "Action Sheet Title Here", + "CANCEL", "DESTROY", + "ITEM 1", "ITEM 2", "ITEM 3"); + if (result == "CANCEL") + t.ReportSuccessEvent(); + else + t.ReportFailEvent(); + }); + + // Test action sheet with items and Cancel, Destroy is the correct option + Add(Test.Alerts.ActionSheetClickDestroy, async t => + { + var result = await DisplayActionSheet( + "Action Sheet Title Here", + "CANCEL", "DESTROY", + "ITEM 1", "ITEM 2", "ITEM 3"); + if (result == "DESTROY") + t.ReportSuccessEvent(); + else + t.ReportFailEvent(); + }); + } + + ExpectedEventViewContainer