Skip to content

Commit

Permalink
fix: Downgrade SiblingUniqueAndFocusable to NeedsReview for Win32 apps
Browse files Browse the repository at this point in the history
Due to a large number of false positives (and given the fact that Win32 applications don't support UIA natively), this commit downgrades `SiblingUniqueAndFocusable` to `NeedsReview` in Win32 applications.

Addresses #1046. Supersedes #1038. Addresses microsoft/accessibility-insights-windows#1838.
  • Loading branch information
codeofdusk committed Sep 14, 2024
1 parent 6d27481 commit cd88bf9
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 5 deletions.
1 change: 1 addition & 0 deletions docs/RulesDescription.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ ButtonInvokeAndTogglePatterns | Error | A button must not support both the Invok
ButtonInvokeAndExpandCollapsePatterns | Warning | A button may have the Invoke and ExpandCollapse patterns together, but it is not recommended. If possible, please have only one of them. | WCAG 1.3.1 InfoAndRelationships
ButtonToggleAndExpandCollapsePatterns | Error | A button must not support both the Toggle and ExpandCollapse patterns. | WCAG 4.1.2 NameRoleValue
SiblingUniqueAndFocusable | Error | Focusable sibling elements must not have the same Name and LocalizedControlType. | WCAG 4.1.2 NameRoleValue
SiblingUniqueAndFocusableWin32 | NeedsReview | Focusable sibling elements must not have the same Name and LocalizedControlType. | WCAG 4.1.2 NameRoleValue
SiblingUniqueAndNotFocusable | NeedsReview | The given element has siblings with the same Name and LocalizedControlType. | WCAG 4.1.2 NameRoleValue
ChildrenNotAllowedInContentView | Error | A separator must not have any children with IsContentElement set to true. | Section 508 502.3.1 ObjectInformation
ContentViewButtonStructure | NeedsReview | The given element is expected to have the following structure: Button and NoChild(IsContentElement). | WCAG 1.3.1 InfoAndRelationships
Expand Down
1 change: 1 addition & 0 deletions src/Core/Enums/RuleId.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ public enum RuleId
ButtonToggleAndExpandCollapsePatterns, // Button should not have Toggle and ExpandCollapse patterns together.

SiblingUniqueAndFocusable,
SiblingUniqueAndFocusableWin32,
SiblingUniqueAndNotFocusable,

ChildrenNotAllowedInContentView,
Expand Down
8 changes: 3 additions & 5 deletions src/Rules/Library/SiblingUniqueAndFocusable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ private static Condition CreateEligibleChildCondition()
var ExcludedType = DataItem | Image | Pane | ScrollBar | Thumb | TreeItem | ListItem | Hyperlink;

return IsKeyboardFocusable
// #1047: covered by SiblingUniqueAndFocusableWin32
& ~Win32Framework
& IsContentOrControlElement
& ~ExcludedType
& ~Patterns.GridItem
Expand Down Expand Up @@ -63,12 +65,8 @@ protected override Condition CreateCondition()
& WPF
& NoChild(Custom | Name.NullOrEmpty);

var ipAddressControl = Win32Framework & ClassName.Is("SysIPAddress32");

return EligibleChild
& NotParent(wpfDataItem)
// microsoft/accessibility-insights-windows#1838: The Win32 IP address control yields false positives for this rule.
& NotParent(ipAddressControl);
& NotParent(wpfDataItem);
}
} // class
} // namespace
66 changes: 66 additions & 0 deletions src/Rules/Library/SiblingUniqueAndFocusableWin32.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using Axe.Windows.Core.Bases;
using Axe.Windows.Core.Enums;
using Axe.Windows.Core.Exceptions;
using Axe.Windows.Core.Misc;
using Axe.Windows.Rules.PropertyConditions;
using Axe.Windows.Rules.Resources;
using System;
using static Axe.Windows.Rules.PropertyConditions.BoolProperties;
using static Axe.Windows.Rules.PropertyConditions.ControlType;
using static Axe.Windows.Rules.PropertyConditions.Framework;
using static Axe.Windows.Rules.PropertyConditions.Relationships;
using static Axe.Windows.Rules.PropertyConditions.StringProperties;

namespace Axe.Windows.Rules.Library
{
[RuleInfo(ID = RuleId.SiblingUniqueAndFocusableWin32)]
class SiblingUniqueAndFocusableWin32 : Rule
{
private static readonly Condition EligibleChild = CreateEligibleChildCondition();

private static Condition CreateEligibleChildCondition()
{
var ExcludedType = Image | Pane | ScrollBar | Thumb | TreeItem | ListItem | Hyperlink;

return IsKeyboardFocusable
& Win32Framework
& IsContentOrControlElement
& ~ExcludedType
& ~Patterns.GridItem
& ParentExists
& Name.NotNullOrEmpty
& LocalizedControlType.NotNullOrEmpty
& BoundingRectangle.Valid;
}

public SiblingUniqueAndFocusableWin32()
{
Info.Description = Descriptions.SiblingUniqueAndFocusable;
Info.HowToFix = HowToFix.SiblingUniqueAndFocusable;
Info.Standard = A11yCriteriaId.NameRoleValue;
Info.ErrorCode = EvaluationCode.NeedsReview;
}

public override bool PassesTest(IA11yElement e)
{
if (e == null) throw new ArgumentNullException(nameof(e));
if (e.Parent == null) throw new ArgumentException(ErrorMessages.ElementParentNull, nameof(e));

var siblings = SiblingCount(EligibleChild
& Name.Is(e.Name)
& LocalizedControlType.Is(e.LocalizedControlType));
var count = siblings.GetValue(e);
if (count < 1) throw new AxeWindowsException(ErrorMessages.NoElementFound.WithParameters(Info.ID));

return count == 1;
}

protected override Condition CreateCondition()
{
return EligibleChild;
}
}
}

0 comments on commit cd88bf9

Please sign in to comment.