Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
9d35b36
Adpat UITests to support multiple tests
Rosuavio Sep 30, 2020
6a6ed62
Added TextBoxMask binding to property test.
Rosuavio Sep 30, 2020
9ef8268
Make Controls section, move TextBoxMask there.
Rosuavio Oct 19, 2020
f3d9823
Rename `TextBoxMask` test page to
Rosuavio Oct 19, 2020
e9b2801
Use DependencyProperty instead of
Rosuavio Oct 19, 2020
ffc9d2b
Create TestPageAttribute to tag test with Page.
Rosuavio Nov 2, 2020
358f6a8
Moved UI bootstrapping to TestAssembly.
Rosuavio Nov 2, 2020
29fd6fc
Split UI tests into seprate files.
Rosuavio Nov 2, 2020
4671203
Move UI test to folder away from supporting code
Rosuavio Nov 3, 2020
c4f08ad
WIP: Make Test App more adptive to test envs
Rosuavio Nov 3, 2020
aad53af
WIP Testing
Rosuavio Nov 3, 2020
d640199
Remove TestPage Attribute.
Rosuavio Nov 18, 2020
183b447
WIP: move code to repated class init
Rosuavio Nov 18, 2020
022ee54
Add UITests.App to Any CPU Build/Deploy Configuration
michael-hawker Nov 19, 2020
b3a5ca3
WIP - Try to use Shared Project for Tests and UI components
michael-hawker Nov 19, 2020
7f4a172
Remove unused Shared Project property and use None include to display.
michael-hawker Nov 20, 2020
ec9d0c9
WIP - Update Shared Project to Properly Include Files for Intellisens…
michael-hawker Nov 20, 2020
150282d
Fix shared project build to find xbf file link - Fix thanks to @jerom…
michael-hawker Nov 24, 2020
8897408
Merge branch 'master' into test-TextBoxMask
Rosuavio Nov 24, 2020
2a42bfd
Initial App Service Connection Test
michael-hawker Nov 25, 2020
7911885
Adding Bi-directional communication pipe
michael-hawker Nov 25, 2020
6bc6446
Merge branch 'master' into test-app-service
michael-hawker Dec 3, 2020
3bf27d9
Revert attempt to move to .NET 5 TFM and use .NET Core 3.1 + PackageR…
michael-hawker Dec 3, 2020
c5532f3
Clean-up Type Enumeration and Logger Usage
michael-hawker Dec 4, 2020
cf9f27b
Explicitly wait for UI Test App to load the Page for the Test before …
michael-hawker Dec 4, 2020
91981aa
Try and run PreTestSetup for TAEF CI succes
michael-hawker Dec 4, 2020
f219907
Add parameter names for magic strings as per PR comments
michael-hawker Dec 8, 2020
32be0c4
Remove internal hardlink by using MVVM Messenger
michael-hawker Dec 9, 2020
f583ee4
Apply suggestions from code review
michael-hawker Dec 9, 2020
a8c3249
Merge branch 'master' into test-app-service
michael-hawker Dec 11, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 103 additions & 0 deletions UITests/UITests.App/App.AppService.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
// 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;
using System.Diagnostics;
using Microsoft.Toolkit.Mvvm.Messaging;
using UITests.App.Pages;
using Windows.ApplicationModel.Activation;
using Windows.ApplicationModel.AppService;
using Windows.ApplicationModel.Background;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;

