Browse Source

Merge branch 'master' into fixes/10420-overlay-popups-event-routing

pull/10448/head
Steven Kirk 4 years ago
committed by GitHub
parent
commit
c0e1786b92
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 10
      samples/IntegrationTestApp/MainWindow.axaml
  2. 63
      src/Avalonia.Controls/Automation/Peers/RadioButtonAutomationPeer.cs
  3. 16
      src/Avalonia.Controls/Automation/SelectionItemPatternIdentifiers.cs
  4. 7
      src/Avalonia.Controls/RadioButton.cs
  5. 2
      src/Windows/Avalonia.Win32/Automation/AutomationNode.cs
  6. 48
      tests/Avalonia.IntegrationTests.Appium/RadioButtonTests.cs

10
samples/IntegrationTestApp/MainWindow.axaml

@ -57,6 +57,16 @@
</StackPanel>
</TabItem>
<TabItem Header="RadioButton">
<StackPanel Orientation="Vertical">
<RadioButton Name="BasicRadioButton">Sample RadioButton</RadioButton>
<StackPanel Orientation="Vertical">
<RadioButton Name="ThreeStatesRadioButton1" IsChecked="True" IsThreeState="True">Three States: Option 1</RadioButton>
<RadioButton Name="ThreeStatesRadioButton2" IsChecked="False" IsThreeState="True">Three States: Option 2</RadioButton>
</StackPanel>
</StackPanel>
</TabItem>
<TabItem Header="CheckBox">
<StackPanel>
<CheckBox Name="UncheckedCheckBox">Unchecked</CheckBox>

63
src/Avalonia.Controls/Automation/Peers/RadioButtonAutomationPeer.cs

@ -0,0 +1,63 @@
using System;
using Avalonia.Automation;
using Avalonia.Automation.Peers;
using Avalonia.Automation.Provider;
namespace Avalonia.Controls.Automation.Peers
{
public class RadioButtonAutomationPeer : ToggleButtonAutomationPeer, ISelectionItemProvider
{
public RadioButtonAutomationPeer(RadioButton owner) : base(owner)
{
owner.PropertyChanged += (a, e) =>
{
if (e.Property == RadioButton.IsCheckedProperty)
{
RaiseToggleStatePropertyChangedEvent((bool?)e.OldValue, (bool?)e.NewValue);
}
};
}
override protected string GetClassNameCore()
{
return "RadioButton";
}
override protected AutomationControlType GetAutomationControlTypeCore()
{
return AutomationControlType.RadioButton;
}
public bool IsSelected => ((RadioButton)Owner).IsChecked == true;
public ISelectionProvider? SelectionContainer => null;
public void AddToSelection()
{
if (((RadioButton)Owner).IsChecked != true)
throw new InvalidOperationException("Operation cannot be performed");
}
public void RemoveFromSelection()
{
if (((RadioButton)Owner).IsChecked == true)
throw new InvalidOperationException("Operation cannot be performed");
}
public void Select()
{
if (!IsEnabled())
throw new InvalidOperationException("Element is disabled thus it cannot be selected");
((RadioButton)Owner).IsChecked = true;
}
internal virtual void RaiseToggleStatePropertyChangedEvent(bool? oldValue, bool? newValue)
{
RaisePropertyChangedEvent(
SelectionItemPatternIdentifiers.IsSelectedProperty,
oldValue == true,
newValue == true);
}
}
}

16
src/Avalonia.Controls/Automation/SelectionItemPatternIdentifiers.cs

@ -0,0 +1,16 @@
using Avalonia.Automation.Provider;
namespace Avalonia.Automation
{
/// <summary>
/// Contains values used as identifiers by <see cref="ISelectionItemProvider"/>.
/// </summary>
public static class SelectionItemPatternIdentifiers
{
/// <summary>Indicates the element is currently selected.</summary>
public static AutomationProperty IsSelectedProperty { get; } = new AutomationProperty();
/// <summary>Indicates the element is currently selected.</summary>
public static AutomationProperty SelectionContainerProperty { get; } = new AutomationProperty();
}
}

7
src/Avalonia.Controls/RadioButton.cs

@ -2,6 +2,8 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using Avalonia.Automation.Peers;
using Avalonia.Controls.Automation.Peers;
using Avalonia.Controls.Primitives;
using Avalonia.Reactive;
using Avalonia.Rendering;
@ -147,6 +149,11 @@ namespace Avalonia.Controls
}
}
protected override AutomationPeer OnCreateAutomationPeer()
{
return new RadioButtonAutomationPeer(this);
}
private void SetGroupName(string? newGroupName)
{
var oldGroupName = GroupName;

2
src/Windows/Avalonia.Win32/Automation/AutomationNode.cs

@ -41,6 +41,8 @@ namespace Avalonia.Win32.Automation
{ SelectionPatternIdentifiers.CanSelectMultipleProperty, UiaPropertyId.SelectionCanSelectMultiple },
{ SelectionPatternIdentifiers.IsSelectionRequiredProperty, UiaPropertyId.SelectionIsSelectionRequired },
{ SelectionPatternIdentifiers.SelectionProperty, UiaPropertyId.SelectionSelection },
{ SelectionItemPatternIdentifiers.IsSelectedProperty, UiaPropertyId.SelectionItemIsSelected },
{ SelectionItemPatternIdentifiers.SelectionContainerProperty, UiaPropertyId.SelectionItemSelectionContainer }
};
private static ConditionalWeakTable<AutomationPeer, AutomationNode> s_nodes = new();

48
tests/Avalonia.IntegrationTests.Appium/RadioButtonTests.cs

@ -0,0 +1,48 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using OpenQA.Selenium.Appium;
using Xunit;
namespace Avalonia.IntegrationTests.Appium
{
[Collection("Default")]
public class RadioButtonTests
{
private readonly AppiumDriver<AppiumWebElement> _session;
public RadioButtonTests(TestAppFixture fixture)
{
_session = fixture.Session;
var tabs = _session.FindElementByAccessibilityId("MainTabs");
tabs.FindElementByName("RadioButton").Click();
}
[Fact]
public void RadioButton_IsChecked_True_When_Clicked()
{
var button = _session.FindElementByAccessibilityId("BasicRadioButton");
Assert.False(button.GetIsChecked());
button.Click();
Assert.True(button.GetIsChecked());
}
[Fact]
public void ThreeState_RadioButton_IsChecked_False_When_Other_ThreeState_RadioButton_Checked()
{
var button1 = _session.FindElementByAccessibilityId("ThreeStatesRadioButton1");
var button2 = _session.FindElementByAccessibilityId("ThreeStatesRadioButton2");
Assert.True(button1.GetIsChecked());
Assert.False(button2.GetIsChecked());
button2.Click();
Assert.False(button1.GetIsChecked());
Assert.True(button2.GetIsChecked());
}
}
}
Loading…
Cancel
Save