Skip to content

Commit

Permalink
Add WindowDecorationsTests (windows only for now)
Browse files Browse the repository at this point in the history
  • Loading branch information
maxkatz6 committed Apr 30, 2024
1 parent 1e84cab commit 01fbe57
Show file tree
Hide file tree
Showing 5 changed files with 267 additions and 8 deletions.
17 changes: 14 additions & 3 deletions samples/IntegrationTestApp/MainWindow.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
xmlns:integrationTestApp="using:IntegrationTestApp"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="IntegrationTestApp.MainWindow"
Name="MainWindow"
Icon="/Assets/icon.ico"
Title="IntegrationTestApp"
x:DataType="integrationTestApp:MainWindow">
Expand All @@ -24,7 +23,7 @@
</NativeMenuItem>
</NativeMenu>
</NativeMenu.Menu>
<DockPanel>
<DockPanel Background="{DynamicResource SystemRegionBrush}">
<NativeMenuBar DockPanel.Dock="Top"/>
<StackPanel DockPanel.Dock="Bottom" Margin="4" Orientation="Horizontal">
<TextBlock Margin="0,0,4,0">WindowState:</TextBlock>
Expand Down Expand Up @@ -177,7 +176,19 @@
</StackPanel>
</Grid>
</TabItem>


<TabItem Header="Window Decorations">
<StackPanel Spacing="4">
<CheckBox Name="WindowExtendClientAreaToDecorationsHint" Content="Extend Client Area to Decorations" />
<CheckBox Name="WindowForceSystemChrome" Content="Force SystemChrome" />
<CheckBox Name="WindowPreferSystemChrome" Content="Prefer SystemChrome" />
<CheckBox Name="WindowMacThickSystemChrome" Content="Mac Thick SystemChrome" />
<TextBox Name="WindowTitleBarHeightHint" Text="-1" Watermark="In dips" />
<Button Name="ApplyWindowDecorations" Content="Apply decorations on this Window" />
<Button Name="ShowNewWindowDecorations" Content="Show new Window with decorations" />
</StackPanel>
</TabItem>

<TabItem Header="Slider">
<DockPanel>
<DockPanel DockPanel.Dock="Top">
Expand Down
46 changes: 46 additions & 0 deletions samples/IntegrationTestApp/MainWindow.axaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
using Avalonia.Interactivity;
using Avalonia.Markup.Xaml;
using Avalonia.Media;
using Avalonia.Platform;
using Avalonia.Threading;
using Avalonia.VisualTree;
using Microsoft.CodeAnalysis;

Expand All @@ -19,6 +21,9 @@ public partial class MainWindow : Window
{
public MainWindow()
{
// Set name in code behind, so source generator will ignore it.
Name = "MainWindow";

InitializeComponent();
InitializeViewMenu();
InitializeGesturesTab();
Expand Down Expand Up @@ -277,6 +282,47 @@ private void OnButtonClick(object? sender, RoutedEventArgs e)
WindowState = WindowState.Normal;
if (source?.Name == nameof(RestoreAll))
OnRestoreAll();
if (source?.Name == nameof(ApplyWindowDecorations))
OnApplyWindowDecorations(this);
if (source?.Name == nameof(ShowNewWindowDecorations))
OnShowNewWindowDecorations();
}

private void OnApplyWindowDecorations(Window window)
{
window.ExtendClientAreaToDecorationsHint = WindowExtendClientAreaToDecorationsHint.IsChecked!.Value;
window.ExtendClientAreaTitleBarHeightHint =
int.TryParse(WindowTitleBarHeightHint.Text, out var val) ? val / DesktopScaling : -1;
window.ExtendClientAreaChromeHints = ExtendClientAreaChromeHints.NoChrome
| (WindowForceSystemChrome.IsChecked == true ? ExtendClientAreaChromeHints.SystemChrome : 0)
| (WindowPreferSystemChrome.IsChecked == true ? ExtendClientAreaChromeHints.PreferSystemChrome : 0)
| (WindowMacThickSystemChrome.IsChecked == true ? ExtendClientAreaChromeHints.OSXThickTitleBar : 0);
AdjustOffsets(window);

window.Background = Brushes.Transparent;
window.PropertyChanged += WindowOnPropertyChanged;

static void WindowOnPropertyChanged(object? sender, AvaloniaPropertyChangedEventArgs e)
{
var window = (Window)sender!;
if (e.Property == OffScreenMarginProperty || e.Property == WindowDecorationMarginProperty)
{
AdjustOffsets(window);
}
}

static void AdjustOffsets(Window window)
{
window.Padding = window.OffScreenMargin;
((Control)window.Content!).Margin = window.WindowDecorationMargin;
}
}

private void OnShowNewWindowDecorations()
{
var window = new ShowWindowTest();
OnApplyWindowDecorations(window);
window.Show();
}
}
}
2 changes: 1 addition & 1 deletion samples/IntegrationTestApp/ShowWindowTest.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
Name="SecondaryWindow"
x:DataType="Window"
Title="Show Window Test">
<integrationTestApp:MeasureBorder Name="MyBorder">
<integrationTestApp:MeasureBorder Name="MyBorder" Background="{DynamicResource SystemRegionBrush}">
<Grid ColumnDefinitions="Auto,Auto" RowDefinitions="Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto">
<Label Grid.Column="0" Grid.Row="1">Client Size</Label>
<TextBox Name="CurrentClientSize" Grid.Column="1" Grid.Row="1" IsReadOnly="True"
Expand Down
202 changes: 202 additions & 0 deletions tests/Avalonia.IntegrationTests.Appium/WindowDecorationsTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
using System;
using System.Threading;
using Avalonia.Controls;
using OpenQA.Selenium;
using OpenQA.Selenium.Appium;
using OpenQA.Selenium.Internal;
using Xunit;

