diff --git a/src/System.Windows.Forms/src/PublicAPI.Unshipped.txt b/src/System.Windows.Forms/src/PublicAPI.Unshipped.txt index e69de29bb2d..67d9e11996f 100644 --- a/src/System.Windows.Forms/src/PublicAPI.Unshipped.txt +++ b/src/System.Windows.Forms/src/PublicAPI.Unshipped.txt @@ -0,0 +1,2 @@ +~override System.Windows.Forms.TabControl.CreateAccessibilityInstance() -> System.Windows.Forms.AccessibleObject +~override System.Windows.Forms.TabPage.CreateAccessibilityInstance() -> System.Windows.Forms.AccessibleObject \ No newline at end of file diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/TabControl.TabControlAccessibleObject.cs b/src/System.Windows.Forms/src/System/Windows/Forms/TabControl.TabControlAccessibleObject.cs new file mode 100644 index 00000000000..a8a8db4dded --- /dev/null +++ b/src/System.Windows.Forms/src/System/Windows/Forms/TabControl.TabControlAccessibleObject.cs @@ -0,0 +1,171 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Drawing; +using static Interop.UiaCore; + +namespace System.Windows.Forms +{ + public partial class TabControl + { + internal class TabControlAccessibleObject : ControlAccessibleObject + { + private readonly TabControl _owningTabControl; + + public TabControlAccessibleObject(TabControl owningTabControl) : base(owningTabControl) + { + _owningTabControl = owningTabControl; + } + + public override Rectangle Bounds + { + get + { + if (!_owningTabControl.IsHandleCreated || GetSystemIAccessibleInternal() is null) + { + return Rectangle.Empty; + } + + // The "NativeMethods.CHILDID_SELF" constant returns to the id of the TabPage, + // which allows to use the native "accLocation" method to get the "Bounds" property + GetSystemIAccessibleInternal()!.accLocation(out int left, out int top, out int width, out int height, NativeMethods.CHILDID_SELF); + return new(left, top, width, height); + } + } + + public override AccessibleRole Role + => Owner.AccessibleRole != AccessibleRole.Default + ? Owner.AccessibleRole + : AccessibleRole.PageTabList; + + public override AccessibleStates State + // The "NativeMethods.CHILDID_SELF" constant returns to the id of the trackbar, + // which allows to use the native "get_accState" method to get the "State" property + => GetSystemIAccessibleInternal()?.get_accState(NativeMethods.CHILDID_SELF) is object accState + ? (AccessibleStates)accState + : AccessibleStates.None; + + internal override IRawElementProviderFragmentRoot FragmentRoot => this; + + internal override bool IsSelectionRequired => true; + + public override AccessibleObject? GetChild(int index) + { + if (!_owningTabControl.IsHandleCreated + || _owningTabControl.TabPages.Count == 0 + || index < 0 + || index > _owningTabControl.TabPages.Count) + { + return null; + } + + return index == 0 + ? _owningTabControl.SelectedTab?.AccessibilityObject + : _owningTabControl.TabPages[index - 1].TabAccessibilityObject; + } + + public override int GetChildCount() + { + if (!_owningTabControl.IsHandleCreated) + { + // We return -1 instead of 0 when the Handle has not been created, + // so that the user can distinguish between the situation + // when something went wrong (in this case, the Handle was not created) + // and the situation when the Handle was created, but the TabControl, + // for example, does not contain TabPages. + return -1; + } + + if (_owningTabControl.TabPages.Count == 0) + { + return 0; + } + + // We add 1 to the number of TabPages, since the TabControl, in addition to the elements + // for the TabPages,contains an element for the Panel of the selected TabPage. + return _owningTabControl.TabPages.Count + 1; + } + + public override AccessibleObject? HitTest(int x, int y) + { + if (!_owningTabControl.IsHandleCreated) + { + return null; + } + + Point point = new(x, y); + if (_owningTabControl.SelectedTab is not null + && _owningTabControl.SelectedTab.AccessibilityObject.Bounds.Contains(point)) + { + return _owningTabControl.SelectedTab.AccessibilityObject; + } + + foreach (TabPage tabPage in _owningTabControl.TabPages) + { + if (tabPage.TabAccessibilityObject.Bounds.Contains(point)) + { + return tabPage.TabAccessibilityObject; + } + } + + return this; + } + + internal override IRawElementProviderFragment? ElementProviderFromPoint(double x, double y) + => HitTest((int)x, (int)y) ?? base.ElementProviderFromPoint(x, y); + + internal override IRawElementProviderFragment? FragmentNavigate(NavigateDirection direction) + { + if (!_owningTabControl.IsHandleCreated) + { + return null; + } + + return direction switch + { + NavigateDirection.FirstChild => _owningTabControl.SelectedTab?.AccessibilityObject, + NavigateDirection.LastChild => _owningTabControl.TabPages.Count > 0 + ? _owningTabControl.TabPages[^1].TabAccessibilityObject + : null, + _ => base.FragmentNavigate(direction) + }; + } + + internal override object? GetPropertyValue(UIA propertyID) + => propertyID switch + { + UIA.RuntimeIdPropertyId => RuntimeId, + UIA.AutomationIdPropertyId => _owningTabControl.Name, + UIA.IsEnabledPropertyId => _owningTabControl.Enabled, + UIA.IsOffscreenPropertyId => (State & AccessibleStates.Offscreen) == AccessibleStates.Offscreen, + UIA.HasKeyboardFocusPropertyId => _owningTabControl.Focused, + UIA.NamePropertyId => Name, + UIA.AccessKeyPropertyId => KeyboardShortcut, + UIA.NativeWindowHandlePropertyId => _owningTabControl.InternalHandle, + UIA.IsSelectionPatternAvailablePropertyId => IsPatternSupported(UIA.SelectionPatternId), + UIA.IsLegacyIAccessiblePatternAvailablePropertyId => IsPatternSupported(UIA.LegacyIAccessiblePatternId), + UIA.IsKeyboardFocusablePropertyId + // This is necessary for compatibility with MSAA proxy: + // IsKeyboardFocusable = true regardless the control is enabled/disabled. + => true, + _ => base.GetPropertyValue(propertyID) + }; + + internal override IRawElementProviderSimple[]? GetSelection() + => !_owningTabControl.IsHandleCreated + || _owningTabControl.SelectedTab is null + ? Array.Empty() + : new IRawElementProviderSimple[] { _owningTabControl.SelectedTab.TabAccessibilityObject }; + + internal override bool IsPatternSupported(UIA patternId) + => patternId switch + { + // The "Enabled" property of the TabControl does not affect the behavior of that property, + // so it is always true + UIA.SelectionPatternId => true, + _ => base.IsPatternSupported(patternId) + }; + } + } +} diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/TabControl.cs b/src/System.Windows.Forms/src/System/Windows/Forms/TabControl.cs index 05e2278112a..28503f08c05 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/TabControl.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/TabControl.cs @@ -808,6 +808,8 @@ public bool ShowToolTips } } + internal override bool SupportsUiaProviders => true; + /// /// Returns the number of tabs in the strip /// @@ -966,6 +968,8 @@ internal void BeginUpdate() BeginUpdateInternal(); } + protected override AccessibleObject CreateAccessibilityInstance() => new TabControlAccessibleObject(this); + protected override Control.ControlCollection CreateControlsInstance() { return new ControlCollection(this); @@ -1278,6 +1282,11 @@ protected override void OnGotFocus(EventArgs e) { NotifyAboutFocusState(SelectedTab, focused: true); base.OnGotFocus(e); + + if (IsAccessibilityObjectCreated && SelectedTab is not null) + { + SelectedTab.TabAccessibilityObject.RaiseAutomationEvent(UiaCore.UIA.AutomationFocusChangedEventId); + } } /// @@ -2050,6 +2059,12 @@ private bool WmSelChange() { OnSelected(new TabControlEventArgs(SelectedTab, SelectedIndex, TabControlAction.Selected)); OnSelectedIndexChanged(EventArgs.Empty); + + if (IsAccessibilityObjectCreated && SelectedTab?.ParentInternal is TabControl) + { + SelectedTab.TabAccessibilityObject.RaiseAutomationEvent(UiaCore.UIA.SelectionItem_ElementSelectedEventId); + SelectedTab.TabAccessibilityObject.RaiseAutomationEvent(UiaCore.UIA.AutomationFocusChangedEventId); + } } else { diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/TabPage.TabAccessibleObject.cs b/src/System.Windows.Forms/src/System/Windows/Forms/TabPage.TabAccessibleObject.cs new file mode 100644 index 00000000000..273db26b2e6 --- /dev/null +++ b/src/System.Windows.Forms/src/System/Windows/Forms/TabPage.TabAccessibleObject.cs @@ -0,0 +1,157 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Drawing; +using Accessibility; +using static Interop; + +namespace System.Windows.Forms +{ + public partial class TabPage + { + internal class TabAccessibleObject : AccessibleObject + { + private TabControl? OwningTabControl => _owningTabPage.ParentInternal as TabControl; + + private readonly TabPage _owningTabPage; + + public TabAccessibleObject(TabPage owningTabPage) + { + _owningTabPage = owningTabPage ?? throw new ArgumentNullException(nameof(owningTabPage)); + } + + public override Rectangle Bounds + { + get + { + if (OwningTabControl is null || !OwningTabControl.IsHandleCreated || SystemIAccessibleInternal is null) + { + return Rectangle.Empty; + } + + int index = CurrentIndex; + + if (index == -1 || (State & AccessibleStates.Invisible) == AccessibleStates.Invisible) + { + return Rectangle.Empty; + } + + // The "GetChildId" method returns to the id of the TabControl element, + // which allows to use the native "accLocation" method to get the "Bounds" property + SystemIAccessibleInternal.accLocation(out int left, out int top, out int width, out int height, GetChildId()); + return new(left, top, width, height); + } + } + + public override string? DefaultAction => SystemIAccessibleInternal?.get_accDefaultAction(GetChildId()); + + public override string? Name => _owningTabPage.Text; + + public override AccessibleRole Role + => SystemIAccessibleInternal?.get_accRole(GetChildId()) is object accRole + ? (AccessibleRole)accRole + : AccessibleRole.None; + + public override AccessibleStates State + => SystemIAccessibleInternal?.get_accState(GetChildId()) is object accState + ? (AccessibleStates)accState + : AccessibleStates.None; + + internal override UiaCore.IRawElementProviderFragmentRoot? FragmentRoot => OwningTabControl?.AccessibilityObject; + + internal override bool IsItemSelected => OwningTabControl?.SelectedTab == _owningTabPage; + + internal override UiaCore.IRawElementProviderSimple? ItemSelectionContainer => OwningTabControl?.AccessibilityObject; + + internal override int[]? RuntimeId + => new int[] + { + RuntimeIDFirstItem, + OwningTabControl is null + ? PARAM.ToInt(IntPtr.Zero) + : PARAM.ToInt(OwningTabControl.InternalHandle), + GetChildId() + }; + + private int CurrentIndex => OwningTabControl?.TabPages.IndexOf(_owningTabPage) ?? -1; + + private IAccessible? SystemIAccessibleInternal + => OwningTabControl?.AccessibilityObject.GetSystemIAccessibleInternal(); + + public override void DoDefaultAction() + { + if (OwningTabControl is not null && OwningTabControl.IsHandleCreated && OwningTabControl.Enabled) + { + OwningTabControl.SelectedTab = _owningTabPage; + } + } + + internal override void AddToSelection() => DoDefaultAction(); + + internal override UiaCore.IRawElementProviderFragment? FragmentNavigate(UiaCore.NavigateDirection direction) + { + if (OwningTabControl is null || !OwningTabControl.IsHandleCreated) + { + return null; + } + + return direction switch + { + UiaCore.NavigateDirection.Parent => OwningTabControl.AccessibilityObject, + UiaCore.NavigateDirection.NextSibling => OwningTabControl.AccessibilityObject.GetChild(GetChildId() + 1), + UiaCore.NavigateDirection.PreviousSibling => OwningTabControl.AccessibilityObject.GetChild(GetChildId() - 1), + _ => null + }; + } + + // +1 is needed because 0 is the Pane id of the selected tab + internal override int GetChildId() => CurrentIndex + 1; + + public override string? Help => SystemIAccessibleInternal?.get_accHelp(GetChildId()); + + public override string? KeyboardShortcut => SystemIAccessibleInternal?.get_accKeyboardShortcut(GetChildId()); + + internal override object? GetPropertyValue(UiaCore.UIA propertyID) + => propertyID switch + { + UiaCore.UIA.ControlTypePropertyId => UiaCore.UIA.TabItemControlTypeId, + UiaCore.UIA.RuntimeIdPropertyId => RuntimeId, + UiaCore.UIA.AutomationIdPropertyId => _owningTabPage.Name, + UiaCore.UIA.AccessKeyPropertyId => KeyboardShortcut ?? string.Empty, + UiaCore.UIA.IsPasswordPropertyId => false, + UiaCore.UIA.HelpTextPropertyId => Help ?? string.Empty, + UiaCore.UIA.IsEnabledPropertyId => OwningTabControl?.Enabled ?? false, + UiaCore.UIA.IsOffscreenPropertyId => (State & AccessibleStates.Offscreen) == AccessibleStates.Offscreen, + UiaCore.UIA.HasKeyboardFocusPropertyId => (State & AccessibleStates.Focused) == AccessibleStates.Focused, + UiaCore.UIA.NamePropertyId => Name, + UiaCore.UIA.IsSelectionItemPatternAvailablePropertyId => IsPatternSupported(UiaCore.UIA.SelectionItemPatternId), + UiaCore.UIA.IsInvokePatternAvailablePropertyId => IsPatternSupported(UiaCore.UIA.InvokePatternId), + UiaCore.UIA.IsLegacyIAccessiblePatternAvailablePropertyId => IsPatternSupported(UiaCore.UIA.LegacyIAccessiblePatternId), + UiaCore.UIA.IsKeyboardFocusablePropertyId + // This is necessary for compatibility with MSAA proxy: + // IsKeyboardFocusable = true regardless the control is enabled/disabled. + => true, + _ => base.GetPropertyValue(propertyID) + }; + + internal override bool IsPatternSupported(UiaCore.UIA patternId) + => patternId switch + { + // The "Enabled" property of the TabControl does not affect the behavior of that property, + // so it is always true + UiaCore.UIA.SelectionItemPatternId => true, + UiaCore.UIA.InvokePatternId => false, + UiaCore.UIA.LegacyIAccessiblePatternId => true, + _ => base.IsPatternSupported(patternId) + }; + + internal override void RemoveFromSelection() + { + // Do nothing, C++ implementation returns UIA_E_INVALIDOPERATION 0x80131509 + } + + internal unsafe override void SelectItem() => DoDefaultAction(); + } + } +} diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/TabPage.TabPageAccessibleObject.cs b/src/System.Windows.Forms/src/System/Windows/Forms/TabPage.TabPageAccessibleObject.cs new file mode 100644 index 00000000000..58668a93afc --- /dev/null +++ b/src/System.Windows.Forms/src/System/Windows/Forms/TabPage.TabPageAccessibleObject.cs @@ -0,0 +1,121 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Drawing; +using static Interop; + +namespace System.Windows.Forms +{ + public partial class TabPage + { + internal class TabPageAccessibleObject : ControlAccessibleObject + { + private readonly TabPage _owningTabPage; + + public TabPageAccessibleObject(TabPage owningTabPage) : base(owningTabPage) + { + _owningTabPage = owningTabPage; + } + + public override Rectangle Bounds + { + get + { + if (!_owningTabPage.IsHandleCreated || GetSystemIAccessibleInternal() is null) + { + return Rectangle.Empty; + } + + // The "NativeMethods.CHILDID_SELF" constant returns to the id of the TabPage, + // which allows to use the native "accLocation" method to get the "Bounds" property + GetSystemIAccessibleInternal()!.accLocation(out int left, out int top, out int width, out int height, NativeMethods.CHILDID_SELF); + return new(left, top, width, height); + } + } + + public override AccessibleStates State + => GetSystemIAccessibleInternal()?.get_accState(GetChildId()) is object accState + ? (AccessibleStates)accState + : AccessibleStates.None; + + internal override UiaCore.IRawElementProviderFragmentRoot? FragmentRoot => OwningTabControl?.AccessibilityObject; + + private TabControl? OwningTabControl => _owningTabPage.ParentInternal as TabControl; + + public override AccessibleObject? GetChild(int index) + { + if (!_owningTabPage.IsHandleCreated) + { + return null; + } + + if (index < 0 || index > _owningTabPage.Controls.Count - 1) + { + return null; + } + + return _owningTabPage.Controls[index].AccessibilityObject; + } + + public override int GetChildCount() => _owningTabPage.IsHandleCreated + ? _owningTabPage.Controls.Count + : -1; + + internal override UiaCore.IRawElementProviderFragment? FragmentNavigate(UiaCore.NavigateDirection direction) + { + if (!_owningTabPage.IsHandleCreated || OwningTabControl is null) + { + return null; + } + + return direction switch + { + UiaCore.NavigateDirection.Parent => OwningTabControl?.AccessibilityObject, + UiaCore.NavigateDirection.NextSibling => GetNextSibling(), + UiaCore.NavigateDirection.PreviousSibling => null, + _ => base.FragmentNavigate(direction) + }; + } + + internal override int GetChildId() => 0; + + internal override object? GetPropertyValue(UiaCore.UIA propertyID) + => propertyID switch + { + UiaCore.UIA.RuntimeIdPropertyId => RuntimeId, + UiaCore.UIA.AutomationIdPropertyId => _owningTabPage.Name, + UiaCore.UIA.IsEnabledPropertyId => _owningTabPage.Enabled, + UiaCore.UIA.IsOffscreenPropertyId => (State & AccessibleStates.Offscreen) == AccessibleStates.Offscreen, + UiaCore.UIA.HasKeyboardFocusPropertyId => _owningTabPage.Focused, + UiaCore.UIA.NamePropertyId => Name, + UiaCore.UIA.AccessKeyPropertyId => KeyboardShortcut, + UiaCore.UIA.NativeWindowHandlePropertyId => _owningTabPage.InternalHandle, + UiaCore.UIA.IsValuePatternAvailablePropertyId => IsPatternSupported(UiaCore.UIA.ValuePatternId), + UiaCore.UIA.IsLegacyIAccessiblePatternAvailablePropertyId => IsPatternSupported(UiaCore.UIA.LegacyIAccessiblePatternId), + UiaCore.UIA.IsKeyboardFocusablePropertyId + // This is necessary for compatibility with MSAA proxy: + // IsKeyboardFocusable = true regardless the control is enabled/disabled. + => true, + _ => base.GetPropertyValue(propertyID) + }; + + internal override bool IsPatternSupported(UiaCore.UIA patternId) + => patternId switch + { + UiaCore.UIA.ValuePatternId => false, + _ => base.IsPatternSupported(patternId) + }; + + private UiaCore.IRawElementProviderFragment? GetNextSibling() + { + if (OwningTabControl is null || _owningTabPage != OwningTabControl.SelectedTab) + { + return null; + } + + return OwningTabControl.TabPages.Count > 0 ? OwningTabControl.TabPages[0].TabAccessibilityObject : null; + } + } + } +} diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/TabPage.cs b/src/System.Windows.Forms/src/System/Windows/Forms/TabPage.cs index ddf96a95f22..9a0e64e0ea8 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/TabPage.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/TabPage.cs @@ -31,6 +31,7 @@ public partial class TabPage : Panel private List _associatedToolTips; private ToolTip _externalToolTip; private readonly ToolTip _internalToolTip = new ToolTip(); + private TabAccessibleObject _tabAccessibilityObject; /// /// Constructs an empty TabPage. @@ -130,6 +131,9 @@ public override Color BackColor } } + protected override AccessibleObject CreateAccessibilityInstance() + => new TabPageAccessibleObject(this); + /// /// Constructs the new instance of the Controls collection objects. /// @@ -374,6 +378,10 @@ public override Size MinimumSize /// internal override bool RenderTransparencyWithVisualStyles => true; + internal override bool SupportsUiaProviders => true; + + internal TabAccessibleObject TabAccessibilityObject => _tabAccessibilityObject ??= new TabAccessibleObject(this); + [Browsable(false)] [EditorBrowsable(EditorBrowsableState.Never)] public new event EventHandler TabIndexChanged diff --git a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/TabControl.TabControlAccessibleObjectTests.cs b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/TabControl.TabControlAccessibleObjectTests.cs index d68932d3d18..29fc861a377 100644 --- a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/TabControl.TabControlAccessibleObjectTests.cs +++ b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/TabControl.TabControlAccessibleObjectTests.cs @@ -2,8 +2,11 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System.Drawing; using Xunit; using static Interop; +using static Interop.UiaCore; +using static System.Windows.Forms.TabControl; namespace System.Windows.Forms.Tests { @@ -12,7 +15,7 @@ public class TabControl_TabControlAccessibilityObjectTests : IClassFixture TabControlAccessibleObject_GetPropertyValue_ [MemberData(nameof(TabControlAccessibleObject_GetPropertyValue_ControlType_IsExpected_ForCustomRole_TestData))] public void TabControlAccessibleObject_GetPropertyValue_ControlType_IsExpected_ForCustomRole(AccessibleRole role) { - using TabControl tabControl = new TabControl(); + using TabControl tabControl = new(); tabControl.AccessibleRole = role; object actual = tabControl.AccessibilityObject.GetPropertyValue(UiaCore.UIA.ControlTypePropertyId); @@ -73,5 +76,630 @@ public void TabControlAccessibleObject_GetPropertyValue_ControlType_IsExpected_F Assert.Equal(expected, actual); Assert.False(tabControl.IsHandleCreated); } + + [WinFormsTheory] + [InlineData(true, false)] + [InlineData(false, true)] + public void TabControlAccessibleObject_Bounds_ReturnsExpected(bool createControl, bool boundsIsEmpty) + { + using TabControl tabControl = new(); + TabControlAccessibleObject accessibleObject = Assert.IsType(tabControl.AccessibilityObject); + + if (createControl) + { + tabControl.CreateControl(); + } + + Assert.Equal(boundsIsEmpty, accessibleObject.Bounds.IsEmpty); + Assert.Equal(createControl, tabControl.IsHandleCreated); + } + + [WinFormsTheory] + [InlineData(true, true, AccessibleStates.Focusable)] + [InlineData(true, false, AccessibleStates.Focusable | AccessibleStates.Unavailable)] + [InlineData(false, true, AccessibleStates.None)] + [InlineData(false, false, AccessibleStates.None)] + public void TabControlAccessibleObject_State_ReturnsExpected(bool createControl, bool enabled, AccessibleStates expectedAccessibleStates) + { + using TabControl tabControl = new() { Enabled = enabled }; + + if (createControl) + { + tabControl.CreateControl(); + } + + TabControlAccessibleObject accessibleObject = Assert.IsType(tabControl.AccessibilityObject); + + Assert.Equal(expectedAccessibleStates, accessibleObject.State); + Assert.Equal(createControl, tabControl.IsHandleCreated); + } + + [WinFormsTheory] + [InlineData(true)] + [InlineData(false)] + public void TabControlAccessibleObject_IsSelectionRequired_ReturnsTrue(bool createControl) + { + using TabControl tabControl = new(); + + if (createControl) + { + tabControl.CreateControl(); + } + + TabControlAccessibleObject accessibleObject = Assert.IsType(tabControl.AccessibilityObject); + + Assert.True(accessibleObject.IsSelectionRequired); + Assert.Equal(createControl, tabControl.IsHandleCreated); + } + + [WinFormsFact] + public void TabControlAccessibleObject_GetChildCount_ReturnsMinusOne_IfHandleIsNotCreated() + { + using TabControl tabControl = new(); + + TabControlAccessibleObject accessibleObject = Assert.IsType(tabControl.AccessibilityObject); + + Assert.Equal(-1, accessibleObject.GetChildCount()); + Assert.False(tabControl.IsHandleCreated); + } + + [WinFormsFact] + public void TabControlAccessibleObject_GetChildCount_ReturnsZero_IfTabPagesListIsEmpty() + { + using TabControl tabControl = new(); + tabControl.CreateControl(); + + TabControlAccessibleObject accessibleObject = Assert.IsType(tabControl.AccessibilityObject); + + Assert.Equal(0, accessibleObject.GetChildCount()); + Assert.True(tabControl.IsHandleCreated); + } + + [WinFormsFact] + public void TabControlAccessibleObject_GetChildCount_ReturnsExpected() + { + using TabControl tabControl = new(); + tabControl.CreateControl(); + TabPageCollection pages = tabControl.TabPages; + pages.AddRange(new TabPage[] { new(), new(), new() }); + + TabControlAccessibleObject accessibleObject = Assert.IsType(tabControl.AccessibilityObject); + + Assert.Equal(4, accessibleObject.GetChildCount()); + Assert.True(pages[0].IsHandleCreated); + Assert.True(pages[1].IsHandleCreated); + Assert.True(pages[2].IsHandleCreated); + Assert.True(tabControl.IsHandleCreated); + } + + [WinFormsFact] + public void TabControlAccessibleObject_GetChild_ReturnsNull_IfHandleIsNotCreated() + { + using TabControl tabControl = new(); + TabPageCollection pages = tabControl.TabPages; + pages.AddRange(new TabPage[] { new(), new() }); + + TabControlAccessibleObject accessibleObject = Assert.IsType(tabControl.AccessibilityObject); + + Assert.Null(accessibleObject.GetChild(-1)); + Assert.Null(accessibleObject.GetChild(0)); + Assert.Null(accessibleObject.GetChild(1)); + Assert.Null(accessibleObject.GetChild(2)); + Assert.Null(accessibleObject.GetChild(3)); + Assert.Null(accessibleObject.GetChild(4)); + Assert.False(pages[0].IsHandleCreated); + Assert.False(pages[1].IsHandleCreated); + Assert.False(tabControl.IsHandleCreated); + } + + [WinFormsFact] + public void TabControlAccessibleObject_GetChild_ReturnsNull_IfTabPagesListIsEmpty() + { + using TabControl tabControl = new(); + tabControl.CreateControl(); + + TabControlAccessibleObject accessibleObject = Assert.IsType(tabControl.AccessibilityObject); + + Assert.Null(accessibleObject.GetChild(-1)); + Assert.Null(accessibleObject.GetChild(0)); + Assert.Null(accessibleObject.GetChild(1)); + Assert.Null(accessibleObject.GetChild(2)); + Assert.Null(accessibleObject.GetChild(3)); + Assert.Null(accessibleObject.GetChild(4)); + Assert.True(tabControl.IsHandleCreated); + } + + [WinFormsFact] + public void TabControlAccessibleObject_GetChild_ReturnsExpected() + { + using TabControl tabControl = new(); + TabPageCollection pages = tabControl.TabPages; + pages.AddRange(new TabPage[] { new(), new() }); + tabControl.CreateControl(); + + TabControlAccessibleObject accessibleObject = Assert.IsType(tabControl.AccessibilityObject); + + Assert.Null(accessibleObject.GetChild(-1)); + Assert.Equal(pages[0].AccessibilityObject, accessibleObject.GetChild(0)); + Assert.Equal(pages[0].TabAccessibilityObject, accessibleObject.GetChild(1)); + Assert.Equal(pages[1].TabAccessibilityObject, accessibleObject.GetChild(2)); + Assert.Null(accessibleObject.GetChild(3)); + Assert.Null(accessibleObject.GetChild(4)); + Assert.True(pages[0].IsHandleCreated); + Assert.False(pages[1].IsHandleCreated); + Assert.True(tabControl.IsHandleCreated); + } + + [WinFormsFact] + public void TabControlAccessibleObject_GetChild_ReturnsExpectd_AfterUpdatingSelectedTab() + { + using TabControl tabControl = new(); + TabPageCollection pages = tabControl.TabPages; + pages.AddRange(new TabPage[] { new(), new(), new() }); + tabControl.CreateControl(); + + TabControlAccessibleObject accessibleObject = Assert.IsType(tabControl.AccessibilityObject); + + Assert.Equal(pages[0].AccessibilityObject, accessibleObject.GetChild(0)); + + tabControl.SelectedIndex = 1; + + Assert.Equal(pages[1].AccessibilityObject, accessibleObject.GetChild(0)); + + tabControl.SelectedIndex = 2; + + Assert.Equal(pages[2].AccessibilityObject, accessibleObject.GetChild(0)); + Assert.True(pages[0].IsHandleCreated); + Assert.True(pages[1].IsHandleCreated); + Assert.True(pages[2].IsHandleCreated); + Assert.True(tabControl.IsHandleCreated); + } + + [WinFormsFact] + public void TabControlAccessibleObject_HitTest_ReturnsNull_IfHandleIsNotCreated() + { + using TabControl tabControl = new(); + TabPageCollection pages = tabControl.TabPages; + pages.AddRange(new TabPage[] { new(), new() }); + + TabControlAccessibleObject accessibleObject = Assert.IsType(tabControl.AccessibilityObject); + + Assert.Null(accessibleObject.HitTest(10, 33)); + Assert.False(pages[0].IsHandleCreated); + Assert.False(pages[1].IsHandleCreated); + Assert.False(tabControl.IsHandleCreated); + } + + [WinFormsFact] + public void TabControlAccessibleObject_HitTest_ReturnsTabControlAccessibleObject_IfTabPagesListIsEmpty() + { + using TabControl tabControl = new(); + TabPageCollection pages = tabControl.TabPages; + tabControl.CreateControl(); + + TabControlAccessibleObject accessibleObject = Assert.IsType(tabControl.AccessibilityObject); + + Assert.Equal(accessibleObject, accessibleObject.HitTest(10, 33)); + Assert.True(tabControl.IsHandleCreated); + } + + [WinFormsFact] + public void TabControlAccessibleObject_HitTest_ReturnsTabPane() + { + using TabControl tabControl = new(); + TabPageCollection pages = tabControl.TabPages; + pages.AddRange(new TabPage[] { new(), new() }); + tabControl.CreateControl(); + + TabControlAccessibleObject accessibleObject = Assert.IsType(tabControl.AccessibilityObject); + AccessibleObject expectedAccessibleObject = tabControl.SelectedTab.AccessibilityObject; + Point point = expectedAccessibleObject.Bounds.Location; + + Assert.Equal(expectedAccessibleObject, accessibleObject.HitTest(point.X, point.Y)); + Assert.True(pages[0].IsHandleCreated); + Assert.False(pages[1].IsHandleCreated); + Assert.True(tabControl.IsHandleCreated); + } + + [WinFormsFact] + public void TabControlAccessibleObject_HitTest_ReturnsFirstItem() + { + using TabControl tabControl = new(); + TabPageCollection pages = tabControl.TabPages; + pages.AddRange(new TabPage[] { new(), new() }); + tabControl.CreateControl(); + + TabControlAccessibleObject accessibleObject = Assert.IsType(tabControl.AccessibilityObject); + AccessibleObject expectedAccessibleObject = pages[0].TabAccessibilityObject; + Point point = expectedAccessibleObject.Bounds.Location; + + Assert.Equal(expectedAccessibleObject, accessibleObject.HitTest(point.X, point.Y)); + Assert.True(pages[0].IsHandleCreated); + Assert.False(pages[1].IsHandleCreated); + Assert.True(tabControl.IsHandleCreated); + } + + [WinFormsFact] + public void TabControlAccessibleObject_HitTest_ReturnsSecondItem() + { + using TabControl tabControl = new(); + TabPageCollection pages = tabControl.TabPages; + pages.AddRange(new TabPage[] { new(), new() }); + tabControl.CreateControl(); + + TabControlAccessibleObject accessibleObject = Assert.IsType(tabControl.AccessibilityObject); + AccessibleObject expectedAccessibleObject = pages[1].TabAccessibilityObject; + Point point = expectedAccessibleObject.Bounds.Location; + + Assert.Equal(expectedAccessibleObject, accessibleObject.HitTest(point.X, point.Y)); + Assert.True(pages[0].IsHandleCreated); + Assert.False(pages[1].IsHandleCreated); + Assert.True(tabControl.IsHandleCreated); + } + + [WinFormsFact] + public void TabControlAccessibleObject_FragmentNavigate_Child_ReturnsNull_IfHandleIsNotCreated() + { + using TabControl tabControl = new(); + TabPageCollection pages = tabControl.TabPages; + pages.AddRange(new TabPage[] { new(), new() }); + + TabControlAccessibleObject accessibleObject = Assert.IsType(tabControl.AccessibilityObject); + + Assert.Null(accessibleObject.FragmentNavigate(NavigateDirection.FirstChild)); + Assert.Null(accessibleObject.FragmentNavigate(NavigateDirection.LastChild)); + Assert.False(pages[0].IsHandleCreated); + Assert.False(pages[1].IsHandleCreated); + Assert.False(tabControl.IsHandleCreated); + } + + [WinFormsFact] + public void TabControlAccessibleObject_FragmentNavigate_Child_ReturnsNull_IfTabPagesListIsEmpty() + { + using TabControl tabControl = new(); + tabControl.CreateControl(); + + TabControlAccessibleObject accessibleObject = Assert.IsType(tabControl.AccessibilityObject); + + Assert.Null(accessibleObject.FragmentNavigate(NavigateDirection.FirstChild)); + Assert.Null(accessibleObject.FragmentNavigate(NavigateDirection.LastChild)); + Assert.True(tabControl.IsHandleCreated); + } + + [WinFormsFact] + public void TabControlAccessibleObject_FragmentNavigate_Child_ReturnsExpected_IfSingleItem() + { + using TabControl tabControl = new(); + TabPageCollection pages = tabControl.TabPages; + pages.Add(new TabPage()); + tabControl.CreateControl(); + + TabControlAccessibleObject accessibleObject = Assert.IsType(tabControl.AccessibilityObject); + + Assert.Equal(tabControl.SelectedTab.AccessibilityObject, accessibleObject.FragmentNavigate(NavigateDirection.FirstChild)); + Assert.Equal(pages[0].TabAccessibilityObject, accessibleObject.FragmentNavigate(NavigateDirection.LastChild)); + Assert.True(pages[0].IsHandleCreated); + Assert.True(tabControl.IsHandleCreated); + } + + [WinFormsFact] + public void TabControlAccessibleObject_FragmentNavigate_Child_ReturnsExpected_IfThreeItems() + { + using TabControl tabControl = new(); + TabPageCollection pages = tabControl.TabPages; + pages.AddRange(new TabPage[] { new(), new(), new() }); + tabControl.CreateControl(); + + TabControlAccessibleObject accessibleObject = Assert.IsType(tabControl.AccessibilityObject); + + Assert.Equal(tabControl.SelectedTab.AccessibilityObject, accessibleObject.FragmentNavigate(NavigateDirection.FirstChild)); + Assert.Equal(pages[0].AccessibilityObject, accessibleObject.FragmentNavigate(NavigateDirection.FirstChild)); + Assert.Equal(pages[2].TabAccessibilityObject, accessibleObject.FragmentNavigate(NavigateDirection.LastChild)); + Assert.True(pages[0].IsHandleCreated); + Assert.False(pages[1].IsHandleCreated); + Assert.False(pages[2].IsHandleCreated); + Assert.True(tabControl.IsHandleCreated); + } + + [WinFormsFact] + public void TabControlAccessibleObject_FragmentNavigate_Child_ReturnsExpected_IfSecondTabIsSelected() + { + using TabControl tabControl = new(); + TabPageCollection pages = tabControl.TabPages; + pages.AddRange(new TabPage[] { new(), new(), new() }); + tabControl.CreateControl(); + + tabControl.SelectedIndex = 1; + TabControlAccessibleObject accessibleObject = Assert.IsType(tabControl.AccessibilityObject); + + Assert.Equal(tabControl.SelectedTab.AccessibilityObject, accessibleObject.FragmentNavigate(NavigateDirection.FirstChild)); + Assert.Equal(pages[1].AccessibilityObject, accessibleObject.FragmentNavigate(NavigateDirection.FirstChild)); + Assert.Equal(pages[2].TabAccessibilityObject, accessibleObject.FragmentNavigate(NavigateDirection.LastChild)); + Assert.True(pages[0].IsHandleCreated); + Assert.True(pages[1].IsHandleCreated); + Assert.False(pages[2].IsHandleCreated); + Assert.True(tabControl.IsHandleCreated); + } + + [WinFormsFact] + public void TabControlAccessibleObject_FragmentNavigate_FirstChild_ReturnsExpectd_AfterUpdatingSelectedTab() + { + using TabControl tabControl = new(); + TabPageCollection pages = tabControl.TabPages; + pages.AddRange(new TabPage[] { new(), new(), new() }); + tabControl.CreateControl(); + + TabControlAccessibleObject accessibleObject = Assert.IsType(tabControl.AccessibilityObject); + + Assert.Equal(pages[0].AccessibilityObject, accessibleObject.FragmentNavigate(NavigateDirection.FirstChild)); + + tabControl.SelectedIndex = 1; + + Assert.Equal(pages[1].AccessibilityObject, accessibleObject.FragmentNavigate(NavigateDirection.FirstChild)); + + tabControl.SelectedIndex = 2; + + Assert.Equal(pages[2].AccessibilityObject, accessibleObject.FragmentNavigate(NavigateDirection.FirstChild)); + Assert.True(pages[0].IsHandleCreated); + Assert.True(pages[1].IsHandleCreated); + Assert.True(pages[2].IsHandleCreated); + Assert.True(tabControl.IsHandleCreated); + } + + [WinFormsTheory] + [InlineData(0)] + [InlineData(1)] + [InlineData(2)] + public void TabControlAccessibleObject_GetSelection_ReturnsExpected(int selectedIndex) + { + using TabControl tabControl = new(); + TabPageCollection pages = tabControl.TabPages; + pages.AddRange(new TabPage[] { new(), new(), new() }); + tabControl.CreateControl(); + tabControl.SelectedIndex = selectedIndex; + + TabControlAccessibleObject accessibleObject = Assert.IsType(tabControl.AccessibilityObject); + IRawElementProviderSimple[] selectedAccessibleObjects = accessibleObject.GetSelection(); + + Assert.Equal(1, selectedAccessibleObjects.Length); + Assert.Equal(pages[selectedIndex].TabAccessibilityObject, selectedAccessibleObjects[0]); + Assert.True(pages[0].IsHandleCreated); + Assert.Equal(selectedIndex == 1, pages[1].IsHandleCreated); + Assert.Equal(selectedIndex == 2, pages[2].IsHandleCreated); + Assert.True(tabControl.IsHandleCreated); + } + + [WinFormsTheory] + [InlineData(0)] + [InlineData(1)] + [InlineData(2)] + public void TabControlAccessibleObject_GetSelection_ReturnsEmptyArray_IfHandleIsNotCreated(int selectedIndex) + { + using TabControl tabControl = new(); + TabPageCollection pages = tabControl.TabPages; + pages.AddRange(new TabPage[] { new(), new(), new() }); + tabControl.SelectedIndex = selectedIndex; + + TabControlAccessibleObject accessibleObject = Assert.IsType(tabControl.AccessibilityObject); + IRawElementProviderSimple[] selectedAccessibleObjects = accessibleObject.GetSelection(); + + Assert.Equal(0, selectedAccessibleObjects.Length); + Assert.False(pages[0].IsHandleCreated); + Assert.False(pages[1].IsHandleCreated); + Assert.False(pages[2].IsHandleCreated); + Assert.False(tabControl.IsHandleCreated); + } + + [WinFormsFact] + public void TabControlAccessibleObject_GetSelection_ReturnsEmptyArray_IfTabPagesListIsEmpty() + { + using TabControl tabControl = new(); + tabControl.CreateControl(); + + TabControlAccessibleObject accessibleObject = Assert.IsType(tabControl.AccessibilityObject); + IRawElementProviderSimple[] selectedAccessibleObjects = accessibleObject.GetSelection(); + + Assert.Equal(0, selectedAccessibleObjects.Length); + Assert.True(tabControl.IsHandleCreated); + } + + [WinFormsFact] + public void TabControlAccessibleObject_Support_SelectionPattern() + { + using TabControl tabControl = new TabControl(); + + TabControlAccessibleObject accessibleObject = Assert.IsType(tabControl.AccessibilityObject); + + Assert.True(accessibleObject.IsPatternSupported(UIA.SelectionPatternId)); + Assert.False(tabControl.IsHandleCreated); + } + + [WinFormsFact] + public void TabControlAccessibleObject_GetPropertyValue_IsSelectionPatternAvailable_ReturnsTrue() + { + using TabControl tabControl = new TabControl(); + + TabControlAccessibleObject accessibleObject = Assert.IsType(tabControl.AccessibilityObject); + + Assert.True((bool)accessibleObject.GetPropertyValue(UIA.IsSelectionPatternAvailablePropertyId)); + Assert.False(tabControl.IsHandleCreated); + } + + [WinFormsFact] + public void TabControlAccessibleObject_Support_LegacyIAccessible() + { + using TabControl tabControl = new TabControl(); + + TabControlAccessibleObject accessibleObject = Assert.IsType(tabControl.AccessibilityObject); + + Assert.True(accessibleObject.IsPatternSupported(UIA.LegacyIAccessiblePatternId)); + Assert.False(tabControl.IsHandleCreated); + } + + [WinFormsFact] + public void TabControlAccessibleObject_GetPropertyValue_IsLegacyIAccessiblePatternAvailable_ReturnsTrue() + { + using TabControl tabControl = new TabControl(); + + TabControlAccessibleObject accessibleObject = Assert.IsType(tabControl.AccessibilityObject); + + Assert.True((bool)accessibleObject.GetPropertyValue(UIA.IsLegacyIAccessiblePatternAvailablePropertyId)); + Assert.False(tabControl.IsHandleCreated); + } + + [WinFormsTheory] + [InlineData("Test")] + [InlineData("")] + [InlineData(null)] + public void TabControlAccessibleObject_Name_ReturnsExpected(string accessibleName) + { + using TabControl tabControl = new TabControl(); + tabControl.AccessibleName = accessibleName; + + TabControlAccessibleObject accessibleObject = Assert.IsType(tabControl.AccessibilityObject); + + Assert.Equal(accessibleName, accessibleObject.Name); + Assert.False(tabControl.IsHandleCreated); + } + + [WinFormsTheory] + [InlineData("Test")] + [InlineData("")] + [InlineData(null)] + public void TabControlAccessibleObject_Description_ReturnsExpected(string accessibleDescription) + { + using TabControl tabControl = new(); + tabControl.AccessibleDescription = accessibleDescription; + + TabControlAccessibleObject accessibleObject = Assert.IsType(tabControl.AccessibilityObject); + + Assert.Equal(accessibleDescription, accessibleObject.Description); + Assert.False(tabControl.IsHandleCreated); + } + + [WinFormsTheory] + [InlineData("Test")] + [InlineData("")] + [InlineData(null)] + public void TabControlAccessibleObject_AccessibleDefaultActionDescription_ReturnsExpected(string accessibleDefaultActionDescription) + { + using TabControl tabControl = new(); + tabControl.AccessibleDefaultActionDescription = accessibleDefaultActionDescription; + + TabControlAccessibleObject accessibleObject = Assert.IsType(tabControl.AccessibilityObject); + + Assert.Equal(accessibleDefaultActionDescription, accessibleObject.DefaultAction); + Assert.False(tabControl.IsHandleCreated); + } + + [WinFormsTheory] + [InlineData(true)] + [InlineData(false)] + public void TabControlAccessibleObject_RuntimeId_ReturnsExpected(bool createControl) + { + using TabControl tabControl = new(); + + if (createControl) + { + tabControl.CreateControl(); + } + + Assert.NotNull(tabControl.AccessibilityObject.RuntimeId); + Assert.Equal(tabControl.InternalHandle, (IntPtr)tabControl.AccessibilityObject.RuntimeId[1]); + Assert.Equal(createControl, tabControl.IsHandleCreated); + } + + [WinFormsFact] + public void TabControlAccessibleObject_GetPropertyValue_HasKeyboardFocusPropertyId_ReturnsFalse() + { + using TabControl tabControl = new TabControl(); + + TabControlAccessibleObject accessibleObject = Assert.IsType(tabControl.AccessibilityObject); + + Assert.False((bool)accessibleObject.GetPropertyValue(UIA.HasKeyboardFocusPropertyId)); + Assert.False(tabControl.IsHandleCreated); + } + + [WinFormsFact] + public void TabControlAccessibleObject_GetPropertyValue_IsKeyboardFocusablePropertyId_ReturnsTrue() + { + using TabControl tabControl = new TabControl(); + + TabControlAccessibleObject accessibleObject = Assert.IsType(tabControl.AccessibilityObject); + + Assert.True((bool)accessibleObject.GetPropertyValue(UIA.IsKeyboardFocusablePropertyId)); + Assert.False(tabControl.IsHandleCreated); + } + + [WinFormsTheory] + [InlineData(true)] + [InlineData(false)] + public void TabControlAccessibleObject_GetPropertyValue_IsEnabledPropertyId_ReturnsTrue(bool enabled) + { + using TabControl tabControl = new TabControl() { Enabled = enabled }; + + TabControlAccessibleObject accessibleObject = Assert.IsType(tabControl.AccessibilityObject); + + Assert.Equal(enabled, (bool)accessibleObject.GetPropertyValue(UIA.IsEnabledPropertyId)); + Assert.False(tabControl.IsHandleCreated); + } + + [WinFormsTheory] + [InlineData(true)] + [InlineData(false)] + public void TabControlAccessibleObject_GetPropertyValue_NativeWindowHandlePropertyId_ReturnsTrue(bool createControl) + { + using TabControl tabControl = new TabControl(); + + if (createControl) + { + tabControl.CreateControl(); + } + + TabControlAccessibleObject accessibleObject = Assert.IsType(tabControl.AccessibilityObject); + + Assert.Equal(tabControl.InternalHandle, (IntPtr)accessibleObject.GetPropertyValue(UIA.NativeWindowHandlePropertyId)); + Assert.Equal(createControl, tabControl.IsHandleCreated); + } + + [WinFormsTheory] + [InlineData(true, "&Name", "Alt+n")] + [InlineData(false, "&Name", "Alt+n")] + [InlineData(true, "Name", null)] + [InlineData(false, "Name", null)] + public void TabControlAccessibleObject_KeyboardShortcut_ReturnExpected(bool createControl, string text, string expectedKeyboardShortcut) + { + using TabControl tabControl = new() { Text = text }; + + if (createControl) + { + tabControl.CreateControl(); + } + + TabControlAccessibleObject accessibleObject = Assert.IsType(tabControl.AccessibilityObject); + + Assert.Equal(expectedKeyboardShortcut, accessibleObject.KeyboardShortcut); + Assert.Equal(createControl, tabControl.IsHandleCreated); + } + + [WinFormsTheory] + [InlineData(true, "&Name", "Alt+n")] + [InlineData(false, "&Name", "Alt+n")] + [InlineData(true, "Name", null)] + [InlineData(false, "Name", null)] + public void TabControlAccessibleObject_GetPropertyValue_AccessKey_ReturnExpected(bool createControl, string text, string expectedKeyboardShortcut) + { + using TabControl tabControl = new() { Text = text }; + + if (createControl) + { + tabControl.CreateControl(); + } + + TabControlAccessibleObject accessibleObject = Assert.IsType(tabControl.AccessibilityObject); + + Assert.Equal(expectedKeyboardShortcut, accessibleObject.GetPropertyValue(UIA.AccessKeyPropertyId)); + Assert.Equal(createControl, tabControl.IsHandleCreated); + } } } diff --git a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/TabPage.TabAccessibleObjectTests.cs b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/TabPage.TabAccessibleObjectTests.cs new file mode 100644 index 00000000000..182d200e354 --- /dev/null +++ b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/TabPage.TabAccessibleObjectTests.cs @@ -0,0 +1,1135 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Xunit; +using static Interop; +using static Interop.UiaCore; +using static System.Windows.Forms.TabControl; +using static System.Windows.Forms.TabPage; + +namespace System.Windows.Forms.Tests +{ + public class TabPage_TabAccessibleObjectTests : IClassFixture + { + [WinFormsTheory] + [InlineData(true, false)] + [InlineData(false, true)] + public void TabAccessibleObject_Bounds_ReturnsExpected(bool createControl, bool boundsIsEmpty) + { + using TabControl tabControl = new(); + TabPageCollection pages = tabControl.TabPages; + pages.Add(new TabPage()); + + if (createControl) + { + tabControl.CreateControl(); + } + + TabAccessibleObject accessibleObject = Assert.IsType(pages[0].TabAccessibilityObject); + + Assert.Equal(boundsIsEmpty, accessibleObject.Bounds.IsEmpty); + Assert.Equal(createControl, pages[0].IsHandleCreated); + Assert.Equal(createControl, tabControl.IsHandleCreated); + } + + [WinFormsTheory] + [InlineData(null, "")] + [InlineData("", "")] + [InlineData("Test", "Test")] + public void TabAccessibleObject_Name_ReturnsTabPageText(string text, string expectedText) + { + using TabControl tabControl = new(); + TabPageCollection pages = tabControl.TabPages; + pages.Add(new TabPage() { Text = text, Name = "Test" }); + + TabAccessibleObject accessibleObject = Assert.IsType(pages[0].TabAccessibilityObject); + + Assert.Equal(expectedText, accessibleObject.Name); + Assert.False(pages[0].IsHandleCreated); + Assert.False(tabControl.IsHandleCreated); + } + + [WinFormsFact] + public void TabAccessibleObject_DefaultAction_ReturnsNull_IfHandleIsNotCreated() + { + using TabControl tabControl = new TabControl(); + TabPageCollection pages = tabControl.TabPages; + pages.Add(new TabPage()); + + TabAccessibleObject accessibleObject = Assert.IsType(pages[0].TabAccessibilityObject); + + Assert.Null(accessibleObject.DefaultAction); + Assert.False(pages[0].IsHandleCreated); + Assert.False(tabControl.IsHandleCreated); + } + + [WinFormsFact] + public void TabAccessibleObject_DefaultAction_Returns_NotEmptyString_IfHandleIsCreated() + { + using TabControl tabControl = new(); + TabPageCollection pages = tabControl.TabPages; + pages.Add(new TabPage()); + tabControl.CreateControl(); + + TabAccessibleObject accessibleObject = Assert.IsType(pages[0].TabAccessibilityObject); + + Assert.NotEmpty(accessibleObject.DefaultAction); + Assert.True(pages[0].IsHandleCreated); + Assert.True(tabControl.IsHandleCreated); + } + + [WinFormsTheory] + [InlineData(true, AccessibleRole.PageTab)] + [InlineData(false, AccessibleRole.None)] + public void TabAccessibleObject_Role_ReturnsNone_IfHandleIsNotCreated(bool createControl, AccessibleRole expectedAccessibleRole) + { + using TabControl tabControl = new(); + TabPageCollection pages = tabControl.TabPages; + pages.Add(new TabPage()); + + if (createControl) + { + tabControl.CreateControl(); + } + + TabAccessibleObject accessibleObject = Assert.IsType(pages[0].TabAccessibilityObject); + + Assert.Equal(expectedAccessibleRole, accessibleObject.Role); + Assert.Equal(createControl, pages[0].IsHandleCreated); + Assert.Equal(createControl, tabControl.IsHandleCreated); + } + + [WinFormsTheory] + [InlineData(true, true)] + [InlineData(true, false)] + [InlineData(false, true)] + [InlineData(false, false)] + public void TabAccessibleObject_State_ReturnsExpected_IfHandleIsCreated(bool tabControlEnabled, bool tabPageEnabled) + { + using TabControl tabControl = new() { Enabled = tabControlEnabled }; + TabPageCollection pages = tabControl.TabPages; + pages.AddRange(new TabPage[] { new() { Enabled = tabPageEnabled }, new() { Enabled = tabPageEnabled } } ); + tabControl.CreateControl(); + + TabAccessibleObject accessibleObject1 = Assert.IsType(pages[0].TabAccessibilityObject); + TabAccessibleObject accessibleObject2 = Assert.IsType(pages[1].TabAccessibilityObject); + + Assert.Equal(AccessibleStates.Focusable | AccessibleStates.Selectable | AccessibleStates.Selected, accessibleObject1.State); + Assert.Equal(AccessibleStates.Focusable | AccessibleStates.Selectable, accessibleObject2.State); + Assert.True(pages[0].IsHandleCreated); + Assert.False(pages[1].IsHandleCreated); + Assert.True(tabControl.IsHandleCreated); + } + + [WinFormsFact] + public void TabAccessibleObject_State_ReturnsNone_IfHandleIsNotCreated() + { + using TabControl tabControl = new(); + TabPageCollection pages = tabControl.TabPages; + pages.Add(new TabPage()); + + TabAccessibleObject accessibleObject = Assert.IsType(pages[0].TabAccessibilityObject); + + Assert.Equal(AccessibleStates.None, accessibleObject.State); + Assert.False(pages[0].IsHandleCreated); + Assert.False(tabControl.IsHandleCreated); + } + + [WinFormsFact] + public void TabAccessibleObject_FragmentRoot_ReturnsTabControlAccessibleObject() + { + using TabControl tabControl = new(); + TabPageCollection pages = tabControl.TabPages; + pages.Add(new TabPage()); + + TabAccessibleObject accessibleObject = Assert.IsType(pages[0].TabAccessibilityObject); + + Assert.Equal(tabControl.AccessibilityObject, accessibleObject.FragmentRoot); + Assert.False(pages[0].IsHandleCreated); + Assert.False(tabControl.IsHandleCreated); + } + + [WinFormsFact] + public void TabAccessibleObject_FragmentNavigate_ReturnsNull_IfHandleIsNotCreated() + { + using TabControl tabControl = new(); + TabPageCollection pages = tabControl.TabPages; + pages.AddRange(new TabPage[] { new(), new() }); + + TabAccessibleObject accessibleObject1 = Assert.IsType(pages[0].TabAccessibilityObject); + TabAccessibleObject accessibleObject2 = Assert.IsType(pages[1].TabAccessibilityObject); + + Assert.Null(accessibleObject1.FragmentNavigate(UiaCore.NavigateDirection.Parent)); + Assert.Null(accessibleObject1.FragmentNavigate(UiaCore.NavigateDirection.NextSibling)); + Assert.Null(accessibleObject1.FragmentNavigate(UiaCore.NavigateDirection.PreviousSibling)); + Assert.Null(accessibleObject1.FragmentNavigate(UiaCore.NavigateDirection.FirstChild)); + Assert.Null(accessibleObject1.FragmentNavigate(UiaCore.NavigateDirection.LastChild)); + + Assert.Null(accessibleObject2.FragmentNavigate(UiaCore.NavigateDirection.Parent)); + Assert.Null(accessibleObject2.FragmentNavigate(UiaCore.NavigateDirection.NextSibling)); + Assert.Null(accessibleObject2.FragmentNavigate(UiaCore.NavigateDirection.PreviousSibling)); + Assert.Null(accessibleObject2.FragmentNavigate(UiaCore.NavigateDirection.FirstChild)); + Assert.Null(accessibleObject2.FragmentNavigate(UiaCore.NavigateDirection.LastChild)); + Assert.False(pages[0].IsHandleCreated); + Assert.False(pages[1].IsHandleCreated); + Assert.False(tabControl.IsHandleCreated); + } + + [WinFormsFact] + public void TabAccessibleObject_FragmentNavigate_Parent_ReturnsTabControlAccessibleObject() + { + using TabControl tabControl = new(); + TabPageCollection pages = tabControl.TabPages; + pages.Add(new TabPage()); + tabControl.CreateControl(); + + TabAccessibleObject accessibleObject = Assert.IsType(pages[0].TabAccessibilityObject); + + Assert.Equal(tabControl.AccessibilityObject, accessibleObject.FragmentNavigate(UiaCore.NavigateDirection.Parent)); + Assert.True(pages[0].IsHandleCreated); + Assert.True(tabControl.IsHandleCreated); + } + + [WinFormsFact] + public void TabAccessibleObject_FragmentNavigate_Sibling_ReturnsExpected() + { + using TabControl tabControl = new(); + TabPageCollection pages = tabControl.TabPages; + pages.AddRange(new TabPage[] { new(), new() }); + tabControl.CreateControl(); + + TabAccessibleObject accessibleObject1 = Assert.IsType(pages[0].TabAccessibilityObject); + TabAccessibleObject accessibleObject2 = Assert.IsType(pages[1].TabAccessibilityObject); + + Assert.Equal(pages[0].AccessibilityObject, accessibleObject1.FragmentNavigate(UiaCore.NavigateDirection.PreviousSibling)); + Assert.Equal(accessibleObject2, accessibleObject1.FragmentNavigate(UiaCore.NavigateDirection.NextSibling)); + + Assert.Equal(accessibleObject1, accessibleObject2.FragmentNavigate(UiaCore.NavigateDirection.PreviousSibling)); + Assert.Null(accessibleObject2.FragmentNavigate(UiaCore.NavigateDirection.NextSibling)); + Assert.True(pages[0].IsHandleCreated); + Assert.False(pages[1].IsHandleCreated); + Assert.True(tabControl.IsHandleCreated); + } + + [WinFormsFact] + public void TabAccessibleObject_FragmentNavigate_Sibling_ReturnsExpected_AfterChaningSelectedTab() + { + using TabControl tabControl = new(); + TabPageCollection pages = tabControl.TabPages; + pages.AddRange(new TabPage[] { new(), new() }); + tabControl.CreateControl(); + + TabAccessibleObject accessibleObject1 = Assert.IsType(pages[0].TabAccessibilityObject); + TabAccessibleObject accessibleObject2 = Assert.IsType(pages[1].TabAccessibilityObject); + + Assert.Equal(pages[0].AccessibilityObject, accessibleObject1.FragmentNavigate(UiaCore.NavigateDirection.PreviousSibling)); + Assert.Equal(accessibleObject2, accessibleObject1.FragmentNavigate(UiaCore.NavigateDirection.NextSibling)); + Assert.Equal(accessibleObject1, accessibleObject2.FragmentNavigate(UiaCore.NavigateDirection.PreviousSibling)); + Assert.Null(accessibleObject2.FragmentNavigate(UiaCore.NavigateDirection.NextSibling)); + + tabControl.SelectedIndex = 1; + + Assert.Equal(pages[1].AccessibilityObject, accessibleObject1.FragmentNavigate(UiaCore.NavigateDirection.PreviousSibling)); + Assert.Equal(accessibleObject2, accessibleObject1.FragmentNavigate(UiaCore.NavigateDirection.NextSibling)); + Assert.Equal(accessibleObject1, accessibleObject2.FragmentNavigate(UiaCore.NavigateDirection.PreviousSibling)); + Assert.Null(accessibleObject2.FragmentNavigate(UiaCore.NavigateDirection.NextSibling)); + Assert.True(pages[0].IsHandleCreated); + Assert.True(pages[1].IsHandleCreated); + Assert.True(tabControl.IsHandleCreated); + } + + [WinFormsFact] + public void TabAccessibleObject_Supports_LegacyIAccessiblePattern() + { + using TabControl tabControl = new(); + TabPageCollection pages = tabControl.TabPages; + pages.Add(new TabPage()); + + TabAccessibleObject accessibleObject = Assert.IsType(pages[0].TabAccessibilityObject); + + Assert.True(accessibleObject.IsPatternSupported(UiaCore.UIA.LegacyIAccessiblePatternId)); + Assert.False(pages[0].IsHandleCreated); + Assert.False(tabControl.IsHandleCreated); + } + + [WinFormsFact] + public void TabAccessibleObject_GetPropertyValue_IsLegacyIAccessiblePatternAvailable_ReturnsTrue() + { + using TabControl tabControl = new(); + TabPageCollection pages = tabControl.TabPages; + pages.Add(new TabPage()); + + TabAccessibleObject accessibleObject = Assert.IsType(pages[0].TabAccessibilityObject); + + Assert.True((bool)accessibleObject.GetPropertyValue(UIA.IsLegacyIAccessiblePatternAvailablePropertyId)); + Assert.False(pages[0].IsHandleCreated); + Assert.False(tabControl.IsHandleCreated); + } + + [WinFormsFact] + public void TabAccessibleObject_Supports_SelectionItemPattern() + { + using TabControl tabControl = new(); + TabPageCollection pages = tabControl.TabPages; + pages.Add(new TabPage()); + + TabAccessibleObject accessibleObject = Assert.IsType(pages[0].TabAccessibilityObject); + + Assert.True(accessibleObject.IsPatternSupported(UiaCore.UIA.SelectionItemPatternId)); + Assert.False(pages[0].IsHandleCreated); + Assert.False(tabControl.IsHandleCreated); + } + + [WinFormsFact] + public void TabAccessibleObject_GetPropertyValue_IsSelectionItemPatternAvailable_ReturnsTrue() + { + using TabControl tabControl = new(); + TabPageCollection pages = tabControl.TabPages; + pages.Add(new TabPage()); + + TabAccessibleObject accessibleObject = Assert.IsType(pages[0].TabAccessibilityObject); + + Assert.True((bool)accessibleObject.GetPropertyValue(UIA.IsSelectionItemPatternAvailablePropertyId)); + Assert.False(pages[0].IsHandleCreated); + Assert.False(tabControl.IsHandleCreated); + } + + [WinFormsFact] + public void TabAccessibleObject_DoesNotSupport_InvokePattern() + { + using TabControl tabControl = new(); + TabPageCollection pages = tabControl.TabPages; + pages.Add(new TabPage()); + + TabAccessibleObject accessibleObject = Assert.IsType(pages[0].TabAccessibilityObject); + + Assert.False(accessibleObject.IsPatternSupported(UiaCore.UIA.InvokePatternId)); + Assert.False(pages[0].IsHandleCreated); + Assert.False(tabControl.IsHandleCreated); + } + + [WinFormsFact] + public void TabAccessibleObject_GetPropertyValue_IsInvokePatternPatternAvailable_ReturnsTrue() + { + using TabControl tabControl = new(); + TabPageCollection pages = tabControl.TabPages; + pages.Add(new TabPage()); + + TabAccessibleObject accessibleObject = Assert.IsType(pages[0].TabAccessibilityObject); + + Assert.False((bool)accessibleObject.GetPropertyValue(UIA.IsInvokePatternAvailablePropertyId)); + Assert.False(pages[0].IsHandleCreated); + Assert.False(tabControl.IsHandleCreated); + } + + [WinFormsFact] + public void TabAccessibleObject_DoDefaultAction_WorksCorrectly() + { + using TabControl tabControl = new(); + TabPageCollection pages = tabControl.TabPages; + pages.AddRange(new TabPage[] { new(), new() }); + tabControl.CreateControl(); + + TabAccessibleObject accessibleObject = Assert.IsType(pages[1].TabAccessibilityObject); + + Assert.Equal(0, tabControl.SelectedIndex); + + accessibleObject.DoDefaultAction(); + + Assert.Equal(1, tabControl.SelectedIndex); + Assert.True(pages[0].IsHandleCreated); + Assert.True(pages[1].IsHandleCreated); + Assert.True(tabControl.IsHandleCreated); + } + + [WinFormsFact] + public void TabAccessibleObject_DoDefaultAction_DoesNotAffectTabControl_IfHandleIsNotCreated() + { + using TabControl tabControl = new(); + TabPageCollection pages = tabControl.TabPages; + pages.AddRange(new TabPage[] { new(), new() }); + + TabAccessibleObject accessibleObject = Assert.IsType(pages[1].TabAccessibilityObject); + + Assert.Equal(-1, tabControl.SelectedIndex); + + accessibleObject.DoDefaultAction(); + + Assert.Equal(-1, tabControl.SelectedIndex); + Assert.False(pages[0].IsHandleCreated); + Assert.False(pages[1].IsHandleCreated); + Assert.False(tabControl.IsHandleCreated); + } + + [WinFormsFact] + public void TabAccessibleObject_DoDefaultAction_DoesNotAffectTabControl_IfTabControlIsDisabled() + { + using TabControl tabControl = new() { Enabled = false }; + TabPageCollection pages = tabControl.TabPages; + pages.AddRange(new TabPage[] { new(), new() }); + tabControl.CreateControl(); + + TabAccessibleObject accessibleObject = Assert.IsType(pages[1].TabAccessibilityObject); + + Assert.Equal(0, tabControl.SelectedIndex); + + accessibleObject.DoDefaultAction(); + + Assert.Equal(0, tabControl.SelectedIndex); + Assert.True(pages[0].IsHandleCreated); + Assert.False(pages[1].IsHandleCreated); + Assert.True(tabControl.IsHandleCreated); + } + + [WinFormsFact] + public void TabAccessibleObject_SelectItem_WorksCorrectly() + { + using TabControl tabControl = new(); + TabPageCollection pages = tabControl.TabPages; + pages.AddRange(new TabPage[] { new(), new() }); + tabControl.CreateControl(); + + TabAccessibleObject accessibleObject = Assert.IsType(pages[1].TabAccessibilityObject); + + Assert.Equal(0, tabControl.SelectedIndex); + + accessibleObject.SelectItem(); + + Assert.Equal(1, tabControl.SelectedIndex); + Assert.True(pages[0].IsHandleCreated); + Assert.True(pages[1].IsHandleCreated); + Assert.True(tabControl.IsHandleCreated); + } + + [WinFormsFact] + public void TabAccessibleObject_SelectItem_DoesNotAffectTabControl_IfHandleIsNotCreated() + { + using TabControl tabControl = new(); + TabPageCollection pages = tabControl.TabPages; + pages.AddRange(new TabPage[] { new(), new() }); + + TabAccessibleObject accessibleObject = Assert.IsType(pages[1].TabAccessibilityObject); + + Assert.Equal(-1, tabControl.SelectedIndex); + + accessibleObject.SelectItem(); + + Assert.Equal(-1, tabControl.SelectedIndex); + Assert.False(pages[0].IsHandleCreated); + Assert.False(pages[1].IsHandleCreated); + Assert.False(tabControl.IsHandleCreated); + } + + [WinFormsFact] + public void TabAccessibleObject_SelectItem_DoesNotAffectTabControl_IfTabControlIsDisabled() + { + using TabControl tabControl = new() { Enabled = false }; + TabPageCollection pages = tabControl.TabPages; + pages.AddRange(new TabPage[] { new(), new() }); + tabControl.CreateControl(); + + TabAccessibleObject accessibleObject = Assert.IsType(pages[1].TabAccessibilityObject); + + Assert.Equal(0, tabControl.SelectedIndex); + + accessibleObject.SelectItem(); + + Assert.Equal(0, tabControl.SelectedIndex); + Assert.True(pages[0].IsHandleCreated); + Assert.False(pages[1].IsHandleCreated); + Assert.True(tabControl.IsHandleCreated); + } + + [WinFormsFact] + public void TabAccessibleObject_AddToSelection_WorksCorrectly() + { + using TabControl tabControl = new(); + TabPageCollection pages = tabControl.TabPages; + pages.AddRange(new TabPage[] { new(), new() }); + tabControl.CreateControl(); + + TabAccessibleObject accessibleObject = Assert.IsType(pages[1].TabAccessibilityObject); + + Assert.Equal(0, tabControl.SelectedIndex); + + accessibleObject.AddToSelection(); + + Assert.Equal(1, tabControl.SelectedIndex); + Assert.True(pages[0].IsHandleCreated); + Assert.True(pages[1].IsHandleCreated); + Assert.True(tabControl.IsHandleCreated); + } + + [WinFormsFact] + public void TabAccessibleObject_AddToSelection__DoesNotAffectTabControl_IfHandleIsNotCreated() + { + using TabControl tabControl = new(); + TabPageCollection pages = tabControl.TabPages; + pages.AddRange(new TabPage[] { new(), new() }); + + TabAccessibleObject accessibleObject = Assert.IsType(pages[1].TabAccessibilityObject); + + Assert.Equal(-1, tabControl.SelectedIndex); + + accessibleObject.AddToSelection(); + + Assert.Equal(-1, tabControl.SelectedIndex); + Assert.False(pages[0].IsHandleCreated); + Assert.False(pages[1].IsHandleCreated); + Assert.False(tabControl.IsHandleCreated); + } + + [WinFormsFact] + public void TabAccessibleObject_AddToSelection_DoesNotAffectTabControl_IfTabControlIsDisabled() + { + using TabControl tabControl = new() { Enabled = false }; + TabPageCollection pages = tabControl.TabPages; + pages.AddRange(new TabPage[] { new(), new() }); + tabControl.CreateControl(); + + TabAccessibleObject accessibleObject = Assert.IsType(pages[1].TabAccessibilityObject); + + Assert.Equal(0, tabControl.SelectedIndex); + + accessibleObject.AddToSelection(); + + Assert.Equal(0, tabControl.SelectedIndex); + Assert.True(pages[0].IsHandleCreated); + Assert.False(pages[1].IsHandleCreated); + Assert.True(tabControl.IsHandleCreated); + } + + [WinFormsTheory] + [InlineData(true, 0)] + [InlineData(false, -1)] + public void TabAccessibleObject_RemoveFromSelection_DoesNotAffectTabControl(bool createControl, int expectedIndex) + { + using TabControl tabControl = new(); + TabPageCollection pages = tabControl.TabPages; + pages.AddRange(new TabPage[] { new(), new() }); + + if (createControl) + { + tabControl.CreateControl(); + } + + TabAccessibleObject accessibleObject = Assert.IsType(pages[0].TabAccessibilityObject); + + Assert.Equal(expectedIndex, tabControl.SelectedIndex); + + accessibleObject.RemoveFromSelection(); + + Assert.Equal(expectedIndex, tabControl.SelectedIndex); + Assert.Equal(createControl, pages[0].IsHandleCreated); + Assert.False(pages[1].IsHandleCreated); + Assert.Equal(createControl, tabControl.IsHandleCreated); + } + + [WinFormsTheory] + [InlineData(true)] + [InlineData(false)] + public void TabAccessibleObject_ItemSelectionContainer_ReturnsTabControlAccessibleObject(bool createControl) + { + using TabControl tabControl = new(); + TabPageCollection pages = tabControl.TabPages; + pages.AddRange(new TabPage[] { new(), new() }); + + if (createControl) + { + tabControl.CreateControl(); + } + + TabAccessibleObject accessibleObject = Assert.IsType(pages[0].TabAccessibilityObject); + + Assert.Equal(tabControl.AccessibilityObject, accessibleObject.ItemSelectionContainer); + Assert.Equal(createControl, pages[0].IsHandleCreated); + Assert.False(pages[1].IsHandleCreated); + Assert.Equal(createControl, tabControl.IsHandleCreated); + } + + [WinFormsFact] + public void TabAccessibleObject_ItemIsSelected_ReturnsExpected_IfHandleIsCreated() + { + using TabControl tabControl = new(); + TabPageCollection pages = tabControl.TabPages; + pages.AddRange(new TabPage[] { new(), new() }); + tabControl.CreateControl(); + + TabAccessibleObject accessibleObject1 = Assert.IsType(pages[0].TabAccessibilityObject); + TabAccessibleObject accessibleObject2 = Assert.IsType(pages[1].TabAccessibilityObject); + + Assert.True(accessibleObject1.IsItemSelected); + Assert.False(accessibleObject2.IsItemSelected); + + tabControl.SelectedIndex = 1; + + Assert.False(accessibleObject1.IsItemSelected); + Assert.True(accessibleObject2.IsItemSelected); + Assert.True(pages[0].IsHandleCreated); + Assert.True(pages[1].IsHandleCreated); + Assert.True(tabControl.IsHandleCreated); + } + + [WinFormsFact] + public void TabAccessibleObject_ItemIsSelected_ReturnsFalse_IfHandleIsNotCreated() + { + using TabControl tabControl = new(); + TabPageCollection pages = tabControl.TabPages; + pages.AddRange(new TabPage[] { new(), new() }); + + TabAccessibleObject accessibleObject1 = Assert.IsType(pages[0].TabAccessibilityObject); + TabAccessibleObject accessibleObject2 = Assert.IsType(pages[1].TabAccessibilityObject); + + Assert.False(accessibleObject1.IsItemSelected); + Assert.False(accessibleObject2.IsItemSelected); + Assert.False(pages[0].IsHandleCreated); + Assert.False(pages[1].IsHandleCreated); + Assert.False(tabControl.IsHandleCreated); + } + + [WinFormsTheory] + [InlineData(true)] + [InlineData(false)] + public void TabAccessibleObject_DoDefaultAction_InvokeRaiseAutomationEvent(bool tabPageEnabled) + { + using TabControl tabControl = new(); + TabPageCollection pages = tabControl.TabPages; + tabControl.CreateControl(); + pages.AddRange(new TabPage[] { new(), new() { Enabled = tabPageEnabled } } ); + + SubTabAccessibleObject tabAccessibleObject = new(pages[1]); + pages[1].TestAccessor().Dynamic._tabAccessibilityObject = tabAccessibleObject; + + Assert.IsType(tabControl.AccessibilityObject); + + pages[1].TabAccessibilityObject.DoDefaultAction(); + + Assert.Equal(1, tabAccessibleObject.CallSelectionItemEventCount); + Assert.Equal(1, tabAccessibleObject.CallFocusChangedEventCount); + Assert.True(pages[0].IsHandleCreated); + Assert.True(pages[1].IsHandleCreated); + Assert.True(tabControl.IsHandleCreated); + } + + [WinFormsFact] + public void TabAccessibleObject_DoDefaultAction_DoesNotInvoke_RaiseAutomationEvent_IfTabAlreadySelected() + { + using TabControl tabControl = new(); + TabPageCollection pages = tabControl.TabPages; + tabControl.CreateControl(); + pages.AddRange(new TabPage[] { new(), new() }); + + SubTabAccessibleObject tabAccessibleObject = new(pages[0]); + pages[0].TestAccessor().Dynamic._tabAccessibilityObject = tabAccessibleObject; + + Assert.IsType(tabControl.AccessibilityObject); + + pages[0].TabAccessibilityObject.DoDefaultAction(); + + Assert.Equal(0, tabAccessibleObject.CallSelectionItemEventCount); + Assert.Equal(0, tabAccessibleObject.CallFocusChangedEventCount); + Assert.True(pages[0].IsHandleCreated); + Assert.True(pages[1].IsHandleCreated); + Assert.True(tabControl.IsHandleCreated); + } + + [WinFormsFact] + public void TabAccessibleObject_DoDefaultAction_DoesNotInvoke_RaiseAutomationEvent_IfAccessibleObjectIsNotCreated() + { + using TabControl tabControl = new(); + TabPageCollection pages = tabControl.TabPages; + tabControl.CreateControl(); + pages.AddRange(new TabPage[] { new(), new() }); + + SubTabAccessibleObject tabAccessibleObject = new(pages[0]); + pages[0].TestAccessor().Dynamic._tabAccessibilityObject = tabAccessibleObject; + + pages[0].TabAccessibilityObject.DoDefaultAction(); + + Assert.Equal(0, tabAccessibleObject.CallSelectionItemEventCount); + Assert.Equal(0, tabAccessibleObject.CallFocusChangedEventCount); + Assert.True(pages[0].IsHandleCreated); + Assert.True(pages[1].IsHandleCreated); + Assert.True(tabControl.IsHandleCreated); + } + + [WinFormsTheory] + [InlineData(true)] + [InlineData(false)] + public void TabAccessibleObject_DoDefaultAction_DoesNotInvoke_RaiseAutomationEvent_IfTabControlIsDisabled(bool tabPageEnabled) + { + using TabControl tabControl = new() { Enabled = false }; + TabPageCollection pages = tabControl.TabPages; + tabControl.CreateControl(); + pages.AddRange(new TabPage[] { new(), new() { Enabled = tabPageEnabled } }); + + SubTabAccessibleObject tabAccessibleObject = new(pages[1]); + pages[1].TestAccessor().Dynamic._tabAccessibilityObject = tabAccessibleObject; + + Assert.IsType(tabControl.AccessibilityObject); + + pages[1].TabAccessibilityObject.DoDefaultAction(); + + Assert.Equal(0, tabAccessibleObject.CallSelectionItemEventCount); + Assert.Equal(0, tabAccessibleObject.CallFocusChangedEventCount); + Assert.True(pages[0].IsHandleCreated); + Assert.True(pages[1].IsHandleCreated); + Assert.True(tabControl.IsHandleCreated); + } + + [WinFormsFact] + public void TabAccessibleObject_SetSelectedTab_InvokeRaiseAutomationEvent() + { + using TabControl tabControl = new(); + TabPageCollection pages = tabControl.TabPages; + tabControl.CreateControl(); + pages.AddRange(new TabPage[] { new(), new() }); + + Assert.IsType(tabControl.AccessibilityObject); + + SubTabAccessibleObject tabAccessibleObject = new(pages[1]); + pages[1].TestAccessor().Dynamic._tabAccessibilityObject = tabAccessibleObject; + + tabControl.SelectedTab = pages[1]; + + Assert.Equal(1, tabAccessibleObject.CallSelectionItemEventCount); + Assert.Equal(1, tabAccessibleObject.CallFocusChangedEventCount); + Assert.True(pages[0].IsHandleCreated); + Assert.True(pages[1].IsHandleCreated); + Assert.True(tabControl.IsHandleCreated); + } + + [WinFormsFact] + public void TabAccessibleObject_SetSelectedTab_DoesNotInvoke_RaiseAutomationEvent_IfAccessibleObjectIsNotCreated() + { + using TabControl tabControl = new(); + TabPageCollection pages = tabControl.TabPages; + tabControl.CreateControl(); + pages.AddRange(new TabPage[] { new(), new() }); + + SubTabAccessibleObject tabAccessibleObject = new(pages[1]); + pages[1].TestAccessor().Dynamic._tabAccessibilityObject = tabAccessibleObject; + + tabControl.SelectedTab = pages[1]; + + Assert.Equal(0, tabAccessibleObject.CallSelectionItemEventCount); + Assert.Equal(0, tabAccessibleObject.CallFocusChangedEventCount); + Assert.True(pages[0].IsHandleCreated); + Assert.True(pages[1].IsHandleCreated); + Assert.True(tabControl.IsHandleCreated); + } + + [WinFormsFact] + public void TabAccessibleObject_SetSelectedTab_DoesNotInvoke_RaiseAutomationEvent_IfTabAlreadySelected() + { + using TabControl tabControl = new(); + TabPageCollection pages = tabControl.TabPages; + tabControl.CreateControl(); + pages.AddRange(new TabPage[] { new(), new() }); + + SubTabAccessibleObject tabAccessibleObject = new(pages[0]); + pages[0].TestAccessor().Dynamic._tabAccessibilityObject = tabAccessibleObject; + + Assert.IsType(tabControl.AccessibilityObject); + + tabControl.SelectedTab = pages[0]; + + Assert.Equal(0, tabAccessibleObject.CallSelectionItemEventCount); + Assert.Equal(0, tabAccessibleObject.CallFocusChangedEventCount); + Assert.True(pages[0].IsHandleCreated); + Assert.True(pages[1].IsHandleCreated); + Assert.True(tabControl.IsHandleCreated); + } + + [WinFormsFact] + public void TabAccessibleObject_SetSelectedIndex_InvokeRaiseAutomationEvent() + { + using TabControl tabControl = new(); + TabPageCollection pages = tabControl.TabPages; + tabControl.CreateControl(); + pages.AddRange(new TabPage[] { new(), new() }); + + SubTabAccessibleObject tabAccessibleObject = new(pages[1]); + pages[1].TestAccessor().Dynamic._tabAccessibilityObject = tabAccessibleObject; + + Assert.IsType(tabControl.AccessibilityObject); + + tabControl.SelectedIndex = 1; + + Assert.Equal(1, tabAccessibleObject.CallSelectionItemEventCount); + Assert.Equal(1, tabAccessibleObject.CallFocusChangedEventCount); + Assert.True(pages[0].IsHandleCreated); + Assert.True(pages[1].IsHandleCreated); + Assert.True(tabControl.IsHandleCreated); + } + + [WinFormsFact] + public void TabAccessibleObject_SetSelectedIndex_DoesNotInvoke_RaiseAutomationEvent_IfAccessibleObjectIsNotCreated() + { + using TabControl tabControl = new(); + TabPageCollection pages = tabControl.TabPages; + tabControl.CreateControl(); + pages.AddRange(new TabPage[] { new(), new() }); + + SubTabAccessibleObject tabAccessibleObject = new(pages[1]); + pages[1].TestAccessor().Dynamic._tabAccessibilityObject = tabAccessibleObject; + + tabControl.SelectedIndex = 1; + + Assert.Equal(0, tabAccessibleObject.CallSelectionItemEventCount); + Assert.Equal(0, tabAccessibleObject.CallFocusChangedEventCount); + Assert.True(pages[0].IsHandleCreated); + Assert.True(pages[1].IsHandleCreated); + Assert.True(tabControl.IsHandleCreated); + } + + [WinFormsFact] + public void TabAccessibleObject_SetSelectedIndex_DoesNotInvoke_RaiseAutomationEvent_IfTabAlreadySelected() + { + using TabControl tabControl = new(); + TabPageCollection pages = tabControl.TabPages; + tabControl.CreateControl(); + pages.AddRange(new TabPage[] { new(), new() }); + + SubTabAccessibleObject tabAccessibleObject = new(pages[0]); + pages[0].TestAccessor().Dynamic._tabAccessibilityObject = tabAccessibleObject; + + Assert.IsType(tabControl.AccessibilityObject); + + tabControl.SelectedIndex = 0; + + Assert.Equal(0, tabAccessibleObject.CallSelectionItemEventCount); + Assert.Equal(0, tabAccessibleObject.CallFocusChangedEventCount); + Assert.True(pages[0].IsHandleCreated); + Assert.True(pages[1].IsHandleCreated); + Assert.True(tabControl.IsHandleCreated); + } + + [WinFormsFact] + public void TabAccessibleObject_OnGotFocus_InvokeTabAccessibleObject_RaiseAutomationEvent() + { + using SubTabControl tabControl = new(); + TabPageCollection pages = tabControl.TabPages; + tabControl.CreateControl(); + pages.AddRange(new TabPage[] { new(), new() }); + + SubTabAccessibleObject tabAccessibleObject = new(pages[0]); + pages[0].TestAccessor().Dynamic._tabAccessibilityObject = tabAccessibleObject; + + Assert.IsType(tabControl.AccessibilityObject); + + tabControl.OnGotFocus(); + + Assert.Equal(1, tabAccessibleObject.CallFocusChangedEventCount); + Assert.True(pages[0].IsHandleCreated); + Assert.True(tabControl.IsHandleCreated); + } + + [WinFormsFact] + public void TabAccessibleObject_OnGotFocus_DoesNotInvoke_RaiseAutomationEvent_IfControlTabAccessibleObjectIsNotCreated() + { + using SubTabControl tabControl = new(); + TabPageCollection pages = tabControl.TabPages; + tabControl.CreateControl(); + pages.AddRange(new TabPage[] { new(), new() }); + + SubTabAccessibleObject tabAccessibleObject = new(pages[0]); + pages[0].TestAccessor().Dynamic._tabAccessibilityObject = tabAccessibleObject; + + tabControl.OnGotFocus(); + + Assert.Equal(0, tabAccessibleObject.CallFocusChangedEventCount); + Assert.True(pages[0].IsHandleCreated); + Assert.True(tabControl.IsHandleCreated); + } + + [WinFormsTheory] + [InlineData(true)] + [InlineData(false)] + public void TabAccessibleObject_AddToSelection_InvokeRaiseAutomationEvent(bool tabPageEnabled) + { + using TabControl tabControl = new(); + TabPageCollection pages = tabControl.TabPages; + tabControl.CreateControl(); + pages.AddRange(new TabPage[] { new(), new() { Enabled = tabPageEnabled } }); + + SubTabAccessibleObject tabAccessibleObject = new(pages[1]); + pages[1].TestAccessor().Dynamic._tabAccessibilityObject = tabAccessibleObject; + + Assert.IsType(tabControl.AccessibilityObject); + + pages[1].TabAccessibilityObject.AddToSelection(); + + Assert.Equal(1, tabAccessibleObject.CallSelectionItemEventCount); + Assert.Equal(1, tabAccessibleObject.CallFocusChangedEventCount); + Assert.True(pages[0].IsHandleCreated); + Assert.True(pages[1].IsHandleCreated); + Assert.True(tabControl.IsHandleCreated); + } + + [WinFormsFact] + public void TabAccessibleObject_AddToSelection_DoesNotInvoke_RaiseAutomationEvent_IfAccessibleObjectIsNotCreated() + { + using TabControl tabControl = new(); + TabPageCollection pages = tabControl.TabPages; + tabControl.CreateControl(); + pages.AddRange(new TabPage[] { new(), new() }); + + SubTabAccessibleObject tabAccessibleObject = new(pages[0]); + pages[0].TestAccessor().Dynamic._tabAccessibilityObject = tabAccessibleObject; + + pages[0].TabAccessibilityObject.AddToSelection(); + + Assert.Equal(0, tabAccessibleObject.CallSelectionItemEventCount); + Assert.Equal(0, tabAccessibleObject.CallFocusChangedEventCount); + Assert.True(pages[0].IsHandleCreated); + Assert.True(pages[1].IsHandleCreated); + Assert.True(tabControl.IsHandleCreated); + } + + [WinFormsFact] + public void TabAccessibleObject_AddToSelection_DoesNotInvoke_RaiseAutomationEvent_IfTabAlreadySelected() + { + using TabControl tabControl = new(); + TabPageCollection pages = tabControl.TabPages; + tabControl.CreateControl(); + pages.AddRange(new TabPage[] { new(), new() }); + + SubTabAccessibleObject tabAccessibleObject = new(pages[0]); + pages[0].TestAccessor().Dynamic._tabAccessibilityObject = tabAccessibleObject; + + pages[0].TabAccessibilityObject.AddToSelection(); + + Assert.Equal(0, tabAccessibleObject.CallSelectionItemEventCount); + Assert.Equal(0, tabAccessibleObject.CallFocusChangedEventCount); + Assert.True(pages[0].IsHandleCreated); + Assert.True(pages[1].IsHandleCreated); + Assert.True(tabControl.IsHandleCreated); + } + + [WinFormsTheory] + [InlineData(true)] + [InlineData(false)] + public void TabAccessibleObject_AddToSelection_DoesNotInvoke_RaiseAutomationEvent_IfTabControlIsDisabled(bool tabPageEnabled) + { + using TabControl tabControl = new() { Enabled = false }; + TabPageCollection pages = tabControl.TabPages; + tabControl.CreateControl(); + pages.AddRange(new TabPage[] { new() { Enabled = tabPageEnabled }, new() }); + + SubTabAccessibleObject tabAccessibleObject = new(pages[0]); + pages[0].TestAccessor().Dynamic._tabAccessibilityObject = tabAccessibleObject; + + Assert.IsType(tabControl.AccessibilityObject); + + pages[0].TabAccessibilityObject.AddToSelection(); + + Assert.Equal(0, tabAccessibleObject.CallSelectionItemEventCount); + Assert.Equal(0, tabAccessibleObject.CallFocusChangedEventCount); + Assert.True(pages[0].IsHandleCreated); + Assert.True(pages[1].IsHandleCreated); + Assert.True(tabControl.IsHandleCreated); + } + + [WinFormsTheory] + [InlineData(true)] + [InlineData(false)] + public void TabAccessibleObject_SelectItem_InvokeRaiseAutomationEvent(bool tabPageEnabled) + { + using TabControl tabControl = new(); + TabPageCollection pages = tabControl.TabPages; + tabControl.CreateControl(); + pages.AddRange(new TabPage[] { new(), new() { Enabled = tabPageEnabled } }); + + SubTabAccessibleObject tabAccessibleObject = new(pages[1]); + pages[1].TestAccessor().Dynamic._tabAccessibilityObject = tabAccessibleObject; + + Assert.IsType(tabControl.AccessibilityObject); + + pages[1].TabAccessibilityObject.SelectItem(); + + Assert.Equal(1, tabAccessibleObject.CallSelectionItemEventCount); + Assert.Equal(1, tabAccessibleObject.CallFocusChangedEventCount); + Assert.True(pages[0].IsHandleCreated); + Assert.True(pages[1].IsHandleCreated); + Assert.True(tabControl.IsHandleCreated); + } + + [WinFormsFact] + public void TabAccessibleObject_SelectItem_DoesNotInvoke_RaiseAutomationEvent_IfAccessibleObjectIsNotCreated() + { + using TabControl tabControl = new(); + TabPageCollection pages = tabControl.TabPages; + tabControl.CreateControl(); + pages.AddRange(new TabPage[] { new(), new() }); + + SubTabAccessibleObject tabAccessibleObject = new(pages[0]); + pages[0].TestAccessor().Dynamic._tabAccessibilityObject = tabAccessibleObject; + + pages[0].TabAccessibilityObject.SelectItem(); + + Assert.Equal(0, tabAccessibleObject.CallSelectionItemEventCount); + Assert.Equal(0, tabAccessibleObject.CallFocusChangedEventCount); + Assert.True(pages[0].IsHandleCreated); + Assert.True(pages[1].IsHandleCreated); + Assert.True(tabControl.IsHandleCreated); + } + + [WinFormsFact] + public void TabAccessibleObject_SelectItem_DoesNotInvoke_RaiseAutomationEvent_IfTabAlreadySelected() + { + using TabControl tabControl = new(); + TabPageCollection pages = tabControl.TabPages; + tabControl.CreateControl(); + pages.AddRange(new TabPage[] { new(), new() }); + + SubTabAccessibleObject tabAccessibleObject = new(pages[0]); + pages[0].TestAccessor().Dynamic._tabAccessibilityObject = tabAccessibleObject; + + Assert.IsType(tabControl.AccessibilityObject); + + pages[0].TabAccessibilityObject.SelectItem(); + + Assert.Equal(0, tabAccessibleObject.CallSelectionItemEventCount); + Assert.Equal(0, tabAccessibleObject.CallFocusChangedEventCount); + Assert.True(pages[0].IsHandleCreated); + Assert.True(pages[1].IsHandleCreated); + Assert.True(tabControl.IsHandleCreated); + } + + [WinFormsTheory] + [InlineData(true)] + [InlineData(false)] + public void TabAccessibleObject_SelectItem_DoesNotInvoke_RaiseAutomationEvent_IfTabControlIsDisabled(bool tabPageEnabled) + { + using TabControl tabControl = new() { Enabled = false }; + TabPageCollection pages = tabControl.TabPages; + tabControl.CreateControl(); + pages.AddRange(new TabPage[] { new(), new() { Enabled = tabPageEnabled } }); + + SubTabAccessibleObject tabAccessibleObject = new(pages[1]); + pages[1].TestAccessor().Dynamic._tabAccessibilityObject = tabAccessibleObject; + + Assert.IsType(tabControl.AccessibilityObject); + + pages[1].TabAccessibilityObject.SelectItem(); + + Assert.Equal(0, tabAccessibleObject.CallSelectionItemEventCount); + Assert.Equal(0, tabAccessibleObject.CallFocusChangedEventCount); + Assert.True(pages[0].IsHandleCreated); + Assert.True(pages[1].IsHandleCreated); + Assert.True(tabControl.IsHandleCreated); + } + + [WinFormsTheory] + [InlineData(true)] + [InlineData(false)] + public void TabAccessibleObject_RuntimeId_ReturnsExpected(bool createControl) + { + using TabControl tabControl = new(); + TabPageCollection pages = tabControl.TabPages; + + if (createControl) + { + tabControl.CreateControl(); + } + + pages.AddRange(new TabPage[] { new TabPage(), new TabPage() }); + TabAccessibleObject accessibleObject1 = Assert.IsType(pages[0].TabAccessibilityObject); + TabAccessibleObject accessibleObject2 = Assert.IsType(pages[1].TabAccessibilityObject); + + Assert.NotNull(accessibleObject1.RuntimeId); + Assert.Equal(tabControl.HandleInternal, (IntPtr)accessibleObject1.RuntimeId[1]); + Assert.Equal(accessibleObject1.GetChildId(), accessibleObject1.RuntimeId[2]); + Assert.NotNull(accessibleObject2.RuntimeId); + Assert.Equal(tabControl.HandleInternal, (IntPtr)accessibleObject2.RuntimeId[1]); + Assert.Equal(accessibleObject2.GetChildId(), accessibleObject2.RuntimeId[2]); + Assert.Equal(createControl, pages[0].IsHandleCreated); + Assert.Equal(createControl, pages[1].IsHandleCreated); + Assert.Equal(createControl, tabControl.IsHandleCreated); + } + + [WinFormsTheory] + [InlineData(true, true, true)] + [InlineData(true, false, true)] + [InlineData(false, true, false)] + [InlineData(false, false, false)] + public void TabAccessibleObject_GetPropertyValue_IsEnabledPropertyId_ReturnsExpected(bool tabControlEnabled, bool tabPageEnabled, bool expectedEnabled) + { + using TabControl tabControl = new() { Enabled = tabControlEnabled }; + TabPageCollection pages = tabControl.TabPages; + pages.Add(new TabPage() { Enabled = tabPageEnabled }); + + Assert.IsType(tabControl.AccessibilityObject); + TabAccessibleObject accessibleObject = Assert.IsType(pages[0].TabAccessibilityObject); + + Assert.Equal(expectedEnabled, (bool)accessibleObject.GetPropertyValue(UIA.IsEnabledPropertyId)); + Assert.False(pages[0].IsHandleCreated); + Assert.False(tabControl.IsHandleCreated); + } + + [WinFormsFact] + public void TabAccessibleObject_GetPropertyValue_IsKeyboardFocusablePropertyId_ReturnsTrue() + { + using TabControl tabControl = new(); + TabPageCollection pages = tabControl.TabPages; + pages.Add(new TabPage()); + + Assert.IsType(tabControl.AccessibilityObject); + TabAccessibleObject accessibleObject = Assert.IsType(pages[0].TabAccessibilityObject); + + Assert.True((bool)accessibleObject.GetPropertyValue(UIA.IsKeyboardFocusablePropertyId)); + Assert.False(pages[0].IsHandleCreated); + Assert.False(tabControl.IsHandleCreated); + } + + [WinFormsFact] + public void TabAccessibleObject_GetPropertyValue_HasKeyboardFocusPropertyId_ReturnsTrue() + { + using TabControl tabControl = new(); + TabPageCollection pages = tabControl.TabPages; + pages.Add(new TabPage()); + + Assert.IsType(tabControl.AccessibilityObject); + TabAccessibleObject accessibleObject = Assert.IsType(pages[0].TabAccessibilityObject); + + Assert.False((bool)accessibleObject.GetPropertyValue(UIA.HasKeyboardFocusPropertyId)); + Assert.False(pages[0].IsHandleCreated); + Assert.False(tabControl.IsHandleCreated); + } + + private class SubTabControl : TabControl + { + internal void OnGotFocus() => base.OnGotFocus(EventArgs.Empty); + } + + private class SubTabAccessibleObject : TabAccessibleObject + { + internal SubTabAccessibleObject(TabPage owningTabPage) : base(owningTabPage) + { + } + + internal int CallSelectionItemEventCount { get; private set; } + + internal int CallFocusChangedEventCount { get; private set; } + + internal override bool RaiseAutomationEvent(UiaCore.UIA eventId) + { + switch (eventId) + { + case UiaCore.UIA.SelectionItem_ElementSelectedEventId: + CallSelectionItemEventCount++; + break; + case UiaCore.UIA.AutomationFocusChangedEventId: + CallFocusChangedEventCount++; + break; + default: + break; + } + + return base.RaiseAutomationEvent(eventId); + } + } + } +} diff --git a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/TabPage.TabPageAccessibleObjectTests.cs b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/TabPage.TabPageAccessibleObjectTests.cs index 13e14719f2d..79b41d090aa 100644 --- a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/TabPage.TabPageAccessibleObjectTests.cs +++ b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/TabPage.TabPageAccessibleObjectTests.cs @@ -3,7 +3,9 @@ // See the LICENSE file in the project root for more information. using Xunit; -using static Interop; +using static Interop.UiaCore; +using static System.Windows.Forms.TabControl; +using static System.Windows.Forms.TabPage; namespace System.Windows.Forms.Tests { @@ -12,7 +14,7 @@ public class TabPage_TabPageAccessibilityObjectTests : IClassFixture TabPageAccessibleObject_GetPropertyValue_ControlType_IsExpected_ForCustomRole_TestData() @@ -64,14 +69,414 @@ public static IEnumerable TabPageAccessibleObject_GetPropertyValue_Con [MemberData(nameof(TabPageAccessibleObject_GetPropertyValue_ControlType_IsExpected_ForCustomRole_TestData))] public void TabPageAccessibleObject_GetPropertyValue_ControlType_IsExpected_ForCustomRole(AccessibleRole role) { - using TabPage tabPage = new TabPage(); + using TabPage tabPage = new(); tabPage.AccessibleRole = role; - object actual = tabPage.AccessibilityObject.GetPropertyValue(UiaCore.UIA.ControlTypePropertyId); - UiaCore.UIA expected = AccessibleRoleControlTypeMap.GetControlType(role); + object actual = tabPage.AccessibilityObject.GetPropertyValue(UIA.ControlTypePropertyId); + UIA expected = AccessibleRoleControlTypeMap.GetControlType(role); Assert.Equal(expected, actual); Assert.False(tabPage.IsHandleCreated); } + + [WinFormsTheory] + [InlineData(true, false)] + [InlineData(false, true)] + public void TabPageAccessibleObject_Bounds_ReturnsExpected(bool createControl, bool boundsIsEmpty) + { + using TabPage tabPage = new(); + + if (createControl) + { + tabPage.CreateControl(); + } + + TabPageAccessibleObject accessibleObject = Assert.IsType(tabPage.AccessibilityObject); + + Assert.Equal(boundsIsEmpty, accessibleObject.Bounds.IsEmpty); + Assert.Equal(createControl, tabPage.IsHandleCreated); + } + + [WinFormsTheory] + [InlineData("Accessible Name", "Text", "Accessible Name")] + [InlineData("", "Text", "")] + [InlineData(null, "Text", "Text")] + [InlineData(null, null, null)] + public void TabPageAccessibleObject_Name_ReturnsExpected(string accessibleName, string tabPageText, string expectedName) + { + using TabPage tabPage = new() + { + AccessibleName = accessibleName, + Text = tabPageText, + Name = "Name", + }; + + TabPageAccessibleObject accessibleObject = Assert.IsType(tabPage.AccessibilityObject); + + Assert.Equal(expectedName, accessibleObject.Name); + Assert.False(tabPage.IsHandleCreated); + } + + [WinFormsTheory] + [InlineData("Test")] + [InlineData("")] + [InlineData(null)] + public void TabPageAccessibleObject_Description_ReturnsExpected(string accessibleDescription) + { + using TabPage tabPage = new(); + tabPage.AccessibleDescription = accessibleDescription; + + TabPageAccessibleObject accessibleObject = Assert.IsType(tabPage.AccessibilityObject); + + Assert.Equal(accessibleDescription, accessibleObject.Description); + Assert.False(tabPage.IsHandleCreated); + } + + [WinFormsTheory] + [InlineData(true)] + [InlineData(false)] + public void TabPageAccessibleObject_RuntimeId_ReturnsExpected(bool createControl) + { + using TabPage tabPage = new(); + + if (createControl) + { + tabPage.CreateControl(); + } + + Assert.NotNull(tabPage.AccessibilityObject.RuntimeId); + Assert.Equal(tabPage.HandleInternal, (IntPtr)tabPage.AccessibilityObject.RuntimeId[1]); + Assert.Equal(createControl, tabPage.IsHandleCreated); + } + + [WinFormsTheory] + [InlineData("Test")] + [InlineData("")] + [InlineData(null)] + public void TabPageAccessibleObject_AccessibleDefaultActionDescription_ReturnsExpected(string accessibleDefaultActionDescription) + { + using TabPage tabPage = new(); + tabPage.AccessibleDefaultActionDescription = accessibleDefaultActionDescription; + + TabPageAccessibleObject accessibleObject = Assert.IsType(tabPage.AccessibilityObject); + + Assert.Equal(accessibleDefaultActionDescription, accessibleObject.DefaultAction); + Assert.False(tabPage.IsHandleCreated); + } + + [WinFormsTheory] + [InlineData(true, true, AccessibleStates.Focusable)] + [InlineData(true, false, AccessibleStates.Focusable | AccessibleStates.Unavailable)] + [InlineData(false, true, AccessibleStates.None)] + [InlineData(false, false, AccessibleStates.None)] + public void TabPageAccessibleObject_State_ReturnExpected(bool createControl, bool enabled, AccessibleStates expectedAccessibleStates) + { + using TabPage tabPage = new() { Enabled = enabled }; + + if (createControl) + { + tabPage.CreateControl(); + } + + TabPageAccessibleObject accessibleObject = Assert.IsType(tabPage.AccessibilityObject); + + Assert.Equal(expectedAccessibleStates, accessibleObject.State); + Assert.Equal(createControl, tabPage.IsHandleCreated); + } + + [WinFormsFact] + public void TabPageAccessibleObject_FragmentNaviage_ReturnsNull_IfTabPageHasNotTabControl() + { + using TabPage tabPage = new(); + tabPage.CreateControl(); + + TabPageAccessibleObject accessibleObject = Assert.IsType(tabPage.AccessibilityObject); + + Assert.Null(accessibleObject.FragmentNavigate(NavigateDirection.Parent)); + Assert.Null(accessibleObject.FragmentNavigate(NavigateDirection.NextSibling)); + Assert.Null(accessibleObject.FragmentNavigate(NavigateDirection.PreviousSibling)); + Assert.Null(accessibleObject.FragmentNavigate(NavigateDirection.FirstChild)); + Assert.Null(accessibleObject.FragmentNavigate(NavigateDirection.LastChild)); + Assert.True(tabPage.IsHandleCreated); + } + + [WinFormsFact] + public void TabPageAccessibleObject_FragmentNaviage_ReturnsNull_IfHandleIsNotCreated() + { + using TabControl tabControl = new(); + TabPageCollection pages = tabControl.TabPages; + pages.Add(new TabPage()); + + TabPageAccessibleObject accessibleObject = Assert.IsType(pages[0].AccessibilityObject); + + Assert.Null(accessibleObject.FragmentNavigate(NavigateDirection.Parent)); + Assert.Null(accessibleObject.FragmentNavigate(NavigateDirection.NextSibling)); + Assert.Null(accessibleObject.FragmentNavigate(NavigateDirection.PreviousSibling)); + Assert.Null(accessibleObject.FragmentNavigate(NavigateDirection.FirstChild)); + Assert.Null(accessibleObject.FragmentNavigate(NavigateDirection.LastChild)); + Assert.False(pages[0].IsHandleCreated); + Assert.False(tabControl.IsHandleCreated); + } + + [WinFormsFact] + public void TabPageAccessibleObject_FragmentNaviage_ReturnsExpected_IfSingleItem() + { + using TabControl tabControl = new(); + tabControl.CreateControl(); + TabPageCollection pages = tabControl.TabPages; + pages.Add(new TabPage()); + + TabPageAccessibleObject accessibleObject = Assert.IsType(pages[0].AccessibilityObject); + + Assert.Equal(tabControl.AccessibilityObject, accessibleObject.FragmentNavigate(NavigateDirection.Parent)); + Assert.Equal(pages[0].TabAccessibilityObject, accessibleObject.FragmentNavigate(NavigateDirection.NextSibling)); + Assert.Null(accessibleObject.FragmentNavigate(NavigateDirection.PreviousSibling)); + Assert.Null(accessibleObject.FragmentNavigate(NavigateDirection.FirstChild)); + Assert.Null(accessibleObject.FragmentNavigate(NavigateDirection.LastChild)); + Assert.True(pages[0].IsHandleCreated); + Assert.True(tabControl.IsHandleCreated); + } + + [WinFormsFact] + public void TabPageAccessibleObject_FragmentNaviage_ReturnsExpected_IfThreeItem() + { + using TabControl tabControl = new(); + TabPageCollection pages = tabControl.TabPages; + pages.AddRange(new TabPage[] { new(), new(), new() }); + tabControl.CreateControl(); + + TabPageAccessibleObject accessibleObject = Assert.IsType(pages[0].AccessibilityObject); + + Assert.Equal(tabControl.AccessibilityObject, accessibleObject.FragmentNavigate(NavigateDirection.Parent)); + Assert.Equal(pages[0].TabAccessibilityObject, accessibleObject.FragmentNavigate(NavigateDirection.NextSibling)); + Assert.Null(accessibleObject.FragmentNavigate(NavigateDirection.PreviousSibling)); + Assert.Null(accessibleObject.FragmentNavigate(NavigateDirection.FirstChild)); + Assert.Null(accessibleObject.FragmentNavigate(NavigateDirection.LastChild)); + Assert.True(pages[0].IsHandleCreated); + Assert.False(pages[1].IsHandleCreated); + Assert.False(pages[2].IsHandleCreated); + Assert.True(tabControl.IsHandleCreated); + } + + [WinFormsFact] + public void TabPageAccessibleObject_FragmentNaviage_ReturnsExpected_AfterChaningSelectedTab() + { + using TabControl tabControl = new(); + tabControl.CreateControl(); + TabPageCollection pages = tabControl.TabPages; + pages.AddRange(new TabPage[] { new(), new(), new() }); + + TabPageAccessibleObject accessibleObject1 = Assert.IsType(pages[0].AccessibilityObject); + TabPageAccessibleObject accessibleObject2 = Assert.IsType(pages[1].AccessibilityObject); + TabPageAccessibleObject accessibleObject3 = Assert.IsType(pages[2].AccessibilityObject); + + // First tab is selected + Assert.Equal(tabControl.AccessibilityObject, accessibleObject1.FragmentNavigate(NavigateDirection.Parent)); + Assert.Equal(pages[0].TabAccessibilityObject, accessibleObject1.FragmentNavigate(NavigateDirection.NextSibling)); + Assert.Null(accessibleObject1.FragmentNavigate(NavigateDirection.PreviousSibling)); + Assert.Null(accessibleObject1.FragmentNavigate(NavigateDirection.FirstChild)); + Assert.Null(accessibleObject1.FragmentNavigate(NavigateDirection.LastChild)); + + Assert.Equal(tabControl.AccessibilityObject, accessibleObject2.FragmentNavigate(NavigateDirection.Parent)); + Assert.Null(accessibleObject2.FragmentNavigate(NavigateDirection.NextSibling)); + Assert.Null(accessibleObject2.FragmentNavigate(NavigateDirection.PreviousSibling)); + Assert.Null(accessibleObject2.FragmentNavigate(NavigateDirection.FirstChild)); + Assert.Null(accessibleObject2.FragmentNavigate(NavigateDirection.LastChild)); + + Assert.Equal(tabControl.AccessibilityObject, accessibleObject3.FragmentNavigate(NavigateDirection.Parent)); + Assert.Null(accessibleObject3.FragmentNavigate(NavigateDirection.NextSibling)); + Assert.Null(accessibleObject3.FragmentNavigate(NavigateDirection.PreviousSibling)); + Assert.Null(accessibleObject3.FragmentNavigate(NavigateDirection.FirstChild)); + Assert.Null(accessibleObject3.FragmentNavigate(NavigateDirection.LastChild)); + + // Second tab is selected + tabControl.SelectedIndex = 1; + + Assert.Equal(tabControl.AccessibilityObject, accessibleObject1.FragmentNavigate(NavigateDirection.Parent)); + Assert.Null(accessibleObject1.FragmentNavigate(NavigateDirection.NextSibling)); + Assert.Null(accessibleObject1.FragmentNavigate(NavigateDirection.PreviousSibling)); + Assert.Null(accessibleObject1.FragmentNavigate(NavigateDirection.FirstChild)); + Assert.Null(accessibleObject1.FragmentNavigate(NavigateDirection.LastChild)); + + Assert.Equal(tabControl.AccessibilityObject, accessibleObject2.FragmentNavigate(NavigateDirection.Parent)); + Assert.Equal(pages[0].TabAccessibilityObject, accessibleObject2.FragmentNavigate(NavigateDirection.NextSibling)); + Assert.Null(accessibleObject2.FragmentNavigate(NavigateDirection.PreviousSibling)); + Assert.Null(accessibleObject2.FragmentNavigate(NavigateDirection.FirstChild)); + Assert.Null(accessibleObject2.FragmentNavigate(NavigateDirection.LastChild)); + + Assert.Equal(tabControl.AccessibilityObject, accessibleObject3.FragmentNavigate(NavigateDirection.Parent)); + Assert.Null(accessibleObject3.FragmentNavigate(NavigateDirection.NextSibling)); + Assert.Null(accessibleObject3.FragmentNavigate(NavigateDirection.PreviousSibling)); + Assert.Null(accessibleObject3.FragmentNavigate(NavigateDirection.FirstChild)); + Assert.Null(accessibleObject3.FragmentNavigate(NavigateDirection.LastChild)); + + // Third tab is selected + tabControl.SelectedIndex = 2; + + Assert.Equal(tabControl.AccessibilityObject, accessibleObject1.FragmentNavigate(NavigateDirection.Parent)); + Assert.Null(accessibleObject1.FragmentNavigate(NavigateDirection.NextSibling)); + Assert.Null(accessibleObject1.FragmentNavigate(NavigateDirection.PreviousSibling)); + Assert.Null(accessibleObject1.FragmentNavigate(NavigateDirection.FirstChild)); + Assert.Null(accessibleObject1.FragmentNavigate(NavigateDirection.LastChild)); + + Assert.Equal(tabControl.AccessibilityObject, accessibleObject2.FragmentNavigate(NavigateDirection.Parent)); + Assert.Null(accessibleObject2.FragmentNavigate(NavigateDirection.NextSibling)); + Assert.Null(accessibleObject2.FragmentNavigate(NavigateDirection.PreviousSibling)); + Assert.Null(accessibleObject2.FragmentNavigate(NavigateDirection.FirstChild)); + Assert.Null(accessibleObject2.FragmentNavigate(NavigateDirection.LastChild)); + + Assert.Equal(tabControl.AccessibilityObject, accessibleObject3.FragmentNavigate(NavigateDirection.Parent)); + Assert.Equal(pages[0].TabAccessibilityObject, accessibleObject3.FragmentNavigate(NavigateDirection.NextSibling)); + Assert.Null(accessibleObject3.FragmentNavigate(NavigateDirection.PreviousSibling)); + Assert.Null(accessibleObject3.FragmentNavigate(NavigateDirection.FirstChild)); + Assert.Null(accessibleObject3.FragmentNavigate(NavigateDirection.LastChild)); + + Assert.True(pages[0].IsHandleCreated); + Assert.True(pages[1].IsHandleCreated); + Assert.True(pages[2].IsHandleCreated); + Assert.True(tabControl.IsHandleCreated); + } + + [WinFormsFact] + public void TabPageAccessibleObject_Supports_LegacyIAccessiblePattern() + { + using TabPage tabPage = new(); + + TabPageAccessibleObject accessibleObject = Assert.IsType(tabPage.AccessibilityObject); + + Assert.True(accessibleObject.IsPatternSupported(UIA.LegacyIAccessiblePatternId)); + Assert.False(tabPage.IsHandleCreated); + } + + [WinFormsFact] + public void TabPageAccessibleObject_DoesNotSupports_ValuePattern() + { + using TabPage tabPage = new(); + + TabPageAccessibleObject accessibleObject = Assert.IsType(tabPage.AccessibilityObject); + + Assert.False(accessibleObject.IsPatternSupported(UIA.ValuePatternId)); + Assert.False(tabPage.IsHandleCreated); + } + + [WinFormsFact] + public void TabPageAccessibleObject_GetPropertyValue_IsLegacyIAccessiblePatternAvailable_ReturnsTrue() + { + using TabPage tabPage = new(); + + TabPageAccessibleObject accessibleObject = Assert.IsType(tabPage.AccessibilityObject); + + Assert.True((bool)accessibleObject.GetPropertyValue(UIA.IsLegacyIAccessiblePatternAvailablePropertyId)); + Assert.False(tabPage.IsHandleCreated); + } + + [WinFormsFact] + public void TabPageAccessibleObject_GetPropertyValue_IsValuePatternAvailable_ReturnsFalse() + { + using TabPage tabPage = new(); + + TabPageAccessibleObject accessibleObject = Assert.IsType(tabPage.AccessibilityObject); + + Assert.False((bool)accessibleObject.GetPropertyValue(UIA.IsValuePatternAvailablePropertyId)); + Assert.False(tabPage.IsHandleCreated); + } + + [WinFormsFact] + public void TabPageAccessibleObject_GetPropertyValue_HasKeyboardFocusPropertyId_ReturnsFalse() + { + using TabPage tabPage = new(); + + TabPageAccessibleObject accessibleObject = Assert.IsType(tabPage.AccessibilityObject); + + Assert.False((bool)accessibleObject.GetPropertyValue(UIA.HasKeyboardFocusPropertyId)); + Assert.False(tabPage.IsHandleCreated); + } + + [WinFormsFact] + public void TabPageAccessibleObject_GetPropertyValue_IsKeyboardFocusablePropertyId_ReturnsTrue() + { + using TabPage tabPage = new(); + + TabPageAccessibleObject accessibleObject = Assert.IsType(tabPage.AccessibilityObject); + + Assert.True((bool)accessibleObject.GetPropertyValue(UIA.IsKeyboardFocusablePropertyId)); + Assert.False(tabPage.IsHandleCreated); + } + + [WinFormsTheory] + [InlineData(true, true, true)] + [InlineData(true, false, false)] + [InlineData(false, true, false)] + [InlineData(false, false, false)] + public void TabPageAccessibleObject_GetPropertyValue_IsEnabledPropertyId_ReturnsExpected(bool tabControlEnabled, bool tabPageEnabled, bool expectedEnabled) + { + using TabControl tabControl = new() { Enabled = tabControlEnabled }; + TabPageCollection pages = tabControl.TabPages; + pages.Add(new TabPage() { Enabled = tabPageEnabled }); + + TabPageAccessibleObject accessibleObject = Assert.IsType(pages[0].AccessibilityObject); + + Assert.Equal(expectedEnabled, (bool)accessibleObject.GetPropertyValue(UIA.IsEnabledPropertyId)); + Assert.False(pages[0].IsHandleCreated); + Assert.False(tabControl.IsHandleCreated); + } + + [WinFormsTheory] + [InlineData(true)] + [InlineData(false)] + public void TabPageAccessibleObject_GetPropertyValue_NativeWindowHandlePropertyId_ReturnsTrue(bool createControl) + { + using TabPage tabPage = new(); + + if (createControl) + { + tabPage.CreateControl(); + } + + TabPageAccessibleObject accessibleObject = Assert.IsType(tabPage.AccessibilityObject); + + Assert.Equal(tabPage.InternalHandle, (IntPtr)accessibleObject.GetPropertyValue(UIA.NativeWindowHandlePropertyId)); + Assert.Equal(createControl, tabPage.IsHandleCreated); + } + + [WinFormsTheory] + [InlineData(true, "&Name", "Alt+n")] + [InlineData(false, "&Name", "Alt+n")] + [InlineData(true, "Name", null)] + [InlineData(false, "Name", null)] + public void TabPageAccessibleObject_KeyboardShortcut_ReturnExpected(bool createControl, string text, string expectedKeyboardShortcut) + { + using TabPage tabPage = new() { Text = text }; + + if (createControl) + { + tabPage.CreateControl(); + } + + TabPageAccessibleObject accessibleObject = Assert.IsType(tabPage.AccessibilityObject); + + Assert.Equal(expectedKeyboardShortcut, accessibleObject.KeyboardShortcut); + Assert.Equal(createControl, tabPage.IsHandleCreated); + } + + [WinFormsTheory] + [InlineData(true, "&Name", "Alt+n")] + [InlineData(false, "&Name", "Alt+n")] + [InlineData(true, "Name", null)] + [InlineData(false, "Name", null)] + public void TabPageAccessibleObject_GetPropertyValue_AccessKey_ReturnExpected(bool createControl, string text, string expectedKeyboardShortcut) + { + using TabPage tabPage = new() { Text = text }; + + if (createControl) + { + tabPage.CreateControl(); + } + + TabPageAccessibleObject accessibleObject = Assert.IsType(tabPage.AccessibilityObject); + + Assert.Equal(expectedKeyboardShortcut, accessibleObject.GetPropertyValue(UIA.AccessKeyPropertyId)); + Assert.Equal(createControl, tabPage.IsHandleCreated); + } } }