menu-selection-indicator.test.tsx2.8 KBView on GitHub /**
* How a menu marks the row you picked.
*
* shadcn's `RadioItem` ships a filled `Circle` in a LEFT gutter, and that default reached the
* agent workspace's Folder and Default file submenus: a solid black disc beside one row, on the
* side that belongs to the option's own icon, in a menu whose checkbox rows were already ticking
* on the right. One question, two marks, two sides.
*
* The rule is in apps/mail/docs/crystallized.md → Counts, ticks and ordinals: a `Check` on the
* RIGHT, the same for a radio set as for a checkbox set, in a lane that is always reserved. This
* test is the guard on it — the dot is a one-line regression to reintroduce, and nothing else in
* the suite would notice.
*/
import { render, screen } from '@testing-library/react';
import {
DropdownMenu,
DropdownMenuCheckboxItem,
DropdownMenuContent,
DropdownMenuRadioGroup,
DropdownMenuRadioItem,
DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu';
function Menu() {
return (
<DropdownMenu defaultOpen>
<DropdownMenuTrigger>Open</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuRadioGroup value="core">
<DropdownMenuRadioItem value="core">Core</DropdownMenuRadioItem>
<DropdownMenuRadioItem value="background">Background</DropdownMenuRadioItem>
</DropdownMenuRadioGroup>
<DropdownMenuCheckboxItem checked>Show archived</DropdownMenuCheckboxItem>
</DropdownMenuContent>
</DropdownMenu>
);
}
describe('menu selection indicator', () => {
it('marks the chosen radio row with a tick, not a filled dot', () => {
const { baseElement } = render(<Menu />);
const chosen = screen.getByRole('menuitemradio', { name: 'Core' });
expect(chosen).toHaveAttribute('aria-checked', 'true');
expect(chosen.querySelector('.lucide-check')).toBeInTheDocument();
// The dot, in any of the shapes it comes in.
expect(baseElement.querySelector('.lucide-circle')).not.toBeInTheDocument();
expect(baseElement.querySelector('.fill-current')).not.toBeInTheDocument();
});
it('puts the tick on the right, in a lane every row reserves', () => {
render(<Menu />);
for (const name of ['Core', 'Background']) {
const row = screen.getByRole('menuitemradio', { name });
// Reserved on the unchosen row too: indenting only the chosen one makes the whole menu
// jump sideways every time you pick something.
expect(row.className).toContain('pr-8');
expect(row.className).not.toContain('pl-8');
}
});
it('ticks a checkbox row the same way, so one menu reads as one system', () => {
render(<Menu />);
const box = screen.getByRole('menuitemcheckbox', { name: 'Show archived' });
expect(box.querySelector('.lucide-check')).toBeInTheDocument();
expect(box.className).toContain('pr-8');
});
});