namespace UITests.App
{
/// <summary>
/// This file contains part of the app related to the AppService for communication between this test host and the test harness processes.
/// </summary>
public sealed partial class App
{
private AppServiceConnection _appServiceConnection;
private BackgroundTaskDeferral _appServiceDeferral;

protected override void OnBackgroundActivated(BackgroundActivatedEventArgs args)
{
base.OnBackgroundActivated(args);
IBackgroundTaskInstance taskInstance = args.TaskInstance;
AppServiceTriggerDetails appService = taskInstance.TriggerDetails as AppServiceTriggerDetails;
_appServiceDeferral = taskInstance.GetDeferral();
taskInstance.Canceled += OnAppServicesCanceled;
_appServiceConnection = appService.AppServiceConnection;
_appServiceConnection.RequestReceived += OnAppServiceRequestReceived;
_appServiceConnection.ServiceClosed += AppServiceConnection_ServiceClosed;
}

private async void OnAppServiceRequestReceived(AppServiceConnection sender, AppServiceRequestReceivedEventArgs args)
{
AppServiceDeferral messageDeferral = args.GetDeferral();
ValueSet message = args.Request.Message;
string cmd = message["Command"] as string;

try
{
// Return the data to the caller.
if (cmd == "Start")
{
var pageName = message["Page"] as string;

Log.Comment("Received request for Page: {0}", pageName);

ValueSet returnMessage = new ValueSet();

// We await the OpenPage method to ensure the navigation has finished.
if (await WeakReferenceMessenger.Default.Send(new RequestPageMessage(pageName)))
{
returnMessage.Add("Status", "OK");
}
else
{
returnMessage.Add("Status", "BAD");
}

await args.Request.SendResponseAsync(returnMessage);
}
}
catch (Exception e)
{
// Your exception handling code here.
Log.Error("Exception processing request: {0}", e.Message);
}
finally
{
// Complete the deferral so that the platform knows that we're done responding to the app service call.
// Note: for error handling: this must be called even if SendResponseAsync() throws an exception.
messageDeferral.Complete();
}
}

private void OnAppServicesCanceled(IBackgroundTaskInstance sender, BackgroundTaskCancellationReason reason)
{
_appServiceDeferral.Complete();
}

private void AppServiceConnection_ServiceClosed(AppServiceConnection sender, AppServiceClosedEventArgs args)
{
_appServiceDeferral.Complete();
}

public async void SendLogMessage(string level, string msg)
{
var message = new ValueSet();
message.Add("Command", "Log");
message.Add("Level", level);
message.Add("Message", msg);

await _appServiceConnection.SendMessageAsync(message);

// TODO: do we care if we have a problem here?
}
}
}
11 changes: 4 additions & 7 deletions UITests/UITests.App/App.xaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
<Application
x:Class="UITests.App.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:UITests.App">

</Application>
<Application x:Class="UITests.App.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:UITests.App" />
17 changes: 16 additions & 1 deletion UITests/UITests.App/App.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
// See the LICENSE file in the project root for more information.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using UITests.App.Pages;
using Windows.ApplicationModel;
using Windows.ApplicationModel.Activation;
using Windows.UI.Xaml;
Expand All @@ -11,12 +15,22 @@

