Skip to content

toBeActiveDescendant #207

Open
Open
@diegohaz

Description

@diegohaz

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()

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions