88 lines
3.1 KiB
TypeScript
88 lines
3.1 KiB
TypeScript
import { describe, it, expect, afterEach } from 'vitest';
|
|
|
|
const { radioGroupNav } = await import('./radioGroupNav');
|
|
|
|
describe('radioGroupNav action', () => {
|
|
const nodes: HTMLElement[] = [];
|
|
|
|
function makeGroup(count: number): { container: HTMLElement; buttons: HTMLElement[] } {
|
|
const container = document.createElement('div');
|
|
container.setAttribute('role', 'radiogroup');
|
|
const buttons: HTMLElement[] = [];
|
|
for (let i = 0; i < count; i++) {
|
|
const btn = document.createElement('button');
|
|
btn.setAttribute('role', 'radio');
|
|
btn.setAttribute('aria-checked', i === 0 ? 'true' : 'false');
|
|
btn.setAttribute('tabindex', i === 0 ? '0' : '-1');
|
|
container.appendChild(btn);
|
|
buttons.push(btn);
|
|
}
|
|
document.body.appendChild(container);
|
|
nodes.push(container);
|
|
return { container, buttons };
|
|
}
|
|
|
|
afterEach(() => {
|
|
nodes.forEach((n) => n.remove());
|
|
nodes.length = 0;
|
|
});
|
|
|
|
it('ArrowRight moves focus to next button', () => {
|
|
const { container, buttons } = makeGroup(4);
|
|
radioGroupNav(container);
|
|
buttons[0].focus();
|
|
buttons[0].dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowRight', bubbles: true }));
|
|
expect(document.activeElement).toBe(buttons[1]);
|
|
});
|
|
|
|
it('ArrowRight wraps from last to first', () => {
|
|
const { container, buttons } = makeGroup(4);
|
|
radioGroupNav(container);
|
|
buttons[3].focus();
|
|
buttons[3].dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowRight', bubbles: true }));
|
|
expect(document.activeElement).toBe(buttons[0]);
|
|
});
|
|
|
|
it('ArrowLeft moves focus to previous button', () => {
|
|
const { container, buttons } = makeGroup(4);
|
|
radioGroupNav(container);
|
|
buttons[2].focus();
|
|
buttons[2].dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowLeft', bubbles: true }));
|
|
expect(document.activeElement).toBe(buttons[1]);
|
|
});
|
|
|
|
it('ArrowLeft wraps from first to last', () => {
|
|
const { container, buttons } = makeGroup(4);
|
|
radioGroupNav(container);
|
|
buttons[0].focus();
|
|
buttons[0].dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowLeft', bubbles: true }));
|
|
expect(document.activeElement).toBe(buttons[3]);
|
|
});
|
|
|
|
it('ArrowRight updates aria-checked on new button and removes it from old', () => {
|
|
const { container, buttons } = makeGroup(4);
|
|
radioGroupNav(container);
|
|
buttons[0].focus();
|
|
buttons[0].dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowRight', bubbles: true }));
|
|
expect(buttons[1].getAttribute('aria-checked')).toBe('true');
|
|
expect(buttons[0].getAttribute('aria-checked')).toBe('false');
|
|
});
|
|
|
|
it('destroy removes keydown listener', () => {
|
|
const { container, buttons } = makeGroup(4);
|
|
const { destroy } = radioGroupNav(container);
|
|
destroy();
|
|
buttons[0].focus();
|
|
buttons[0].dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowRight', bubbles: true }));
|
|
expect(document.activeElement).toBe(buttons[0]);
|
|
});
|
|
|
|
it('ignores non-arrow keys', () => {
|
|
const { container, buttons } = makeGroup(4);
|
|
radioGroupNav(container);
|
|
buttons[0].focus();
|
|
buttons[0].dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter', bubbles: true }));
|
|
expect(document.activeElement).toBe(buttons[0]);
|
|
});
|
|
});
|