Browse Source

Merge pull request #7953 from AvaloniaUI/fixes/7906-menuitem-focus

Some menu fixes and integration tests.
pull/7317/merge
Steven Kirk 4 years ago
committed by GitHub
parent
commit
0a2b0cae23
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 8
      samples/IntegrationTestApp/MainWindow.axaml
  2. 2
      samples/IntegrationTestApp/MainWindow.axaml.cs
  3. 4
      src/Avalonia.Controls/MenuItem.cs
  4. 14
      src/Avalonia.Controls/Platform/DefaultMenuInteractionHandler.cs
  5. 13
      tests/Avalonia.Controls.UnitTests/Platform/DefaultMenuInteractionHandlerTests.cs
  6. 19
      tests/Avalonia.IntegrationTests.Appium/ElementExtensions.cs
  7. 104
      tests/Avalonia.IntegrationTests.Appium/MenuTests.cs

8
samples/IntegrationTestApp/MainWindow.axaml

@ -82,12 +82,16 @@
<Menu DockPanel.Dock="Top">
<MenuItem Name="RootMenuItem" Header="_Root">
<MenuItem Name="Child1MenuItem" Header="_Child 1" InputGesture="Ctrl+O" Click="MenuClicked"/>
<MenuItem Name="Child2MenuItem" Header="_Child 1">
<MenuItem Name="Child2MenuItem" Header="C_hild 2">
<MenuItem Name="GrandchildMenuItem" Header="_Grandchild" Click="MenuClicked"/>
</MenuItem>
</MenuItem>
</Menu>
<TextBlock Name="ClickedMenuItem">None</TextBlock>
<StackPanel>
<TextBlock Name="ClickedMenuItem">None</TextBlock>
<Button Name="MenuClickedMenuItemReset">Reset</Button>
<TextBox Name="MenuFocusTest"/>
</StackPanel>
</DockPanel>
</TabItem>
</TabControl>

2
samples/IntegrationTestApp/MainWindow.axaml.cs

@ -62,6 +62,8 @@ namespace IntegrationTestApp
this.FindControl<ComboBox>("BasicComboBox").SelectedIndex = 0;
if (source?.Name == "ListBoxSelectionClear")
this.FindControl<ListBox>("BasicListBox").SelectedIndex = -1;
if (source?.Name == "MenuClickedMenuItemReset")
this.FindControl<TextBlock>("ClickedMenuItem").Text = "None";
}
}
}

4
src/Avalonia.Controls/MenuItem.cs

