I am confused, isn't the content of the element considered as part of it's accessible name, why does the below test fail to find the alert with the text?
import React from "react";
import "@testing-library/jest-dom/extend-expect";
import userEvent from "@testing-library/user-event";
import { render, screen } from "@testing-library/react";
function Counter() {
const [count, setCount] = React.useState(0);
return (
<div>
<div>{count}</div>
<div role="alert">Please wait</div>
<button onClick={() => setCount(count + 1)}>click me</button>
</div>
);
}
test("renders alert", async () => {
render(<Counter />);
const loadingScreen = await screen.findByRole("alert", {
name: /Please wait/i
});
expect(loadingScreen).toBeInTheDocument();
});
From the Accessible name calculation documentation, the div
element in your case matches the last rule.
Other elements The
title
attribute.
Why? Because the div
element with the alert
role does not support getting their name from the content they contain. For example, the following link is named "Home".
<a href="/">Home</a>
When assistive technologies render an element that gets its accessible name from its content, such as a link or button, the accessible name is the only content the user can perceive for that element.
Note: Not all accessible names of element and role are the text content of the element!
Elements having one of the following roles are, by default, named by a string calculated from their descendant content. See the full list Roles Supporting Name from Content
Two choices:
title
attribute<div role='alert' title='Please wait'>
Please wait...
</div>
aria-label
attribute<div role='alert' aria-label='Please wait'>
Please wait...
</div>
Below is a test example, we can create a div
element with a 'heading'
role, and find it by role and its accessible name(the text content of it).
import '@testing-library/jest-dom';
import { render, screen } from '@testing-library/react';
import React from 'react';
function Counter() {
const [count, setCount] = React.useState(0);
return (
<div>
<div>{count}</div>
<div role='alert' aria-label='Please wait'>
Please wait...
</div>
<div role='heading'>An example heading</div>
<button onClick={() => setCount(count + 1)}>click me</button>
</div>
);
}
test('renders alert', async () => {
render(<Counter />);
const loadingScreen = await screen.findByRole('alert', {
name: /Please wait/i,
});
expect(loadingScreen).toBeInTheDocument();
const heading = await screen.findByRole('heading', { name: /An example heading/i });
expect(heading).toBeInTheDocument();
});
Test result:
PASS stackoverflow/76800902/index.test.tsx
✓ renders alert (54 ms)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 1.289 s, estimated 2 s
package versions:
"@testing-library/react": "^11.2.7",
"react": "^16.14.0",