Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(framework-issues-logic): Split IsControlElementTrueRequired into 3 rules #706

Merged
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/RulesDescription.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,8 @@ IsContentElementFalseOptional | NeedsReview | The recommended value of the IsCon
IsContentElementTrueOptional | NeedsReview | The recommended value of the IsContentElement property for the given control type is true. Please consider if this is an element that should be reported to an assistive technology user as content. | Section 508 502.3.1 ObjectInformation
IsControlElementTrueOptional | NeedsReview | The recommended value of the IsControlElement property for the given control type is true. Please consider if this is an element that should be reported to an assistive technology user as a control. Note that almost all controls are required to have the IsControl Property set to true. | Section 508 502.3.1 ObjectInformation
IsControlElementTrueRequired | Error | The given ControlType must have the IsControlElement property set to TRUE. | Section 508 502.3.1 ObjectInformation
IsControlElementTrueRequiredButtonWPF | Error | The given ControlType must have the IsControlElement property set to TRUE. | Section 508 502.3.1 ObjectInformation
IsControlElementTrueRequiredTextInEditXAML | Error | The given ControlType must have the IsControlElement property set to TRUE. | Section 508 502.3.1 ObjectInformation
IsKeyboardFocusableShouldBeTrue | Warning | The IsKeyboardFocusable property for the given element should be true based on its control type. | WCAG 2.1.1 Keyboard
IsKeyboardFocusableFalseButDisabled | NeedsReview | The IsKeyboardFocusable property is false for an element where it would normally be true. However, the IsEnabled property on the element is also false, so the value of IsKeyboardFocusable may be acceptable. | WCAG 2.1.1 Keyboard
IsKeyboardFocusableForListItemShouldBeTrue | Warning | The IsKeyboardFocusable property for the given list item is false, but the element has children that are focusable. The element should probably be focusable instead of its children. | WCAG 2.1.1 Keyboard
Expand Down
2 changes: 2 additions & 0 deletions src/Core/Enums/RuleId.cs
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,8 @@ public enum RuleId
IsContentElementTrueOptional,
IsControlElementTrueOptional,
IsControlElementTrueRequired,
IsControlElementTrueRequiredButtonWPF,
IsControlElementTrueRequiredTextInEditXAML,

IsKeyboardFocusableShouldBeTrue,
IsKeyboardFocusableFalseButDisabled,
Expand Down
5 changes: 4 additions & 1 deletion src/Rules/Library/IsControlElementTrueRequired.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,10 @@ public override bool PassesTest(IA11yElement e)

protected override Condition CreateCondition()
{
return BoundingRectangle.Valid & ElementGroups.IsControlElementTrueRequired;
return BoundingRectangle.Valid
& ElementGroups.IsControlElementTrueRequired
& ~ElementGroups.XAMLTextInEdit
& ~ElementGroups.WPFButton;
}
} // class
} // namespace
40 changes: 40 additions & 0 deletions src/Rules/Library/IsControlElementTrueRequiredButtonWPF.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// 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.Types;
using Axe.Windows.Rules.PropertyConditions;
using Axe.Windows.Rules.Resources;
using System;
using static Axe.Windows.Rules.PropertyConditions.BoolProperties;

