mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-08-24 19:28:48 +00:00
LibWeb: Fix accessible-name computation for “tooltip” & empty-alt cases
This change fixes accessible-name computation for: - an element that has empty text content but that also has a title attribute (“tooltip”) with a non-empty value - an img element whose alt attribute is the empty string but that also has a “title” attribute with a non-empty value Otherwise, without this change, the accessible name unexpectedly isn’t computed correctly for those cases.
This commit is contained in:
parent
4ae1bca67d
commit
3594cdf948
Notes:
github-actions[bot]
2024-11-09 13:09:02 +00:00
Author: https://github.com/sideshowbarker
Commit: 3594cdf948
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/2209
Reviewed-by: https://github.com/trflynn89
3 changed files with 122 additions and 5 deletions
|
@ -0,0 +1,33 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 23 tests
|
||||||
|
|
||||||
|
23 Pass
|
||||||
|
Details
|
||||||
|
Result Test Name MessagePass link with img with tooltip label
|
||||||
|
Pass link with text with tooltip label and no contents
|
||||||
|
Pass link with text with tooltip label and contents
|
||||||
|
Pass div with text with tooltip label
|
||||||
|
Pass img with tooltip label without alt
|
||||||
|
Pass img with tooltip label with empty alt
|
||||||
|
Pass img with tooltip label with alt
|
||||||
|
Pass img with tooltip label without title
|
||||||
|
Pass select with tooltip label
|
||||||
|
Pass button with tooltip label
|
||||||
|
Pass checkbox input with tooltip label
|
||||||
|
Pass radio input with tooltip label
|
||||||
|
Pass text input with placeholder and tooltip label
|
||||||
|
Pass password input with placeholder and tooltip label
|
||||||
|
Pass number input with placeholder and tooltip label
|
||||||
|
Pass search input with placeholder and tooltip label
|
||||||
|
Pass tel input with placeholder and tooltip label
|
||||||
|
Pass email input with placeholder and tooltip label
|
||||||
|
Pass url input with placeholder and tooltip label
|
||||||
|
Pass textarea with placeholder and tooltip label
|
||||||
|
Pass abbr with tooltip label
|
||||||
|
Pass summary with tooltip label and contents
|
||||||
|
Pass iframe with tooltip label
|
|
@ -0,0 +1,70 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Name Comp: Tooltip</title>
|
||||||
|
<script src="../../resources/testharness.js"></script>
|
||||||
|
<script src="../../resources/testharnessreport.js"></script>
|
||||||
|
<script src="../../resources/testdriver.js"></script>
|
||||||
|
<script src="../../resources/testdriver-vendor.js"></script>
|
||||||
|
<script src="../../resources/testdriver-actions.js"></script>
|
||||||
|
<script src="../../wai-aria/scripts/aria-utils.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<p>Tests the <a href="https://w3c.github.io/accname/#comp_tooltip">#comp_tooltip</a> portions of the AccName <em>Name Computation</em> algorithm.</p>
|
||||||
|
|
||||||
|
<a href="#" title="title" data-expectedlabel="title" data-testname="link with img with tooltip label" class="ex"><img alt="" src="data:image/gif;base65,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw=="></a>
|
||||||
|
<a href="#" title="title" data-expectedlabel="title" data-testname="link with text with tooltip label and no contents" class="ex"></a>
|
||||||
|
<a href="#" title="title" data-expectedlabel="contents" data-testname="link with text with tooltip label and contents" class="ex">contents</a>
|
||||||
|
<div title="title" role="group" data-expectedlabel="title" data-testname="div with text with tooltip label" class="ex">contents</div><!-- Note: group role disallows nameFrom:contents -->
|
||||||
|
<img title="title" data-expectedlabel="title" data-testname="img with tooltip label without alt" class="ex" src="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==">
|
||||||
|
<img title="title" data-expectedlabel="title" alt="" data-testname="img with tooltip label with empty alt" class="ex" src="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==">
|
||||||
|
<img title="title" data-expectedlabel="alt" alt="alt" data-testname="img with tooltip label with alt" class="ex" src="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==">
|
||||||
|
<img data-expectedlabel="alt" alt="alt" data-testname="img with tooltip label without title" class="ex" src="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==">
|
||||||
|
|
||||||
|
<select title="title" data-expectedlabel="title" data-testname="select with tooltip label" class="ex">
|
||||||
|
<option value="" disabled selected>select options</option>
|
||||||
|
<option value="1">option 1</option>
|
||||||
|
<option value="2">option 2</option>
|
||||||
|
<option value="3">option 3</option>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- TODO: Move these: https://github.com/web-platform-tests/interop-accessibility/issues/78 -->
|
||||||
|
<button title="title" data-expectedlabel="contents" data-testname="button with tooltip label" class="ex">contents</button>
|
||||||
|
<input type="checkbox" title="title" data-expectedlabel="title" data-testname="checkbox input with tooltip label" class="ex">
|
||||||
|
<input type="radio" title="title" data-expectedlabel="title" data-testname="radio input with tooltip label" class="ex">
|
||||||
|
|
||||||
|
<!-- TODO: Move these: https://github.com/web-platform-tests/interop-accessibility/issues/78 -->
|
||||||
|
<!-- https://w3c.github.io/html-aam/#input-type-text-input-type-password-input-type-number-input-type-search-input-type-tel-input-type-email-input-type-url-and-textarea-element-accessible-name-computation -->
|
||||||
|
<input type="text" title="title" data-expectedlabel="title" placeholder="placeholder" data-testname="text input with placeholder and tooltip label" class="ex">
|
||||||
|
<input type="password" title="title" data-expectedlabel="title" placeholder="placeholder" data-testname="password input with placeholder and tooltip label" class="ex">
|
||||||
|
<input type="number" title="title" data-expectedlabel="title" placeholder="placeholder" data-testname="number input with placeholder and tooltip label" class="ex">
|
||||||
|
<input type="search" title="title" data-expectedlabel="title" placeholder="placeholder" data-testname="search input with placeholder and tooltip label" class="ex">
|
||||||
|
<input type="tel" title="title" data-expectedlabel="title" placeholder="placeholder" data-testname="tel input with placeholder and tooltip label" class="ex">
|
||||||
|
<input type="email" title="title" data-expectedlabel="title" placeholder="placeholder" data-testname="email input with placeholder and tooltip label" class="ex">
|
||||||
|
<input type="url" title="title" data-expectedlabel="title" placeholder="placeholder" data-testname="url input with placeholder and tooltip label" class="ex">
|
||||||
|
<textarea title="title" data-expectedlabel="title" placeholder="placeholder" data-testname="textarea with placeholder and tooltip label" class="ex"></textarea>
|
||||||
|
|
||||||
|
<!-- TODO: Move these: https://github.com/web-platform-tests/interop-accessibility/issues/78 -->
|
||||||
|
<!-- https://w3c.github.io/html-aam/#text-level-element-accessible-name-computation -->
|
||||||
|
<abbr title="Web Platform Tests" data-expectedlabel="Web Platform Tests" data-testname="abbr with tooltip label" class="ex">WPT</abbr>
|
||||||
|
<!-- kbd test disabled: see resolution at https://github.com/web-platform-tests/interop-accessibility/issues/131 -->
|
||||||
|
<!-- <kbd title="Control + Option" data-expectedlabel="Control + Option" data-testname="kbd with tooltip label" class="ex">CTRL + OPT</kbd> -->
|
||||||
|
|
||||||
|
<!-- TODO: Move these: https://github.com/web-platform-tests/interop-accessibility/issues/78 -->
|
||||||
|
<!-- https://w3c.github.io/html-aam/#summary-element-accessible-name-computation -->
|
||||||
|
<details>
|
||||||
|
<summary title="title" data-expectedlabel="contents" data-testname="summary with tooltip label and contents" class="ex">contents</summary>
|
||||||
|
details
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<!-- TODO: Move these: https://github.com/web-platform-tests/interop-accessibility/issues/78 -->
|
||||||
|
<!-- https://w3c.github.io/html-aam/#iframe-element-accessible-name-computation -->
|
||||||
|
<iframe title="title" data-expectedlabel="title" data-testname="iframe with tooltip label" width="20px" height="20px" class="ex"></iframe>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
AriaUtils.verifyLabelsBySelector(".ex");
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -34,6 +34,7 @@
|
||||||
#include <LibWeb/DOM/StaticNodeList.h>
|
#include <LibWeb/DOM/StaticNodeList.h>
|
||||||
#include <LibWeb/HTML/CustomElements/CustomElementReactionNames.h>
|
#include <LibWeb/HTML/CustomElements/CustomElementReactionNames.h>
|
||||||
#include <LibWeb/HTML/HTMLAnchorElement.h>
|
#include <LibWeb/HTML/HTMLAnchorElement.h>
|
||||||
|
#include <LibWeb/HTML/HTMLImageElement.h>
|
||||||
#include <LibWeb/HTML/HTMLInputElement.h>
|
#include <LibWeb/HTML/HTMLInputElement.h>
|
||||||
#include <LibWeb/HTML/HTMLSelectElement.h>
|
#include <LibWeb/HTML/HTMLSelectElement.h>
|
||||||
#include <LibWeb/HTML/HTMLSlotElement.h>
|
#include <LibWeb/HTML/HTMLSlotElement.h>
|
||||||
|
@ -2188,6 +2189,7 @@ ErrorOr<String> Node::name_or_description(NameOrDescription target, Document con
|
||||||
|
|
||||||
if (is_element()) {
|
if (is_element()) {
|
||||||
auto const* element = static_cast<DOM::Element const*>(this);
|
auto const* element = static_cast<DOM::Element const*>(this);
|
||||||
|
auto role = element->role_or_default();
|
||||||
// 2. Compute the text alternative for the current node:
|
// 2. Compute the text alternative for the current node:
|
||||||
// A. If the current node is hidden and is not directly referenced by aria-labelledby or aria-describedby, nor directly referenced by a native host language text alternative element (e.g. label in HTML) or attribute, return the empty string.
|
// A. If the current node is hidden and is not directly referenced by aria-labelledby or aria-describedby, nor directly referenced by a native host language text alternative element (e.g. label in HTML) or attribute, return the empty string.
|
||||||
// FIXME: Check for references
|
// FIXME: Check for references
|
||||||
|
@ -2312,11 +2314,22 @@ ErrorOr<String> Node::name_or_description(NameOrDescription target, Document con
|
||||||
// - Otherwise, return the value of aria-label.
|
// - Otherwise, return the value of aria-label.
|
||||||
return element->aria_label().value();
|
return element->aria_label().value();
|
||||||
}
|
}
|
||||||
// TODO: D. Otherwise, if the current node's native markup provides an attribute (e.g. title) or element (e.g. HTML label) that defines a text alternative,
|
|
||||||
// return that alternative in the form of a flat string as defined by the host language, unless the element is marked as presentational (role="presentation" or role="none").
|
// E. Host Language Label: Otherwise, if the current node's native markup provides an attribute (e.g. alt) or
|
||||||
|
// element (e.g. HTML label or SVG title) that defines a text alternative, return that alternative in the form
|
||||||
|
// of a flat string as defined by the host language, unless the element is marked as presentational
|
||||||
|
// (role="presentation" or role="none").
|
||||||
|
if (role != ARIA::Role::presentation && role != ARIA::Role::none) {
|
||||||
|
if (is<HTML::HTMLImageElement>(*element)) {
|
||||||
|
if (auto alt = element->get_attribute(HTML::AttributeNames::alt); alt.has_value())
|
||||||
|
return alt.release_value();
|
||||||
|
}
|
||||||
|
// TODO: Add handling for SVGTitleElement, and also confirm (through existing WPT test cases) whether
|
||||||
|
// HTMLLabelElement is already handled (by the code for step C. “Embedded Control” above) in conformance
|
||||||
|
// with the spec requirements — and if not, then add handling for it here.
|
||||||
|
}
|
||||||
|
|
||||||
// F. Otherwise, if the current node's role allows name from content, or if the current node is referenced by aria-labelledby, aria-describedby, or is a native host language text alternative element (e.g. label in HTML), or is a descendant of a native host language text alternative element:
|
// F. Otherwise, if the current node's role allows name from content, or if the current node is referenced by aria-labelledby, aria-describedby, or is a native host language text alternative element (e.g. label in HTML), or is a descendant of a native host language text alternative element:
|
||||||
auto role = element->role_or_default();
|
|
||||||
if ((role.has_value() && ARIA::allows_name_from_content(role.value())) || is_descendant == IsDescendant::Yes) {
|
if ((role.has_value() && ARIA::allows_name_from_content(role.value())) || is_descendant == IsDescendant::Yes) {
|
||||||
// i. Set the accumulated text to the empty string.
|
// i. Set the accumulated text to the empty string.
|
||||||
total_accumulated_text.clear();
|
total_accumulated_text.clear();
|
||||||
|
@ -2348,7 +2361,8 @@ ErrorOr<String> Node::name_or_description(NameOrDescription target, Document con
|
||||||
|
|
||||||
return IterationDecision::Continue;
|
return IterationDecision::Continue;
|
||||||
});
|
});
|
||||||
// iv. Return the accumulated text.
|
// v. Return the accumulated text if it is not the empty string ("").
|
||||||
|
if (!total_accumulated_text.is_empty())
|
||||||
return total_accumulated_text.to_string();
|
return total_accumulated_text.to_string();
|
||||||
// Important: Each node in the subtree is consulted only once. If text has been collected from a descendant, but is referenced by another IDREF in some descendant node, then that second, or subsequent, reference is not followed. This is done to avoid infinite loops.
|
// Important: Each node in the subtree is consulted only once. If text has been collected from a descendant, but is referenced by another IDREF in some descendant node, then that second, or subsequent, reference is not followed. This is done to avoid infinite loops.
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue