diff --git a/tests/Avalonia.IntegrationTests.Appium/WindowTests.cs b/tests/Avalonia.IntegrationTests.Appium/WindowTests.cs index 6d99a2f651..fe9720625c 100644 --- a/tests/Avalonia.IntegrationTests.Appium/WindowTests.cs +++ b/tests/Avalonia.IntegrationTests.Appium/WindowTests.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.Runtime.InteropServices; using System.Threading; using Avalonia.Controls; @@ -9,24 +8,21 @@ using OpenQA.Selenium.Appium; using OpenQA.Selenium.Interactions; using SixLabors.ImageSharp.PixelFormats; using Xunit; -using Xunit.Sdk; namespace Avalonia.IntegrationTests.Appium { [Collection("Default")] - public class WindowTests + public class WindowTests : WindowTestsBase { private readonly ISession _session; private readonly AppiumDriver _driver; - private readonly IWindowElement _mainWindow; - public WindowTests(DefaultAppFixture fixture) + public WindowTests(DefaultAppFixture fixture) : base (fixture.Session) { _session = fixture.Session; _driver = fixture.Driver; - - _mainWindow = _session.GetWindow("MainWindow"); - var tab = _mainWindow.FindElementByName("Window"); + + var tab = MainWindow.FindElementByName("Window"); tab.Click(); } @@ -169,7 +165,7 @@ namespace Avalonia.IntegrationTests.Appium public void ShowMode(ShowWindowMode mode) { using var window = OpenWindow(null, mode, WindowStartupLocation.Manual); - var windowState = _mainWindow.FindElementByAccessibilityId("CurrentWindowState"); + var windowState = window.FindElementByAccessibilityId("CurrentWindowState"); var original = GetWindowInfo(window); Assert.Equal("Normal", windowState.GetComboBoxValue()); @@ -210,11 +206,13 @@ namespace Avalonia.IntegrationTests.Appium [Fact] public void TransparentWindow() { - var showTransparentWindow = _mainWindow.FindElementByAccessibilityId("ShowTransparentWindow"); + var showTransparentWindow = MainWindow.FindElementByAccessibilityId("ShowTransparentWindow"); + showTransparentWindow.Click(); Thread.Sleep(1000); - - var window = _mainWindow.FindElementByAccessibilityId("TransparentWindow"); + + var window = _session.GetWindow("TransparentWindow"); + var screenshot = window.GetScreenshot(); window.Click(); @@ -230,11 +228,11 @@ namespace Avalonia.IntegrationTests.Appium [Fact] public void TransparentPopup() { - var showTransparentWindow = _mainWindow.FindElementByAccessibilityId("ShowTransparentPopup"); + var showTransparentWindow = MainWindow.FindElementByAccessibilityId("ShowTransparentPopup"); showTransparentWindow.Click(); Thread.Sleep(1000); - var window = _mainWindow.FindElementByAccessibilityId("TransparentPopupBackground"); + using var window = _session.GetWindow("TransparentPopupBackground"); var container = window.FindElementByAccessibilityId("PopupContainer"); var screenshot = container.GetScreenshot(); @@ -300,168 +298,5 @@ namespace Avalonia.IntegrationTests.Appium return data; } - - 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 if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) - { - if (Math.Abs(expected.X - actual.X) > 15) - throw new EqualException(expected, actual); - if (Math.Abs(expected.Y - actual.Y) > 15) - throw new EqualException(expected, actual); - } - else - { - Assert.Equal(expected, actual); - } - } - - private IWindowElement OpenWindow( - Size? size, - ShowWindowMode mode, - WindowStartupLocation location = WindowStartupLocation.Manual, - WindowState state = Controls.WindowState.Normal, - bool canResize = true) - { - var timer = new SplitTimer(); - - var elements = _mainWindow.GetChildren(); - - timer.SplitLog("getChildren"); - - if (size.HasValue) - { - var sizeTextBox = _mainWindow.FindElementByAccessibilityId("ShowWindowSize"); - timer.SplitLog(nameof(sizeTextBox)); - sizeTextBox.SendKeys($"{size.Value.Width}, {size.Value.Height}"); - } - - var modeComboBox = _mainWindow.FindElementByAccessibilityId("ShowWindowMode"); - timer.SplitLog(nameof(modeComboBox)); - - if (modeComboBox.GetComboBoxValue() != mode.ToString()) - { - modeComboBox.Click(); - _mainWindow.FindElementByName(mode.ToString()).SendClick(); - } - - var locationComboBox = _mainWindow.FindElementByAccessibilityId("ShowWindowLocation"); - timer.SplitLog(nameof(locationComboBox)); - if (locationComboBox.GetComboBoxValue() != location.ToString()) - { - locationComboBox.Click(); - _mainWindow.FindElementByName(location.ToString()).SendClick(); - } - - var stateComboBox = _mainWindow.FindElementByAccessibilityId("ShowWindowState"); - timer.SplitLog(nameof(stateComboBox)); - if (stateComboBox.GetComboBoxValue() != state.ToString()) - { - stateComboBox.Click(); - _mainWindow.FindElementByAccessibilityId($"ShowWindowState{state}").SendClick(); - } - - var canResizeCheckBox = _mainWindow.FindElementByAccessibilityId("ShowWindowCanResize"); - timer.SplitLog(nameof(canResizeCheckBox)); - if (canResizeCheckBox.GetIsChecked() != canResize) - canResizeCheckBox.Click(); - - timer.Reset(); - - var showButton = _mainWindow.FindElementByAccessibilityId("ShowWindow"); - timer.SplitLog(nameof(showButton)); - - var result = _session.GetNewWindow(()=> showButton.Click()); - timer.SplitLog("GetNewWindow"); - - return result; - } - - private static WindowInfo GetWindowInfo(IWindowElement window) - { - var dictionary = new Dictionary(); - - PixelRect? ReadOwnerRect() - { - if (dictionary.ContainsKey("ownerrect")) - { - return PixelRect.Parse(dictionary["ownerrect"]); - } - - return null; - } - - var retry = 0; - - for (;;) - { - try - { - var timer = new SplitTimer(); - var summary = window.FindElementByAccessibilityId("CurrentSummary").Text; - - var items = summary.Split("::"); - - foreach (var item in items) - { - var kv = item.Split(":"); - - if (kv.Length == 2) - { - var key = kv[0]; - var value = kv[1]; - - dictionary[key] = value; - } - } - - timer.SplitLog("summary"); - - var result = new WindowInfo( - Size.Parse(dictionary["clientSize"]), - Size.Parse(dictionary["frameSize"]), - PixelPoint.Parse(dictionary["position"]), - ReadOwnerRect(), - PixelRect.Parse(dictionary["screen"]), - double.Parse(dictionary["scaling"]), - Enum.Parse(dictionary["windowstate"])); - - return result; - } - catch (OpenQA.Selenium.NoSuchElementException) when (retry++ < 3) - { - // MacOS sometimes seems to need a bit of time to get itself back in order after switching out - // of fullscreen. - Thread.Sleep(1000); - } - } - } - - public enum ShowWindowMode - { - NonOwned, - Owned, - Modal - } - - private record WindowInfo( - Size ClientSize, - Size FrameSize, - PixelPoint Position, - PixelRect? OwnerRect, - PixelRect ScreenRect, - double Scaling, - WindowState WindowState); } } diff --git a/tests/Avalonia.IntegrationTests.Appium/WindowTestsBase.cs b/tests/Avalonia.IntegrationTests.Appium/WindowTestsBase.cs new file mode 100644 index 0000000000..7fe49023af --- /dev/null +++ b/tests/Avalonia.IntegrationTests.Appium/WindowTestsBase.cs @@ -0,0 +1,197 @@ +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Threading; +using Avalonia.Controls; +using Avalonia.IntegrationTests.Appium.Wrappers; +using OpenQA.Selenium.Appium; +using Xunit; +using Xunit.Sdk; + +namespace Avalonia.IntegrationTests.Appium; + +public class WindowTestsBase +{ + private readonly ISession _session; + private readonly IWindowElement _mainWindow; + + public WindowTestsBase(ISession session) + { + _session = session; + _mainWindow = _session.GetWindow("MainWindow"); + } + + protected IWindowElement MainWindow => _mainWindow; + + protected ISession Session => _session; + + protected IWindowElement OpenWindow( + Size? size, + ShowWindowMode mode, + WindowStartupLocation location = WindowStartupLocation.Manual, + WindowState state = Controls.WindowState.Normal, + bool canResize = true) + { + var timer = new SplitTimer(); + + var elements = _mainWindow.GetChildren(); + + timer.SplitLog("getChildren"); + + if (size.HasValue) + { + var sizeTextBox = _mainWindow.FindElementByAccessibilityId("ShowWindowSize"); + timer.SplitLog(nameof(sizeTextBox)); + sizeTextBox.SendKeys($"{size.Value.Width}, {size.Value.Height}"); + } + + var modeComboBox = _mainWindow.FindElementByAccessibilityId("ShowWindowMode"); + timer.SplitLog(nameof(modeComboBox)); + + if (modeComboBox.GetComboBoxValue() != mode.ToString()) + { + modeComboBox.Click(); + _mainWindow.FindElementByName(mode.ToString()).SendClick(); + } + + var locationComboBox = _mainWindow.FindElementByAccessibilityId("ShowWindowLocation"); + timer.SplitLog(nameof(locationComboBox)); + if (locationComboBox.GetComboBoxValue() != location.ToString()) + { + locationComboBox.Click(); + _mainWindow.FindElementByName(location.ToString()).SendClick(); + } + + var stateComboBox = _mainWindow.FindElementByAccessibilityId("ShowWindowState"); + timer.SplitLog(nameof(stateComboBox)); + if (stateComboBox.GetComboBoxValue() != state.ToString()) + { + stateComboBox.Click(); + _mainWindow.FindElementByAccessibilityId($"ShowWindowState{state}").SendClick(); + } + + var canResizeCheckBox = _mainWindow.FindElementByAccessibilityId("ShowWindowCanResize"); + timer.SplitLog(nameof(canResizeCheckBox)); + if (canResizeCheckBox.GetIsChecked() != canResize) + canResizeCheckBox.Click(); + + timer.Reset(); + + var showButton = _mainWindow.FindElementByAccessibilityId("ShowWindow"); + timer.SplitLog(nameof(showButton)); + + var result = _session.GetNewWindow(() => showButton.Click()); + + timer.SplitLog("GetNewWindow"); + + return result; + } + + protected 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 if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + { + if (Math.Abs(expected.X - actual.X) > 15) + throw new EqualException(expected, actual); + if (Math.Abs(expected.Y - actual.Y) > 15) + throw new EqualException(expected, actual); + } + else + { + Assert.Equal(expected, actual); + } + } + + protected static WindowInfo GetWindowInfo(IWindowElement window) + { + var dictionary = new Dictionary(); + + PixelRect? ReadOwnerRect() + { + if (dictionary.ContainsKey("ownerrect")) + { + return PixelRect.Parse(dictionary["ownerrect"]); + } + + return null; + } + + var retry = 0; + + for (;;) + { + try + { + var timer = new SplitTimer(); + var summary = window.FindElementByAccessibilityId("CurrentSummary").Text; + + var items = summary.Split("::"); + + foreach (var item in items) + { + var kv = item.Split(":"); + + if (kv.Length == 2) + { + var key = kv[0]; + var value = kv[1]; + + dictionary[key] = value; + } + } + + timer.SplitLog("summary"); + + var result = new WindowInfo( + Size.Parse(dictionary["clientSize"]), + Size.Parse(dictionary["frameSize"]), + PixelPoint.Parse(dictionary["position"]), + ReadOwnerRect(), + PixelRect.Parse(dictionary["screen"]), + double.Parse(dictionary["scaling"]), + Enum.Parse(dictionary["windowstate"])); + + return result; + } + catch (OpenQA.Selenium.NoSuchElementException) when (retry++ < 3) + { + // MacOS sometimes seems to need a bit of time to get itself back in order after switching out + // of fullscreen. + Thread.Sleep(1000); + } + } + } + + protected int GetWindowOrder(IWindowElement window) + { + var order = window.FindByXPath("//*[@identifier='CurrentOrder']"); + return int.Parse(order.Text); + } + + public enum ShowWindowMode + { + NonOwned, + Owned, + Modal + } + + protected record WindowInfo( + Size ClientSize, + Size FrameSize, + PixelPoint Position, + PixelRect? OwnerRect, + PixelRect ScreenRect, + double Scaling, + WindowState WindowState); +} diff --git a/tests/Avalonia.IntegrationTests.Appium/WindowTests_MacOS.cs b/tests/Avalonia.IntegrationTests.Appium/WindowTests_MacOS.cs index 55f93bb9d8..bbb52c564c 100644 --- a/tests/Avalonia.IntegrationTests.Appium/WindowTests_MacOS.cs +++ b/tests/Avalonia.IntegrationTests.Appium/WindowTests_MacOS.cs @@ -13,13 +13,13 @@ using Xunit; namespace Avalonia.IntegrationTests.Appium { [Collection("Default")] - public class WindowTests_MacOS + public class WindowTests_MacOS : WindowTestsBase { private readonly IWindowElement _mainWindow; private readonly ISession _session; private readonly AppiumDriver _driver; - public WindowTests_MacOS(DefaultAppFixture fixture) + public WindowTests_MacOS(DefaultAppFixture fixture) : base (fixture.Session) { _session = fixture.Session; _driver = fixture.Driver; @@ -48,7 +48,7 @@ namespace Avalonia.IntegrationTests.Appium [PlatformFact(TestPlatforms.MacOS)] public void WindowOrder_Modal_Dialog_Stays_InFront_Of_Parent() { - using (var window = OpenWindow(new PixelSize(200, 100), ShowWindowMode.Modal, WindowStartupLocation.Manual)) + using (var window = OpenWindow(new Size(200, 100), ShowWindowMode.Modal, WindowStartupLocation.Manual)) { _mainWindow.Click(); @@ -61,9 +61,17 @@ namespace Avalonia.IntegrationTests.Appium [PlatformFact(TestPlatforms.MacOS)] public void WindowOrder_Modal_Dialog_Stays_InFront_Of_Parent_When_Clicking_Resize_Grip() { + AppiumWebElement GetWindow(string identifier) + { + // 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 _driver.FindElementByXPath( + $"XCUIElementTypeWindow//*[@identifier='{identifier}']/parent::XCUIElementTypeWindow"); + } + var mainWindow = GetWindow("MainWindow"); - using (var window = OpenWindow(new PixelSize(200, 100), ShowWindowMode.Modal, WindowStartupLocation.Manual)) + using (var window = OpenWindow(new Size(200, 100), ShowWindowMode.Modal, WindowStartupLocation.Manual)) { new Actions(_driver) .MoveToElement(mainWindow, 100, 1) @@ -92,7 +100,7 @@ namespace Avalonia.IntegrationTests.Appium try { - using (var window = OpenWindow(new PixelSize(200, 100), ShowWindowMode.Modal, WindowStartupLocation.Manual)) + using (var window = OpenWindow(new Size(200, 100), ShowWindowMode.Modal, WindowStartupLocation.Manual)) { var secondaryWindowIndex = GetWindowOrder(window); Assert.Equal(1, secondaryWindowIndex); @@ -107,7 +115,7 @@ namespace Avalonia.IntegrationTests.Appium [PlatformFact(TestPlatforms.MacOS)] public void WindowOrder_Owned_Dialog_Stays_InFront_Of_Parent() { - using (var window = OpenWindow(new PixelSize(200, 100), ShowWindowMode.Owned, WindowStartupLocation.Manual)) + using (var window = OpenWindow(new Size(200, 100), ShowWindowMode.Owned, WindowStartupLocation.Manual)) { _mainWindow.SendClick(); var secondaryWindowIndex = GetWindowOrder(window); @@ -129,7 +137,7 @@ namespace Avalonia.IntegrationTests.Appium Assert.Equal("FullScreen", windowState.Text); // Open child window. - using (var window = OpenWindow(new PixelSize(200, 100), ShowWindowMode.Owned, WindowStartupLocation.Manual)) + using (var window = OpenWindow(new Size(200, 100), ShowWindowMode.Owned, WindowStartupLocation.Manual)) { _mainWindow.SendClick(); var secondaryWindowIndex = GetWindowOrder(window); @@ -150,7 +158,7 @@ namespace Avalonia.IntegrationTests.Appium [PlatformFact(TestPlatforms.MacOS)] public void WindowOrder_Owned_Dialog_Stays_InFront_Of_Parent_After_Modal_Closed() { - using (var window = OpenWindow(new PixelSize(200, 300), ShowWindowMode.Owned, WindowStartupLocation.Manual)) + using (var window = OpenWindow(new Size(200, 300), ShowWindowMode.Owned, WindowStartupLocation.Manual)) { OpenWindow(null, ShowWindowMode.Modal, WindowStartupLocation.Manual).Dispose(); @@ -166,7 +174,7 @@ namespace Avalonia.IntegrationTests.Appium IElement windowState; // Open child window. - using (OpenWindow(new PixelSize(200, 100), ShowWindowMode.Owned, WindowStartupLocation.Manual)) + using (OpenWindow(new Size(200, 100), ShowWindowMode.Owned, WindowStartupLocation.Manual)) { // Enter fullscreen _mainWindow.FindElementByAccessibilityId("EnterFullscreen").Click(); @@ -199,7 +207,7 @@ namespace Avalonia.IntegrationTests.Appium [PlatformFact(TestPlatforms.MacOS)] public void WindowOrder_NonOwned_Window_Does_Not_Stay_InFront_Of_Parent() { - using (var window = OpenWindow(new PixelSize(800, 100), ShowWindowMode.NonOwned, WindowStartupLocation.Manual)) + using (var window = OpenWindow(new Size(800, 100), ShowWindowMode.NonOwned, WindowStartupLocation.Manual)) { _mainWindow.Click(); @@ -215,10 +223,10 @@ namespace Avalonia.IntegrationTests.Appium [PlatformFact(TestPlatforms.MacOS)] public void WindowOrder_Owned_Is_Correct_After_Closing_Window() { - using (var window = OpenWindow(new PixelSize(300, 500), ShowWindowMode.Owned, WindowStartupLocation.CenterOwner)) + using (var window = OpenWindow(new Size(300, 500), ShowWindowMode.Owned, WindowStartupLocation.CenterOwner)) { // Open a second child window, and close it. - using (OpenWindow(new PixelSize(200, 200), ShowWindowMode.Owned, WindowStartupLocation.CenterOwner)) + using (OpenWindow(new Size(200, 200), ShowWindowMode.Owned, WindowStartupLocation.CenterOwner)) { } @@ -237,7 +245,7 @@ namespace Avalonia.IntegrationTests.Appium Assert.True(zoomButton.Enabled); Assert.True(miniaturizeButton.Enabled); - using (OpenWindow(new PixelSize(200, 100), ShowWindowMode.Modal, WindowStartupLocation.CenterOwner)) + using (OpenWindow(new Size(200, 100), ShowWindowMode.Modal, WindowStartupLocation.CenterOwner)) { Assert.False(closeButton.Enabled); Assert.False(zoomButton.Enabled); @@ -248,7 +256,7 @@ namespace Avalonia.IntegrationTests.Appium [PlatformFact(TestPlatforms.MacOS)] public void Minimize_Button_Is_Disabled_On_Modal_Dialog() { - using (var secondaryWindow = OpenWindow(new PixelSize(200, 100), ShowWindowMode.Modal, WindowStartupLocation.CenterOwner)) + using (var secondaryWindow = OpenWindow(new Size(200, 100), ShowWindowMode.Modal, WindowStartupLocation.CenterOwner)) { var (closeButton, miniaturizeButton, zoomButton) = (secondaryWindow as WindowElement).GetChromeButtons(); @@ -262,7 +270,7 @@ namespace Avalonia.IntegrationTests.Appium [InlineData(ShowWindowMode.Owned)] public void Minimize_Button_Disabled_Owned_Window(ShowWindowMode mode) { - using (var secondaryWindow = OpenWindow(new PixelSize(200, 100), mode, WindowStartupLocation.Manual)) + using (var secondaryWindow = OpenWindow(new Size(200, 100), mode, WindowStartupLocation.Manual)) { var (_, miniaturizeButton, _) = (secondaryWindow as WindowElement).GetChromeButtons(); @@ -275,7 +283,7 @@ namespace Avalonia.IntegrationTests.Appium [InlineData(ShowWindowMode.NonOwned)] public void Minimize_Button_Minimizes_Window(ShowWindowMode mode) { - using (var secondaryWindow = OpenWindow(new PixelSize(200, 100), mode, WindowStartupLocation.Manual)) + using (var secondaryWindow = OpenWindow(new Size(200, 100), mode, WindowStartupLocation.Manual)) { var (_, miniaturizeButton, _) = (secondaryWindow as WindowElement).GetChromeButtons(); @@ -332,59 +340,5 @@ namespace Avalonia.IntegrationTests.Appium Assert.False(zoomButton.Enabled); } } - - private IWindowElement OpenWindow( - PixelSize? size, - ShowWindowMode mode, - WindowStartupLocation location, - bool canResize = true) - { - var sizeTextBox = _mainWindow.FindElementByAccessibilityId("ShowWindowSize"); - var modeComboBox = _mainWindow.FindElementByAccessibilityId("ShowWindowMode"); - var locationComboBox = _mainWindow.FindElementByAccessibilityId("ShowWindowLocation"); - var canResizeCheckBox = _mainWindow.FindElementByAccessibilityId("ShowWindowCanResize"); - var showButton = _mainWindow.FindElementByAccessibilityId("ShowWindow"); - - if (size.HasValue) - sizeTextBox.SendKeys($"{size.Value.Width}, {size.Value.Height}"); - - if (modeComboBox.GetComboBoxValue() != mode.ToString()) - { - modeComboBox.Click(); - _mainWindow.FindElementByName(mode.ToString()).SendClick(); - } - - if (locationComboBox.GetComboBoxValue() != location.ToString()) - { - locationComboBox.Click(); - _mainWindow.FindElementByName(location.ToString()).SendClick(); - } - - if (canResizeCheckBox.GetIsChecked() != canResize) - canResizeCheckBox.Click(); - - return _session.GetNewWindow(() => showButton.Click()); - } - - private AppiumWebElement GetWindow(string identifier) - { - // 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 _driver.FindElementByXPath( - $"XCUIElementTypeWindow//*[@identifier='{identifier}']/parent::XCUIElementTypeWindow"); - } - - private int GetWindowOrder(IWindowElement window) - { - var order = window.FindByXPath("//*[@identifier='CurrentOrder']"); - return int.Parse(order.Text); - } - - public enum ShowWindowMode - { - NonOwned, - Owned, - Modal - } } } diff --git a/tests/Avalonia.IntegrationTests.Appium/Wrappers/Element.cs b/tests/Avalonia.IntegrationTests.Appium/Wrappers/Element.cs index dc415ca933..59b47d191c 100644 --- a/tests/Avalonia.IntegrationTests.Appium/Wrappers/Element.cs +++ b/tests/Avalonia.IntegrationTests.Appium/Wrappers/Element.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using OpenQA.Selenium; using OpenQA.Selenium.Appium; @@ -16,34 +17,9 @@ public class Element : IElement protected IWebElement Inner => _inner; - private string? _name; - public string Name - { - get - { - if (_name is null) - { - _name = _inner.GetAttribute("title"); - } - - return _name; - } - } - - private string? _text; + public virtual string Name => _inner.GetAttribute("title"); - public string Text - { - get - { - if (_text is null) - { - _text = _inner.Text; - } - - return _text; - } - } + public virtual string Text => _inner.Text; public bool Enabled => _inner.Enabled; diff --git a/tests/Avalonia.IntegrationTests.Appium/Wrappers/MacSession.cs b/tests/Avalonia.IntegrationTests.Appium/Wrappers/MacSession.cs index 1a6faae54c..e550b18151 100644 --- a/tests/Avalonia.IntegrationTests.Appium/Wrappers/MacSession.cs +++ b/tests/Avalonia.IntegrationTests.Appium/Wrappers/MacSession.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Threading; using OpenQA.Selenium; using OpenQA.Selenium.Appium; using OpenQA.Selenium.Appium.Mac; @@ -23,7 +24,6 @@ public class MacSession : ISession { get { - // Double XCUIElementTypeWindow is a hack for Avalonia a11y returning 2 nested windows. return _driver.FindElementsByXPath( "/XCUIElementTypeApplication/XCUIElementTypeWindow") .Select(x => new WindowElement(x)) @@ -48,14 +48,18 @@ public class MacSession : ISession var timer = new SplitTimer(); // Store the old window. - var oldWindows = Windows.ToList(); - + var oldWindowTitles = Windows.ToList() + .Select(x => (Value: x.Text, x)) + .Where(x => !string.IsNullOrEmpty(x.Value)) + .ToDictionary(x => x.Value, x => x.x); + timer.SplitLog("list windows"); - // open window with click openWindow(); timer.SplitLog("openWindow"); + + Thread.Sleep(1000); // find the new window var newWindows = Windows.ToList(); @@ -70,11 +74,11 @@ public class MacSession : ISession .Where(x => !string.IsNullOrEmpty(x.Value)) .ToDictionary(x => x.Value, x => x.x); - var result = Assert.Single(newWindowTitles.Where(x => !oldWindows.Contains(x.Value))).Value; + var result = Assert.Single(newWindowTitles.Keys.Except(oldWindowTitles.Keys)); timer.SplitLog("Asset"); - return result; + return newWindowTitles[result]; } internal static Func GetElementFactory() diff --git a/tests/Avalonia.IntegrationTests.Appium/Wrappers/WindowElement.cs b/tests/Avalonia.IntegrationTests.Appium/Wrappers/WindowElement.cs index 11d3f5742a..e2e99ea70f 100644 --- a/tests/Avalonia.IntegrationTests.Appium/Wrappers/WindowElement.cs +++ b/tests/Avalonia.IntegrationTests.Appium/Wrappers/WindowElement.cs @@ -7,11 +7,46 @@ namespace Avalonia.IntegrationTests.Appium.Wrappers; public class WindowElement : Element, IWindowElement, IEquatable { private bool _isDisposed; + private string? _text; + private string? _name; public WindowElement(IWebElement inner) : base(inner) { } + public override string Name + { + get + { + if (_name is null) + { + _name = base.Name; + } + + return _name; + } + } + + public override string Text + { + get + { + if (_text is null) + { + try + { + _text = base.Text; + } + catch (Exception) + { + _text = "DeadBeef"; + } + } + + return _text; + } + } + public string Id => (Inner as AppiumWebElement).Id; public void Close()