Browse Source

Added integration tests for WindowStartupLocation.

pull/8232/head
Steven Kirk 4 years ago
parent
commit
4c8240b7bf
  1. 17
      samples/IntegrationTestApp/MainWindow.axaml
  2. 38
      samples/IntegrationTestApp/MainWindow.axaml.cs
  3. 26
      samples/IntegrationTestApp/ShowWindowTest.axaml
  4. 40
      samples/IntegrationTestApp/ShowWindowTest.axaml.cs
  5. 4
      tests/Avalonia.IntegrationTests.Appium/Avalonia.IntegrationTests.Appium.csproj
  6. 164
      tests/Avalonia.IntegrationTests.Appium/WindowTests.cs

17
samples/IntegrationTestApp/MainWindow.axaml

@ -94,6 +94,23 @@
</StackPanel>
</DockPanel>
</TabItem>
<TabItem Header="Window">
<StackPanel>
<TextBox Name="ShowWindowSize" Watermark="Window Size"/>
<ComboBox Name="ShowWindowMode" SelectedIndex="0">
<ComboBoxItem>NonOwned</ComboBoxItem>
<ComboBoxItem>Owned</ComboBoxItem>
<ComboBoxItem>Modal</ComboBoxItem>
</ComboBox>
<ComboBox Name="ShowWindowLocation" SelectedIndex="0">
<ComboBoxItem>Manual</ComboBoxItem>
<ComboBoxItem>CenterScreen</ComboBoxItem>
<ComboBoxItem>CenterOwner</ComboBoxItem>
</ComboBox>
<Button Name="ShowWindow">Show Window</Button>
</StackPanel>
</TabItem>
</TabControl>
</DockPanel>
</Window>

38
samples/IntegrationTestApp/MainWindow.axaml.cs

@ -5,6 +5,7 @@ using Avalonia;
using Avalonia.Controls;
using Avalonia.Interactivity;
using Avalonia.Markup.Xaml;
using Avalonia.VisualTree;
namespace IntegrationTestApp
{
@ -46,6 +47,41 @@ namespace IntegrationTestApp
}
}
private void ShowWindow()
{
var sizeTextBox = this.GetControl<TextBox>("ShowWindowSize");
var modeComboBox = this.GetControl<ComboBox>("ShowWindowMode");
var locationComboBox = this.GetControl<ComboBox>("ShowWindowLocation");
var size = !string.IsNullOrWhiteSpace(sizeTextBox.Text) ? Size.Parse(sizeTextBox.Text) : (Size?)null;
var owner = (Window)this.GetVisualRoot()!;
var window = new ShowWindowTest
{
WindowStartupLocation = (WindowStartupLocation)locationComboBox.SelectedIndex,
};
if (size.HasValue)
{
window.Width = size.Value.Width;
window.Height = size.Value.Height;
}
sizeTextBox.Text = string.Empty;
switch (modeComboBox.SelectedIndex)
{
case 0:
window.Show();
break;
case 1:
window.Show(owner);
break;
case 2:
window.ShowDialog(owner);
break;
}
}
private void MenuClicked(object? sender, RoutedEventArgs e)
{
var clickedMenuItemTextBlock = this.FindControl<TextBlock>("ClickedMenuItem");
@ -64,6 +100,8 @@ namespace IntegrationTestApp
this.FindControl<ListBox>("BasicListBox").SelectedIndex = -1;
if (source?.Name == "MenuClickedMenuItemReset")
this.FindControl<TextBlock>("ClickedMenuItem").Text = "None";
if (source?.Name == "ShowWindow")
ShowWindow();
}
}
}

26
samples/IntegrationTestApp/ShowWindowTest.axaml

