Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support complex aria-labelledby queries #1260

Open
jossmac opened this issue Dec 18, 2023 · 3 comments
Open

Support complex aria-labelledby queries #1260

jossmac opened this issue Dec 18, 2023 · 3 comments

Comments

@jossmac
Copy link

jossmac commented Dec 18, 2023

Describe the feature you'd like:

I'd like getByLabelText to resolve the associated elements of aria-labelledby. As I'm writing this it occurs to me that this might be too costly and perhaps better suited to something like axe.

Describe alternatives you've considered:

I've resorted to a combination of getByRole + getByText and checking IDs.

Teachability, Documentation, Adoption, Migration Strategy:

The summarised/pseudo code looks something like:

let contentId = 'content-id';
let spinnerId = 'spinner-id';

return (
  <button
    aria-disabled={props.pending ? true : undefined}
    aria-labelledby={props.pending ? `${contentId} ${spinnerId}` : undefined}
  >
    <span id={contentId}>{props.children}</span>
    {props.pending && (
      <span id={spinnerId} aria-label="pending" aria-hidden>
        ...
      </span>
    )}
  </button>
);

The desired test would look something like:

it('supports "pending" prop', () => {
  let { getByLabelText } = render(<Button pending>Submit</Button>);
  expect(getByLabelText(`Submit ${PENDING_LABEL}`)).toHaveAttribute('aria-disabled', 'true');
});
@MatanBobi
Copy link
Member

Hi @jossmac, thanks for opening this.
I'm not sure I'm entirely understanding your request, but since you already have a solution that works, you can build a custom query in your own codebase.
Do you believe this use case is worth adding to the core library?

@jossmac
Copy link
Author

jossmac commented Jan 16, 2024

I wasn't aware of custom queries, thanks for the heads up!

Looking at this with fresh eyes, I think there's a sensible way to write the expectation with existing APIs e.g.

it('supports "pending" prop', () => {
  let { getByRole } = render(<Button pending>Submit</Button>);
  expect(
    getByRole("button", { name: `Submit ${PENDING_LABEL}` })
  ).toHaveAttribute("aria-disabled", "true");
});

@jossmac jossmac closed this as completed Jan 16, 2024
@jossmac
Copy link
Author

jossmac commented Jan 16, 2024

Do you believe this use case is worth adding to the core library?

No, I think my mental model was at odds with the library's design decisions.


However, I think it should be documented somewhere* that getByLabelText() will only resolve the first ID when "aria-labelledby" is provided. In addition to improved docs, it could be helpful to warn consumers when the query encounters an "aria-labelledby" value that contains spaces.

Single ID, works as expected:

const { getByLabelText } = render(
  <>
    <div id="label-1">first</div>
    <button aria-labelledby="label-1" />
  </>
);

expect(getByLabelText("first")).toBeVisible(); // passes

Multiple IDs, does not work as expected:

const { getByLabelText } = render(
  <>
    <div id="label-1">first</div>
    <div id="label-2">second</div>
    <button aria-labelledby="label-1 label-2" />
  </>
);

expect(getByLabelText("first second")).toBeVisible(); // fails. shouldn't really, but understandable knowing what i do now

Which could lead to tests passing that really shouldn't e.g.

const { getByLabelText } = render(
  <>
    <div id="label-1">first</div>
    <div id="label-2">second</div>
    <button aria-labelledby="label-1 label-2" />
  </>
);

expect(getByLabelText("first")).toBeVisible(); // passes, incorrectly

*Found this documentation under a somewhat confusing heading:

The example above does NOT find the input node for label text broken up by elements.

@jossmac jossmac reopened this Jan 16, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants