WindowTests_MacOS.cs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Threading;
  5. using Avalonia.Controls;
  6. using OpenQA.Selenium;
  7. using OpenQA.Selenium.Appium;
  8. using OpenQA.Selenium.Interactions;
  9. using Xunit;
  10. namespace Avalonia.IntegrationTests.Appium
  11. {
  12. [Collection("Default")]
  13. public class WindowTests_MacOS
  14. {
  15. private readonly AppiumDriver<AppiumWebElement> _session;
  16. public WindowTests_MacOS(TestAppFixture fixture)
  17. {
  18. var retry = 0;
  19. _session = fixture.Session;
  20. for (;;)
  21. {
  22. try
  23. {
  24. var tabs = _session.FindElementByAccessibilityId("MainTabs");
  25. var tab = tabs.FindElementByName("Window");
  26. tab.Click();
  27. return;
  28. }
  29. catch (WebDriverException) when (retry++ < 3)
  30. {
  31. // MacOS sometimes seems to need a bit of time to get itself back in order after switching out
  32. // of fullscreen.
  33. Thread.Sleep(1000);
  34. }
  35. }
  36. }
  37. [PlatformFact(TestPlatforms.MacOS)]
  38. public void WindowOrder_Modal_Dialog_Stays_InFront_Of_Parent()
  39. {
  40. var mainWindow = _session.FindElementByAccessibilityId("MainWindow");
  41. using (OpenWindow(new PixelSize(200, 100), ShowWindowMode.Modal, WindowStartupLocation.Manual))
  42. {
  43. mainWindow.Click();
  44. var secondaryWindowIndex = GetWindowOrder("SecondaryWindow");
  45. Assert.Equal(1, secondaryWindowIndex);
  46. }
  47. }
  48. [PlatformFact(TestPlatforms.MacOS)]
  49. public void WindowOrder_Modal_Dialog_Stays_InFront_Of_Parent_When_Clicking_Resize_Grip()
  50. {
  51. var mainWindow = GetWindow("MainWindow");
  52. using (OpenWindow(new PixelSize(200, 100), ShowWindowMode.Modal, WindowStartupLocation.Manual))
  53. {
  54. new Actions(_session)
  55. .MoveToElement(mainWindow, 100, 1)
  56. .ClickAndHold()
  57. .Perform();
  58. var secondaryWindowIndex = GetWindowOrder("SecondaryWindow");
  59. new Actions(_session)
  60. .MoveToElement(mainWindow, 100, 1)
  61. .Release()
  62. .Perform();
  63. Assert.Equal(1, secondaryWindowIndex);
  64. }
  65. }
  66. [PlatformFact(TestPlatforms.MacOS)]
  67. public void WindowOrder_Modal_Dialog_Stays_InFront_Of_Parent_When_In_Fullscreen()
  68. {
  69. var mainWindow = GetWindow("MainWindow");
  70. var buttons = mainWindow.GetChromeButtons();
  71. buttons.maximize.Click();
  72. Thread.Sleep(500);
  73. try
  74. {
  75. using (OpenWindow(new PixelSize(200, 100), ShowWindowMode.Modal, WindowStartupLocation.Manual))
  76. {
  77. var secondaryWindowIndex = GetWindowOrder("SecondaryWindow");
  78. Assert.Equal(1, secondaryWindowIndex);
  79. }
  80. }
  81. finally
  82. {
  83. _session.FindElementByAccessibilityId("ExitFullscreen").Click();
  84. }
  85. }
  86. [PlatformFact(TestPlatforms.MacOS)]
  87. public void WindowOrder_Owned_Dialog_Stays_InFront_Of_Parent()
  88. {
  89. var mainWindow = _session.FindElementByAccessibilityId("MainWindow");
  90. using (OpenWindow(new PixelSize(200, 100), ShowWindowMode.Owned, WindowStartupLocation.Manual))
  91. {
  92. mainWindow.SendClick();
  93. var secondaryWindowIndex = GetWindowOrder("SecondaryWindow");
  94. Assert.Equal(1, secondaryWindowIndex);
  95. }
  96. }
  97. [PlatformFact(TestPlatforms.MacOS)]
  98. public void WindowOrder_NonOwned_Window_Does_Not_Stay_InFront_Of_Parent()
  99. {
  100. var mainWindow = _session.FindElementByAccessibilityId("MainWindow");
  101. using (OpenWindow(new PixelSize(800, 100), ShowWindowMode.NonOwned, WindowStartupLocation.Manual))
  102. {
  103. mainWindow.Click();
  104. var secondaryWindowIndex = GetWindowOrder("SecondaryWindow");
  105. Assert.Equal(2, secondaryWindowIndex);
  106. var sendToBack = _session.FindElementByAccessibilityId("SendToBack");
  107. sendToBack.Click();
  108. }
  109. }
  110. [PlatformFact(TestPlatforms.MacOS)]
  111. public void WindowOrder_Owned_Is_Correct_After_Closing_Window()
  112. {
  113. using (OpenWindow(new PixelSize(300, 500), ShowWindowMode.Owned, WindowStartupLocation.CenterOwner))
  114. {
  115. // Open a second child window, and close it.
  116. using (OpenWindow(new PixelSize(200, 200), ShowWindowMode.Owned, WindowStartupLocation.CenterOwner))
  117. {
  118. }
  119. var secondaryWindowIndex = GetWindowOrder("SecondaryWindow");
  120. Assert.Equal(1, secondaryWindowIndex);
  121. }
  122. }
  123. [PlatformFact(TestPlatforms.MacOS)]
  124. public void Parent_Window_Has_Disabled_ChromeButtons_When_Modal_Dialog_Shown()
  125. {
  126. var window = GetWindow("MainWindow");
  127. var (closeButton, miniaturizeButton, zoomButton) = window.GetChromeButtons();
  128. Assert.True(closeButton.Enabled);
  129. Assert.True(zoomButton.Enabled);
  130. Assert.True(miniaturizeButton.Enabled);
  131. using (OpenWindow(new PixelSize(200, 100), ShowWindowMode.Modal, WindowStartupLocation.CenterOwner))
  132. {
  133. Assert.False(closeButton.Enabled);
  134. Assert.False(zoomButton.Enabled);
  135. Assert.False(miniaturizeButton.Enabled);
  136. }
  137. }
  138. [PlatformFact(TestPlatforms.MacOS)]
  139. public void Minimize_Button_Is_Disabled_On_Modal_Dialog()
  140. {
  141. using (OpenWindow(new PixelSize(200, 100), ShowWindowMode.Modal, WindowStartupLocation.CenterOwner))
  142. {
  143. var secondaryWindow = GetWindow("SecondaryWindow");
  144. var (closeButton, miniaturizeButton, zoomButton) = secondaryWindow.GetChromeButtons();
  145. Assert.True(closeButton.Enabled);
  146. Assert.True(zoomButton.Enabled);
  147. Assert.False(miniaturizeButton.Enabled);
  148. }
  149. }
  150. [PlatformTheory(TestPlatforms.MacOS)]
  151. [InlineData(ShowWindowMode.NonOwned)]
  152. [InlineData(ShowWindowMode.Owned)]
  153. public void Minimize_Button_Minimizes_Window(ShowWindowMode mode)
  154. {
  155. using (OpenWindow(new PixelSize(200, 100), mode, WindowStartupLocation.Manual))
  156. {
  157. var secondaryWindow = GetWindow("SecondaryWindow");
  158. var (_, miniaturizeButton, _) = secondaryWindow.GetChromeButtons();
  159. miniaturizeButton.Click();
  160. Thread.Sleep(1000);
  161. var hittable = _session.FindElementsByXPath("/XCUIElementTypeApplication/XCUIElementTypeWindow")
  162. .Select(x => x.GetAttribute("hittable")).ToList();
  163. Assert.Equal(new[] { "true", "false" }, hittable);
  164. _session.FindElementByAccessibilityId("RestoreAll").Click();
  165. Thread.Sleep(1000);
  166. hittable = _session.FindElementsByXPath("/XCUIElementTypeApplication/XCUIElementTypeWindow")
  167. .Select(x => x.GetAttribute("hittable")).ToList();
  168. Assert.Equal(new[] { "true", "true" }, hittable);
  169. }
  170. }
  171. [PlatformFact(TestPlatforms.MacOS)]
  172. public void Hidden_Child_Window_Is_Not_Reshown_When_Parent_Clicked()
  173. {
  174. var mainWindow = _session.FindElementByAccessibilityId("MainWindow");
  175. // We don't use dispose to close the window here, because it seems that hiding and re-showing a window
  176. // causes Appium to think it's a different window.
  177. OpenWindow(null, ShowWindowMode.Owned, WindowStartupLocation.Manual);
  178. var secondaryWindow = GetWindow("SecondaryWindow");
  179. var hideButton = secondaryWindow.FindElementByAccessibilityId("HideButton");
  180. hideButton.Click();
  181. var windows = _session.FindElementsByXPath("XCUIElementTypeWindow");
  182. Assert.Single(windows);
  183. mainWindow.Click();
  184. windows = _session.FindElementsByXPath("XCUIElementTypeWindow");
  185. Assert.Single(windows);
  186. _session.FindElementByAccessibilityId("RestoreAll").Click();
  187. // Close the window manually.
  188. secondaryWindow = GetWindow("SecondaryWindow");
  189. secondaryWindow.GetChromeButtons().close.Click();
  190. }
  191. private IDisposable OpenWindow(PixelSize? size, ShowWindowMode mode, WindowStartupLocation location)
  192. {
  193. var sizeTextBox = _session.FindElementByAccessibilityId("ShowWindowSize");
  194. var modeComboBox = _session.FindElementByAccessibilityId("ShowWindowMode");
  195. var locationComboBox = _session.FindElementByAccessibilityId("ShowWindowLocation");
  196. var showButton = _session.FindElementByAccessibilityId("ShowWindow");
  197. if (size.HasValue)
  198. sizeTextBox.SendKeys($"{size.Value.Width}, {size.Value.Height}");
  199. modeComboBox.Click();
  200. _session.FindElementByName(mode.ToString()).SendClick();
  201. locationComboBox.Click();
  202. _session.FindElementByName(location.ToString()).SendClick();
  203. return showButton.OpenWindowWithClick();
  204. }
  205. private AppiumWebElement GetWindow(string identifier)
  206. {
  207. // The Avalonia a11y tree currently exposes two nested Window elements, this is a bug and should be fixed
  208. // but in the meantime use the `parent::' selector to return the parent "real" window.
  209. return _session.FindElementByXPath(
  210. $"XCUIElementTypeWindow//*[@identifier='{identifier}']/parent::XCUIElementTypeWindow");
  211. }
  212. private int GetWindowOrder(string identifier)
  213. {
  214. var window = GetWindow(identifier);
  215. var order = window.FindElementByXPath("//*[@identifier='Order']");
  216. return int.Parse(order.Text);
  217. }
  218. public enum ShowWindowMode
  219. {
  220. NonOwned,
  221. Owned,
  222. Modal
  223. }
  224. }
  225. }