Skip to main content

GlassSwitch Tests

The GlassSwitch component has a comprehensive test suite that covers rendering, state management, accessibility, styling, and component props.

Test file location

src/components/GlassSwitch.test.jsx

Running the tests

# Run all tests
npm test

# Run only GlassSwitch tests
npm test -- GlassSwitch.test.jsx

# Run tests in watch mode
npm test -- --watch GlassSwitch.test.jsx

Test organization

1. Basic rendering

  • Renders a switch button with the correct role

2. Checked state management

  • Sets aria-checked to "true" when isOn={true}
  • Sets aria-checked to "false" when isOn={false}

3. User interaction

  • Calls onChange callback when clicked
  • Is keyboard accessible (focusable and responds to Enter key)

4. CSS class application

  • Applies correct CSS classes when checked (includes checked class)
  • Does not apply checked class when unchecked

5. Thumb content

  • Renders custom thumbContent when provided
  • Renders fallback thumb content
    • Off styling: when thumbContent is not provided and isOff
    • On styling: when thumbContent is not provided and isOn

6. Component props

  • Can be disabled via disabled prop
  • Sets correct aria-label for accessibility

Mocking strategy

  • Tooltip component: Mocked as a simple wrapper that renders children
  • CSS modules: Mocked to verify class name application and styling logic
  • userEvent: Used from @testing-library/user-event for realistic user interactions

Example test snippets

Testing checked state

it('sets aria-checked to true when checked', () => {
render(<GlassSwitch isOn={true} onChange={() => {}} ariaLabel="Toggle" />);
expect(screen.getByRole('switch')).toHaveAttribute('aria-checked', 'true');
});

Testing user interaction

it('calls onChange when clicked', async () => {
const user = userEvent.setup();
const onChange = vi.fn();

render(<GlassSwitch isOn={false} onChange={onChange} ariaLabel="Toggle" />);
await user.click(screen.getByRole('switch'));

expect(onChange).toHaveBeenCalledOnce();
});

Testing keyboard accessibility

it('is keyboard accessible', async () => {
const user = userEvent.setup();
const onChange = vi.fn();

render(<GlassSwitch isOn={false} onChange={onChange} ariaLabel="Toggle" />);
const button = screen.getByRole('switch');

button.focus();
expect(button).toHaveFocus();

await user.keyboard('{Enter}');

expect(onChange).toHaveBeenCalled();
});

Testing CSS classes

it('applies correct CSS classes when checked', () => {
render(<GlassSwitch isOn={true} onChange={() => {}} ariaLabel="Toggle" />);
const switchButton = screen.getByRole('switch');

expect(switchButton).toHaveClass('mocked-switch-class');
expect(switchButton).toHaveClass('mocked-checked-class');
});

Testing custom thumb content

it('renders with thumbContent when provided', () => {
const thumbContent = <span data-testid="custom-thumb">Custom</span>;
render(<GlassSwitch isOn={false} onChange={() => {}} ariaLabel="Toggle" thumbContent={thumbContent} />);

expect(screen.getByTestId('custom-thumb')).toBeInTheDocument();
});

Testing disabled state

it('can be disabled', () => {
const onChange = vi.fn();
render(<GlassSwitch isOn={false} onChange={onChange} ariaLabel="Toggle" disabled={true} />);
const switchButton = screen.getByRole('switch');

expect(switchButton).toBeDisabled();
});

Testing aria-label

it('sets correct aria-label', () => {
render(<GlassSwitch isOn={false} onChange={() => {}} ariaLabel="My Custom Label" />);

expect(screen.getByLabelText('My Custom Label')).toBeInTheDocument();
});

Test utilities

  • Vitest - Test framework with mocking capabilities
  • @testing-library/react - Component rendering and querying
  • @testing-library/user-event - User interaction simulation

Test coverage areas

The test suite ensures:

  1. Accessibility: ARIA attributes, keyboard navigation, labels
  2. Functionality: Click handlers, state management
  3. Styling: CSS class application based on props
  4. Props: All component props work correctly
  5. Edge cases: Fallback content, disabled state