Browse Source
* Add accessibility ID to the TrayPopupRoot on Windows * [Windows] Add left click and menu item click e2e tests for TrayIcon * [Windows] Add TrayIcon visibility toggle tests * Implement macOS tray icon tests * Make it easier to read tray icon logs * Try to handle win10 accessibility names * Try to upload PageSource * Set condition: always * Hopefully, it works on CI * Try to upload PageSource #2 * Fix win10, hopefully for the last timepull/16265/head
committed by
GitHub
8 changed files with 215 additions and 20 deletions
@ -0,0 +1,152 @@ |
|||
using System; |
|||
using System.IO; |
|||
using System.Linq; |
|||
using System.Threading; |
|||
using OpenQA.Selenium; |
|||
using OpenQA.Selenium.Appium; |
|||
using OpenQA.Selenium.Interactions; |
|||
using Xunit; |
|||
|
|||
namespace Avalonia.IntegrationTests.Appium; |
|||
|
|||
[Collection("Default")] |
|||
public class TrayIconTests : IDisposable |
|||
{ |
|||
private readonly AppiumDriver _session; |
|||
private readonly AppiumDriver? _rootSession; |
|||
private const string TrayIconName = "IntegrationTestApp TrayIcon"; |
|||
|
|||
public TrayIconTests(DefaultAppFixture fixture) |
|||
{ |
|||
_session = fixture.Session; |
|||
|
|||
// "Root" is a special name for windows the desktop session, that has access to task bar.
|
|||
if (OperatingSystem.IsWindows()) |
|||
{ |
|||
_rootSession = fixture.CreateNestedSession("Root"); |
|||
} |
|||
|
|||
var tabs = _session.FindElementByAccessibilityId("MainTabs"); |
|||
var tab = tabs.FindElementByName("Desktop"); |
|||
tab.Click(); |
|||
} |
|||
|
|||
// Left click is only supported on Windows.
|
|||
[PlatformFact(TestPlatforms.Windows)] |
|||
public void Should_Handle_Left_Click() |
|||
{ |
|||
var avaloinaTrayIconButton = GetTrayIconButton(_rootSession ?? _session, TrayIconName); |
|||
Assert.NotNull(avaloinaTrayIconButton); |
|||
|
|||
avaloinaTrayIconButton.SendClick(); |
|||
|
|||
Thread.Sleep(2000); |
|||
|
|||
var checkBox = _session.FindElementByAccessibilityId("TrayIconClicked"); |
|||
Assert.True(checkBox.GetIsChecked()); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_Handle_Context_Menu_Item_Click() |
|||
{ |
|||
var avaloinaTrayIconButton = GetTrayIconButton(_rootSession ?? _session, TrayIconName); |
|||
Assert.NotNull(avaloinaTrayIconButton); |
|||
|
|||
var contextMenu = ShowAndGetTrayMenu(avaloinaTrayIconButton, TrayIconName); |
|||
Assert.NotNull(contextMenu); |
|||
|
|||
var menuItem = contextMenu.FindElementByName("Raise Menu Clicked"); |
|||
menuItem.SendClick(); |
|||
|
|||
Thread.Sleep(2000); |
|||
|
|||
var checkBox = _session.FindElementByAccessibilityId("TrayIconMenuClicked"); |
|||
Assert.True(checkBox.GetIsChecked()); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Can_Toggle_TrayIcon_Visibility() |
|||
{ |
|||
var avaloinaTrayIconButton = GetTrayIconButton(_rootSession ?? _session, TrayIconName); |
|||
Assert.NotNull(avaloinaTrayIconButton); |
|||
|
|||
var toggleButton = _session.FindElementByAccessibilityId("ToggleTrayIconVisible"); |
|||
toggleButton.SendClick(); |
|||
|
|||
avaloinaTrayIconButton = GetTrayIconButton(_rootSession ?? _session, TrayIconName); |
|||
Assert.Null(avaloinaTrayIconButton); |
|||
|
|||
toggleButton.SendClick(); |
|||
|
|||
avaloinaTrayIconButton = GetTrayIconButton(_rootSession ?? _session, TrayIconName); |
|||
Assert.NotNull(avaloinaTrayIconButton); |
|||
} |
|||
|
|||
private static AppiumWebElement? GetTrayIconButton(AppiumDriver session, string trayIconName) |
|||
{ |
|||
if (OperatingSystem.IsWindows()) |
|||
{ |
|||
var taskBar = session.FindElementsByClassName("Shell_TrayWnd") |
|||
.FirstOrDefault() ?? throw new InvalidOperationException("Couldn't find Taskbar on current system."); |
|||
|
|||
if (TryToGetIcon(taskBar, trayIconName) is { } trayIcon) |
|||
{ |
|||
return trayIcon; |
|||
} |
|||
else |
|||
{ |
|||
// Add a sleep here, as previous test might still run popup closing animation.
|
|||
Thread.Sleep(1000); |
|||
|
|||
// win11: SystemTrayIcon
|
|||
// win10: Notification Chevron
|
|||
var trayIconsButton = taskBar.FindElementsByAccessibilityId("SystemTrayIcon").FirstOrDefault() |
|||
?? taskBar.FindElementsByName("Notification Chevron").FirstOrDefault() |
|||
?? throw new InvalidOperationException("SystemTrayIcon cannot be found."); |
|||
trayIconsButton.Click(); |
|||
|
|||
// win11: TopLevelWindowForOverflowXamlIsland
|
|||
// win10: NotifyIconOverflowWindow
|
|||
var trayIconsFlyout = session.FindElementsByClassName("TopLevelWindowForOverflowXamlIsland").FirstOrDefault() |
|||
?? session.FindElementsByClassName("NotifyIconOverflowWindow").FirstOrDefault() |
|||
?? throw new InvalidOperationException("System tray overflow window cannot be found."); |
|||
return TryToGetIcon(trayIconsFlyout, trayIconName); |
|||
} |
|||
|
|||
static AppiumWebElement? TryToGetIcon(AppiumWebElement parent, string trayIconName) => |
|||
parent.FindElementsByName(trayIconName).LastOrDefault() |
|||
// Some icons (including Avalonia) for some reason include leading whitespace in their name.
|
|||
// Couldn't find any info on that, which is weird.
|
|||
?? parent.FindElementsByName(" " + trayIconName).LastOrDefault(); |
|||
} |
|||
if (OperatingSystem.IsMacOS()) |
|||
{ |
|||
return session.FindElementsByXPath("//XCUIElementTypeStatusItem").FirstOrDefault(); |
|||
} |
|||
|
|||
throw new PlatformNotSupportedException(); |
|||
} |
|||
|
|||
private static AppiumWebElement ShowAndGetTrayMenu(AppiumWebElement trayIcon, string trayIconName) |
|||
{ |
|||
if (OperatingSystem.IsWindows()) |
|||
{ |
|||
var session = (AppiumDriver)trayIcon.WrappedDriver; |
|||
new Actions(trayIcon.WrappedDriver).ContextClick(trayIcon).Perform(); |
|||
|
|||
Thread.Sleep(1000); |
|||
|
|||
return session.FindElementByXPath($"//Window[@AutomationId='AvaloniaTrayPopupRoot_{trayIconName}']"); |
|||
} |
|||
else |
|||
{ |
|||
trayIcon.Click(); |
|||
return trayIcon.FindElementByXPath("//XCUIElementTypeStatusItem/XCUIElementTypeMenu"); |
|||
} |
|||
} |
|||
|
|||
public void Dispose() |
|||
{ |
|||
_rootSession?.Dispose(); |
|||
} |
|||
} |
|||
Loading…
Reference in new issue