Skip to content

Commit

Permalink
Upgrade user-event to v14 (#2190)
Browse files Browse the repository at this point in the history
* Upgrade `userEvent` to v14

* Fix Autocomplete tests

Co-authored-by: Cole Bemis <[email protected]>
  • Loading branch information
iansan5653 and colebemis authored Jul 28, 2022
1 parent 5ff5bb8 commit 4156b71
Show file tree
Hide file tree
Showing 13 changed files with 155 additions and 120 deletions.
23 changes: 9 additions & 14 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@
"@testing-library/jest-dom": "5.16.4",
"@testing-library/react": "12.1.5",
"@testing-library/react-hooks": "7.0.2",
"@testing-library/user-event": "13.1.9",
"@testing-library/user-event": "^14.3.0",
"@types/chroma-js": "2.1.3",
"@types/enzyme": "3.10.9",
"@types/jest": "27.0.2",
Expand Down
17 changes: 10 additions & 7 deletions src/SegmentedControl/SegmentedControl.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,8 @@ describe('SegmentedControl', () => {
}
})

it('calls onChange with index of clicked segment button', () => {
it('calls onChange with index of clicked segment button', async () => {
const user = userEvent.setup()
const handleChange = jest.fn()
const {getByText} = render(
<SegmentedControl aria-label="File view" onChange={handleChange}>
Expand All @@ -169,12 +170,13 @@ describe('SegmentedControl', () => {

expect(handleChange).not.toHaveBeenCalled()
if (buttonToClick) {
userEvent.click(buttonToClick)
await user.click(buttonToClick)
}
expect(handleChange).toHaveBeenCalledWith(1)
})

it('calls segment button onClick if it is passed', () => {
it('calls segment button onClick if it is passed', async () => {
const user = userEvent.setup()
const handleClick = jest.fn()
const {getByText} = render(
<SegmentedControl aria-label="File view">
Expand All @@ -190,12 +192,13 @@ describe('SegmentedControl', () => {

expect(handleClick).not.toHaveBeenCalled()
if (buttonToClick) {
userEvent.click(buttonToClick)
await user.click(buttonToClick)
}
expect(handleClick).toHaveBeenCalled()
})

it('focuses the selected button first', () => {
it('focuses the selected button first', async () => {
const user = userEvent.setup()
const {getByRole} = render(
<>
<button>Before</button>
Expand All @@ -212,8 +215,8 @@ describe('SegmentedControl', () => {

expect(document.activeElement?.id).not.toEqual(initialFocusButtonNode.id)

userEvent.tab() // focus the button before the segmented control
userEvent.tab() // move focus into the segmented control
await user.tab() // focus the button before the segmented control
await user.tab() // move focus into the segmented control

expect(document.activeElement?.id).toEqual(initialFocusButtonNode.id)
})
Expand Down
68 changes: 37 additions & 31 deletions src/__tests__/Autocomplete.test.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react'
import {render} from '../utils/testing'
import {render as HTMLRender, fireEvent} from '@testing-library/react'
import {render as HTMLRender, fireEvent, waitFor} from '@testing-library/react'
import {toHaveNoViolations} from 'jest-axe'
import 'babel-polyfill'
import Autocomplete, {AutocompleteInputProps} from '../Autocomplete'
Expand Down Expand Up @@ -193,7 +193,8 @@ describe('Autocomplete', () => {
})

describe('Autocomplete.Input', () => {
it('calls onChange', () => {
it('calls onChange', async () => {
const user = userEvent.setup()
const onChangeMock = jest.fn()
const {container} = HTMLRender(
<LabelledAutocomplete
Expand All @@ -204,7 +205,7 @@ describe('Autocomplete', () => {
const inputNode = container.querySelector('#autocompleteInput')

expect(onChangeMock).not.toHaveBeenCalled()
inputNode && userEvent.type(inputNode, 'z')
inputNode && (await user.type(inputNode, 'z'))
expect(onChangeMock).toHaveBeenCalled()
})

Expand Down Expand Up @@ -244,15 +245,16 @@ describe('Autocomplete', () => {
expect(onKeyUpMock).toHaveBeenCalled()
})

it('calls onKeyPress', () => {
it('calls onKeyPress', async () => {
const user = userEvent.setup()
const onKeyPressMock = jest.fn()
const {getByLabelText} = HTMLRender(
<LabelledAutocomplete inputProps={{onKeyPress: onKeyPressMock}} menuProps={{items: [], selectedItemIds: []}} />
)
const inputNode = getByLabelText(AUTOCOMPLETE_LABEL)

expect(onKeyPressMock).not.toHaveBeenCalled()
userEvent.type(inputNode, '{enter}')
await user.type(inputNode, '{enter}')
expect(onKeyPressMock).toHaveBeenCalled()
})

Expand All @@ -265,7 +267,7 @@ describe('Autocomplete', () => {
expect(inputNode.getAttribute('aria-expanded')).toBe('true')
})

it('closes the menu when the input is blurred', () => {
it('closes the menu when the input is blurred', async () => {
const {getByLabelText} = HTMLRender(<LabelledAutocomplete menuProps={{items: [], selectedItemIds: []}} />)
const inputNode = getByLabelText(AUTOCOMPLETE_LABEL)

Expand All @@ -276,49 +278,50 @@ describe('Autocomplete', () => {
fireEvent.blur(inputNode)

// wait a tick for blur to finish
setTimeout(() => {
expect(inputNode.getAttribute('aria-expanded')).not.toBe('true')
}, 0)
await waitFor(() => expect(inputNode.getAttribute('aria-expanded')).not.toBe('true'))
})

it('sets the input value to the suggested item text and highlights the untyped part of the word', () => {
it('sets the input value to the suggested item text and highlights the untyped part of the word', async () => {
const user = userEvent.setup()
const {container, getByDisplayValue} = HTMLRender(
<LabelledAutocomplete menuProps={{items: mockItems, selectedItemIds: []}} />
)
const inputNode = container.querySelector('#autocompleteInput')

inputNode && userEvent.type(inputNode, 'ze')
inputNode && (await user.type(inputNode, 'ze'))
expect(getByDisplayValue('zero')).toBeDefined()
})

it('does not show or highlight suggestion text after the user hits Backspace until they hit another key', () => {
it('does not show or highlight suggestion text after the user hits Backspace until they hit another key', async () => {
const user = userEvent.setup()
const {container, getByDisplayValue} = HTMLRender(
<LabelledAutocomplete menuProps={{items: mockItems, selectedItemIds: []}} />
)
const inputNode = container.querySelector('#autocompleteInput')

expect((inputNode as HTMLInputElement).selectionStart).toBe(0)
inputNode && userEvent.type(inputNode, 'ze')
inputNode && (await user.type(inputNode, 'ze'))
expect(getByDisplayValue('zero')).toBeDefined()
expect((inputNode as HTMLInputElement).selectionStart).toBe(2)
expect((inputNode as HTMLInputElement).selectionEnd).toBe(4)
inputNode && userEvent.type(inputNode, '{backspace}')
inputNode && (await user.keyboard('{backspace}'))
expect((inputNode as HTMLInputElement).selectionStart).toBe(2)
expect(getByDisplayValue('ze')).toBeDefined()
inputNode && userEvent.type(inputNode, 'r')
inputNode && (await user.keyboard('r'))
expect((inputNode as HTMLInputElement).selectionStart).toBe(3)
expect((inputNode as HTMLInputElement).selectionEnd).toBe(4)
expect(getByDisplayValue('zero')).toBeDefined()
})

it('clears the input value when the user hits Escape', () => {
it('clears the input value when the user hits Escape', async () => {
const user = userEvent.setup()
const {container} = HTMLRender(<LabelledAutocomplete menuProps={{items: mockItems, selectedItemIds: []}} />)
const inputNode = container.querySelector('#autocompleteInput')

expect(inputNode?.getAttribute('aria-expanded')).not.toBe('true')
inputNode && userEvent.type(inputNode, 'ze')
inputNode && (await user.type(inputNode, 'ze'))
expect(inputNode?.getAttribute('aria-expanded')).toBe('true')
inputNode && userEvent.type(inputNode, '{esc}')
inputNode && (await user.keyboard('{escape}'))
expect(inputNode?.getAttribute('aria-expanded')).not.toBe('true')
})

Expand All @@ -332,18 +335,20 @@ describe('Autocomplete', () => {
})

describe('Autocomplete.Menu', () => {
it('calls a custom filter function', () => {
it('calls a custom filter function', async () => {
const user = userEvent.setup()
const filterFnMock = jest.fn()
const {container} = HTMLRender(
<LabelledAutocomplete menuProps={{items: mockItems, selectedItemIds: [], filterFn: filterFnMock}} />
)
const inputNode = container.querySelector('#autocompleteInput')

inputNode && userEvent.type(inputNode, 'ze')
inputNode && (await user.type(inputNode, 'ze'))
expect(filterFnMock).toHaveBeenCalled()
})

it('calls a custom sort function when the menu closes', () => {
it('calls a custom sort function when the menu closes', async () => {
const user = userEvent.setup()
const sortOnCloseFnMock = jest.fn()
const {container} = HTMLRender(
<LabelledAutocomplete menuProps={{items: mockItems, selectedItemIds: [], sortOnCloseFn: sortOnCloseFnMock}} />
Expand All @@ -354,29 +359,29 @@ describe('Autocomplete', () => {
// current sort order matches the result of `sortOnCloseFnMock`
expect(sortOnCloseFnMock).toHaveBeenCalledTimes(mockItems.length - 1)
if (inputNode) {
userEvent.type(inputNode, 'ze')
await user.type(inputNode, 'ze')
// eslint-disable-next-line github/no-blur
fireEvent.blur(inputNode)
}

// wait a tick for blur to finish
setTimeout(() => {
expect(sortOnCloseFnMock).toHaveBeenCalledTimes(mockItems.length)
}, 0)
await waitFor(() => expect(sortOnCloseFnMock).toHaveBeenCalled())
})

it("calls onOpenChange with the menu's open state", () => {
it("calls onOpenChange with the menu's open state", async () => {
const user = userEvent.setup()
const onOpenChangeMock = jest.fn()
const {container} = HTMLRender(
<LabelledAutocomplete menuProps={{items: mockItems, selectedItemIds: [], onOpenChange: onOpenChangeMock}} />
)
const inputNode = container.querySelector('#autocompleteInput')

inputNode && userEvent.type(inputNode, 'ze')
inputNode && (await user.type(inputNode, 'ze'))
expect(onOpenChangeMock).toHaveBeenCalled()
})

it('calls onSelectedChange with the data for the selected items', () => {
it('calls onSelectedChange with the data for the selected items', async () => {
const user = userEvent.setup()
const onSelectedChangeMock = jest.fn()
const {container} = HTMLRender(
<LabelledAutocomplete
Expand All @@ -388,7 +393,7 @@ describe('Autocomplete', () => {
expect(onSelectedChangeMock).not.toHaveBeenCalled()
if (inputNode) {
fireEvent.focus(inputNode)
userEvent.type(inputNode, '{enter}')
await user.type(inputNode, '{enter}')
}

// wait a tick for the keyboard event to be dispatched to the menu item
Expand All @@ -397,7 +402,8 @@ describe('Autocomplete', () => {
}, 0)
})

it('does not close the menu when clicking an item in the menu if selectionVariant=multiple', () => {
it('does not close the menu when clicking an item in the menu if selectionVariant=multiple', async () => {
const user = userEvent.setup()
const {getByText, container} = HTMLRender(
<LabelledAutocomplete menuProps={{items: mockItems, selectedItemIds: [], selectionVariant: 'multiple'}} />
)
Expand All @@ -408,7 +414,7 @@ describe('Autocomplete', () => {
inputNode && fireEvent.focus(inputNode)
expect(inputNode?.getAttribute('aria-expanded')).toBe('true')
fireEvent.click(itemToClickNode)
inputNode && userEvent.type(inputNode, '{enter}')
inputNode && (await user.type(inputNode, '{enter}'))
expect(inputNode?.getAttribute('aria-expanded')).toBe('true')
})

Expand Down
17 changes: 10 additions & 7 deletions src/__tests__/Checkbox.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,19 +45,20 @@ describe('Checkbox', () => {
expect(checkbox.checked).toEqual(true)
})

it('accepts a change handler that can alter the checkbox state', () => {
it('accepts a change handler that can alter the checkbox state', async () => {
const user = userEvent.setup()
const handleChange = jest.fn()
const {getByRole} = render(<Checkbox onChange={handleChange} />)

const checkbox = getByRole('checkbox') as HTMLInputElement

expect(checkbox.checked).toEqual(false)

userEvent.click(checkbox)
await user.click(checkbox)
expect(handleChange).toHaveBeenCalled()
expect(checkbox.checked).toEqual(true)

userEvent.click(checkbox)
await user.click(checkbox)
expect(handleChange).toHaveBeenCalled()
expect(checkbox.checked).toEqual(false)
})
Expand All @@ -72,7 +73,8 @@ describe('Checkbox', () => {
expect(checkbox.checked).toEqual(false)
})

it('renders an inactive checkbox state correctly', () => {
it('renders an inactive checkbox state correctly', async () => {
const user = userEvent.setup()
const handleChange = jest.fn()
const {getByRole, rerender} = render(<Checkbox disabled onChange={handleChange} />)

Expand All @@ -82,7 +84,7 @@ describe('Checkbox', () => {
expect(checkbox.checked).toEqual(false)
expect(checkbox).toHaveAttribute('aria-disabled', 'true')

userEvent.click(checkbox)
await user.click(checkbox)

expect(checkbox.disabled).toEqual(true)
expect(checkbox.checked).toEqual(false)
Expand All @@ -94,14 +96,15 @@ describe('Checkbox', () => {
expect(checkbox).toHaveAttribute('aria-disabled', 'false')
})

it('renders an uncontrolled component correctly', () => {
it('renders an uncontrolled component correctly', async () => {
const user = userEvent.setup()
const {getByRole} = render(<Checkbox defaultChecked />)

const checkbox = getByRole('checkbox') as HTMLInputElement

expect(checkbox.checked).toEqual(true)

userEvent.click(checkbox)
await user.click(checkbox)

expect(checkbox.checked).toEqual(false)
})
Expand Down
Loading

0 comments on commit 4156b71

Please sign in to comment.