test(persons): replace fragile CSS class tests with aria-checked behavior tests
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -25,32 +25,47 @@ describe('PersonTypeSelector', () => {
|
||||
|
||||
expect(hiddenInput.value).toBe('INSTITUTION');
|
||||
});
|
||||
it('selected button uses semantic bg-primary and text-primary-fg classes', () => {
|
||||
|
||||
it('hidden input value updates when user navigates with ArrowLeft (wraps around)', async () => {
|
||||
const { container } = render(PersonTypeSelector, { value: 'PERSON' });
|
||||
const buttons = container.querySelectorAll('[role="radio"]');
|
||||
const selected = Array.from(buttons).find((b) => b.getAttribute('aria-checked') === 'true');
|
||||
expect(selected).not.toBeNull();
|
||||
expect(selected!.className).toContain('bg-primary');
|
||||
expect(selected!.className).toContain('text-primary-fg');
|
||||
const hiddenInput = container.querySelector('input[type="hidden"]') as HTMLInputElement;
|
||||
expect(hiddenInput.value).toBe('PERSON');
|
||||
|
||||
const personButton = container.querySelector('[aria-checked="true"]') as HTMLElement;
|
||||
personButton.focus();
|
||||
await userEvent.keyboard('{ArrowLeft}');
|
||||
|
||||
expect(hiddenInput.value).toBe('UNKNOWN');
|
||||
});
|
||||
it('exactly one button is aria-checked=true for the initial value', () => {
|
||||
const { container } = render(PersonTypeSelector, { value: 'INSTITUTION' });
|
||||
const buttons = Array.from(container.querySelectorAll('[role="radio"]'));
|
||||
const checked = buttons.filter((b) => b.getAttribute('aria-checked') === 'true');
|
||||
const unchecked = buttons.filter((b) => b.getAttribute('aria-checked') === 'false');
|
||||
expect(checked).toHaveLength(1);
|
||||
expect(unchecked).toHaveLength(3);
|
||||
});
|
||||
|
||||
it('unselected buttons use semantic bg-surface, text-ink, border-line classes', () => {
|
||||
it('aria-checked=true moves to clicked button on click', async () => {
|
||||
const { container } = render(PersonTypeSelector, { value: 'PERSON' });
|
||||
const buttons = container.querySelectorAll('[role="radio"]');
|
||||
const unselected = Array.from(buttons).filter((b) => b.getAttribute('aria-checked') !== 'true');
|
||||
expect(unselected.length).toBeGreaterThan(0);
|
||||
for (const btn of unselected) {
|
||||
expect(btn.className).toContain('bg-surface');
|
||||
expect(btn.className).toContain('text-ink');
|
||||
expect(btn.className).toContain('border-line');
|
||||
const buttons = Array.from(container.querySelectorAll('[role="radio"]'));
|
||||
const groupButton = buttons.find((b) => b.getAttribute('value') === 'GROUP') as HTMLElement;
|
||||
await userEvent.click(groupButton);
|
||||
expect(groupButton.getAttribute('aria-checked')).toBe('true');
|
||||
const others = buttons.filter((b) => b !== groupButton);
|
||||
for (const btn of others) {
|
||||
expect(btn.getAttribute('aria-checked')).toBe('false');
|
||||
}
|
||||
});
|
||||
|
||||
it('focus ring uses semantic ring-focus-ring class', () => {
|
||||
it('selected button has tabindex=0, unselected buttons have tabindex=-1', () => {
|
||||
const { container } = render(PersonTypeSelector, { value: 'PERSON' });
|
||||
const buttons = container.querySelectorAll('[role="radio"]');
|
||||
for (const btn of buttons) {
|
||||
expect(btn.className).toContain('ring-focus-ring');
|
||||
const buttons = Array.from(container.querySelectorAll('[role="radio"]'));
|
||||
const selected = buttons.find((b) => b.getAttribute('aria-checked') === 'true');
|
||||
const unselected = buttons.filter((b) => b.getAttribute('aria-checked') !== 'true');
|
||||
expect(selected!.getAttribute('tabindex')).toBe('0');
|
||||
for (const btn of unselected) {
|
||||
expect(btn.getAttribute('tabindex')).toBe('-1');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user