namespace Avalonia.IntegrationTests.Appium;

[Collection("Default")]
public class WindowDecorationsTests : IDisposable
{
private readonly AppiumDriver<AppiumWebElement> _session;

public WindowDecorationsTests(DefaultAppFixture fixture)
{
_session = fixture.Session;

var tabs = _session.FindElementByAccessibilityId("MainTabs");
var tab = tabs.FindElementByName("Window Decorations");
tab.Click();
}

[Fact(Skip = "Fix me")]
public void Window_Size_Should_Be_Consistent_Between_Toggles()
{
var window = _session.FindElementByAccessibilityId("MainWindow");
var original = window.Size;

// Step 1: keep extend client area to false, but adjust some value that should not have any effect.
SetParameters(false, false, false, false, 10);
ApplyToCurrentWindow();
Assert.Equal(original, window.Size);

// Step 2: enable and disable extended system chrome.
SetParameters(true, true, false, false, 20);
ApplyToCurrentWindow();
SetParameters(false, false, false, false, 20);
ApplyToCurrentWindow();
Assert.Equal(original, window.Size);

// Step 3: enable and disable extended client chrome.
SetParameters(true, false, true, false, 30);
ApplyToCurrentWindow();
SetParameters(false, false, true, false, 20);
ApplyToCurrentWindow();
Assert.Equal(original, window.Size);
}

[PlatformTheory(TestPlatforms.Windows)]
[InlineData(-1)]
[InlineData(25)]
[InlineData(50)]
public void Should_Apply_Client_Side_Chrome(int titleBarHeight)
{
SetParameters(true, false, true, false, titleBarHeight);

ApplyToCurrentWindow();

Thread.Sleep(500);

var (actualTitleBarHeight, actualButtonHeight) = ReadClientDecorationsHeight(_session);

if (titleBarHeight == -1) // default value - accept any greater than zero.
{
Assert.True(actualTitleBarHeight > 0);
Assert.True(actualButtonHeight > 0);
}
else
{
Assert.Equal(titleBarHeight, actualTitleBarHeight);
// In Avalonia title bar buttons are not constrained by title bar height, so it can be higher.
// Assert.True(buttonHeight <= titleBarHeight, "Button is higher than requested title bar height.");
}
}

[PlatformTheory(TestPlatforms.Windows)]
[InlineData(-1)]
[InlineData(25)]
[InlineData(50)]
public void Should_Apply_Server_Side_Chrome(int titleBarHeight)
{
SetParameters(true, true, false, false, titleBarHeight);

ApplyToCurrentWindow();

Thread.Sleep(500);

var (actualTitleBarHeight, actualButtonHeight) = ReadServerDecorationsHeight(_session);

if (titleBarHeight == -1) // default value - accept any greater than zero.
{
// On windows, system chrome is always 0px height, when client area is extended.
if (!OperatingSystem.IsWindows())
Assert.True(actualTitleBarHeight > 0);
Assert.True(actualButtonHeight > 0, "Button is highter than requested title bar height.");
}
else
{
if (!OperatingSystem.IsWindows())
Assert.Equal(titleBarHeight, actualTitleBarHeight);
Assert.True(actualButtonHeight <= titleBarHeight, "Button is highter than requested title bar height.");
}
}

[PlatformTheory(TestPlatforms.Windows)]
[InlineData(-1)]
[InlineData(25)]
[InlineData(50)]
public void Should_Apply_Client_Side_Chrome_On_New_Window(int titleBarHeight)
{
SetParameters(true, false, true, false, titleBarHeight);

using (ApplyOnNewWindow())
{
Thread.Sleep(500);

var secondaryWindow = WindowTests.GetWindow(_session, "SecondaryWindow");

var (actualTitleBarHeight, actualButtonHeight) = ReadClientDecorationsHeight(secondaryWindow);

if (titleBarHeight == -1) // default value - accept any greater than zero.
{
Assert.True(actualTitleBarHeight > 0);
Assert.True(actualButtonHeight > 0);
}
else
{
Assert.Equal(titleBarHeight, actualTitleBarHeight);
// In Avalonia title bar buttons are not constrained by title bar height, so it can be higher.
// Assert.True(buttonHeight <= titleBarHeight, "Button is higher than requested title bar height.");
}
}
}

private void SetParameters(
bool extendClientArea,
bool forceSystemChrome,
bool preferSystemChrome,
bool macOsThickSystemChrome,
int titleBarHeight)
{
var extendClientAreaCheckBox = _session.FindElementByAccessibilityId("WindowExtendClientAreaToDecorationsHint");
var forceSystemChromeCheckBox = _session.FindElementByAccessibilityId("WindowForceSystemChrome");
var preferSystemChromeCheckBox = _session.FindElementByAccessibilityId("WindowPreferSystemChrome");
var macOsThickSystemChromeCheckBox = _session.FindElementByAccessibilityId("WindowMacThickSystemChrome");
var titleBarHeightBox = _session.FindElementByAccessibilityId("WindowTitleBarHeightHint");

if (extendClientAreaCheckBox.GetIsChecked() != extendClientArea)
extendClientAreaCheckBox.Click();
if (forceSystemChromeCheckBox.GetIsChecked() != forceSystemChrome)
forceSystemChromeCheckBox.Click();
if (preferSystemChromeCheckBox.GetIsChecked() != preferSystemChrome)
preferSystemChromeCheckBox.Click();
if (macOsThickSystemChromeCheckBox.GetIsChecked() != macOsThickSystemChrome)
macOsThickSystemChromeCheckBox.Click();

titleBarHeightBox.Click();
titleBarHeightBox.Clear();
if (titleBarHeight >= 0)
titleBarHeightBox.SendKeys(titleBarHeight.ToString());
}

private (int titleBarHeight, int buttonHeight) ReadClientDecorationsHeight(IFindsByClassName root)
{
var titlebar = (AppiumWebElement)root.FindElementByClassName("TitleBar");
var minimize = titlebar.FindElementByName("Minimize");
_ = titlebar.FindElementByName("Maximize");
_ = titlebar.FindElementByName("Close");

return (titlebar.Size.Height, minimize.Size.Height);
}

private (int titleBarHeight, int buttonHeight) ReadServerDecorationsHeight(IFindsByTagName root)
{
var titlebar = (AppiumWebElement)root.FindElementByTagName("TitleBar");
var minimize = titlebar.FindElementByName("Minimize");
_ = titlebar.FindElementByName("Maximize");
_ = titlebar.FindElementByName("Close");

return (titlebar.Size.Height, minimize.Size.Height);
}

private void ApplyToCurrentWindow()
{
var applyWindowDecorations = _session.FindElementByAccessibilityId("ApplyWindowDecorations");
applyWindowDecorations.Click();
}

private IDisposable ApplyOnNewWindow()
{
var showNewWindowDecorations = _session.FindElementByAccessibilityId("ShowNewWindowDecorations");
return showNewWindowDecorations.OpenWindowWithClick();
}

public void Dispose()
{
SetParameters(false, false, false, false, -1);
ApplyToCurrentWindow();
}
}
8 changes: 4 additions & 4 deletions tests/Avalonia.IntegrationTests.Appium/WindowTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ public void Window_Has_Disabled_Maximize_Button_When_CanResize_Is_False(ShowWind
{
using (OpenWindow(null, mode, WindowStartupLocation.Manual, canResize: false, extendClientArea: extendClientArea))
{
var secondaryWindow = GetWindow("SecondaryWindow");
var secondaryWindow = GetWindow(_session, "SecondaryWindow");
AppiumWebElement? maximizeButton;

if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
Expand Down Expand Up @@ -413,18 +413,18 @@ private static void AssertCloseEnough(PixelPoint expected, PixelPoint actual)
return showButton.OpenWindowWithClick();
}

private AppiumWebElement GetWindow(string identifier)
internal static AppiumWebElement GetWindow(AppiumDriver<AppiumWebElement> session, string identifier)
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
// The Avalonia a11y tree currently exposes two nested Window elements, this is a bug and should be fixed
// but in the meantime use the `parent::' selector to return the parent "real" window.
return _session.FindElementByXPath(
return session.FindElementByXPath(
$"XCUIElementTypeWindow//*[@identifier='{identifier}']/parent::XCUIElementTypeWindow");
}
else
{
return _session.FindElementByXPath($"//Window[@AutomationId='{identifier}']");
return session.FindElementByXPath($"//Window[@AutomationId='{identifier}']");
}
}

Expand Down

0 comments on commit 01fbe57

Please sign in to comment.