namespace Axe.Windows.Rules.Library
{
[RuleInfo(ID = RuleId.IsControlElementTrueRequiredButtonWPF)]
class IsControlElementTrueRequiredButtonWPF : Rule
{
public IsControlElementTrueRequiredButtonWPF()
{
this.Info.Description = Descriptions.IsControlElementTrueRequired;
this.Info.HowToFix = HowToFix.IsControlElementTrueRequired;
this.Info.Standard = A11yCriteriaId.ObjectInformation;
this.Info.PropertyID = PropertyType.UIA_IsControlElementPropertyId;
this.Info.ErrorCode = EvaluationCode.Error;
this.Info.FrameworkIssueLink = "https://aka.ms/FrameworkIssue-IsControlElementTrueRequiredButtonWPF";
}

public override bool PassesTest(IA11yElement e)
{
if (e == null) throw new ArgumentNullException(nameof(e));

return IsControlElement.Matches(e);
}

protected override Condition CreateCondition()
{
return BoundingRectangle.Valid
& ElementGroups.IsControlElementTrueRequired
& ElementGroups.WPFButton;
}
} // class
} // namespace
40 changes: 40 additions & 0 deletions src/Rules/Library/IsControlElementTrueRequiredTextInEditXAML.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// 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.Types;
using Axe.Windows.Rules.PropertyConditions;
using Axe.Windows.Rules.Resources;
using System;
using static Axe.Windows.Rules.PropertyConditions.BoolProperties;

namespace Axe.Windows.Rules.Library
{
[RuleInfo(ID = RuleId.IsControlElementTrueRequiredTextInEditXAML)]
class IsControlElementTrueRequiredTextInEditXAML : Rule
{
public IsControlElementTrueRequiredTextInEditXAML()
{
this.Info.Description = Descriptions.IsControlElementTrueRequired;
this.Info.HowToFix = HowToFix.IsControlElementTrueRequired;
this.Info.Standard = A11yCriteriaId.ObjectInformation;
this.Info.PropertyID = PropertyType.UIA_IsControlElementPropertyId;
this.Info.ErrorCode = EvaluationCode.Error;
this.Info.FrameworkIssueLink = "https://aka.ms/FrameworkIssue-IsControlElementTrueRequiredTextBoxXAML";
}

public override bool PassesTest(IA11yElement e)
{
if (e == null) throw new ArgumentNullException(nameof(e));

return IsControlElement.Matches(e);
}

protected override Condition CreateCondition()
{
return BoundingRectangle.Valid
& ElementGroups.IsControlElementTrueRequired
& ElementGroups.XAMLTextInEdit;
}
} // class
} // namespace
2 changes: 2 additions & 0 deletions src/Rules/PropertyConditions/ElementGroups.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ static class ElementGroups
public static Condition IsButtonText = Text & Parent(Button);
public static Condition ListXAML = List & XAML;
public static Condition HyperlinkInTextXAML = Hyperlink & XAML & Parent(Text);
public static Condition WPFButton = WPF & Button;
public static Condition XAMLTextInEdit = XAML & Text & Parent(Edit);

public static Condition AllowSameNameAndControlType = CreateAllowSameNameAndControlTypeCondition();

Expand Down
129 changes: 129 additions & 0 deletions src/RulesTest/Library/IsControlElementTrueRequiredButtonWPFTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
// 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 Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using System;
using System.Drawing;

