From 602a24b7afcb6d8a01213abbbc7f29134dd1d4bc Mon Sep 17 00:00:00 2001 From: michael-hawker <24302614+michael-hawker@users.noreply.github.com> Date: Mon, 21 Jun 2021 15:32:05 -0700 Subject: [PATCH 1/8] XAML Styler GridSplitter Control XAML (no changes) --- .../GridSplitter/GridSplitter.xaml | 35 +++++++++++-------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/Microsoft.Toolkit.Uwp.UI.Controls.Layout/GridSplitter/GridSplitter.xaml b/Microsoft.Toolkit.Uwp.UI.Controls.Layout/GridSplitter/GridSplitter.xaml index 2b98ce6be8d..451e054d16f 100644 --- a/Microsoft.Toolkit.Uwp.UI.Controls.Layout/GridSplitter/GridSplitter.xaml +++ b/Microsoft.Toolkit.Uwp.UI.Controls.Layout/GridSplitter/GridSplitter.xaml @@ -4,29 +4,37 @@ - - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/UITests/UITests.Tests.Shared/Controls/GridSplitterTestPage.xaml.cs b/UITests/UITests.Tests.Shared/Controls/GridSplitterTestPage.xaml.cs new file mode 100644 index 00000000000..39c39b82dfd --- /dev/null +++ b/UITests/UITests.Tests.Shared/Controls/GridSplitterTestPage.xaml.cs @@ -0,0 +1,20 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; + +namespace UITests.App.Pages +{ + /// + /// An empty page that can be used on its own or navigated to within a Frame. + /// + public sealed partial class GridSplitterTestPage : Page + { + public GridSplitterTestPage() + { + this.InitializeComponent(); + } + } +} diff --git a/UITests/UITests.Tests.Shared/TestAssembly.cs b/UITests/UITests.Tests.Shared/TestAssembly.cs index 1992c2b94e1..fa51a04393d 100644 --- a/UITests/UITests.Tests.Shared/TestAssembly.cs +++ b/UITests/UITests.Tests.Shared/TestAssembly.cs @@ -74,6 +74,16 @@ internal static Task OpenPage(string pageName) }); } + internal static async Task SendCustomMessageToApp(ValueSet message) + { + if (CommunicationService is null) + { + await InitalizeComService(); + } + + return await CommunicationService.SendMessageAsync(message); + } + private static async Task SendMessageToApp(ValueSet message) { if (CommunicationService is null) @@ -83,10 +93,15 @@ private static async Task SendMessageToApp(ValueSet message) var response = await CommunicationService.SendMessageAsync(message); + return CheckResponseStatusOK(response); + } + + internal static bool CheckResponseStatusOK(AppServiceResponse response) + { return response.Status == AppServiceResponseStatus.Success - && response.Message.TryGetValue("Status", out var s) - && s is string status - && status == "OK"; + && response.Message.TryGetValue("Status", out var s) + && s is string status + && status == "OK"; } private static void CommunicationService_RequestReceived(AppServiceConnection sender, AppServiceRequestReceivedEventArgs args) diff --git a/UITests/UITests.Tests.Shared/UITests.Tests.Shared.projitems b/UITests/UITests.Tests.Shared/UITests.Tests.Shared.projitems index 192c7eb36a2..136a1a627ca 100644 --- a/UITests/UITests.Tests.Shared/UITests.Tests.Shared.projitems +++ b/UITests/UITests.Tests.Shared/UITests.Tests.Shared.projitems @@ -1,4 +1,4 @@ - + $(MSBuildAllProjects);$(MSBuildThisFileFullPath) true @@ -7,20 +7,19 @@ UITests.Tests.Shared - - + + - @@ -30,15 +29,15 @@ - - + + \ No newline at end of file diff --git a/UITests/UITests.Tests.Shared/VisualTreeHelper.cs b/UITests/UITests.Tests.Shared/VisualTreeHelper.cs new file mode 100644 index 00000000000..f558d12dfbb --- /dev/null +++ b/UITests/UITests.Tests.Shared/VisualTreeHelper.cs @@ -0,0 +1,67 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Text.Json; +using System.Text.Json.Serialization; +using System.Threading.Tasks; + +#if USING_TAEF +using WEX.Logging.Interop; +#endif + +namespace UITests.Tests +{ + /// + /// Helper class to access some VisualTree info through our communication pipeline to the host app + /// using TestAssembly.SendMessageToApp. + /// + internal static class VisualTreeHelper + { + private static JsonSerializerOptions SerializerOptions { get; } = new JsonSerializerOptions(JsonSerializerDefaults.General) + { + NumberHandling = JsonNumberHandling.AllowNamedFloatingPointLiterals, + }; + + /// + /// Looks for the specified element by name and retrieves the specified property path. + /// + /// Name of element to search for. + /// Name of property to retrieve from element. + /// Type of data to serialize result back as. + /// Retrieved value or default. + public static async Task FindElementPropertyAsync(string name, string property) + { + var response = await TestAssembly.SendCustomMessageToApp(new() + { + { "Command", "Custom" }, + { "Id", "VisualTreeHelper.FindElementProperty" }, + { "ElementName", name }, + { "Property", property }, + }); + + if (!TestAssembly.CheckResponseStatusOK(response)) + { + Log.Error("[Harness] VisualTreeHelper: Error trying to retrieve property {0} from element named {1}.", property, name); + + return default(T); + } + + if (response.Message.TryGetValue("Result", out object value) && value is string str) + { + Log.Comment("[Harness] VisualTreeHelper.FindElementPropertyAsync - Received: {0}", str); + + try + { + return JsonSerializer.Deserialize(str, SerializerOptions); + } + catch + { + Log.Error("[Harness] VisualTreeHelper.FindElementPropertyAsync - Couldn't deserialize result as {0}", typeof(T)); + } + } + + return default(T); + } + } +} diff --git a/UITests/UITests.Tests.TAEF/UITests.Tests.TAEF.csproj b/UITests/UITests.Tests.TAEF/UITests.Tests.TAEF.csproj index da8d60bfd20..18dc3731d9a 100644 --- a/UITests/UITests.Tests.TAEF/UITests.Tests.TAEF.csproj +++ b/UITests/UITests.Tests.TAEF/UITests.Tests.TAEF.csproj @@ -44,6 +44,8 @@ Version="10.0.19041.0" /> + + @@ -52,7 +54,7 @@ - + From 9945868cdb538f7d6bb504c5b40453f9a4e3df5c Mon Sep 17 00:00:00 2001 From: michael-hawker <24302614+michael-hawker@users.noreply.github.com> Date: Wed, 23 Jun 2021 16:55:25 -0700 Subject: [PATCH 3/8] Add Vertical Splitter tests to compliment bound tests for horizontal splitter --- .../Controls/GridSplitterTest.cs | 110 ++++++++++++++++++ .../Controls/GridSplitterTestPage.xaml | 11 +- 2 files changed, 114 insertions(+), 7 deletions(-) diff --git a/UITests/UITests.Tests.Shared/Controls/GridSplitterTest.cs b/UITests/UITests.Tests.Shared/Controls/GridSplitterTest.cs index 27ad1d02ac7..2827b4f0b8e 100644 --- a/UITests/UITests.Tests.Shared/Controls/GridSplitterTest.cs +++ b/UITests/UITests.Tests.Shared/Controls/GridSplitterTest.cs @@ -94,6 +94,105 @@ public async Task TestGridSplitterDragHorizontalPastMinimumAsync() Verify.AreEqual(columnDefinitionEnd.MinWidth, columnDefinitionEnd.ActualWidth, "Column was not the minimum size expected."); } + [TestMethod] + [TestPage("GridSplitterTestPage")] + public async Task TestGridSplitterDragHorizontalPastMaximumAsync() + { + var amount = 150; + + var gridSplitter = FindElement.ById("GridSplitterHorizontal"); + + Verify.IsNotNull(gridSplitter, "Can't find Horizontal GridSplitter"); + + // Drag to the Left + InputHelper.DragDistance(gridSplitter, amount, Direction.East, 1000); + + Wait.ForMilliseconds(1050); + Wait.ForIdle(); + + ColumnDefinition columnDefinitionEnd = (await VisualTreeHelper.FindElementPropertyAsync>("GridSplitterRoot", "ColumnDefinitions"))?.FirstOrDefault(); + + Wait.ForIdle(); + + Verify.AreEqual(columnDefinitionEnd.MaxWidth, columnDefinitionEnd.ActualWidth, "Column was not the maximum size expected."); + } + + [TestMethod] + [TestPage("GridSplitterTestPage")] + public async Task TestGridSplitterDragVerticalAsync() + { + var amount = 50; + var tolerance = 10; + + var grid = FindElement.ByName("GridSplitterRoot"); + var gridSplitter = FindElement.ById("GridSplitterVertical"); + + Verify.IsNotNull(grid, "Can't find GridSplitterRoot"); + Verify.IsNotNull(gridSplitter, "Can't find Vertical GridSplitter"); + + RowDefinition rowDefinitionStart = (await VisualTreeHelper.FindElementPropertyAsync>("GridSplitterRoot", "RowDefinitions"))?.FirstOrDefault(); + + Verify.IsNotNull(rowDefinitionStart, "Couldn't retrieve Row Definition"); + + // Drag to the Left + InputHelper.DragDistance(gridSplitter, amount, Direction.North, 1000); + + Wait.ForMilliseconds(1050); + Wait.ForIdle(); + + RowDefinition rowDefinitionEnd = (await VisualTreeHelper.FindElementPropertyAsync>("GridSplitterRoot", "RowDefinitions"))?.FirstOrDefault(); + + Wait.ForIdle(); + + Verify.IsTrue(Math.Abs(rowDefinitionStart.ActualHeight - amount - rowDefinitionEnd.ActualHeight) <= tolerance, $"RowDefinition not in range expected {rowDefinitionStart.ActualHeight - amount} was {rowDefinitionEnd.ActualHeight}"); + } + + [TestMethod] + [TestPage("GridSplitterTestPage")] + public async Task TestGridSplitterDragVerticalPastMinimumAsync() + { + var amount = 150; + + var gridSplitter = FindElement.ById("GridSplitterVertical"); + + Verify.IsNotNull(gridSplitter, "Can't find Vertical GridSplitter"); + + // Drag to the Left + InputHelper.DragDistance(gridSplitter, amount, Direction.North, 1000); + + Wait.ForMilliseconds(1050); + Wait.ForIdle(); + + RowDefinition rowDefinitionEnd = (await VisualTreeHelper.FindElementPropertyAsync>("GridSplitterRoot", "RowDefinitions"))?.FirstOrDefault(); + + Wait.ForIdle(); + + Verify.AreEqual(rowDefinitionEnd.MinHeight, rowDefinitionEnd.ActualHeight, "Row was not the minimum size expected."); + } + + [TestMethod] + [TestPage("GridSplitterTestPage")] + public async Task TestGridSplitterDragVerticalPastMaximumAsync() + { + var amount = 150; + + var gridSplitter = FindElement.ById("GridSplitterVertical"); + + Verify.IsNotNull(gridSplitter, "Can't find Vertical GridSplitter"); + + // Drag to the Left + InputHelper.DragDistance(gridSplitter, amount, Direction.South, 1000); + + Wait.ForMilliseconds(1050); + Wait.ForIdle(); + + RowDefinition rowDefinitionEnd = (await VisualTreeHelper.FindElementPropertyAsync>("GridSplitterRoot", "RowDefinitions"))?.FirstOrDefault(); + + Wait.ForIdle(); + + Verify.AreEqual(rowDefinitionEnd.MaxHeight, rowDefinitionEnd.ActualHeight, "Row was not the maximum size expected."); + } + private class ColumnDefinition { public GridLength Width { get; set; } @@ -105,6 +204,17 @@ private class ColumnDefinition public double MaxWidth { get; set; } } + private class RowDefinition + { + public GridLength Height { get; set; } + + public double ActualHeight { get; set; } + + public double MinHeight { get; set; } + + public double MaxHeight { get; set; } + } + private class GridLength { public int GridUnitType { get; set; } // 0 Auto, 1 Pixel, 2 Star diff --git a/UITests/UITests.Tests.Shared/Controls/GridSplitterTestPage.xaml b/UITests/UITests.Tests.Shared/Controls/GridSplitterTestPage.xaml index 9016e2de988..ad822bae857 100644 --- a/UITests/UITests.Tests.Shared/Controls/GridSplitterTestPage.xaml +++ b/UITests/UITests.Tests.Shared/Controls/GridSplitterTestPage.xaml @@ -29,9 +29,10 @@ BorderBrush="{ThemeResource SystemControlHighlightChromeHighBrush}" BorderThickness="0,0,1,1"> - - + + HorizontalAlignment="Left"> From da0abbf1240b374a2480de63ffd7ef5894bf7b64 Mon Sep 17 00:00:00 2001 From: michael-hawker <24302614+michael-hawker@users.noreply.github.com> Date: Wed, 7 Jul 2021 14:57:07 -0700 Subject: [PATCH 4/8] Add extra log messages to help debug UI test in CI --- UITests/UITests.App/App.AppService.xaml.cs | 2 ++ UITests/UITests.Tests.Shared/TestAssembly.cs | 9 +++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/UITests/UITests.App/App.AppService.xaml.cs b/UITests/UITests.App/App.AppService.xaml.cs index 7ff873d99b6..2d46790d55c 100644 --- a/UITests/UITests.App/App.AppService.xaml.cs +++ b/UITests/UITests.App/App.AppService.xaml.cs @@ -50,6 +50,8 @@ private async void OnAppServiceRequestReceived(AppServiceConnection sender, AppS return; } + Log.Comment("Received Command: {0}", cmd); + switch (cmd) { case "OpenPage": diff --git a/UITests/UITests.Tests.Shared/TestAssembly.cs b/UITests/UITests.Tests.Shared/TestAssembly.cs index fa51a04393d..3c987dcad72 100644 --- a/UITests/UITests.Tests.Shared/TestAssembly.cs +++ b/UITests/UITests.Tests.Shared/TestAssembly.cs @@ -98,9 +98,14 @@ private static async Task SendMessageToApp(ValueSet message) internal static bool CheckResponseStatusOK(AppServiceResponse response) { + object message = null; + var hasMessage = response?.Message?.TryGetValue("Status", out message) is true; + + Log.Comment("[Harness] Checking Response AppServiceResponseStatus({0}), Message Status: {1}", response.Status.ToString(), message?.ToString()); + return response.Status == AppServiceResponseStatus.Success - && response.Message.TryGetValue("Status", out var s) - && s is string status + && hasMessage + && message is string status && status == "OK"; } From caf0d7ff3f2f75c293984ea7a3749b0e7689606a Mon Sep 17 00:00:00 2001 From: michael-hawker <24302614+michael-hawker@users.noreply.github.com> Date: Fri, 9 Jul 2021 02:16:37 -0700 Subject: [PATCH 5/8] Add more diagnostics output on Service Connection Closed --- UITests/UITests.App/App.AppService.xaml.cs | 4 ++++ UITests/UITests.App/TestInterop.cs | 8 ++++++-- UITests/UITests.Tests.Shared/TestAssembly.cs | 6 ++++++ 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/UITests/UITests.App/App.AppService.xaml.cs b/UITests/UITests.App/App.AppService.xaml.cs index 2d46790d55c..944cd93d555 100644 --- a/UITests/UITests.App/App.AppService.xaml.cs +++ b/UITests/UITests.App/App.AppService.xaml.cs @@ -118,11 +118,15 @@ private async void OnAppServiceRequestReceived(AppServiceConnection sender, AppS private void OnAppServicesCanceled(IBackgroundTaskInstance sender, BackgroundTaskCancellationReason reason) { + Log.Error("Background Task Instance Canceled. Reason: {0}", reason.ToString()); + _appServiceDeferral.Complete(); } private void AppServiceConnection_ServiceClosed(AppServiceConnection sender, AppServiceClosedEventArgs args) { + Log.Error("AppServiceConnection Service Closed. AppServicesClosedStatus: {0}", args.Status.ToString(); + _appServiceDeferral.Complete(); } diff --git a/UITests/UITests.App/TestInterop.cs b/UITests/UITests.App/TestInterop.cs index 956f34f9e35..f17e12142c7 100644 --- a/UITests/UITests.App/TestInterop.cs +++ b/UITests/UITests.App/TestInterop.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System; +using System.Diagnostics; using Windows.UI.Xaml; namespace UITests.App.Pages @@ -37,9 +37,13 @@ private static void LogMessage(string level, string format, object[] args) format = format.Replace("{", "{{").Replace("}", "}}"); } + var message = string.Format(format, args); + + Debug.WriteLine(message); + // Send back to Test Harness via AppService // TODO: Make this a cleaner connection/pattern - ((App)Application.Current).SendLogMessage(level, string.Format(format, args)); + _ = ((App)Application.Current).SendLogMessage(level, message); } } } \ No newline at end of file diff --git a/UITests/UITests.Tests.Shared/TestAssembly.cs b/UITests/UITests.Tests.Shared/TestAssembly.cs index 3c987dcad72..47d45afbcdd 100644 --- a/UITests/UITests.Tests.Shared/TestAssembly.cs +++ b/UITests/UITests.Tests.Shared/TestAssembly.cs @@ -44,6 +44,7 @@ private static async Task InitalizeComService() CommunicationService = new AppServiceConnection(); CommunicationService.RequestReceived += CommunicationService_RequestReceived; + CommunicationService.ServiceClosed += CommunicationService_ServiceClosed; // Here, we use the app service name defined in the app service // provider's Package.appxmanifest file in the section. @@ -63,6 +64,11 @@ private static async Task InitalizeComService() } } + private static void CommunicationService_ServiceClosed(AppServiceConnection sender, AppServiceClosedEventArgs args) + { + Log.Warning("[Harness] Communication Service Closed! AppServiceClosedStatus: {0}", args.Status.ToString()); + } + internal static Task OpenPage(string pageName) { Log.Comment("[Harness] Sending Host Page Request: {0}", pageName); From aa1c5575f508af17a0c7260186ba20b936904284 Mon Sep 17 00:00:00 2001 From: Rosario Pulella Date: Fri, 9 Jul 2021 13:34:02 -0400 Subject: [PATCH 6/8] Update UITests/UITests.App/App.AppService.xaml.cs --- UITests/UITests.App/App.AppService.xaml.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/UITests/UITests.App/App.AppService.xaml.cs b/UITests/UITests.App/App.AppService.xaml.cs index 944cd93d555..ced08c8935f 100644 --- a/UITests/UITests.App/App.AppService.xaml.cs +++ b/UITests/UITests.App/App.AppService.xaml.cs @@ -125,7 +125,7 @@ private void OnAppServicesCanceled(IBackgroundTaskInstance sender, BackgroundTas private void AppServiceConnection_ServiceClosed(AppServiceConnection sender, AppServiceClosedEventArgs args) { - Log.Error("AppServiceConnection Service Closed. AppServicesClosedStatus: {0}", args.Status.ToString(); + Log.Error("AppServiceConnection Service Closed. AppServicesClosedStatus: {0}", args.Status.ToString()); _appServiceDeferral.Complete(); } From dfe88cf532982824a3e275c869e07a74050852f4 Mon Sep 17 00:00:00 2001 From: michael-hawker <24302614+michael-hawker@users.noreply.github.com> Date: Fri, 9 Jul 2021 12:54:52 -0700 Subject: [PATCH 7/8] Add extendedBackgroundTaskTime capability to try and prevent AppService BackgroundTask timeout. --- UITests/UITests.App/Package.appxmanifest | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/UITests/UITests.App/Package.appxmanifest b/UITests/UITests.App/Package.appxmanifest index 5e031837706..bb5c6d4e96e 100644 --- a/UITests/UITests.App/Package.appxmanifest +++ b/UITests/UITests.App/Package.appxmanifest @@ -2,7 +2,8 @@ xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10" xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest" xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10" - IgnorableNamespaces="uap mp"> + xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities" + IgnorableNamespaces="uap mp rescap"> + + \ No newline at end of file From c6f8fee4ad7f107f3d29e5a3e9e118c6f68d95e2 Mon Sep 17 00:00:00 2001 From: michael-hawker <24302614+michael-hawker@users.noreply.github.com> Date: Thu, 15 Jul 2021 11:36:04 -0700 Subject: [PATCH 8/8] Address PR comments --- UITests/UITests.App/UITests.App.csproj | 1 - .../Controls/GridSplitterTestPage.xaml | 9 +-------- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/UITests/UITests.App/UITests.App.csproj b/UITests/UITests.App/UITests.App.csproj index d1f918751e8..21515c4f9b8 100644 --- a/UITests/UITests.App/UITests.App.csproj +++ b/UITests/UITests.App/UITests.App.csproj @@ -252,7 +252,6 @@ Microsoft.Toolkit - 14.0 diff --git a/UITests/UITests.Tests.Shared/Controls/GridSplitterTestPage.xaml b/UITests/UITests.Tests.Shared/Controls/GridSplitterTestPage.xaml index ad822bae857..074df833eb2 100644 --- a/UITests/UITests.Tests.Shared/Controls/GridSplitterTestPage.xaml +++ b/UITests/UITests.Tests.Shared/Controls/GridSplitterTestPage.xaml @@ -73,11 +73,7 @@ - - + HorizontalAlignment="Left"/> -