@ -0,0 +1,26 @@
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="IntegrationTestApp.ShowWindowTest"
Title="Show Window Test">
<Grid ColumnDefinitions="Auto,Auto" RowDefinitions="Auto,Auto,Auto,Auto,Auto,Auto,Auto">
<Button Name="CloseWindow" Grid.Row="0" Click="CloseWindow_Click">Close</Button>
<Label Grid.Column="0" Grid.Row="1">Client Size</Label>
<TextBox Name="ClientSize" Grid.Column="1" Grid.Row="1" IsReadOnly="True"/>
<Label Grid.Column="0" Grid.Row="2">Frame Size</Label>
<TextBox Name="FrameSize" Grid.Column="1" Grid.Row="2" IsReadOnly="True"/>
<Label Grid.Column="0" Grid.Row="3">Position</Label>
<TextBox Name="Position" Grid.Column="1" Grid.Row="3" IsReadOnly="True"/>
<Label Grid.Column="0" Grid.Row="4">Owner Rect</Label>
<TextBox Name="OwnerRect" Grid.Column="1" Grid.Row="4" IsReadOnly="True"/>
<Label Grid.Column="0" Grid.Row="5">Screen Rect</Label>
<TextBox Name="ScreenRect" Grid.Column="1" Grid.Row="5" IsReadOnly="True"/>
<Label Grid.Column="0" Grid.Row="6">Scaling</Label>
<TextBox Name="Scaling" Grid.Column="1" Grid.Row="6" IsReadOnly="True"/>
</Grid>
</Window>

40
samples/IntegrationTestApp/ShowWindowTest.axaml.cs

@ -0,0 +1,40 @@
using System;
using Avalonia.Controls;
using Avalonia.Interactivity;
using Avalonia.Markup.Xaml;
using Avalonia.Rendering;
namespace IntegrationTestApp
{
public class ShowWindowTest : Window
{
public ShowWindowTest()
{
InitializeComponent();
}
private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
}
protected override void OnOpened(EventArgs e)
{
base.OnOpened(e);
this.GetControl<TextBox>("ClientSize").Text = $"{Width}, {Height}";
this.GetControl<TextBox>("FrameSize").Text = $"{FrameSize}";
this.GetControl<TextBox>("Position").Text = $"{Position}";
this.GetControl<TextBox>("ScreenRect").Text = $"{Screens.ScreenFromVisual(this)?.WorkingArea}";
this.GetControl<TextBox>("Scaling").Text = $"{((IRenderRoot)this).RenderScaling}";
if (Owner is not null)
{
var ownerRect = this.GetControl<TextBox>("OwnerRect");
var owner = (Window)Owner;
ownerRect.Text = $"{owner.Position}, {owner.FrameSize}";
}
}
private void CloseWindow_Click(object sender, RoutedEventArgs e) => Close();
}
}

4
tests/Avalonia.IntegrationTests.Appium/Avalonia.IntegrationTests.Appium.csproj

@ -5,6 +5,10 @@
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Avalonia.Controls\Avalonia.Controls.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Appium.WebDriver" Version="4.3.1" />
<PackageReference Include="Xunit.Extensions.Ordering" Version="1.4.5" />

164
tests/Avalonia.IntegrationTests.Appium/WindowTests.cs

