import React, { useState } from 'react' import { render } from '@testing-library/react' import { Switch } from './switch' import { SwitchState, assertSwitch, getSwitch, assertActiveElement, getSwitchLabel, getByText, } 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('`type` attribute', () => { it('should set the `type` to "button" by default', async () => { render( Trigger ) expect(getSwitch()).toHaveAttribute('type', 'button') }) it('should not set the `type` to "button" if it already contains a `type`', async () => { render( Trigger ) expect(getSwitch()).toHaveAttribute('type', 'submit') }) it('should set the `type` to "button" when using the `as` prop which resolves to a "button"', async () => { let CustomButton = React.forwardRef((props, ref) => ( ) // 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 }) }) }) describe('Form compatibility', () => { it('should be possible to submit a form with an boolean value', async () => { let submits = jest.fn() function Example() { let [state, setState] = useState(false) return (
{ event.preventDefault() submits([...new FormData(event.currentTarget).entries()]) }} > Enable notifications
) } render() // Submit the form await click(getByText('Submit')) // Verify that the form has been submitted expect(submits).lastCalledWith([]) // no data // Toggle await click(getSwitchLabel()) // Submit the form again await click(getByText('Submit')) // Verify that the form has been submitted expect(submits).lastCalledWith([['notifications', 'on']]) }) it('should be possible to submit a form with a provided string value', async () => { let submits = jest.fn() function Example() { let [state, setState] = useState(false) return (
{ event.preventDefault() submits([...new FormData(event.currentTarget).entries()]) }} > Apple
) } render() // Submit the form await click(getByText('Submit')) // Verify that the form has been submitted expect(submits).lastCalledWith([]) // no data // Toggle await click(getSwitchLabel()) // Submit the form again await click(getByText('Submit')) // Verify that the form has been submitted expect(submits).lastCalledWith([['fruit', 'apple']]) }) })