Skip to content

Commit

Permalink
SIA-R16: accept <input list="foo"> comboboxes (#948)
Browse files Browse the repository at this point in the history
* Add failing test
* Hack around problem
  • Loading branch information
Jym77 authored Oct 15, 2021
1 parent 99a6775 commit a782500
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 8 deletions.
47 changes: 39 additions & 8 deletions packages/alfa-rules/src/sia-r16/rule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,16 @@ import { Page } from "@siteimprove/alfa-web";
import * as aria from "@siteimprove/alfa-aria";

import { expectation } from "../common/expectation";

import { hasRole } from "../common/predicate/has-role";
import { isFocusable } from "../common/predicate/is-focusable";
import { isIgnored } from "../common/predicate/is-ignored";

const { isElement, hasNamespace } = Element;
import {
hasAttribute,
hasRole,
isFocusable,
isIgnored,
} from "../common/predicate";

const { isElement, hasInputType, hasName, hasNamespace } = Element;
const { isEmpty } = Iterable;
const { and, not, property } = Predicate;
const { and, not, property, test } = Predicate;

export default Rule.Atomic.of<Page, Element>({
uri: "https://alfa.siteimprove.com/rules/sia-r16",
Expand Down Expand Up @@ -79,7 +81,10 @@ function hasRequiredValues(
if (role.isAttributeRequired(attribute)) {
required.push(attribute);

if (node.attribute(attribute).every(property("value", isEmpty))) {
if (
node.attribute(attribute).every(property("value", isEmpty)) &&
!isManagedAttribute(element, role.name, attribute)
) {
missing.push(attribute);
result = false;
}
Expand Down Expand Up @@ -195,3 +200,29 @@ export namespace Outcomes {
)
);
}

// Some aria-* attributes are managed by UAs out of the HTML AAM and we
// incorrectly flagged them as missing
// See https://github.com/w3c/html-aam/issues/349
function isManagedAttribute(
element: Element,
role: aria.Role.Name,
attribute: aria.Attribute.Name
): boolean {
if (
role === "combobox" &&
attribute === "aria-expanded" &&
test(
and(
hasName("input"),
hasInputType("email", "search", "tel", "text", "url"),
hasAttribute("list")
),
element
)
) {
return true;
}

return false;
}
20 changes: 20 additions & 0 deletions packages/alfa-rules/test/sia-r16/rule.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -128,3 +128,23 @@ test("evaluate() is inapplicable to elements that are not exposed", async (t) =>

t.deepEqual(await evaluate(R16, { document }), [inapplicable(R16)]);
});

test(`evaluate() passes a native \`<input type="text" list="foo">\` combobox`, async (t) => {
const target = <input type="text" list="foo" />;
const datalist = (
<datalist id="foo">
<option value="foo">foo</option>
<option value="bar">bar</option>
</datalist>
);

const document = h.document([target, datalist]);

t.deepEqual(await evaluate(R16, { document }), [
passed(R16, target, {
1: Outcomes.HasAllStates(
RoleAndRequiredAttributes.of("", "combobox", ["aria-expanded"], [])
),
}),
]);
});

0 comments on commit a782500

Please sign in to comment.