namespace Axe.Windows.RulesTests.Library
{
[TestClass]
public class IsControlElementTrueRequiredButtonWPFTests
{
private readonly Rectangle ValidRectangle = new Rectangle(100, 200, 300, 400); // Arbitrary values
private const int NonRequiredControlType = Axe.Windows.Core.Types.ControlType.UIA_PaneControlTypeId;
private const int GenericRequiredControlType = Axe.Windows.Core.Types.ControlType.UIA_ComboBoxControlTypeId;
private const int TextType = Axe.Windows.Core.Types.ControlType.UIA_TextControlTypeId;
private const int ButtonType = Axe.Windows.Core.Types.ControlType.UIA_ButtonControlTypeId;
private const int EditType = Axe.Windows.Core.Types.ControlType.UIA_EditControlTypeId;

private static Rules.IRule Rule = new Rules.Library.IsControlElementTrueRequiredButtonWPF();
private Mock<IA11yElement> _elementMock;
private Mock<IA11yElement> _parentMock;

[TestInitialize]
public void BeforeEach()
{
_elementMock = new Mock<IA11yElement>(MockBehavior.Strict);
_parentMock = new Mock<IA11yElement>(MockBehavior.Strict);
}

private void VerifyAllMocks()
{
_elementMock.VerifyAll();
_parentMock.VerifyAll();
}

[TestMethod]
public void FrameworkIssueLink_IsNotNull()
{
Assert.IsNotNull(Rule.Info.FrameworkIssueLink);
}

[TestMethod]
public void Condition_EmptyBoundingRectangle_ReturnsFalse()
{
_elementMock.Setup(m => m.BoundingRectangle).Returns(Rectangle.Empty);

Assert.IsFalse(Rule.Condition.Matches(_elementMock.Object));

VerifyAllMocks();
}

[TestMethod]
public void Condition_ControlTypeDoesNotRequireControlElement_ReturnsFalse()
{
_elementMock.Setup(m => m.BoundingRectangle).Returns(ValidRectangle);
_elementMock.Setup(m => m.ControlTypeId).Returns(NonRequiredControlType);

Assert.IsFalse(Rule.Condition.Matches(_elementMock.Object));

VerifyAllMocks();
}

[TestMethod]
public void Condition_ControlTypeIsXamlText_ReturnsFalse()
{
_elementMock.Setup(m => m.BoundingRectangle).Returns(ValidRectangle);
_elementMock.Setup(m => m.ControlTypeId).Returns(TextType);
_elementMock.Setup(m => m.Framework).Returns("XAML");

Assert.IsFalse(Rule.Condition.Matches(_elementMock.Object));

VerifyAllMocks();
}

[TestMethod]
public void Condition_ControlTypeIsWpfButton_ReturnsTrue()
{
_elementMock.Setup(m => m.BoundingRectangle).Returns(ValidRectangle);
_elementMock.Setup(m => m.ControlTypeId).Returns(ButtonType);
_elementMock.Setup(m => m.Framework).Returns("WPF");

Assert.IsTrue(Rule.Condition.Matches(_elementMock.Object));

VerifyAllMocks();
}

[TestMethod]
public void Condition_ControlTypeIsGenericRequiredType_ReturnsFalse()
{
_elementMock.Setup(m => m.BoundingRectangle).Returns(ValidRectangle);
_elementMock.Setup(m => m.ControlTypeId).Returns(GenericRequiredControlType);
_elementMock.Setup(m => m.Framework).Returns("A framework");

Assert.IsFalse(Rule.Condition.Matches(_elementMock.Object));

VerifyAllMocks();
}

[TestMethod]
public void PassesTest_ElementIsNull_ThrowsArgumentNullException()
{
ArgumentNullException e = Assert.ThrowsException<ArgumentNullException>(() => Rule.PassesTest(null));

VerifyAllMocks();
}

[TestMethod]
public void PassesTest_IsControlElementIsFalse_ReturnsFalse()
{
_elementMock.Setup(m => m.IsControlElement).Returns(false);

Assert.IsFalse(Rule.PassesTest(_elementMock.Object));

VerifyAllMocks();
}

[TestMethod]
public void PassesTest_IsControlElementIsTrue_ReturnsTrue()
{
_elementMock.Setup(m => m.IsControlElement).Returns(true);

Assert.IsTrue(Rule.PassesTest(_elementMock.Object));

VerifyAllMocks();
}
}
}
125 changes: 125 additions & 0 deletions src/RulesTest/Library/IsControlElementTrueRequiredTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
// 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 Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using System;
using System.Drawing;

