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