import React, { useState } from 'react'; import { describe, it, expect, vi } from 'vitest'; import { render, fireEvent } from '@testing-library/react'; import { PixelSwitch } from '../../forms/PixelSwitch'; describe('PixelSwitch', () => { it('renders role=switch with the label and aria-checked=false by default', () => { const { getByRole, getByText } = render(); const sw = getByRole('switch'); expect(sw.getAttribute('aria-checked')).toBe('false'); expect(getByText('Dark mode')).toBeTruthy(); }); it('toggles internally when uncontrolled (defaultChecked) and reports via onChange', () => { const onChange = vi.fn(); const { getByRole } = render( , ); const sw = getByRole('switch'); expect(sw.getAttribute('aria-checked')).toBe('true'); fireEvent.click(sw); expect(onChange).toHaveBeenLastCalledWith(false); expect(sw.getAttribute('aria-checked')).toBe('false'); }); it('controlled mode: aria-checked follows the checked prop', () => { const onChange = vi.fn(); function Wrap() { const [checked, setChecked] = useState(false); return ( { onChange(next); setChecked(next); }} /> ); } const { getByRole } = render(); const sw = getByRole('switch'); fireEvent.click(sw); expect(onChange).toHaveBeenLastCalledWith(true); expect(sw.getAttribute('aria-checked')).toBe('true'); }); it('disabled blocks toggling and exposes aria-disabled', () => { const onChange = vi.fn(); const { getByRole } = render( , ); const sw = getByRole('switch') as HTMLButtonElement; expect(sw.disabled).toBe(true); expect(sw.getAttribute('aria-disabled')).toBe('true'); fireEvent.click(sw); expect(onChange).not.toHaveBeenCalled(); expect(sw.getAttribute('aria-checked')).toBe('false'); }); it('serializes a hidden input only while on when name is set', () => { const { container, getByRole } = render( , ); expect(container.querySelector('input[type="hidden"]')).toBeNull(); fireEvent.click(getByRole('switch')); const hidden = container.querySelector('input[type="hidden"]') as HTMLInputElement; expect(hidden).toBeTruthy(); expect(hidden.name).toBe('notify'); expect(hidden.value).toBe('enabled'); }); it('required wires aria-required onto the trigger', () => { const { getByRole } = render(); expect(getByRole('switch').getAttribute('aria-required')).toBe('true'); }); it('forwards id and ref to the trigger button', () => { const ref = React.createRef(); const { getByRole } = render(); const sw = getByRole('switch'); expect(sw.id).toBe('sw-1'); expect(ref.current).toBe(sw); }); });