// @vitest-environment jsdom
/**
* What a face is called, everywhere one appears.
*
* These are the names an app's own tests compute — `getByRole('button', { name })`
* runs the same algorithm — and every one of them was wrong until 2026-09-08:
* a face read as its initials, and a face beside a name read the name twice.
* The initials are a drawing of a name, not text.
*/
import { afterEach, describe, expect, it } from 'vitest'
import { cleanup, render, screen } from '@testing-library/react'
import { Avatar } from './Avatar'
import { AvatarGroup } from './AvatarGroup'
import { MenuItem, MenuPanel } from './Menu'
import { Person } from './Person'
import { PersonTrigger } from './PersonTrigger'
afterEach(cleanup)
/**
* `getByRole`'s `name` matches the *accessible* name exactly, computed by the
* same algorithm a browser uses — so a query that finds nothing is the failure
* being asserted, and the message names what it looked for. This is also how
* both apps query their own controls, which is what makes it the right test.
*/
describe('a face beside a name says nothing of its own', () => {
it('a button holding a Person is called the person, once', () => {
render(
,
)
// "AD Ana Duarte" before: the initials were read as text.
expect(screen.getByRole('button', { name: 'Ana Duarte' })).toBeTruthy()
})
it('and once when there is a picture rather than initials', () => {
render(
,
)
// "Ana Duarte Ana Duarte" before: the alt text and the name were both read.
expect(screen.getByRole('button', { name: 'Ana Duarte' })).toBeTruthy()
})
it('a menu row led by a face is called by its label', () => {
render(
} onClick={() => {}} />
,
)
expect(screen.getByRole('button', { name: 'Ana Duarte' })).toBeTruthy()
})
it('a bare face is not in the accessibility tree at all', () => {
const { container } = render()
expect(container.firstElementChild?.getAttribute('aria-hidden')).toBe('true')
})
})
describe('a face that stands on its own says whose it is', () => {
it('the compact PersonTrigger is called the person', () => {
render()
// "AD" before — the initials, and the only name the control had.
expect(screen.getByRole('button', { name: 'Ana Duarte' })).toBeTruthy()
})
it('a caller may name the destination instead', () => {
render()
expect(screen.getByRole('button', { name: 'Account menu' })).toBeTruthy()
})
it('an unnamed person falls back to what the caller calls them', () => {
render()
expect(screen.getByRole('button', { name: 'Anonymous' })).toBeTruthy()
})
it('the row shape is called the person, without the initials in front', () => {
render()
expect(screen.getByRole('button', { name: 'Ana Duarte' })).toBeTruthy()
})
it('a stack of faces names each of them', () => {
render()
// "AD" and "BC" before.
expect(screen.getAllByRole('img').map((el) => el.getAttribute('aria-label'))).toEqual(['Ana Duarte', 'Ben Carter'])
})
})
describe('the compact trigger keeps a focus ring', () => {
/** `focus:outline-none` took the browser's ring away and put nothing back,
* so the account trigger had no visible focus at all. */
it('does not remove its own outline', () => {
render()
expect(screen.getByRole('button').className).not.toContain('outline-none')
})
})