24 changed files with 1459 additions and 0 deletions
@ -0,0 +1,42 @@ |
|||
using Avalonia; |
|||
using Avalonia.Automation; |
|||
using Avalonia.Automation.Provider; |
|||
using Avalonia.Controls.Primitives; |
|||
using Avalonia.Media; |
|||
|
|||
namespace Avalonia.Automation.Peers; |
|||
|
|||
public class ColorSpectrumAutomationPeer : ControlAutomationPeer, IValueProvider |
|||
{ |
|||
public ColorSpectrumAutomationPeer(ColorSpectrum owner) |
|||
: base(owner) |
|||
{ |
|||
owner.PropertyChanged += OwnerPropertyChanged; |
|||
} |
|||
|
|||
public bool IsReadOnly => false; |
|||
public new ColorSpectrum Owner => (ColorSpectrum)base.Owner; |
|||
public string? Value => Owner.Color.ToString(); |
|||
|
|||
public void SetValue(string? value) |
|||
{ |
|||
if (!Color.TryParse(value, out var color)) |
|||
{ |
|||
throw new System.FormatException($"Invalid color string: '{value}'."); |
|||
} |
|||
|
|||
Owner.Color = color; |
|||
} |
|||
|
|||
protected override AutomationControlType GetAutomationControlTypeCore() => AutomationControlType.Custom; |
|||
|
|||
protected override string GetClassNameCore() => nameof(ColorSpectrum); |
|||
|
|||
private void OwnerPropertyChanged(object? sender, AvaloniaPropertyChangedEventArgs e) |
|||
{ |
|||
if (e.Property == ColorSpectrum.ColorProperty) |
|||
{ |
|||
RaisePropertyChangedEvent(ValuePatternIdentifiers.ValueProperty, e.OldValue?.ToString(), e.NewValue?.ToString()); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,68 @@ |
|||
using System; |
|||
using Avalonia.Automation; |
|||
using Avalonia.Automation.Provider; |
|||
using Avalonia.Controls; |
|||
|
|||
namespace Avalonia.Automation.Peers |
|||
{ |
|||
public class AutoCompleteBoxAutomationPeer : ControlAutomationPeer, IExpandCollapseProvider, IValueProvider |
|||
{ |
|||
public AutoCompleteBoxAutomationPeer(AutoCompleteBox owner) |
|||
: base(owner) |
|||
{ |
|||
owner.PropertyChanged += OwnerPropertyChanged; |
|||
} |
|||
|
|||
public new AutoCompleteBox Owner => (AutoCompleteBox)base.Owner; |
|||
|
|||
public ExpandCollapseState ExpandCollapseState => ToState(Owner.IsDropDownOpen); |
|||
public bool ShowsMenu => true; |
|||
public void Collapse() => Owner.IsDropDownOpen = false; |
|||
public void Expand() => Owner.IsDropDownOpen = true; |
|||
public bool IsReadOnly => false; |
|||
|
|||
public string? Value |
|||
{ |
|||
get => Owner.Text; |
|||
set |
|||
{ |
|||
if (value == Owner.Text) |
|||
return; |
|||
|
|||
Owner.Text = value; |
|||
} |
|||
} |
|||
|
|||
void IValueProvider.SetValue(string? value) => Owner.Text = value; |
|||
|
|||
protected override AutomationControlType GetAutomationControlTypeCore() |
|||
{ |
|||
return AutomationControlType.Group; |
|||
} |
|||
|
|||
protected override string GetClassNameCore() => nameof(AutoCompleteBox); |
|||
|
|||
private void OwnerPropertyChanged(object? sender, AvaloniaPropertyChangedEventArgs e) |
|||
{ |
|||
if (e.Property == AutoCompleteBox.IsDropDownOpenProperty) |
|||
{ |
|||
RaisePropertyChangedEvent( |
|||
ExpandCollapsePatternIdentifiers.ExpandCollapseStateProperty, |
|||
ToState(e.GetOldValue<bool>()), |
|||
ToState(e.GetNewValue<bool>())); |
|||
} |
|||
else if (e.Property == AutoCompleteBox.TextProperty) |
|||
{ |
|||
RaisePropertyChangedEvent( |
|||
ValuePatternIdentifiers.ValueProperty, |
|||
e.OldValue, |
|||
e.NewValue); |
|||
} |
|||
} |
|||
|
|||
private static ExpandCollapseState ToState(bool value) |
|||
{ |
|||
return value ? ExpandCollapseState.Expanded : ExpandCollapseState.Collapsed; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,57 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using Avalonia.Automation; |
|||
using Avalonia.Automation.Provider; |
|||
using Avalonia.Controls; |
|||
using Avalonia.Controls.Primitives; |
|||
|
|||
namespace Avalonia.Automation.Peers |
|||
{ |
|||
public class CalendarAutomationPeer : ControlAutomationPeer, ISelectionProvider, IValueProvider |
|||
{ |
|||
public CalendarAutomationPeer(Calendar owner) |
|||
: base(owner) |
|||
{ |
|||
owner.SelectedDatesChanged += OwnerSelectedDatesChanged; |
|||
} |
|||
|
|||
public new Calendar Owner => (Calendar)base.Owner; |
|||
|
|||
public bool CanSelectMultiple => |
|||
Owner.SelectionMode == CalendarSelectionMode.SingleRange || |
|||
Owner.SelectionMode == CalendarSelectionMode.MultipleRange; |
|||
|
|||
public bool IsSelectionRequired => false; |
|||
|
|||
public IReadOnlyList<AutomationPeer> GetSelection() |
|||
{ |
|||
return Owner.SelectedDates.Select(date => Owner.FindDayButtonFromDay(date)) |
|||
.OfType<CalendarDayButton>().Select(GetOrCreate).ToList(); |
|||
} |
|||
|
|||
public bool IsReadOnly => true; |
|||
|
|||
public string? Value => string.Join( |
|||
System.Globalization.CultureInfo.CurrentCulture.TextInfo.ListSeparator, |
|||
Owner.SelectedDates.Select(x => x.ToString(System.Globalization.CultureInfo.CurrentCulture))); |
|||
|
|||
public void SetValue(string? value) |
|||
{ |
|||
throw new NotSupportedException(); |
|||
} |
|||
|
|||
protected override AutomationControlType GetAutomationControlTypeCore() |
|||
{ |
|||
return AutomationControlType.Calendar; |
|||
} |
|||
|
|||
protected override string GetClassNameCore() => nameof(Calendar); |
|||
|
|||
private void OwnerSelectedDatesChanged(object? sender, SelectionChangedEventArgs e) |
|||
{ |
|||
RaisePropertyChangedEvent(SelectionPatternIdentifiers.SelectionProperty, null, null); |
|||
RaisePropertyChangedEvent(ValuePatternIdentifiers.ValueProperty, null, null); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,72 @@ |
|||
using System; |
|||
using Avalonia.Automation; |
|||
using Avalonia.Automation.Provider; |
|||
using Avalonia.Controls; |
|||
|
|||
namespace Avalonia.Automation.Peers |
|||
{ |
|||
public class CalendarDatePickerAutomationPeer : ControlAutomationPeer, |
|||
IInvokeProvider, |
|||
IExpandCollapseProvider, |
|||
IValueProvider |
|||
{ |
|||
public CalendarDatePickerAutomationPeer(CalendarDatePicker owner) |
|||
: base(owner) |
|||
{ |
|||
Owner.PropertyChanged += OwnerPropertyChanged; |
|||
} |
|||
|
|||
public new CalendarDatePicker Owner => (CalendarDatePicker)base.Owner; |
|||
|
|||
public ExpandCollapseState ExpandCollapseState => ToState(Owner.IsDropDownOpen); |
|||
|
|||
public bool ShowsMenu => true; |
|||
|
|||
public bool IsReadOnly => false; |
|||
|
|||
public string? Value => Owner.Text; |
|||
|
|||
public void Invoke() |
|||
{ |
|||
EnsureEnabled(); |
|||
Owner.IsDropDownOpen = true; |
|||
} |
|||
|
|||
public void Expand() => Owner.IsDropDownOpen = true; |
|||
|
|||
public void Collapse() => Owner.IsDropDownOpen = false; |
|||
|
|||
public void SetValue(string? value) => Owner.Text = value; |
|||
|
|||
protected override AutomationControlType GetAutomationControlTypeCore() => AutomationControlType.Button; |
|||
|
|||
protected override string GetClassNameCore() => "CalendarDatePicker"; |
|||
|
|||
protected override bool IsContentElementCore() => true; |
|||
|
|||
protected override bool IsControlElementCore() => true; |
|||
|
|||
private void OwnerPropertyChanged(object? sender, AvaloniaPropertyChangedEventArgs e) |
|||
{ |
|||
if (e.Property == CalendarDatePicker.TextProperty) |
|||
{ |
|||
RaisePropertyChangedEvent( |
|||
ValuePatternIdentifiers.ValueProperty, |
|||
e.OldValue, |
|||
e.NewValue); |
|||
} |
|||
else if (e.Property == CalendarDatePicker.IsDropDownOpenProperty) |
|||
{ |
|||
RaisePropertyChangedEvent( |
|||
ExpandCollapsePatternIdentifiers.ExpandCollapseStateProperty, |
|||
ToState(e.GetOldValue<bool>()), |
|||
ToState(e.GetNewValue<bool>())); |
|||
} |
|||
} |
|||
|
|||
private static ExpandCollapseState ToState(bool isExpanded) |
|||
{ |
|||
return isExpanded ? ExpandCollapseState.Expanded : ExpandCollapseState.Collapsed; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,35 @@ |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using Avalonia.Controls; |
|||
using Avalonia.LogicalTree; |
|||
using Avalonia.VisualTree; |
|||
|
|||
namespace Avalonia.Automation.Peers |
|||
{ |
|||
public class NativeMenuBarAutomationPeer(NativeMenuBar owner) : ControlAutomationPeer(owner) |
|||
{ |
|||
protected override AutomationControlType GetAutomationControlTypeCore() |
|||
{ |
|||
return AutomationControlType.MenuBar; |
|||
} |
|||
|
|||
protected override IReadOnlyList<AutomationPeer>? GetChildrenCore() |
|||
{ |
|||
var menu = Owner.VisualChildren.OfType<MenuBase>().FirstOrDefault() ?? |
|||
Owner.GetVisualDescendants().OfType<MenuBase>().FirstOrDefault(); |
|||
|
|||
if (menu is null) |
|||
{ |
|||
return base.GetChildrenCore(); |
|||
} |
|||
|
|||
var children = menu.GetLogicalChildren() |
|||
.OfType<Control>() |
|||
.Where(x => x.IsVisible) |
|||
.Select(GetOrCreate) |
|||
.ToList(); |
|||
|
|||
return children.Count > 0 ? children : base.GetChildrenCore(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,73 @@ |
|||
using System; |
|||
using Avalonia.Automation; |
|||
using Avalonia.Automation.Provider; |
|||
using Avalonia.Controls; |
|||
|
|||
namespace Avalonia.Automation.Peers |
|||
{ |
|||
public class NumericUpDownAutomationPeer : ControlAutomationPeer, IRangeValueProvider |
|||
{ |
|||
public NumericUpDownAutomationPeer(NumericUpDown owner) |
|||
: base(owner) |
|||
{ |
|||
Owner.PropertyChanged += OwnerPropertyChanged; |
|||
} |
|||
|
|||
public new NumericUpDown Owner => (NumericUpDown)base.Owner; |
|||
|
|||
public bool IsReadOnly => Owner.IsReadOnly; |
|||
|
|||
public double Maximum => (double)Owner.Maximum; |
|||
|
|||
public double Minimum => (double)Owner.Minimum; |
|||
|
|||
public double Value => Owner.Value.HasValue |
|||
? (double)Owner.Value.Value |
|||
: (double)Math.Clamp(0m, Owner.Minimum, Owner.Maximum); |
|||
|
|||
public double SmallChange => (double)Owner.Increment; |
|||
|
|||
public double LargeChange => (double)Owner.Increment; |
|||
|
|||
public void SetValue(double value) |
|||
{ |
|||
Owner.Value = (decimal)value; |
|||
} |
|||
|
|||
protected override AutomationControlType GetAutomationControlTypeCore() => AutomationControlType.Spinner; |
|||
|
|||
protected override string GetClassNameCore() => "NumericUpDown"; |
|||
|
|||
private void OwnerPropertyChanged(object? sender, AvaloniaPropertyChangedEventArgs e) |
|||
{ |
|||
if (e.Property == NumericUpDown.MinimumProperty) |
|||
{ |
|||
RaisePropertyChangedEvent( |
|||
RangeValuePatternIdentifiers.MinimumProperty, |
|||
e.OldValue, |
|||
e.NewValue); |
|||
} |
|||
else if (e.Property == NumericUpDown.MaximumProperty) |
|||
{ |
|||
RaisePropertyChangedEvent( |
|||
RangeValuePatternIdentifiers.MaximumProperty, |
|||
e.OldValue, |
|||
e.NewValue); |
|||
} |
|||
else if (e.Property == NumericUpDown.ValueProperty) |
|||
{ |
|||
RaisePropertyChangedEvent( |
|||
RangeValuePatternIdentifiers.ValueProperty, |
|||
e.OldValue, |
|||
e.NewValue); |
|||
} |
|||
else if (e.Property == NumericUpDown.IsReadOnlyProperty) |
|||
{ |
|||
RaisePropertyChangedEvent( |
|||
RangeValuePatternIdentifiers.IsReadOnlyProperty, |
|||
e.OldValue, |
|||
e.NewValue); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,73 @@ |
|||
using Avalonia.Automation; |
|||
using Avalonia.Automation.Provider; |
|||
using Avalonia.Controls; |
|||
|
|||
namespace Avalonia.Automation.Peers |
|||
{ |
|||
public class SplitButtonAutomationPeer : ContentControlAutomationPeer, IInvokeProvider, IExpandCollapseProvider |
|||
{ |
|||
private ExpandCollapseState _expandCollapseState; |
|||
|
|||
public SplitButtonAutomationPeer(SplitButton owner) |
|||
: base(owner) |
|||
{ |
|||
_expandCollapseState = ToState(owner.IsFlyoutOpen); |
|||
owner.FlyoutStateChanged += OwnerFlyoutStateChanged; |
|||
} |
|||
|
|||
public new SplitButton Owner => (SplitButton)base.Owner; |
|||
|
|||
public ExpandCollapseState ExpandCollapseState => ToState(Owner.IsFlyoutOpen); |
|||
|
|||
public bool ShowsMenu => true; |
|||
|
|||
public void Collapse() |
|||
{ |
|||
Owner.CloseFlyoutForAutomation(); |
|||
} |
|||
|
|||
public void Expand() |
|||
{ |
|||
Owner.OpenFlyoutForAutomation(); |
|||
} |
|||
|
|||
void IInvokeProvider.Invoke() |
|||
{ |
|||
EnsureEnabled(); |
|||
Owner.InvokePrimary(); |
|||
} |
|||
|
|||
protected override AutomationControlType GetAutomationControlTypeCore() |
|||
{ |
|||
return AutomationControlType.SplitButton; |
|||
} |
|||
|
|||
protected override string GetClassNameCore() |
|||
{ |
|||
return "SplitButton"; |
|||
} |
|||
|
|||
protected override bool IsContentElementCore() => true; |
|||
protected override bool IsControlElementCore() => true; |
|||
|
|||
private void OwnerFlyoutStateChanged(object? sender, System.EventArgs e) |
|||
{ |
|||
var oldState = _expandCollapseState; |
|||
var newState = ToState(Owner.IsFlyoutOpen); |
|||
|
|||
if (oldState != newState) |
|||
{ |
|||
_expandCollapseState = newState; |
|||
RaisePropertyChangedEvent( |
|||
ExpandCollapsePatternIdentifiers.ExpandCollapseStateProperty, |
|||
oldState, |
|||
newState); |
|||
} |
|||
} |
|||
|
|||
private static ExpandCollapseState ToState(bool isOpen) |
|||
{ |
|||
return isOpen ? ExpandCollapseState.Expanded : ExpandCollapseState.Collapsed; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,50 @@ |
|||
using Avalonia.Automation.Provider; |
|||
using Avalonia.Controls; |
|||
|
|||
namespace Avalonia.Automation.Peers |
|||
{ |
|||
public class ToggleSplitButtonAutomationPeer : SplitButtonAutomationPeer, IToggleProvider |
|||
{ |
|||
public ToggleSplitButtonAutomationPeer(ToggleSplitButton owner) |
|||
: base(owner) |
|||
{ |
|||
owner.PropertyChanged += OwnerPropertyChanged; |
|||
} |
|||
|
|||
public new ToggleSplitButton Owner => (ToggleSplitButton)base.Owner; |
|||
|
|||
ToggleState IToggleProvider.ToggleState => ToState(Owner.IsChecked); |
|||
|
|||
void IToggleProvider.Toggle() |
|||
{ |
|||
EnsureEnabled(); |
|||
Owner.ToggleForAutomation(); |
|||
} |
|||
|
|||
protected override AutomationControlType GetAutomationControlTypeCore() |
|||
{ |
|||
return AutomationControlType.SplitButton; |
|||
} |
|||
|
|||
protected override string GetClassNameCore() |
|||
{ |
|||
return "ToggleSplitButton"; |
|||
} |
|||
|
|||
private void OwnerPropertyChanged(object? sender, AvaloniaPropertyChangedEventArgs e) |
|||
{ |
|||
if (e.Property == ToggleSplitButton.IsCheckedProperty) |
|||
{ |
|||
RaisePropertyChangedEvent( |
|||
TogglePatternIdentifiers.ToggleStateProperty, |
|||
ToState(e.GetOldValue<bool>()), |
|||
ToState(e.GetNewValue<bool>())); |
|||
} |
|||
} |
|||
|
|||
private static ToggleState ToState(bool value) |
|||
{ |
|||
return value ? ToggleState.On : ToggleState.Off; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,14 @@ |
|||
using Avalonia.Automation.Provider; |
|||
using Avalonia.Controls; |
|||
|
|||
namespace Avalonia.Automation.Peers |
|||
{ |
|||
public class ToolTipAutomationPeer(ToolTip owner) : ControlAutomationPeer(owner) |
|||
{ |
|||
public new ToolTip Owner => (ToolTip)base.Owner; |
|||
|
|||
protected override AutomationControlType GetAutomationControlTypeCore() => AutomationControlType.ToolTip; |
|||
|
|||
protected override string GetClassNameCore() => "ToolTip"; |
|||
} |
|||
} |
|||
@ -0,0 +1,91 @@ |
|||
using System; |
|||
using Avalonia.Automation; |
|||
using Avalonia.Automation.Peers; |
|||
using Avalonia.Automation.Provider; |
|||
using Avalonia.Controls.Primitives; |
|||
using Avalonia.Media; |
|||
using Avalonia.UnitTests; |
|||
using Xunit; |
|||
|
|||
namespace Avalonia.Controls.UnitTests.Automation; |
|||
|
|||
public class ColorSpectrumAutomationPeerTests |
|||
{ |
|||
public class AutomationPeerTests : ScopedTestBase |
|||
{ |
|||
[Fact] |
|||
public void Creates_ColorSpectrumAutomationPeer() |
|||
{ |
|||
var spectrum = new ColorSpectrum(); |
|||
var peer = ControlAutomationPeer.CreatePeerForElement(spectrum); |
|||
|
|||
Assert.IsType<ColorSpectrumAutomationPeer>(peer); |
|||
} |
|||
|
|||
[Fact] |
|||
public void ControlType_Is_Custom() |
|||
{ |
|||
var spectrum = new ColorSpectrum(); |
|||
var peer = (ColorSpectrumAutomationPeer)ControlAutomationPeer.CreatePeerForElement(spectrum); |
|||
|
|||
Assert.Equal(AutomationControlType.Custom, peer.GetAutomationControlType()); |
|||
} |
|||
|
|||
[Fact] |
|||
public void ClassName_Is_ColorSpectrum() |
|||
{ |
|||
var spectrum = new ColorSpectrum(); |
|||
var peer = (ColorSpectrumAutomationPeer)ControlAutomationPeer.CreatePeerForElement(spectrum); |
|||
|
|||
Assert.Equal("ColorSpectrum", peer.GetClassName()); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Implements_IValueProvider() |
|||
{ |
|||
var spectrum = new ColorSpectrum(); |
|||
var peer = (ColorSpectrumAutomationPeer)ControlAutomationPeer.CreatePeerForElement(spectrum); |
|||
|
|||
Assert.Equal(Colors.White.ToString(), peer.Value); |
|||
|
|||
var valueProvider = Assert.IsAssignableFrom<IValueProvider>(peer); |
|||
valueProvider.SetValue("#00FF00"); |
|||
|
|||
Assert.Equal(Colors.Lime.ToString(), peer.Value); |
|||
Assert.Equal(Colors.Lime, spectrum.Color); |
|||
} |
|||
|
|||
[Fact] |
|||
public void SetValue_Uses_Color_Parse_And_Throws_FormatException_On_Invalid_Input() |
|||
{ |
|||
var spectrum = new ColorSpectrum(); |
|||
var peer = (ColorSpectrumAutomationPeer)ControlAutomationPeer.CreatePeerForElement(spectrum); |
|||
var valueProvider = Assert.IsAssignableFrom<IValueProvider>(peer); |
|||
|
|||
Assert.Throws<FormatException>(() => valueProvider.SetValue("not-a-color")); |
|||
} |
|||
|
|||
[Fact] |
|||
public void ValueProperty_Raises_AutomationPropertyChangedEvent_On_Color_Change() |
|||
{ |
|||
var spectrum = new ColorSpectrum(); |
|||
var peer = (ColorSpectrumAutomationPeer)ControlAutomationPeer.CreatePeerForElement(spectrum); |
|||
AutomationPropertyChangedEventArgs? changed = null; |
|||
|
|||
peer.PropertyChanged += (_, e) => |
|||
{ |
|||
if (e.Property == ValuePatternIdentifiers.ValueProperty) |
|||
{ |
|||
changed = e; |
|||
} |
|||
}; |
|||
|
|||
spectrum.Color = Colors.Black; |
|||
|
|||
Assert.NotNull(changed); |
|||
Assert.Equal(ValuePatternIdentifiers.ValueProperty, changed!.Property); |
|||
Assert.Equal(Colors.White.ToString(), changed.OldValue); |
|||
Assert.Equal(Colors.Black.ToString(), changed.NewValue); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,292 @@ |
|||
using System; |
|||
using System.Globalization; |
|||
using System.Linq; |
|||
using Avalonia; |
|||
using Avalonia.Automation; |
|||
using Avalonia.Automation.Peers; |
|||
using Avalonia.Automation.Provider; |
|||
using Avalonia.Controls; |
|||
using Avalonia.Controls.Primitives; |
|||
using Avalonia.UnitTests; |
|||
using Xunit; |
|||
|
|||
namespace Avalonia.Controls.UnitTests.Automation; |
|||
|
|||
public class AutoCompleteBoxAutomationPeerTests : ScopedTestBase |
|||
{ |
|||
[Fact] |
|||
public void Creates_AutoCompleteBoxAutomationPeer() |
|||
{ |
|||
var target = new AutoCompleteBox(); |
|||
var peer = ControlAutomationPeer.CreatePeerForElement(target); |
|||
|
|||
Assert.IsType<AutoCompleteBoxAutomationPeer>(peer); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Implements_IExpandCollapse_And_IValue_Providers() |
|||
{ |
|||
var target = new AutoCompleteBox(); |
|||
var peer = ControlAutomationPeer.CreatePeerForElement(target); |
|||
|
|||
Assert.IsAssignableFrom<IExpandCollapseProvider>(peer); |
|||
Assert.IsAssignableFrom<IValueProvider>(peer); |
|||
Assert.False(peer is IInvokeProvider); |
|||
} |
|||
|
|||
[Fact] |
|||
public void ControlType_Is_Group_And_ClassName_Is_AutoCompleteBox() |
|||
{ |
|||
var target = new AutoCompleteBox(); |
|||
var peer = (AutoCompleteBoxAutomationPeer)ControlAutomationPeer.CreatePeerForElement(target); |
|||
|
|||
Assert.Equal(AutomationControlType.Group, peer.GetAutomationControlType()); |
|||
Assert.Equal(nameof(AutoCompleteBox), peer.GetClassName()); |
|||
} |
|||
|
|||
[Fact] |
|||
public void ExpandCollapse_Tracks_IsDropDownOpen() |
|||
{ |
|||
var target = new AutoCompleteBox |
|||
{ |
|||
ItemsSource = new[] { "alpha" }, |
|||
Text = "a" |
|||
}; |
|||
var peer = (IExpandCollapseProvider)ControlAutomationPeer.CreatePeerForElement(target); |
|||
Assert.True(peer.ShowsMenu); |
|||
|
|||
target.IsDropDownOpen = false; |
|||
Assert.False(target.IsDropDownOpen); |
|||
|
|||
peer.Expand(); |
|||
Assert.True(target.IsDropDownOpen); |
|||
Assert.Equal(ExpandCollapseState.Expanded, peer.ExpandCollapseState); |
|||
|
|||
peer.Collapse(); |
|||
Assert.False(target.IsDropDownOpen); |
|||
Assert.Equal(ExpandCollapseState.Collapsed, peer.ExpandCollapseState); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Value_Tracks_And_Sets_Text() |
|||
{ |
|||
var target = new AutoCompleteBox { Text = "one" }; |
|||
var peer = (IValueProvider)ControlAutomationPeer.CreatePeerForElement(target); |
|||
|
|||
Assert.Equal("one", peer.Value); |
|||
peer.SetValue("two"); |
|||
Assert.Equal("two", target.Text); |
|||
Assert.Equal("two", ((IValueProvider)peer).Value); |
|||
} |
|||
|
|||
[Fact] |
|||
public void ValueProvider_IsMutable() |
|||
{ |
|||
var target = new AutoCompleteBox(); |
|||
var peer = (IValueProvider)ControlAutomationPeer.CreatePeerForElement(target); |
|||
|
|||
Assert.False(peer.IsReadOnly); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Property_Change_Events_Raise_For_DropDown_And_Text() |
|||
{ |
|||
var target = new AutoCompleteBox(); |
|||
var peer = (AutoCompleteBoxAutomationPeer)ControlAutomationPeer.CreatePeerForElement(target); |
|||
|
|||
AutomationPropertyChangedEventArgs? expandCollapseChanged = null; |
|||
AutomationPropertyChangedEventArgs? valueChanged = null; |
|||
peer.PropertyChanged += (_, e) => |
|||
{ |
|||
if (e.Property == ExpandCollapsePatternIdentifiers.ExpandCollapseStateProperty) |
|||
{ |
|||
expandCollapseChanged = e; |
|||
} |
|||
else if (e.Property == ValuePatternIdentifiers.ValueProperty) |
|||
{ |
|||
valueChanged = e; |
|||
} |
|||
}; |
|||
|
|||
target.IsDropDownOpen = true; |
|||
Assert.NotNull(expandCollapseChanged); |
|||
Assert.Equal(ExpandCollapsePatternIdentifiers.ExpandCollapseStateProperty, expandCollapseChanged!.Property); |
|||
Assert.Equal(ExpandCollapseState.Collapsed, expandCollapseChanged.OldValue); |
|||
Assert.Equal(ExpandCollapseState.Expanded, expandCollapseChanged.NewValue); |
|||
|
|||
target.Text = "query"; |
|||
Assert.NotNull(valueChanged); |
|||
Assert.Equal(ValuePatternIdentifiers.ValueProperty, valueChanged!.Property); |
|||
Assert.Equal(string.Empty, valueChanged.OldValue); |
|||
Assert.Equal("query", valueChanged.NewValue); |
|||
} |
|||
} |
|||
|
|||
public class CalendarAutomationPeerTests : ScopedTestBase |
|||
{ |
|||
[Fact] |
|||
public void Creates_CalendarAutomationPeer() |
|||
{ |
|||
var target = new Calendar(); |
|||
var peer = ControlAutomationPeer.CreatePeerForElement(target); |
|||
|
|||
Assert.IsType<CalendarAutomationPeer>(peer); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Implements_ISelection_And_IValue_Providers() |
|||
{ |
|||
var target = new Calendar(); |
|||
var peer = ControlAutomationPeer.CreatePeerForElement(target); |
|||
|
|||
Assert.IsAssignableFrom<ISelectionProvider>(peer); |
|||
Assert.IsAssignableFrom<IValueProvider>(peer); |
|||
} |
|||
|
|||
[Fact] |
|||
public void ControlType_Is_Calendar_And_ClassName_Is_Calendar() |
|||
{ |
|||
var target = new Calendar(); |
|||
var peer = (CalendarAutomationPeer)ControlAutomationPeer.CreatePeerForElement(target); |
|||
|
|||
Assert.Equal(AutomationControlType.Calendar, peer.GetAutomationControlType()); |
|||
Assert.Equal(nameof(Calendar), peer.GetClassName()); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData(CalendarSelectionMode.SingleDate, false)] |
|||
[InlineData(CalendarSelectionMode.SingleRange, true)] |
|||
[InlineData(CalendarSelectionMode.MultipleRange, true)] |
|||
[InlineData(CalendarSelectionMode.None, false)] |
|||
public void CanSelectMultiple_Reflects_SelectionMode(CalendarSelectionMode selectionMode, bool canSelectMultiple) |
|||
{ |
|||
var target = new Calendar { SelectionMode = selectionMode }; |
|||
var peer = (ISelectionProvider)ControlAutomationPeer.CreatePeerForElement(target); |
|||
|
|||
Assert.Equal(canSelectMultiple, peer.CanSelectMultiple); |
|||
Assert.False(peer.IsSelectionRequired); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Selection_Events_Include_Selection_And_Value_Properties() |
|||
{ |
|||
var target = new Calendar { SelectionMode = CalendarSelectionMode.SingleDate }; |
|||
var peer = (CalendarAutomationPeer)ControlAutomationPeer.CreatePeerForElement(target); |
|||
|
|||
AutomationPropertyChangedEventArgs? selectionChanged = null; |
|||
AutomationPropertyChangedEventArgs? valueChanged = null; |
|||
peer.PropertyChanged += (_, e) => |
|||
{ |
|||
if (e.Property == SelectionPatternIdentifiers.SelectionProperty) |
|||
{ |
|||
selectionChanged = e; |
|||
} |
|||
else if (e.Property == ValuePatternIdentifiers.ValueProperty) |
|||
{ |
|||
valueChanged = e; |
|||
} |
|||
}; |
|||
|
|||
target.SelectedDate = new DateTime(2010, 1, 1); |
|||
|
|||
Assert.NotNull(selectionChanged); |
|||
Assert.NotNull(valueChanged); |
|||
Assert.Equal(SelectionPatternIdentifiers.SelectionProperty, selectionChanged!.Property); |
|||
Assert.Equal(ValuePatternIdentifiers.ValueProperty, valueChanged!.Property); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Value_Joins_Selected_Dates_With_CurrentCulture() |
|||
{ |
|||
var previousCulture = CultureInfo.CurrentCulture; |
|||
try |
|||
{ |
|||
CultureInfo.CurrentCulture = CultureInfo.GetCultureInfo("en-GB"); |
|||
|
|||
var selectedDates = new[] { new DateTime(2026, 5, 7), new DateTime(2026, 5, 8) }; |
|||
var target = new Calendar |
|||
{ |
|||
SelectionMode = CalendarSelectionMode.MultipleRange |
|||
}; |
|||
var peer = (CalendarAutomationPeer)ControlAutomationPeer.CreatePeerForElement(target); |
|||
|
|||
foreach (var date in selectedDates) |
|||
{ |
|||
target.SelectedDates.Add(date); |
|||
} |
|||
|
|||
Assert.Equal( |
|||
string.Join(CultureInfo.CurrentCulture.TextInfo.ListSeparator, selectedDates.Select(x => x.ToString(CultureInfo.CurrentCulture))), |
|||
peer.Value); |
|||
} |
|||
finally |
|||
{ |
|||
CultureInfo.CurrentCulture = previousCulture; |
|||
} |
|||
} |
|||
|
|||
[Fact] |
|||
public void SetValue_Throws_NotSupported() |
|||
{ |
|||
var peer = (IValueProvider)ControlAutomationPeer.CreatePeerForElement(new Calendar()); |
|||
|
|||
Assert.Throws<NotSupportedException>(() => peer.SetValue("2026-01-01")); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Value_Is_ReadOnly() |
|||
{ |
|||
var peer = (IValueProvider)ControlAutomationPeer.CreatePeerForElement(new Calendar()); |
|||
|
|||
Assert.True(peer.IsReadOnly); |
|||
} |
|||
|
|||
[Fact] |
|||
public void GetSelection_Returns_Empty_When_DayButton_Not_Realized() |
|||
{ |
|||
var target = new Calendar { SelectionMode = CalendarSelectionMode.SingleDate, SelectedDate = new DateTime(2026, 5, 7) }; |
|||
var peer = (CalendarAutomationPeer)ControlAutomationPeer.CreatePeerForElement(target); |
|||
|
|||
var selection = peer.GetSelection(); |
|||
|
|||
Assert.Empty(selection); |
|||
} |
|||
|
|||
[Fact] |
|||
public void GetSelection_Returns_Realized_DayButton_Peers() |
|||
{ |
|||
var selectedDate = new DateTime(2026, 5, 7); |
|||
var target = new Calendar |
|||
{ |
|||
SelectionMode = CalendarSelectionMode.SingleDate, |
|||
DisplayDate = new DateTime(2026, 5, 1), |
|||
SelectedDate = selectedDate, |
|||
}; |
|||
var monthView = new Grid(); |
|||
var calendarItem = new CalendarItem |
|||
{ |
|||
Owner = target, |
|||
MonthView = monthView |
|||
}; |
|||
target.Root = new Panel { Children = { calendarItem } }; |
|||
|
|||
for (var i = 0; i < Calendar.ColumnsPerMonth; i++) |
|||
{ |
|||
monthView.Children.Add(new TextBlock()); |
|||
} |
|||
|
|||
for (var i = 0; i < Calendar.RowsPerMonth * Calendar.ColumnsPerMonth - Calendar.ColumnsPerMonth; i++) |
|||
{ |
|||
monthView.Children.Add(new CalendarDayButton |
|||
{ |
|||
Owner = target, |
|||
DataContext = i == 0 ? selectedDate : selectedDate.AddDays(i + 1) |
|||
}); |
|||
} |
|||
|
|||
var peer = (CalendarAutomationPeer)ControlAutomationPeer.CreatePeerForElement(target); |
|||
var selection = peer.GetSelection(); |
|||
|
|||
Assert.Single(selection); |
|||
} |
|||
} |
|||
@ -0,0 +1,266 @@ |
|||
using System; |
|||
using Avalonia.Automation; |
|||
using Avalonia.Automation.Peers; |
|||
using Avalonia.Automation.Provider; |
|||
using Avalonia.Controls; |
|||
using Avalonia.UnitTests; |
|||
using Xunit; |
|||
|
|||
#nullable enable |
|||
|
|||
namespace Avalonia.Controls.UnitTests.Automation; |
|||
|
|||
public class FoundationAutomationPeerTests |
|||
{ |
|||
public class ToolTipPeer : ScopedTestBase |
|||
{ |
|||
[Fact] |
|||
public void Creates_ToolTipAutomationPeer() |
|||
{ |
|||
var control = new ToolTip(); |
|||
var peer = ControlAutomationPeer.CreatePeerForElement(control); |
|||
|
|||
Assert.IsType<ToolTipAutomationPeer>(peer); |
|||
} |
|||
|
|||
[Fact] |
|||
public void ControlType_Is_ToolTip() |
|||
{ |
|||
var control = new ToolTip(); |
|||
var peer = (ToolTipAutomationPeer)ControlAutomationPeer.CreatePeerForElement(control); |
|||
|
|||
Assert.Equal(AutomationControlType.ToolTip, peer.GetAutomationControlType()); |
|||
Assert.Equal("ToolTip", peer.GetClassName()); |
|||
} |
|||
} |
|||
|
|||
public class CalendarDatePickerPeer : ScopedTestBase |
|||
{ |
|||
[Fact] |
|||
public void Creates_CalendarDatePickerAutomationPeer() |
|||
{ |
|||
var control = new CalendarDatePicker(); |
|||
var peer = ControlAutomationPeer.CreatePeerForElement(control); |
|||
|
|||
Assert.IsType<CalendarDatePickerAutomationPeer>(peer); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Implements_IInvoke_And_IValue_Providers() |
|||
{ |
|||
var control = new CalendarDatePicker(); |
|||
var peer = ControlAutomationPeer.CreatePeerForElement(control); |
|||
|
|||
Assert.IsAssignableFrom<IInvokeProvider>(peer); |
|||
Assert.IsAssignableFrom<IExpandCollapseProvider>(peer); |
|||
Assert.IsAssignableFrom<IValueProvider>(peer); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Has_Button_ControlType() |
|||
{ |
|||
var control = new CalendarDatePicker(); |
|||
var peer = (CalendarDatePickerAutomationPeer)ControlAutomationPeer.CreatePeerForElement(control); |
|||
|
|||
Assert.Equal(AutomationControlType.Button, peer.GetAutomationControlType()); |
|||
Assert.Equal("CalendarDatePicker", peer.GetClassName()); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Invoke_Opens_DropDown() |
|||
{ |
|||
var control = new CalendarDatePicker(); |
|||
var peer = (IInvokeProvider)ControlAutomationPeer.CreatePeerForElement(control); |
|||
|
|||
peer.Invoke(); |
|||
|
|||
Assert.True(control.IsDropDownOpen); |
|||
} |
|||
|
|||
[Fact] |
|||
public void ExpandCollapse_Tracks_IsDropDownOpen() |
|||
{ |
|||
var control = new CalendarDatePicker(); |
|||
var peer = (IExpandCollapseProvider)ControlAutomationPeer.CreatePeerForElement(control); |
|||
|
|||
Assert.True(peer.ShowsMenu); |
|||
Assert.Equal(ExpandCollapseState.Collapsed, peer.ExpandCollapseState); |
|||
|
|||
peer.Expand(); |
|||
Assert.True(control.IsDropDownOpen); |
|||
Assert.Equal(ExpandCollapseState.Expanded, peer.ExpandCollapseState); |
|||
|
|||
peer.Collapse(); |
|||
Assert.False(control.IsDropDownOpen); |
|||
Assert.Equal(ExpandCollapseState.Collapsed, peer.ExpandCollapseState); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Value_Mirrors_Owner_Text() |
|||
{ |
|||
var control = new CalendarDatePicker { Text = "typed value" }; |
|||
var peer = (CalendarDatePickerAutomationPeer)ControlAutomationPeer.CreatePeerForElement(control); |
|||
|
|||
Assert.Equal("typed value", peer.Value); |
|||
|
|||
control.Text = "updated typed value"; |
|||
|
|||
Assert.Equal("updated typed value", peer.Value); |
|||
} |
|||
|
|||
[Fact] |
|||
public void SetValue_Updates_Text() |
|||
{ |
|||
var control = new CalendarDatePicker(); |
|||
var peer = (IValueProvider)ControlAutomationPeer.CreatePeerForElement(control); |
|||
|
|||
Assert.False(peer.IsReadOnly); |
|||
|
|||
peer.SetValue("automation text"); |
|||
|
|||
Assert.Equal("automation text", control.Text); |
|||
} |
|||
|
|||
[Fact] |
|||
public void PropertyChanged_Raises_Value_When_Text_Changes() |
|||
{ |
|||
var control = new CalendarDatePicker(); |
|||
var peer = (CalendarDatePickerAutomationPeer)ControlAutomationPeer.CreatePeerForElement(control); |
|||
AutomationPropertyChangedEventArgs? changed = null; |
|||
|
|||
peer.PropertyChanged += (_, e) => |
|||
{ |
|||
if (e.Property == ValuePatternIdentifiers.ValueProperty) |
|||
changed = e; |
|||
}; |
|||
|
|||
control.Text = "January"; |
|||
|
|||
Assert.NotNull(changed); |
|||
Assert.Equal(ValuePatternIdentifiers.ValueProperty, changed!.Property); |
|||
Assert.Null(changed.OldValue); |
|||
Assert.Equal("January", changed.NewValue); |
|||
} |
|||
|
|||
[Fact] |
|||
public void PropertyChanged_Raises_ExpandCollapseState_When_DropDown_Open_Changes() |
|||
{ |
|||
var control = new CalendarDatePicker(); |
|||
var peer = (CalendarDatePickerAutomationPeer)ControlAutomationPeer.CreatePeerForElement(control); |
|||
AutomationPropertyChangedEventArgs? changed = null; |
|||
|
|||
peer.PropertyChanged += (_, e) => |
|||
{ |
|||
if (e.Property == ExpandCollapsePatternIdentifiers.ExpandCollapseStateProperty) |
|||
changed = e; |
|||
}; |
|||
|
|||
control.IsDropDownOpen = true; |
|||
|
|||
Assert.NotNull(changed); |
|||
Assert.Equal(ExpandCollapsePatternIdentifiers.ExpandCollapseStateProperty, changed!.Property); |
|||
Assert.Equal(ExpandCollapseState.Collapsed, changed.OldValue); |
|||
Assert.Equal(ExpandCollapseState.Expanded, changed.NewValue); |
|||
} |
|||
} |
|||
|
|||
public class NumericUpDownPeer : ScopedTestBase |
|||
{ |
|||
[Fact] |
|||
public void Creates_NumericUpDownAutomationPeer() |
|||
{ |
|||
var control = new NumericUpDown(); |
|||
var peer = ControlAutomationPeer.CreatePeerForElement(control); |
|||
|
|||
Assert.IsType<NumericUpDownAutomationPeer>(peer); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Is_Spinner_ControlType() |
|||
{ |
|||
var control = new NumericUpDown(); |
|||
var peer = (NumericUpDownAutomationPeer)ControlAutomationPeer.CreatePeerForElement(control); |
|||
|
|||
Assert.Equal(AutomationControlType.Spinner, peer.GetAutomationControlType()); |
|||
Assert.Equal("NumericUpDown", peer.GetClassName()); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Implements_IRangeValueProvider() |
|||
{ |
|||
var control = new NumericUpDown(); |
|||
var peer = ControlAutomationPeer.CreatePeerForElement(control); |
|||
|
|||
Assert.IsAssignableFrom<IRangeValueProvider>(peer); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Range_Values_Reflect_Owner() |
|||
{ |
|||
var control = new NumericUpDown |
|||
{ |
|||
Minimum = 10, |
|||
Maximum = 20, |
|||
Increment = 3, |
|||
IsReadOnly = true, |
|||
Value = 14, |
|||
}; |
|||
|
|||
var peer = (IRangeValueProvider)ControlAutomationPeer.CreatePeerForElement(control); |
|||
|
|||
Assert.Equal(10d, peer.Minimum); |
|||
Assert.Equal(20d, peer.Maximum); |
|||
Assert.Equal(14d, peer.Value); |
|||
Assert.Equal(3d, peer.SmallChange); |
|||
Assert.Equal(3d, peer.LargeChange); |
|||
Assert.True(peer.IsReadOnly); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Null_Value_Reports_Default_Clamped_To_Range() |
|||
{ |
|||
var control = new NumericUpDown |
|||
{ |
|||
Minimum = 10, |
|||
Maximum = 20, |
|||
Value = null, |
|||
}; |
|||
|
|||
var peer = (IRangeValueProvider)ControlAutomationPeer.CreatePeerForElement(control); |
|||
|
|||
Assert.Equal(10d, peer.Value); |
|||
} |
|||
|
|||
[Fact] |
|||
public void SetValue_Updates_Owner_Value() |
|||
{ |
|||
var control = new NumericUpDown(); |
|||
var peer = (IRangeValueProvider)ControlAutomationPeer.CreatePeerForElement(control); |
|||
|
|||
peer.SetValue(42.5); |
|||
|
|||
Assert.Equal(42.5m, control.Value); |
|||
} |
|||
|
|||
[Fact] |
|||
public void PropertyChanged_Raises_Range_When_Value_Changes() |
|||
{ |
|||
var control = new NumericUpDown(); |
|||
var peer = (NumericUpDownAutomationPeer)ControlAutomationPeer.CreatePeerForElement(control); |
|||
AutomationPropertyChangedEventArgs? changed = null; |
|||
|
|||
peer.PropertyChanged += (_, e) => |
|||
{ |
|||
if (e.Property == RangeValuePatternIdentifiers.ValueProperty) |
|||
changed = e; |
|||
}; |
|||
|
|||
control.Value = 7.5m; |
|||
|
|||
Assert.NotNull(changed); |
|||
Assert.Equal(RangeValuePatternIdentifiers.ValueProperty, changed!.Property); |
|||
Assert.Null(changed.OldValue); |
|||
Assert.Equal(7.5m, changed.NewValue); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,73 @@ |
|||
using System.Linq; |
|||
using Avalonia; |
|||
using Avalonia.Automation; |
|||
using Avalonia.Automation.Peers; |
|||
using Avalonia.Controls; |
|||
using Avalonia.Controls.Templates; |
|||
using Avalonia.UnitTests; |
|||
using Avalonia.VisualTree; |
|||
using Xunit; |
|||
|
|||
namespace Avalonia.Controls.UnitTests.Automation; |
|||
|
|||
public class NativeMenuBarAutomationPeerTests |
|||
{ |
|||
public class PeerCreation : ScopedTestBase |
|||
{ |
|||
[Fact] |
|||
public void Creates_NativeMenuBarAutomationPeer() |
|||
{ |
|||
var control = new NativeMenuBar { Template = CreateTemplate() }; |
|||
var peer = ControlAutomationPeer.CreatePeerForElement(control); |
|||
|
|||
Assert.IsType<NativeMenuBarAutomationPeer>(peer); |
|||
} |
|||
|
|||
[Fact] |
|||
public void ControlType_Is_MenuBar() |
|||
{ |
|||
var control = new NativeMenuBar { Template = CreateTemplate() }; |
|||
var peer = (NativeMenuBarAutomationPeer)ControlAutomationPeer.CreatePeerForElement(control); |
|||
|
|||
Assert.Equal(AutomationControlType.MenuBar, peer.GetAutomationControlType()); |
|||
} |
|||
} |
|||
|
|||
public class Children : ScopedTestBase |
|||
{ |
|||
[Fact] |
|||
public void Exposes_Realized_MenuItems_Via_VisualChildren() |
|||
{ |
|||
var control = new NativeMenuBar { Template = CreateTemplate() }; |
|||
control.ApplyTemplate(); |
|||
var menu = Assert.IsType<Menu>(control.GetVisualChildren().Single()); |
|||
menu.ApplyTemplate(); |
|||
menu.Measure(Size.Infinity); |
|||
menu.Arrange(new Rect(0, 0, 300, 30)); |
|||
control.Measure(Size.Infinity); |
|||
control.Arrange(new Rect(0, 0, 300, 30)); |
|||
|
|||
var peer = (NativeMenuBarAutomationPeer)ControlAutomationPeer.CreatePeerForElement(control); |
|||
var presenterChildren = peer.GetChildren(); |
|||
|
|||
Assert.Equal(2, presenterChildren.Count); |
|||
Assert.All(presenterChildren, x => Assert.IsType<MenuItemAutomationPeer>(x)); |
|||
Assert.Equal("File", presenterChildren[0].GetName()); |
|||
Assert.Equal("Edit", presenterChildren[1].GetName()); |
|||
} |
|||
} |
|||
|
|||
private static FuncControlTemplate CreateTemplate() |
|||
{ |
|||
return new FuncControlTemplate((_, ns) => |
|||
new Menu |
|||
{ |
|||
Name = "PART_NativeMenuPresenter", |
|||
Items = |
|||
{ |
|||
new MenuItem { Header = "File" }, |
|||
new MenuItem { Header = "Edit" }, |
|||
}, |
|||
}.RegisterInNameScope(ns)); |
|||
} |
|||
} |
|||
@ -0,0 +1,196 @@ |
|||
using Avalonia.Automation; |
|||
using Avalonia.Automation.Peers; |
|||
using Avalonia.Automation.Provider; |
|||
using Avalonia.Controls; |
|||
using Avalonia.UnitTests; |
|||
using Xunit; |
|||
|
|||
namespace Avalonia.Controls.UnitTests.Automation; |
|||
|
|||
public class SplitButtonAutomationPeerTests : ScopedTestBase |
|||
{ |
|||
[Fact] |
|||
public void Creates_SplitButtonAutomationPeer() |
|||
{ |
|||
var target = new SplitButton(); |
|||
var peer = ControlAutomationPeer.CreatePeerForElement(target); |
|||
|
|||
Assert.IsType<SplitButtonAutomationPeer>(peer); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Implements_IExpandCollapseProvider() |
|||
{ |
|||
var target = new SplitButton(); |
|||
var peer = ControlAutomationPeer.CreatePeerForElement(target); |
|||
|
|||
Assert.IsAssignableFrom<IExpandCollapseProvider>(peer); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Implements_IInvokeProvider() |
|||
{ |
|||
var target = new SplitButton(); |
|||
var peer = ControlAutomationPeer.CreatePeerForElement(target); |
|||
|
|||
Assert.IsAssignableFrom<IInvokeProvider>(peer); |
|||
} |
|||
|
|||
[Fact] |
|||
public void ControlType_Is_SplitButton() |
|||
{ |
|||
var target = new SplitButton(); |
|||
var peer = (SplitButtonAutomationPeer)ControlAutomationPeer.CreatePeerForElement(target); |
|||
|
|||
Assert.Equal(AutomationControlType.SplitButton, peer.GetAutomationControlType()); |
|||
} |
|||
|
|||
[Fact] |
|||
public void ClassName_Is_SplitButton() |
|||
{ |
|||
var target = new SplitButton(); |
|||
var peer = (SplitButtonAutomationPeer)ControlAutomationPeer.CreatePeerForElement(target); |
|||
|
|||
Assert.Equal("SplitButton", peer.GetClassName()); |
|||
} |
|||
|
|||
[Fact] |
|||
public void ShowsMenu_Is_True() |
|||
{ |
|||
var target = new SplitButton(); |
|||
var peer = (IExpandCollapseProvider)ControlAutomationPeer.CreatePeerForElement(target); |
|||
|
|||
Assert.True(peer.ShowsMenu); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Invoke_Triggers_Click() |
|||
{ |
|||
var clicked = 0; |
|||
var target = new SplitButton(); |
|||
var peer = (IInvokeProvider)ControlAutomationPeer.CreatePeerForElement(target); |
|||
|
|||
target.Click += (_, _) => clicked++; |
|||
peer.Invoke(); |
|||
|
|||
Assert.Equal(1, clicked); |
|||
} |
|||
|
|||
[Fact] |
|||
public void ExpandCollapse_State_Tracks_Flyout() |
|||
{ |
|||
using (UnitTestApplication.Start(TestServices.StyledWindow)) |
|||
{ |
|||
var target = new SplitButton |
|||
{ |
|||
Flyout = new Flyout() |
|||
}; |
|||
var window = new Window |
|||
{ |
|||
Content = target, |
|||
}; |
|||
window.Show(); |
|||
|
|||
var peer = (SplitButtonAutomationPeer)ControlAutomationPeer.CreatePeerForElement(target); |
|||
|
|||
Assert.Equal(ExpandCollapseState.Collapsed, peer.ExpandCollapseState); |
|||
|
|||
peer.Expand(); |
|||
Assert.Equal(ExpandCollapseState.Expanded, peer.ExpandCollapseState); |
|||
Assert.True(target.Flyout?.IsOpen); |
|||
|
|||
peer.Collapse(); |
|||
Assert.Equal(ExpandCollapseState.Collapsed, peer.ExpandCollapseState); |
|||
Assert.False(target.Flyout!.IsOpen); |
|||
} |
|||
} |
|||
|
|||
[Fact] |
|||
public void ExpandCollapse_Raises_PropertyChanged() |
|||
{ |
|||
using (UnitTestApplication.Start(TestServices.StyledWindow)) |
|||
{ |
|||
var target = new SplitButton |
|||
{ |
|||
Flyout = new Flyout() |
|||
}; |
|||
var window = new Window |
|||
{ |
|||
Content = target, |
|||
}; |
|||
window.Show(); |
|||
|
|||
var peer = (SplitButtonAutomationPeer)ControlAutomationPeer.CreatePeerForElement(target); |
|||
AutomationPropertyChangedEventArgs? changed = null; |
|||
peer.PropertyChanged += (_, e) => |
|||
{ |
|||
if (e.Property == ExpandCollapsePatternIdentifiers.ExpandCollapseStateProperty) |
|||
{ |
|||
changed = e; |
|||
} |
|||
}; |
|||
|
|||
peer.Expand(); |
|||
|
|||
Assert.NotNull(changed); |
|||
Assert.Equal(ExpandCollapseState.Collapsed, changed!.OldValue); |
|||
Assert.Equal(ExpandCollapseState.Expanded, changed.NewValue); |
|||
} |
|||
} |
|||
} |
|||
|
|||
public class ToggleSplitButtonAutomationPeerTests : ScopedTestBase |
|||
{ |
|||
[Fact] |
|||
public void Creates_ToggleSplitButtonAutomationPeer() |
|||
{ |
|||
var target = new ToggleSplitButton(); |
|||
var peer = ControlAutomationPeer.CreatePeerForElement(target); |
|||
|
|||
Assert.IsType<ToggleSplitButtonAutomationPeer>(peer); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Implements_IToggleProvider() |
|||
{ |
|||
var target = new ToggleSplitButton(); |
|||
var peer = ControlAutomationPeer.CreatePeerForElement(target); |
|||
|
|||
Assert.IsAssignableFrom<IToggleProvider>(peer); |
|||
} |
|||
|
|||
[Fact] |
|||
public void ControlType_Is_SplitButton() |
|||
{ |
|||
var target = new ToggleSplitButton(); |
|||
var peer = (SplitButtonAutomationPeer)ControlAutomationPeer.CreatePeerForElement(target); |
|||
|
|||
Assert.Equal(AutomationControlType.SplitButton, peer.GetAutomationControlType()); |
|||
} |
|||
|
|||
[Fact] |
|||
public void ClassName_Is_ToggleSplitButton() |
|||
{ |
|||
var target = new ToggleSplitButton(); |
|||
var peer = (ToggleSplitButtonAutomationPeer)ControlAutomationPeer.CreatePeerForElement(target); |
|||
|
|||
Assert.Equal("ToggleSplitButton", peer.GetClassName()); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Toggle_Changes_IsChecked_And_Fires_Click() |
|||
{ |
|||
var clicked = 0; |
|||
var target = new ToggleSplitButton(); |
|||
var peer = (IToggleProvider)ControlAutomationPeer.CreatePeerForElement(target); |
|||
|
|||
Assert.Equal(ToggleState.Off, peer.ToggleState); |
|||
|
|||
target.Click += (_, _) => clicked++; |
|||
peer.Toggle(); |
|||
|
|||
Assert.True(target.IsChecked); |
|||
Assert.Equal(ToggleState.On, peer.ToggleState); |
|||
Assert.Equal(1, clicked); |
|||
} |
|||
} |
|||
Loading…
Reference in new issue