namespace UITests.App
{
/// <summary>
/// Application class for hosting UI pages to test.
/// </summary>
public sealed partial class App
{
public App()
{
this.InitializeComponent();
this.Suspending += OnSuspending;
this.UnhandledException += this.App_UnhandledException;
}

private void App_UnhandledException(object sender, Windows.UI.Xaml.UnhandledExceptionEventArgs e)
{
// TODO: Also Log to a file?
Log.Error("Unhandled Exception: " + e.Message);
}

/// <summary>
Expand Down Expand Up @@ -53,7 +67,7 @@ protected override void OnLaunched(LaunchActivatedEventArgs e)
// When the navigation stack isn't restored navigate to the first page,
// configuring the new page by passing required information as a navigation
// parameter
rootFrame.Navigate(typeof(MainPage), e.Arguments);
rootFrame.Navigate(typeof(MainTestHost), e.Arguments);
}

// Ensure the current window is active
Expand All @@ -68,6 +82,7 @@ protected override void OnLaunched(LaunchActivatedEventArgs e)
/// <param name="e">Details about the navigation failure</param>
private void OnNavigationFailed(object sender, NavigationFailedEventArgs e)
{
Log.Error("Failed to load root page: " + e.SourcePageType.FullName);
throw new Exception("Failed to load Page " + e.SourcePageType.FullName);
}

Expand Down
19 changes: 0 additions & 19 deletions UITests/UITests.App/MainPage.xaml

This file was deleted.

19 changes: 0 additions & 19 deletions UITests/UITests.App/MainPage.xaml.cs

This file was deleted.

17 changes: 17 additions & 0 deletions UITests/UITests.App/MainTestHost.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<Page x:Class="UITests.App.MainTestHost"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:testhelpers="using:AppTestAutomationHelpers"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
mc:Ignorable="d">

<Grid>
<testhelpers:TestAutomationHelpersPanel />

<Frame x:Name="navigationFrame"
Navigated="NavigationFrame_Navigated"
NavigationFailed="NavigationFrame_NavigationFailed" />
</Grid>
</Page>
118 changes: 118 additions & 0 deletions UITests/UITests.App/MainTestHost.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
// 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;
using System.Reflection;
using System.Threading.Tasks;
using Microsoft.Toolkit.Mvvm.Messaging;
using Microsoft.Toolkit.Uwp.Extensions;
using UITests.App.Pages;
using Windows.System;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media.Animation;

namespace UITests.App
{
/// <summary>
/// MainPage hosting all other test pages.
/// </summary>
public sealed partial class MainTestHost : IRecipient<RequestPageMessage>
{
private DispatcherQueue _queue;

private Assembly _executingAssembly = Assembly.GetExecutingAssembly();

private TaskCompletionSource<bool> _loadingStateTask;

public MainTestHost()
{
InitializeComponent();

WeakReferenceMessenger.Default.Register<RequestPageMessage>(this);

_queue = DispatcherQueue.GetForCurrentThread();
}

public void Receive(RequestPageMessage message)
{
// Reply with task back to so it can be properly awaited link:App.AppService.xaml.cs#L56
message.Reply(OpenPage(message.PageName));
}

private async Task<bool> OpenPage(string pageName)
{
try
{
Log.Comment("Trying to Load Page: " + pageName);

_loadingStateTask = new TaskCompletionSource<bool>();

// Ensure we're on the UI thread as we'll be called from the AppService now.
_ = _queue.EnqueueAsync(() =>
{
// Navigate without extra animations
navigationFrame.Navigate(FindPageType(pageName), new SuppressNavigationTransitionInfo());
});

// Wait for load to complete
await _loadingStateTask.Task;
}
catch (Exception e)
{
Log.Error("Exception Loading Page {0}: {1} ", pageName, e.Message);
return false;
}

return true;
}

private Type FindPageType(string pageName)
{
try
{
return _executingAssembly.GetType("UITests.App.Pages." + pageName);
}
catch (Exception e)
{
Log.Error("Exception Finding Page {0}: {1} ", pageName, e.Message);
}

return null;
}

private void NavigationFrame_Navigated(object sender, Windows.UI.Xaml.Navigation.NavigationEventArgs e)
{
Log.Comment("Navigated to Page {0}", e.SourcePageType.FullName);
if (e.Content is Page page)
{
if (page.IsLoaded)
{
Log.Comment("Loaded Page {0}", e.SourcePageType.FullName);
_loadingStateTask.SetResult(true);
}
else
{
page.Loaded += this.Page_Loaded;
}
}
}

private void Page_Loaded(object sender, RoutedEventArgs e)
{
var page = sender as Page;

page.Loaded -= Page_Loaded;

Log.Comment("Loaded Page (E) {0}", page.GetType().FullName);
_loadingStateTask.SetResult(true);
}

private void NavigationFrame_NavigationFailed(object sender, Windows.UI.Xaml.Navigation.NavigationFailedEventArgs e)
{
Log.Error("Failed to navigate to page {0}", e.SourcePageType.FullName);
_loadingStateTask.SetResult(false);
}
}
}
5 changes: 5 additions & 0 deletions UITests/UITests.App/Package.appxmanifest
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@
<uap:DefaultTile Wide310x150Logo="Assets\Wide310x150Logo.png"/>
<uap:SplashScreen Image="Assets\SplashScreen.png" />
</uap:VisualElements>
<Extensions>
<uap:Extension Category="windows.appService">
<uap:AppService Name="TestHarnessCommunicationService"/>
</uap:Extension>
</Extensions>
</Application>
</Applications>

Expand Down
18 changes: 18 additions & 0 deletions UITests/UITests.App/RequestPageMessage.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// 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 Microsoft.Toolkit.Mvvm.Messaging.Messages;

namespace UITests.App
{
public sealed class RequestPageMessage : AsyncRequestMessage<bool>
{
public RequestPageMessage(string name)
{
PageName = name;
}

public string PageName { get; }
}
}
Loading