@ -644,7 +644,9 @@ namespace Avalonia.Controls
/// <param name="e">The property change event.</param>
private void IsSelectedChanged(AvaloniaPropertyChangedEventArgs e)
{
if ((bool)e.NewValue!)
var parentMenu = Parent as Menu;
if ((bool)e.NewValue! && (parentMenu is null || parentMenu.IsOpen))
{
Focus();
}

14
src/Avalonia.Controls/Platform/DefaultMenuInteractionHandler.cs

@ -149,13 +149,18 @@ namespace Avalonia.Controls.Platform
case Key.Up:
case Key.Down:
{
if (item?.IsTopLevel == true)
if (item?.IsTopLevel == true && item.HasSubMenu)
{
if (item.HasSubMenu && !item.IsSubMenuOpen)
if (!item.IsSubMenuOpen)
{
Open(item, true);
e.Handled = true;
}
else
{
item.MoveSelection(NavigationDirection.First, true);
}
e.Handled = true;
}
else
{
@ -247,7 +252,8 @@ namespace Avalonia.Controls.Platform
// new menu.
if (item.IsSubMenuOpen &&
item.Parent is IMenu &&
item.Parent.SelectedItem is object)
item.Parent.SelectedItem is object &&
item.Parent.SelectedItem != item)
{
item.Close();
Open(item.Parent.SelectedItem, true);

13
tests/Avalonia.Controls.UnitTests/Platform/DefaultMenuInteractionHandlerTests.cs

@ -53,6 +53,19 @@ namespace Avalonia.Controls.UnitTests.Platform
Assert.True(e.Handled);
}
[Fact]
public void Down_Selects_First_Item_Of_Already_Opened_Submenu()
{
var target = new DefaultMenuInteractionHandler(false);
var item = Mock.Of<IMenuItem>(x => x.IsTopLevel == true && x.HasSubMenu == true && x.IsSubMenuOpen);
var e = new KeyEventArgs { Key = Key.Down, Source = item };
target.KeyDown(item, e);
Mock.Get(item).Verify(x => x.MoveSelection(NavigationDirection.First, true));
Assert.True(e.Handled);
}
[Fact]
public void Right_Selects_Next_MenuItem()
{

19
tests/Avalonia.IntegrationTests.Appium/ElementExtensions.cs

@ -29,6 +29,20 @@ namespace Avalonia.IntegrationTests.Appium
_ => throw new ArgumentOutOfRangeException($"Unexpected IsChecked value.")
};
public static bool GetIsFocused(this AppiumWebElement element)
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
var active = element.WrappedDriver.SwitchTo().ActiveElement() as AppiumWebElement;
return element.Id == active?.Id;
}
else
{
// https://stackoverflow.com/questions/71807788/check-if-element-is-focused-in-appium
throw new NotSupportedException("Couldn't work out how to check if an element is focused on mac.");
}
}
public static void SendClick(this AppiumWebElement element)
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
@ -44,6 +58,11 @@ namespace Avalonia.IntegrationTests.Appium
}
}
public static void MovePointerOver(this AppiumWebElement element)
{
new Actions(element.WrappedDriver).MoveToElement(element).Perform();
}
public static string GetAttribute(AppiumWebElement element, string windows, string macOS)
{
return element.GetAttribute(RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? windows : macOS);

104
tests/Avalonia.IntegrationTests.Appium/MenuTests.cs

@ -1,4 +1,7 @@
using OpenQA.Selenium.Appium;
using System.Threading;
using OpenQA.Selenium;
using OpenQA.Selenium.Appium;
using OpenQA.Selenium.Interactions;
using Xunit;
namespace Avalonia.IntegrationTests.Appium
@ -15,6 +18,12 @@ namespace Avalonia.IntegrationTests.Appium
var tabs = _session.FindElementByAccessibilityId("MainTabs");
var tab = tabs.FindElementByName("Menu");
tab.Click();
var reset = _session.FindElementByAccessibilityId("MenuClickedMenuItemReset");
reset.Click();
var clickedMenuItem = _session.FindElementByAccessibilityId("ClickedMenuItem");
Assert.Equal("None", clickedMenuItem.Text);
}
[Fact]
@ -48,16 +57,107 @@ namespace Avalonia.IntegrationTests.Appium
Assert.Equal("_Grandchild", clickedMenuItem.Text);
}
[PlatformFact(SkipOnOSX = true)]
public void Select_Child_With_Alt_Arrow_Keys()
{
new Actions(_session)
.KeyDown(Keys.Alt).KeyUp(Keys.Alt)
.SendKeys(Keys.Down + Keys.Enter)
.Perform();
var clickedMenuItem = _session.FindElementByAccessibilityId("ClickedMenuItem");
Assert.Equal("_Child 1", clickedMenuItem.Text);
}
[PlatformFact(SkipOnOSX = true)]
public void Select_Grandchild_With_Alt_Arrow_Keys()
{
new Actions(_session)
.KeyDown(Keys.Alt).KeyUp(Keys.Alt)
.SendKeys(Keys.Down + Keys.Down + Keys.Right + Keys.Enter)
.Perform();
var clickedMenuItem = _session.FindElementByAccessibilityId("ClickedMenuItem");
Assert.Equal("_Grandchild", clickedMenuItem.Text);
}
[PlatformFact(SkipOnOSX = true)]
public void Select_Child_With_Alt_Access_Keys()
{
new Actions(_session)
.KeyDown(Keys.Alt).KeyUp(Keys.Alt)
.SendKeys("rc")
.Perform();
var clickedMenuItem = _session.FindElementByAccessibilityId("ClickedMenuItem");
Assert.Equal("_Child 1", clickedMenuItem.Text);
}
[PlatformFact(SkipOnOSX = true)]
public void Select_Grandchild_With_Alt_Access_Keys()
{
new Actions(_session)
.KeyDown(Keys.Alt).KeyUp(Keys.Alt)
.SendKeys("rhg")
.Perform();
var clickedMenuItem = _session.FindElementByAccessibilityId("ClickedMenuItem");
Assert.Equal("_Grandchild", clickedMenuItem.Text);
}
[PlatformFact(SkipOnOSX = true)]
public void Select_Child_With_Click_Arrow_Keys()
{
var rootMenuItem = _session.FindElementByAccessibilityId("RootMenuItem");
rootMenuItem.SendClick();
new Actions(_session)
.SendKeys(Keys.Down + Keys.Enter)
.Perform();
var clickedMenuItem = _session.FindElementByAccessibilityId("ClickedMenuItem");
Assert.Equal("_Child 1", clickedMenuItem.Text);
}
[PlatformFact(SkipOnOSX = true)]
public void Select_Grandchild_With_Click_Arrow_Keys()
{
var rootMenuItem = _session.FindElementByAccessibilityId("RootMenuItem");
rootMenuItem.SendClick();
new Actions(_session)
.SendKeys(Keys.Down + Keys.Down + Keys.Right + Keys.Enter)
.Perform();
var clickedMenuItem = _session.FindElementByAccessibilityId("ClickedMenuItem");
Assert.Equal("_Grandchild", clickedMenuItem.Text);
}
[PlatformFact(SkipOnOSX = true)]
public void Child_AcceleratorKey()
{
var rootMenuItem = _session.FindElementByAccessibilityId("RootMenuItem");
rootMenuItem.SendClick();
var childMenuItem = _session.FindElementByAccessibilityId("Child1MenuItem");
Assert.Equal("Ctrl+O", childMenuItem.GetAttribute("AcceleratorKey"));
}
[PlatformFact(SkipOnOSX = true)]
public void PointerOver_Does_Not_Steal_Focus()
{
// Issue #7906
var textBox = _session.FindElementByAccessibilityId("MenuFocusTest");
textBox.Click();
Assert.True(textBox.GetIsFocused());
var rootMenuItem = _session.FindElementByAccessibilityId("RootMenuItem");
rootMenuItem.MovePointerOver();
Assert.True(textBox.GetIsFocused());
}
}
}

Loading…
Cancel
Save