@ -0,0 +1,164 @@
using System;
using System.Linq;
using System.Runtime.InteropServices;
using Avalonia.Controls;
using OpenQA.Selenium.Appium;
using Xunit;
using Xunit.Sdk;
namespace Avalonia.IntegrationTests.Appium
{
[Collection("Default")]
public class WindowTests
{
private readonly AppiumDriver<AppiumWebElement> _session;
public WindowTests(TestAppFixture fixture)
{
_session = fixture.Session;
var tabs = _session.FindElementByAccessibilityId("MainTabs");
var tab = tabs.FindElementByName("Window");
tab.Click();
}
[Theory]
[MemberData(nameof(StartupLocationData))]
public void StartupLocation(string? size, ShowWindowMode mode, WindowStartupLocation location)
{
var mainWindowHandle = GetCurrentWindowHandleHack();
try
{
var sizeTextBox = _session.FindElementByAccessibilityId("ShowWindowSize");
var modeComboBox = _session.FindElementByAccessibilityId("ShowWindowMode");
var locationComboBox = _session.FindElementByAccessibilityId("ShowWindowLocation");
var showButton = _session.FindElementByAccessibilityId("ShowWindow");
if (size is not null)
sizeTextBox.SendKeys(size);
modeComboBox.Click();
_session.FindElementByName(mode.ToString()).SendClick();
locationComboBox.Click();
_session.FindElementByName(location.ToString()).SendClick();
showButton.Click();
SwitchToNewWindowHack(oldWindowHandle: mainWindowHandle);
var clientSize = Size.Parse(_session.FindElementByAccessibilityId("ClientSize").Text);
var frameSize = Size.Parse(_session.FindElementByAccessibilityId("FrameSize").Text);
var position = PixelPoint.Parse(_session.FindElementByAccessibilityId("Position").Text);
var screenRect = PixelRect.Parse(_session.FindElementByAccessibilityId("ScreenRect").Text);
var scaling = double.Parse(_session.FindElementByAccessibilityId("Scaling").Text);
Assert.True(frameSize.Width >= clientSize.Width, "Expected frame width >= client width.");
Assert.True(frameSize.Height > clientSize.Height, "Expected frame height > client height.");
var frameRect = new PixelRect(position, PixelSize.FromSize(frameSize, scaling));
switch (location)
{
case WindowStartupLocation.CenterScreen:
{
var expected = screenRect.CenterRect(frameRect);
AssertCloseEnough(expected.Position, frameRect.Position);
break;
}
}
}
finally
{
try
{
var closeButton = _session.FindElementByAccessibilityId("CloseWindow");
closeButton.Click();
SwitchToMainWindowHack(mainWindowHandle);
}
catch { }
}
}
public static TheoryData<string?, ShowWindowMode, WindowStartupLocation> StartupLocationData()
{
var sizes = new[] { null, "400,300" };
var data = new TheoryData<string?, ShowWindowMode, WindowStartupLocation>();
foreach (var size in sizes)
{
foreach (var mode in Enum.GetValues<ShowWindowMode>())
{
foreach (var location in Enum.GetValues<WindowStartupLocation>())
{
if (!(location == WindowStartupLocation.CenterOwner && mode == ShowWindowMode.NonOwned))
{
data.Add(size, mode, location);
}
}
}
}
return data;
}
private string? GetCurrentWindowHandleHack()
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
// HACK: WinAppDriver only seems to switch to a newly opened window if the window has an owner,
// otherwise the session remains targeting the previous window. Return the handle for the
// current window so we know which window to switch to when another is opened.
return _session.WindowHandles.Single();
}
return null;
}
private void SwitchToNewWindowHack(string? oldWindowHandle)
{
if (oldWindowHandle is not null)
{
var newWindowHandle = _session.WindowHandles.FirstOrDefault(x => x != oldWindowHandle);
// HACK: Looks like WinAppDriver only adds window handles for non-owned windows, but luckily
// non-owned windows is where we're having the problem, so if we find a window handle that
// isn't the main window handle then switch to it.
if (newWindowHandle is not null)
_session.SwitchTo().Window(newWindowHandle);
}
}
private void SwitchToMainWindowHack(string? mainWindowHandle)
{
if (mainWindowHandle is not null)
_session.SwitchTo().Window(mainWindowHandle);
}
private static void AssertCloseEnough(PixelPoint expected, PixelPoint actual)
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
// On win32, accurate frame information cannot be obtained until a window is shown but
// WindowStartupLocation needs to be calculated before the window is shown, meaning that
// the position of a centered window can be off by a bit. From initial testing, looks
// like this shouldn't be more than 10 pixels.
if (Math.Abs(expected.X - actual.X) > 10)
throw new EqualException(expected, actual);
if (Math.Abs(expected.Y - actual.Y) > 10)
throw new EqualException(expected, actual);
}
else
{
Assert.Equal(expected, actual);
}
}
public enum ShowWindowMode
{
NonOwned,
Owned,
Modal
}
}
}
Loading…
Cancel
Save