Skip to content

Commit

Permalink
Setup WinUI to run window scoped tests in new window (#7308)
Browse files Browse the repository at this point in the history
* Setup WinUI to run window scoped tests in new window

* - fix csproj file

* - fix namespaces

* - fix namespaces
  • Loading branch information
PureWeen committed May 19, 2022
1 parent 4b833b0 commit 8356889
Show file tree
Hide file tree
Showing 17 changed files with 132 additions and 134 deletions.
Expand Up @@ -15,6 +15,7 @@
using Microsoft.Maui.Hosting;
using Microsoft.Maui.Handlers;
using Microsoft.UI.Xaml.Controls;
using Microsoft.Maui.DeviceTests.Stubs;

namespace Microsoft.Maui.DeviceTests
{
Expand Down
Expand Up @@ -7,6 +7,7 @@
using Microsoft.Maui;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Controls.Handlers;
using Microsoft.Maui.DeviceTests.Stubs;
using Microsoft.Maui.Handlers;
using Microsoft.Maui.Hosting;
using Microsoft.Maui.Platform;
Expand Down
Expand Up @@ -4,6 +4,7 @@
using System.Text;
using System.Threading.Tasks;
using Microsoft.Maui.Controls;
using Microsoft.Maui.DeviceTests.Stubs;
using Microsoft.Maui.Handlers;
using Microsoft.Maui.Hosting;
using Xunit;
Expand Down
Expand Up @@ -7,6 +7,7 @@
using Microsoft.Maui;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Controls.Handlers;
using Microsoft.Maui.DeviceTests.Stubs;
using Microsoft.Maui.Platform;
using Xunit;

Expand Down
Expand Up @@ -5,6 +5,7 @@
using System.Text;
using System.Threading.Tasks;
using Microsoft.Maui.Controls;
using Microsoft.Maui.DeviceTests.Stubs;
using Microsoft.Maui.Handlers;
using Microsoft.Maui.Hosting;
using Xunit;
Expand Down
Expand Up @@ -13,6 +13,7 @@
using Microsoft.Maui.Hosting;
using Microsoft.Maui.Handlers;
using Microsoft.Maui.Graphics;
using Microsoft.Maui.DeviceTests.Stubs;

namespace Microsoft.Maui.DeviceTests
{
Expand Down
Expand Up @@ -11,6 +11,7 @@
using Microsoft.Maui.Hosting;
using Microsoft.Maui.Handlers;
using Microsoft.Maui.Graphics;
using Microsoft.Maui.DeviceTests.Stubs;

#if ANDROID || IOS
using ShellHandler = Microsoft.Maui.Controls.Handlers.Compatibility.ShellRenderer;
Expand Down
15 changes: 2 additions & 13 deletions src/Controls/tests/DeviceTests/HandlerTestBase.Android.cs
Expand Up @@ -37,7 +37,7 @@ public AView GetSemanticPlatformElement(IViewHandler viewHandler)
}

static Drawable _decorDrawable;
Task RunWindowTest<THandler>(IWindow window, Func<THandler, Task> action)
Task SetupWindowForTests<THandler>(IWindow window, Func<Task> runTests)
where THandler : class, IElementHandler
{
return InvokeOnMainThreadAsync(async () =>
Expand All @@ -60,18 +60,7 @@ Task RunWindowTest<THandler>(IWindow window, Func<THandler, Task> action)
.Commit();
await viewFragment.FinishedLoading;
if (window.Content is Shell shell)
await OnLoadedAsync(shell.CurrentPage);
if (typeof(THandler).IsAssignableFrom(window.Handler.GetType()))
await action((THandler)window.Handler);
else if (typeof(THandler).IsAssignableFrom(window.Content.Handler.GetType()))
await action((THandler)window.Content.Handler);
else if (window.Content is ContentPage cp && typeof(THandler).IsAssignableFrom(cp.Content.Handler.GetType()))
await action((THandler)cp.Content.Handler);
else
throw new Exception($"I can't work with {typeof(THandler)}");
await runTests.Invoke();
}
finally
{
Expand Down
72 changes: 16 additions & 56 deletions src/Controls/tests/DeviceTests/HandlerTestBase.Windows.cs
@@ -1,23 +1,19 @@
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Automation.Peers;
using NativeAutomationProperties = Microsoft.UI.Xaml.Automation.AutomationProperties;
using WPanel = Microsoft.UI.Xaml.Controls.Panel;
using WNavigationViewItem = Microsoft.UI.Xaml.Controls.NavigationViewItem;
using WFrameworkElement = Microsoft.UI.Xaml.FrameworkElement;
using WWindow = Microsoft.UI.Xaml.Window;
using Microsoft.Maui.Hosting;
using Microsoft.Maui.Handlers;
using Microsoft.Maui;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Controls.Handlers;
using Microsoft.Maui.Platform;
using System.Threading.Tasks;
using System;
using Microsoft.Extensions.DependencyInjection;
using System.Collections.Generic;
using WPoint = Windows.Foundation.Point;
using WAppBarButton = Microsoft.UI.Xaml.Controls.AppBarButton;
using Xunit;
using Microsoft.Maui.DeviceTests.Stubs;

namespace Microsoft.Maui.DeviceTests
{
Expand All @@ -27,65 +23,29 @@ public partial class HandlerTestBase
((AccessibilityView)((DependencyObject)viewHandler.PlatformView).GetValue(NativeAutomationProperties.AccessibilityViewProperty))
== AccessibilityView.Content;

Task RunWindowTest<THandler>(IWindow window, Func<THandler, Task> action)

Task SetupWindowForTests<THandler>(IWindow window, Func<Task> runTests)
where THandler : class, IElementHandler
{
return InvokeOnMainThreadAsync(async () =>
{
var testingRootPanel = (WPanel)MauiProgram.CurrentWindow.Content;
IElementHandler newWindowHandler = null;
NavigationRootManager navigationRootManager = null;
var applicationContext = MauiContext.MakeApplicationScope(UI.Xaml.Application.Current);
var appStub = new MauiAppNewWindowStub(window);
UI.Xaml.Application.Current.SetApplicationHandler(appStub, applicationContext);
WWindow newWindow = null;
try
{
var scopedContext = new MauiContext(MauiContext.Services);
scopedContext.AddWeakSpecific(MauiProgram.CurrentWindow);
var mauiContext = scopedContext.MakeScoped(true);
navigationRootManager = mauiContext.GetNavigationRootManager();
MauiContext
.Services
.GetRequiredService<WWindow>()
.SetWindowHandler(window, mauiContext);
newWindowHandler = window.Handler;
var content = window.Content.Handler.ToPlatform();
await content.OnLoadedAsync();
await Task.Delay(10);
if (typeof(THandler).IsAssignableFrom(newWindowHandler.GetType()))
await action((THandler)newWindowHandler);
else if (typeof(THandler).IsAssignableFrom(window.Content.Handler.GetType()))
await action((THandler)window.Content.Handler);
else if (window.Content is ContentPage cp && typeof(THandler).IsAssignableFrom(cp.Content.Handler.GetType()))
await action((THandler)cp.Content.Handler);
else
throw new Exception($"I can't work with {typeof(THandler)}");
ApplicationExtensions.CreatePlatformWindow(UI.Xaml.Application.Current, appStub, new Handlers.OpenWindowRequest());
newWindow = window.Handler.PlatformView as WWindow;
await runTests.Invoke();
}
finally
{
if (navigationRootManager != null)
navigationRootManager.Disconnect();
if (newWindowHandler != null)
newWindowHandler.DisconnectHandler();
// Set the root window panel back to the testing panel
if (testingRootPanel != null && MauiProgram.CurrentWindow.Content != testingRootPanel)
{
MauiProgram.CurrentWindow.Content = testingRootPanel;
await testingRootPanel.OnLoadedAsync();
await Task.Delay(10);
}
// reset the appbar title to our test runner
MauiProgram
.CurrentWindow
.GetWindow()
.Handler
.MauiContext
.GetNavigationRootManager()
.UpdateAppTitleBar(true);
window.Handler.DisconnectHandler();
await Task.Delay(10);
newWindow?.Close();
appStub.Handler.DisconnectHandler();
}
});
}
Expand Down Expand Up @@ -176,7 +136,7 @@ protected MauiToolbar GetPlatformToolbar(IElementHandler handler)

return true;
}

protected object GetTitleView(IElementHandler handler)
{
var toolbar = GetPlatformToolbar(handler);
Expand Down
41 changes: 37 additions & 4 deletions src/Controls/tests/DeviceTests/HandlerTestBase.cs
@@ -1,4 +1,5 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Maui.Controls;
Expand Down Expand Up @@ -68,6 +69,7 @@ public void EnsureHandlerCreated(Action<MauiAppBuilder> additionalCreationAction
handlers.AddHandler(typeof(VerticalStackLayout), typeof(LayoutHandler));
handlers.AddHandler(typeof(Controls.Window), typeof(WindowHandlerStub));
handlers.AddHandler(typeof(Controls.ContentPage), typeof(PageHandler));
handlers.AddHandler(typeof(MauiAppNewWindowStub), typeof(ApplicationHandler));
});

appBuilder.Services.AddSingleton<IDispatcherProvider>(svc => TestDispatcher.Provider);
Expand All @@ -82,7 +84,7 @@ public void EnsureHandlerCreated(Action<MauiAppBuilder> additionalCreationAction

public void Dispose()
{
((IDisposable)_mauiApp).Dispose();
((IDisposable)_mauiApp)?.Dispose();

_mauiApp = null;
_mauiContext = null;
Expand Down Expand Up @@ -141,8 +143,8 @@ protected THandler CreateHandler<THandler>(IElement element, IMauiContext mauiCo
#else
// Windows cannot measure without the view being loaded
// iOS needs more love when I get an IDE again
var w = view.Width;
var h = view.Height;
var w = view.Width.Equals(double.NaN) ? -1 : view.Width;
var h = view.Height.Equals(double.NaN) ? -1 : view.Height;
#endif

view.Arrange(new Rect(0, 0, w, h));
Expand Down Expand Up @@ -174,6 +176,7 @@ protected Task CreateHandlerAndAddToWindow<THandler>(IElement view, Action<THand
});
}

static SemaphoreSlim _takeOverMainContentSempahore = new SemaphoreSlim(1);
protected Task CreateHandlerAndAddToWindow<THandler>(IElement view, Func<THandler, Task> action)
where THandler : class, IElementHandler
{
Expand All @@ -194,7 +197,37 @@ protected Task CreateHandlerAndAddToWindow<THandler>(IElement view, Func<THandle
window = new Controls.Window(new ContentPage() { Content = (View)view });
}
await RunWindowTest<THandler>(window, (handler) => action(handler as THandler));
try
{
await _takeOverMainContentSempahore.WaitAsync();
await SetupWindowForTests<THandler>(window, async () =>
{
IView content = window.Content;
if (content is IPageContainer<Page> pc)
content = pc.CurrentPage;
await OnLoadedAsync(content as VisualElement);
#if WINDOWS
await Task.Delay(10);
#endif
if (typeof(THandler).IsAssignableFrom(window.Handler.GetType()))
await action((THandler)window.Handler);
else if (typeof(THandler).IsAssignableFrom(window.Content.Handler.GetType()))
await action((THandler)window.Content.Handler);
else if (window.Content is ContentPage cp && typeof(THandler).IsAssignableFrom(cp.Content.Handler.GetType()))
await action((THandler)cp.Content.Handler);
else
throw new Exception($"I can't work with {typeof(THandler)}");
});
}
finally
{
_takeOverMainContentSempahore.Release();
}
});
}

Expand Down
21 changes: 4 additions & 17 deletions src/Controls/tests/DeviceTests/HandlerTestBase.iOS.cs
Expand Up @@ -4,6 +4,7 @@
using Microsoft.Maui.Controls.Handlers.Compatibility;
using Microsoft.Maui.Controls.Platform;
using Microsoft.Maui.Controls.Platform.Compatibility;
using Microsoft.Maui.DeviceTests.Stubs;
using Microsoft.Maui.Platform;
using UIKit;

Expand All @@ -23,29 +24,15 @@ protected bool GetExcludedWithChildren(IViewHandler viewHandler)
return platformView.AccessibilityElementsHidden;
}

Task RunWindowTest<THandler>(IWindow window, Func<THandler, Task> action)
Task SetupWindowForTests<THandler>(IWindow window, Func<Task> runTests)
where THandler : class, IElementHandler
{
return InvokeOnMainThreadAsync(async () =>
{
try
{
_ = window.ToHandler(MauiContext);
IView content = window.Content;
if (content is IPageContainer<Page> pc)
content = pc.CurrentPage;
await OnLoadedAsync(content as VisualElement);
if (typeof(THandler).IsAssignableFrom(window.Handler.GetType()))
await action((THandler)window.Handler);
else if (typeof(THandler).IsAssignableFrom(window.Content.Handler.GetType()))
await action((THandler)window.Content.Handler);
else if (window.Content is ContentPage cp && typeof(THandler).IsAssignableFrom(cp.Content.Handler.GetType()))
await action((THandler)cp.Content.Handler);
else
throw new Exception($"I can't work with {typeof(THandler)}");
await runTests.Invoke();
}
finally
{
Expand Down Expand Up @@ -91,7 +78,7 @@ protected bool IsBackButtonVisible(IElementHandler handler)
protected object GetTitleView(IElementHandler handler)
{
var activeVC = GetVisibleViewController(handler);
if ( activeVC.NavigationItem.TitleView is
if (activeVC.NavigationItem.TitleView is
ShellPageRendererTracker.TitleViewContainer tvc)
{
return tvc.View.Handler.PlatformView;
Expand Down
41 changes: 41 additions & 0 deletions src/Controls/tests/DeviceTests/Stubs/MauiAppNewWindowStub.cs
@@ -0,0 +1,41 @@
using System;
using System.Collections.Generic;

namespace Microsoft.Maui.DeviceTests.Stubs
{
class MauiAppNewWindowStub : IApplication
{
readonly IWindow _window;

public MauiAppNewWindowStub(IWindow window)
{
_window = window;
}

public IReadOnlyList<IWindow> Windows => new List<IWindow>() { _window };

public IElementHandler Handler { get; set; }

public IElement Parent => null;

public void CloseWindow(IWindow window)
{
Handler?.Invoke(nameof(IApplication.CloseWindow), window);
}

public IWindow CreateWindow(IActivationState activationState)
{
return _window;
}

public void OpenWindow(IWindow window)
{
throw new NotImplementedException();
}

public void ThemeChanged()
{
throw new NotImplementedException();
}
}
}
Expand Up @@ -5,7 +5,7 @@
using static Microsoft.Maui.DeviceTests.HandlerTestBase;
using AActivity = Android.App.Activity;

namespace Microsoft.Maui.DeviceTests
namespace Microsoft.Maui.DeviceTests.Stubs
{
public class WindowHandlerStub : ElementHandler<IWindow, AActivity>, IWindowHandler
{
Expand Down

0 comments on commit 8356889

Please sign in to comment.