Browse Source
* Add missing AutomationPeers from built-in Controls. * revert native menu bar peers * Add back a thin automation peer for native menu bar. * Use ColorChanged for ColorSpectrumAutomationPeer * Fix NativeMenuBar/ColorSpectrum automation peer regressions Flatten MenuItem children under NativeMenuBarAutomationPeer and raise ColorChanged when Color is set directly so ColorSpectrumAutomationPeer notifies AT clients. * Drop NativeMenuBarAutomationPeer.GetChildrenCore override Bisect confirmed this override caused 5 Windows IT tests (Slider, Screen, DragDrop) to fail by producing an inconsistent UIA tree where MenuItem peers list NativeMenuBar as parent while their visual parent is the inner Menu. Reverted to the thin peer that only reports ControlType=MenuBar, and dropped the now-irrelevant children assertion test.master
committed by
GitHub
24 changed files with 1410 additions and 2 deletions
@ -0,0 +1,40 @@ |
|||
using Avalonia; |
|||
using Avalonia.Automation; |
|||
using Avalonia.Automation.Provider; |
|||
using Avalonia.Controls; |
|||
using Avalonia.Controls.Primitives; |
|||
using Avalonia.Media; |
|||
|
|||
namespace Avalonia.Automation.Peers; |
|||
|
|||
public class ColorSpectrumAutomationPeer : ControlAutomationPeer, IValueProvider |
|||
{ |
|||
public ColorSpectrumAutomationPeer(ColorSpectrum owner) |
|||
: base(owner) |
|||
{ |
|||
owner.ColorChanged += OwnerOnColorChanged; |
|||
} |
|||
|
|||
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 OwnerOnColorChanged(object? sender, ColorChangedEventArgs e) |
|||
{ |
|||
RaisePropertyChangedEvent(ValuePatternIdentifiers.ValueProperty, e.OldColor.ToString(), e.NewColor.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,12 @@ |
|||
using Avalonia.Controls; |
|||
|
|||
namespace Avalonia.Automation.Peers |
|||
{ |
|||
public class NativeMenuBarAutomationPeer(NativeMenuBar owner) : ControlAutomationPeer(owner) |
|||
{ |
|||
protected override AutomationControlType GetAutomationControlTypeCore() |
|||
{ |
|||
return AutomationControlType.MenuBar; |
|||
} |
|||
} |
|||
} |
|||
@ -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,46 @@ |
|||
using Avalonia.Automation; |
|||
using Avalonia.Automation.Peers; |
|||
using Avalonia.Controls; |
|||
using Avalonia.Controls.Templates; |
|||
using Avalonia.UnitTests; |
|||
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()); |
|||
} |
|||
} |
|||
|
|||
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