namespace Axe.Windows.RulesTests.Library
{
[TestClass]
public class IsControlElementTrueRequiredTests
{
private readonly Rectangle ValidRectangle = new Rectangle(100, 200, 300, 400); // Arbitrary values
private const int NonRequiredControlType = Axe.Windows.Core.Types.ControlType.UIA_PaneControlTypeId;
private const int GenericRequiredControlType = Axe.Windows.Core.Types.ControlType.UIA_ComboBoxControlTypeId;
private const int TextType = Axe.Windows.Core.Types.ControlType.UIA_TextControlTypeId;
private const int ButtonType = Axe.Windows.Core.Types.ControlType.UIA_ButtonControlTypeId;
private const int EditType = Axe.Windows.Core.Types.ControlType.UIA_EditControlTypeId;

private static Rules.IRule Rule = new Rules.Library.IsControlElementTrueRequired();
private Mock<IA11yElement> _elementMock;
private Mock<IA11yElement> _parentMock;

[TestInitialize]
public void BeforeEach()
{
_elementMock = new Mock<IA11yElement>(MockBehavior.Strict);
_parentMock = new Mock<IA11yElement>(MockBehavior.Strict);
}

private void VerifyAllMocks()
{
_elementMock.VerifyAll();
_parentMock.VerifyAll();
}

[TestMethod]
public void Condition_EmptyBoundingRectangle_ReturnsFalse()
{
_elementMock.Setup(m => m.BoundingRectangle).Returns(Rectangle.Empty);

Assert.IsFalse(Rule.Condition.Matches(_elementMock.Object));

VerifyAllMocks();
}

[TestMethod]
public void Condition_ControlTypeDoesNotRequireControlElement_ReturnsFalse()
{
_elementMock.Setup(m => m.BoundingRectangle).Returns(ValidRectangle);
_elementMock.Setup(m => m.ControlTypeId).Returns(NonRequiredControlType);

Assert.IsFalse(Rule.Condition.Matches(_elementMock.Object));

VerifyAllMocks();
}

[TestMethod]
public void Condition_ControlTypeIsXamlTextInEdit_ReturnsFalse()
{
_elementMock.Setup(m => m.BoundingRectangle).Returns(ValidRectangle);
_elementMock.Setup(m => m.ControlTypeId).Returns(TextType);
_elementMock.Setup(m => m.Framework).Returns("XAML");
_parentMock.Setup(m => m.ControlTypeId).Returns(EditType);
_elementMock.Setup(m => m.Parent).Returns(_parentMock.Object);

Assert.IsFalse(Rule.Condition.Matches(_elementMock.Object));

VerifyAllMocks();
}

[TestMethod]
public void Condition_ControlTypeIsWpfButton_ReturnsFalse()
{
_elementMock.Setup(m => m.BoundingRectangle).Returns(ValidRectangle);
_elementMock.Setup(m => m.ControlTypeId).Returns(ButtonType);
_elementMock.Setup(m => m.Framework).Returns("WPF");

Assert.IsFalse(Rule.Condition.Matches(_elementMock.Object));

VerifyAllMocks();
}

[TestMethod]
public void Condition_ControlTypeIsGenericRequiredType_ReturnsTrue()
{
_elementMock.Setup(m => m.BoundingRectangle).Returns(ValidRectangle);
_elementMock.Setup(m => m.ControlTypeId).Returns(GenericRequiredControlType);
_elementMock.Setup(m => m.Framework).Returns("A framework");

Assert.IsTrue(Rule.Condition.Matches(_elementMock.Object));

VerifyAllMocks();
}

[TestMethod]
public void PassesTest_ElementIsNull_ThrowsArgumentNullException()
{
ArgumentNullException e = Assert.ThrowsException<ArgumentNullException>(() => Rule.PassesTest(null));

VerifyAllMocks();
}

[TestMethod]
public void PassesTest_IsControlElementIsFalse_ReturnsFalse()
{
_elementMock.Setup(m => m.IsControlElement).Returns(false);

Assert.IsFalse(Rule.PassesTest(_elementMock.Object));

VerifyAllMocks();
}

[TestMethod]
public void PassesTest_IsControlElementIsTrue_ReturnsTrue()
{
_elementMock.Setup(m => m.IsControlElement).Returns(true);

Assert.IsTrue(Rule.PassesTest(_elementMock.Object));

VerifyAllMocks();
}
}
}
Loading