diff --git a/lib/clear-suggestions.js b/lib/clear-suggestions.js index 15b9080c..6c95f7ab 100644 --- a/lib/clear-suggestions.js +++ b/lib/clear-suggestions.js @@ -6,5 +6,6 @@ function clearSuggestions(state) { state.selectedIndex = -1; removeListElement(state); state.input.removeAttribute("aria-controls"); + state.input.removeAttribute("aria-activedescendant"); state.plete.setAttribute("aria-expanded", "false"); } diff --git a/lib/highlight.js b/lib/highlight.js index e54ab339..a16f070d 100644 --- a/lib/highlight.js +++ b/lib/highlight.js @@ -5,6 +5,7 @@ function highlight(state, index) { const item = state.list.querySelectorAll("plete-item")[index]; if (item) { item.classList.add("highlight"); + state.input.setAttribute("aria-activedescendant", item.id); } } } diff --git a/lib/render.js b/lib/render.js index 447fcb13..5cf9b9d5 100644 --- a/lib/render.js +++ b/lib/render.js @@ -9,7 +9,8 @@ function render(state, data) { addListElement(state, select); const boundRenderItem = renderItem.bind(null, state); - data.map(boundRenderItem).forEach(function(item) { + data.map(boundRenderItem).forEach(function(item, idx) { + item.id = `plete-item-${idx}`; state.list.appendChild(item); }); diff --git a/test/aria-support.test.js b/test/aria-support.test.js index 899b8486..cadc7bf7 100644 --- a/test/aria-support.test.js +++ b/test/aria-support.test.js @@ -1,4 +1,4 @@ -import { assert } from "@sinonjs/referee-sinon"; +import { assert, refute } from "@sinonjs/referee-sinon"; import { fireEvent, waitForElement } from "@testing-library/dom"; import { setupTest } from "./test-helper"; @@ -47,6 +47,32 @@ describe("Plete", function() { }); }); + it("adds an `aria-activedescendant` attribute to the input", function() { + const listItems = this.list.querySelectorAll("plete-item"); + + assert.isTrue(listItems.length > 0); + refute.isNull(this.input); + refute.isNull(this.input.getAttribute("aria-activedescendant")); + }); + + it("renders the list items with an `id` attribute", function() { + const listItems = this.list.querySelectorAll("plete-item"); + + assert.isTrue(listItems.length > 0); + listItems.forEach(function(item) { + refute.isNull(item.getAttribute("id")); + }); + }); + + it("`aria-activedescendant` attribute corresponds to an `id` attribute of another DOM node", function() { + const listItems = this.list.querySelectorAll("plete-item"); + + assert.isTrue(listItems.length > 0); + refute.isNull(this.input); + const activeDescendant = this.input.getAttribute("aria-activedescendant"); + refute.isNull(document.getElementById(activeDescendant)); + }); + it("sets `aria-expanded` on the `plete` element to 'true'", function() { const plete = this.input.closest("plete");