import React, { useState } from 'react' import { render } from '@testing-library/react' import { Switch } from './switch' import { SwitchState, assertSwitch, getSwitch, assertActiveElement, getSwitchLabel, } from '../../test-utils/accessibility-assertions' import { press, click, Keys } from '../../test-utils/interactions' jest.mock('../../hooks/use-id') describe('Safe guards', () => { it('should be possible to render a Switch without crashing', () => { render() }) }) describe('Rendering', () => { it('should be possible to render an (on) Switch using a render prop', () => { render( {({ checked }) => {checked ? 'On' : 'Off'}} ) assertSwitch({ state: SwitchState.On, textContent: 'On' }) }) it('should be possible to render an (off) Switch using a render prop', () => { render( {({ checked }) => {checked ? 'On' : 'Off'}} ) assertSwitch({ state: SwitchState.Off, textContent: 'Off' }) }) it('should be possible to render an (on) Switch using an `as` prop', () => { render() assertSwitch({ state: SwitchState.On, tag: 'span' }) }) it('should be possible to render an (off) Switch using an `as` prop', () => { render() assertSwitch({ state: SwitchState.Off, tag: 'span' }) }) it('should be possible to use the switch contents as the label', () => { render( Enable notifications ) assertSwitch({ state: SwitchState.Off, label: 'Enable notifications' }) }) }) describe('Render composition', () => { it('should be possible to render a Switch.Group, Switch and Switch.Label', () => { render( Enable notifications ) assertSwitch({ state: SwitchState.Off, label: 'Enable notifications' }) }) it('should be possible to render a Switch.Group, Switch and Switch.Label (before the Switch)', () => { render( Label B Label A ) // Warning! Using aria-label or aria-labelledby will hide any descendant content from assistive // technologies. // // Thus: Label A should not be part of the "label" in this case assertSwitch({ state: SwitchState.Off, label: 'Label B' }) }) it('should be possible to render a Switch.Group, Switch and Switch.Label (after the Switch)', () => { render( Label A Label B ) // Warning! Using aria-label or aria-labelledby will hide any descendant content from assistive // technologies. // // Thus: Label A should not be part of the "label" in this case assertSwitch({ state: SwitchState.Off, label: 'Label B' }) }) it('should be possible to render a Switch.Group, Switch and Switch.Description (before the Switch)', async () => { render( This is an important feature ) assertSwitch({ state: SwitchState.Off, description: 'This is an important feature' }) }) it('should be possible to render a Switch.Group, Switch and Switch.Description (after the Switch)', () => { render( This is an important feature ) assertSwitch({ state: SwitchState.Off, description: 'This is an important feature' }) }) it('should be possible to render a Switch.Group, Switch, Switch.Label and Switch.Description', () => { render( Label A This is an important feature ) assertSwitch({ state: SwitchState.Off, label: 'Label A', description: 'This is an important feature', }) }) }) describe('Keyboard interactions', () => { describe('`Space` key', () => { it('should be possible to toggle the Switch with Space', async () => { let handleChange = jest.fn() function Example() { let [state, setState] = useState(false) return ( { setState(value) handleChange(value) }} /> ) } render() // Ensure checkbox is off assertSwitch({ state: SwitchState.Off }) // Focus the switch getSwitch()?.focus() // Toggle await press(Keys.Space) // Ensure state is on assertSwitch({ state: SwitchState.On }) // Toggle await press(Keys.Space) // Ensure state is off assertSwitch({ state: SwitchState.Off }) }) }) describe('`Enter` key', () => { it('should not be possible to use Enter to toggle the Switch', async () => { let handleChange = jest.fn() render() // Ensure checkbox is off assertSwitch({ state: SwitchState.Off }) // Focus the switch getSwitch()?.focus() // Try to toggle await press(Keys.Enter) expect(handleChange).not.toHaveBeenCalled() }) }) describe('`Tab` key', () => { it('should be possible to tab away from the Switch', async () => { render(
) // Ensure checkbox is off assertSwitch({ state: SwitchState.Off }) // Focus the switch getSwitch()?.focus() // Expect the switch to be active assertActiveElement(getSwitch()) // Toggle await press(Keys.Tab) // Expect the button to be active assertActiveElement(document.getElementById('btn')) }) }) }) describe('Mouse interactions', () => { it('should be possible to toggle the Switch with a click', async () => { let handleChange = jest.fn() function Example() { let [state, setState] = useState(false) return ( { setState(value) handleChange(value) }} /> ) } render() // Ensure checkbox is off assertSwitch({ state: SwitchState.Off }) // Toggle await click(getSwitch()) // Ensure state is on assertSwitch({ state: SwitchState.On }) // Toggle await click(getSwitch()) // Ensure state is off assertSwitch({ state: SwitchState.Off }) }) it('should be possible to toggle the Switch with a click on the Label', async () => { let handleChange = jest.fn() function Example() { let [state, setState] = useState(false) return ( { setState(value) handleChange(value) }} /> The label ) } render() // Ensure checkbox is off assertSwitch({ state: SwitchState.Off }) // Toggle await click(getSwitchLabel()) // Ensure the switch is focused assertActiveElement(getSwitch()) // Ensure state is on assertSwitch({ state: SwitchState.On }) // Toggle await click(getSwitchLabel()) // Ensure the switch is focused assertActiveElement(getSwitch()) // Ensure state is off assertSwitch({ state: SwitchState.Off }) }) it('should not be possible to toggle the Switch with a click on the Label (passive)', async () => { let handleChange = jest.fn() function Example() { let [state, setState] = useState(false) return ( { setState(value) handleChange(value) }} /> The label ) } render() // Ensure checkbox is off assertSwitch({ state: SwitchState.Off }) // Toggle await click(getSwitchLabel()) // Ensure state is still off assertSwitch({ state: SwitchState.Off }) }) })