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

fix(engine): fix issues related to element text calculation #1759

Merged
merged 8 commits into from
Dec 12, 2023
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -2521,13 +2521,14 @@ export class RPTUtil {
public static isInnerTextOnlyEmpty(element) {
// Get the innerText of the element
let text = element.innerText;

if (text === undefined && element.textContent !== undefined) {
// In headless mode, innerText is sometimes 'undefined'

if ((text === undefined || !text || text.trim().length === 0) && element.nodeName.toLowerCase() !== 'slot' && element.textContent !== undefined) {
//ignore slot because its text will be filled by the corresponding content in the light DOM
// innerText is sometimes 'undefined' in headless mode, or null if the element is invisible or not erxpanded
// so we try textContent as a workaround
text = element.textContent
}

let retVal = !(text !== null && text.trim().length > 0);
if (element.nodeType === 1 && element.nodeName.toLowerCase() === "slot") {
//TODO: need to conside its own content, a slot may have its own content or assigned content
Expand Down Expand Up @@ -2642,7 +2643,7 @@ export class RPTUtil {
node.nodeName.toLowerCase() === "svg"
&& RPTUtil.svgHasName(node as any)
);

// Now we check if this node is of type element, visible
if (!hasContent && node.nodeType === 1 && VisUtil.isNodeVisible(node)) {
// Check if the innerText of the element is empty or not
Expand Down
11 changes: 9 additions & 2 deletions accessibility-checker-engine/src/v4/rules/input_label_before.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
limitations under the License.
*****************************************************************************/

import { Rule, RuleResult, RuleFail, RuleContext, RulePotential, RuleManual, RulePass, RuleContextHierarchy } from "../api/IRule";
import { Rule, RuleResult, RuleFail, RuleContext, RulePass, RuleContextHierarchy } from "../api/IRule";
import { eRulePolicy, eToolkitLevel } from "../api/IRule";
import { RPTUtil } from "../../v2/checker/accessibility/util/legacy";

Expand Down Expand Up @@ -58,14 +58,21 @@ export let input_label_before: Rule = {

// Get only the non-hidden labels for element
let labelElem = RPTUtil.getLabelForElementHidden(ruleContext, true);

if (labelElem == null || !RPTUtil.hasInnerContentHidden(labelElem)) {
// Due to dependency, label must be done via title - this rule doesn't apply
return null;
}

let value = RPTUtil.compareNodeOrder(labelElem, ruleContext);
if (value == -2) {
tombrunet marked this conversation as resolved.
Show resolved Hide resolved
// ignore if no label or the content for the label is only from the nested input control
let text = RPTUtil.getInnerText(ruleContext);
if (text && text.trim().length > 0 && RPTUtil.getInnerText(ruleContext).trim() === text.trim()) {
// Due to dependency, label must be done via title - this rule doesn't apply
return null;
}

// input nested in label
let passed = false;
let walkNode = ruleContext.previousSibling;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
limitations under the License.
*****************************************************************************/

import { Rule, RuleResult, RuleFail, RuleContext, RulePotential, RuleManual, RulePass, RuleContextHierarchy } from "../api/IRule";
import { Rule, RuleResult, RuleFail, RuleContext, RulePass, RuleContextHierarchy } from "../api/IRule";
import { eRulePolicy, eToolkitLevel } from "../api/IRule";
import { RPTUtil } from "../../v2/checker/accessibility/util/legacy";
import { FragmentUtil } from "../../v2/checker/accessibility/util/fragment";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ <h3>Input type Tests</h3>
<label for="textarea1">
<span></span>
<textarea id="textarea1" aria-label="textarea1 label" rows="2" cols="50" name="autos">
Text area label is below input control
no Text area label for the input control
</textarea>
</label>

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
<!DOCTYPE html>
<!--
/******************************************************************************
Copyright:: 2020- IBM, Inc

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*****************************************************************************/
-->

<html lang="en-US">
<head>
<title>Shadow DOM input Label</title>
<meta charset="UTF-8" />
</head>
<body>
<main id="main">
<div className="App">
<details>
<summary>Detail summary</summary>
<div>
<label id="1" for="input">
<p>Detail Label Text</p>
</label>
<input id="input" type="text" />
</div>
</details>
<!--details>
<summary>Direct Detail summary</summary>
<div>
<label id="2" for="input">
Direct Detail Label Text
</label>
<input id="input" type="text" />
</div>
</details>
<div>
<summary>Div summary</summary>
<div>
<label id="3" for="input">
<p>Div Label Text</p>
</label>
<input id="input" type="text" />
</div>
</div>
<div>
<summary>Direct Div summary</summary>
<div>
<label id="4" for="input">
<p>Direct Div Label Text</p>
</label>
<input id="input" type="text" />
</div>
</div-->
</div>
</main>
<script type="text/javascript">
UnitTest = {
ruleIds: ["label_content_exists"],
results: [
{
"ruleId": "label_content_exists",
"value": [
"INFORMATION",
"PASS"
],
"path": {
"dom": "/html[1]/body[1]/main[1]/div[1]/details[1]/div[1]/label[1]",
"aria": "/document[1]/main[1]/group[1]"
},
"reasonId": "Pass_Regular",
"message": "<label> element has accessible name with inner content",
"messageArgs": [],
"apiArgs": [],
"category": "Accessibility"
}
]
}

</script>
</body>
</html>