Skip to content

Commit f4d9d8e

Browse files
committed
add more tests
1 parent 7aea660 commit f4d9d8e

3 files changed

Lines changed: 69 additions & 5 deletions

File tree

packages/mui-material/src/Avatar/Avatar.test.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,4 +278,30 @@ describe('<Avatar />', () => {
278278
),
279279
).not.to.throw();
280280
});
281+
282+
describe('accessibility', () => {
283+
// 1.3.1 Info and Relationships: the root is a generic container, and the
284+
// no-image states are decorative, so no spurious semantics are exposed.
285+
it('renders a generic root with no ARIA role', () => {
286+
const { container } = render(<Avatar alt="Remy Sharp" src="/fake.png" />);
287+
expect(container.firstChild).to.have.tagName('div');
288+
expect(container.firstChild).not.to.have.attribute('role');
289+
});
290+
291+
it('hides the Person fallback from assistive technology', () => {
292+
const { container } = render(<Avatar />);
293+
const fallback = container.querySelector('svg');
294+
expect(fallback).to.have.attribute('data-testid', 'PersonIcon');
295+
expect(fallback).to.have.attribute('aria-hidden', 'true');
296+
});
297+
298+
it('hides a decorative SvgIcon child from assistive technology', () => {
299+
const { container } = render(
300+
<Avatar>
301+
<CancelIcon />
302+
</Avatar>,
303+
);
304+
expect(container.querySelector('svg')).to.have.attribute('aria-hidden', 'true');
305+
});
306+
});
281307
});

packages/mui-material/src/Avatar/accessibility.md

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ Rated against WCAG 2.2 Level A and AA. See the [reports legend](../accessibility
88
| ⚠️ Partially Supports | 2 |
99
| ❌ Does Not Support | 0 |
1010
| ➖ Not Applicable | 44 |
11-
| 🚩 Unverified | 9/11 |
11+
| 🚩 Unverified | 6/11 |
1212

1313
## Known gaps
1414

@@ -49,10 +49,11 @@ Rated against WCAG 2.2 Level A and AA. See the [reports legend](../accessibility
4949

5050
#### 1.4.5 Images of Text · AA
5151

52-
`🚩 Unverified` · `✅ Supports` · `◐ Shared`
52+
`✅ Supports` · `◐ Shared`
5353

5454
- Letter/initials children and the `alt[0]` fallback are live, CSS-styled DOM text, not images of text.
5555
- The only risk is an author deliberately passing a bitmap of text as the avatar image.
56+
- Confirmed by a unit test in `Avatar.test.js` (initials render as a text node, not an `<img>`).
5657

5758
**Manual testing steps**
5859

@@ -83,10 +84,11 @@ Rated against WCAG 2.2 Level A and AA. See the [reports legend](../accessibility
8384

8485
#### 1.3.1 Info and Relationships · A
8586

86-
`🚩 Unverified` · `✅ Supports` · `◐ Shared`
87+
`✅ Supports` · `◐ Shared`
8788

8889
- The only relationship (image-to-name) is conveyed natively via `<img>` and `alt` text.
8990
- If an author builds meaning by composing the avatar with surrounding content (for example, a name and avatar in a list item), conveying that structure is the author's responsibility.
91+
- Confirmed by unit tests in `Avatar.test.js` (the root exposes no role; the `Person` fallback and `SvgIcon` children are `aria-hidden`).
9092

9193
**Manual testing steps**
9294

@@ -149,9 +151,10 @@ Rated against WCAG 2.2 Level A and AA. See the [reports legend](../accessibility
149151

150152
#### 1.4.12 Text Spacing · AA
151153

152-
`🚩 Unverified` · `✅ Supports` · `● Component`
154+
`✅ Supports` · `● Component`
153155

154156
- An avatar holds 1 to 2 character initials (or the `alt[0]` fallback) in a fixed 40px box with `overflow: hidden`, so the only risk to text legibility is clipping. Increasing text spacing would overflow the content but not clip it.
157+
- Confirmed by a Playwright regression test (`test/regressions/index.test.js`): the `OP` initials stay within the box after the four text-spacing overrides.
155158

156159
**Manual testing steps**
157160

@@ -219,5 +222,5 @@ Rated against WCAG 2.2 Level A and AA. See the [reports legend](../accessibility
219222
- **Standard.** WCAG 2.2, Level A and AA.
220223
- **Component version.** `@mui/material` 9.1.1.
221224
- **Scope.** The Avatar component in isolation, rendered through its documented API. `AvatarGroup` is a separate component and is out of scope.
222-
- **Automated.** axe-core via the Playwright regression harness, enrolling `LetterAvatars`, `BackgroundLetterAvatars`, `IconAvatars`, `VariantAvatars`, and the `AvatarA11yImage` fixture (results in [`avatars.a11y.json`](../../../../docs/data/material/components/avatars/avatars.a11y.json)); `color-contrast` is recorded but not asserted on the low-contrast letter demos (via `skipAssertions`). Plus unit tests in `Avatar.test.js` (for example, `alt` forwarding at `Avatar.test.js:65`).
225+
- **Automated.** axe-core via the Playwright regression harness (results in [`avatars.a11y.json`](../../../../docs/data/material/components/avatars/avatars.a11y.json)), a text-spacing clip test in the same harness, and unit tests in `Avatar.test.js`.
223226
- **Assistive-technology review.** Spot checked but not audited. `🚩` criteria are assessed from source pending a review with NVDA, JAWS, and VoiceOver.

test/regressions/index.test.js

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,41 @@ async function main() {
349349
});
350350
});
351351
});
352+
353+
describe('Avatar', () => {
354+
// Deterministic clip check for 1.4.12 Text Spacing, which axe cannot cover.
355+
// Renders `LetterAvatars` and targets the two-character ("OP") avatar,
356+
// whose fixed 40px box with `overflow: hidden` is the only clipping risk.
357+
test('1.4.12 Text Spacing: initials stay visible under the WCAG overrides', async ({
358+
pooled,
359+
}) => {
360+
const { page } = pooled;
361+
await renderFixture(page, '/docs-components-avatars/LetterAvatars');
362+
const clipped = await page.evaluate(() => {
363+
const style = document.createElement('style');
364+
style.textContent =
365+
'* { line-height: 1.5 !important; letter-spacing: 0.12em !important; word-spacing: 0.16em !important; }';
366+
document.head.appendChild(style);
367+
const avatar = Array.from(document.querySelectorAll('.MuiAvatar-root')).find(
368+
(node) => node.textContent === 'OP',
369+
);
370+
const range = document.createRange();
371+
range.selectNodeContents(avatar);
372+
const text = range.getBoundingClientRect();
373+
const box = avatar.getBoundingClientRect();
374+
style.remove();
375+
return (
376+
text.left < box.left - 0.5 ||
377+
text.right > box.right + 0.5 ||
378+
text.top < box.top - 0.5 ||
379+
text.bottom > box.bottom + 0.5
380+
);
381+
});
382+
if (clipped) {
383+
throw new Error('Avatar initials are clipped under WCAG text-spacing overrides');
384+
}
385+
});
386+
});
352387
});
353388
}
354389

0 commit comments

Comments
 (0)