Description
Describe the feature you'd like:
I'm testing composite components that use aria-activedescendant
to move focus. I would like to test whether some item is "virtually" focused or not after pressing arrow keys:
const Test = () => (
<Composite aria-label="composite">
<CompositeItem>item1</CompositeItem>
<CompositeItem>item2</CompositeItem>
<CompositeItem>item3</CompositeItem>
</Composite>
);
const { getByText, getByLabelText } = render(<Test />);
const composite = getByLabelText("composite");
const item1 = getByText("item1");
const item2 = getByText("item2");
const item3 = getByText("item3");
composite.focus();
pressArrowRight();
expect(composite).toHaveFocus();
expect(item1).toBeActiveDescendant();
pressArrowRight();
expect(composite).toHaveFocus();
expect(item2).toBeActiveDescendant();
...
Suggested implementation:
I'm not sure about the code specific to create jest matchers, but this the utility I'm currently using:
function expectActiveDescendant(element) {
const { activeElement } = element.ownerDocument;
const id = activeElement && activeElement.getAttribute("aria-activedescendant");
expect(id).toBe(element.id);
}
Alternative implementations could also check for aria-selected="true"
on the element
, but from what I see, not all implementations include aria-selected
, whereas aria-activedescendant
is mandatory on the focused element.
Describe alternatives you've considered:
I'm currently using the utility function above. It's simple, but, since there are not so many people who know how aria-activedescendant
works (for example, that it should be in the current activeElement
), I guess the community would benefit from a matcher like that.
Teachability, Documentation, Adoption, Migration Strategy:
toBeActiveDescendant
toBeActiveDescendant(element: Element)
This allows you to check whether the given element is currently referenced in the aria-activedescendant
attribute on the element which currently has DOM focus.
Examples
<ul role="listbox" aria-activedescendant="option1" data-testid="listbox">
<li role="option" id="option1" aria-selected="true" data-testid="option1">option 1</li>
<li role="option" id="option2">option 2</li>
<li role="option" id="option3">option 3</li>
</ul>
const listbox = getByTestId('listbox')
const option1 = getByTestId('option1')
listbox.focus()
expect(option1).toBeActiveDescendant()