Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RTL migration: controls #602

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/controls/paginator/page-link.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ function PageLink({ className, active, onClick, children, ...rest }) {
return (
<li className={classnames(className, { active: active })}>
<a
role="link"
chawes13 marked this conversation as resolved.
Show resolved Hide resolved
onClick={onClick}
onKeyPress={triggerOnKeys(onClick, ENTER_KEY_CODE)} // keyboard interaction requirement
aria-current={active ? 'page' : false}
Expand Down
3 changes: 3 additions & 0 deletions test/controls/color-picker.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ import React from 'react'
import { mount } from 'enzyme'
import { ColorPicker } from '../../src/'

// TODO: Migrate after incoming change to use a button instead of a div
// https://github.com/LaunchPadLab/lp-components/pull/596
chawes13 marked this conversation as resolved.
Show resolved Hide resolved

test('ColorPicker toggles expanded when swatch is clicked', () => {
const wrapper = mount(<ColorPicker />)
expect(wrapper.find('.popover').exists()).toBe(false)
Expand Down
105 changes: 56 additions & 49 deletions test/controls/paginator/paginator.test.js
Original file line number Diff line number Diff line change
@@ -1,99 +1,106 @@
import React from 'react'
import { mount } from 'enzyme'
import { render, screen } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import { Paginator } from '../../../src/'

test('Previous button renders unless value is min', () => {
const wrapper = mount(<Paginator value={5} min={1} max={10} />)
expect(wrapper.find('.prev').exists()).toBe(true)
wrapper.setProps({ value: 1 })
expect(wrapper.find('.prev').exists()).toBe(false)
test('Previous control renders unless value is min', () => {
const { rerender } = render(<Paginator value={5} min={1} max={10} />)
expect(screen.getByRole('link', { name: /previous page/i })).toBeInTheDocument()
rerender(<Paginator value={1} min={1} max={10} />)
expect(screen.queryByRole('link', { name: /previous page/i })).not.toBeInTheDocument()
})

test('Next button renders unless value is max', () => {
const wrapper = mount(<Paginator value={5} min={1} max={10} />)
expect(wrapper.find('.next').exists()).toBe(true)
wrapper.setProps({ value: 10 })
expect(wrapper.find('.next').exists()).toBe(false)
test('Next control renders unless value is max', () => {
const { rerender } = render(<Paginator value={5} min={1} max={10} />)
expect(screen.getByRole('link', { name: /next page/i })).toBeInTheDocument()
rerender(<Paginator value={10} min={1} max={10} />)
expect(screen.queryByRole('link', { name: /next page/i })).not.toBeInTheDocument()
})

test('Button with current value is marked as active', () => {
const wrapper = mount(<Paginator value={5} min={1} max={10} />)
expect(wrapper.find('.active').text()).toBe('5')
test('Control with current value is marked as active', () => {
render(<Paginator value={5} min={1} max={10} />)
expect(screen.getByText(5).parentElement).toHaveClass('active')
})

test('Button click sets value', () => {
test('Control click sets value', async () => {
const onChange = jest.fn()
const wrapper = mount(
const user = userEvent.setup()

render(
<Paginator value={5} min={1} max={10} onChange={onChange} />
)
wrapper.find('li > a').at(2).simulate('click')
await user.click(screen.getAllByRole('link').at(2))
expect(onChange).toHaveBeenCalledWith(4)
})

test('Previous button decrements value', () => {
test('Previous control decrements value', async () => {
const onChange = jest.fn()
const wrapper = mount(
<Paginator value={5} min={1} max={10} onChange={onChange} />
const user = userEvent.setup()
const currentValue = 5
render(
<Paginator value={currentValue} min={1} max={10} onChange={onChange} />
)
wrapper.find('li > a').first().simulate('click')
expect(onChange).toHaveBeenCalledWith(4)
await user.click(screen.getByRole('link', { name: /previous page/i }))
expect(onChange).toHaveBeenCalledWith(currentValue - 1)
})

test('Next button increments value', () => {
test('Next control increments value', async () => {
const onChange = jest.fn()
const wrapper = mount(
<Paginator value={5} min={1} max={10} onChange={onChange} />
const user = userEvent.setup()
const currentValue = 5
render(
<Paginator value={currentValue} min={1} max={10} onChange={onChange} />
)
wrapper.find('li > a').last().simulate('click')
expect(onChange).toHaveBeenCalledWith(6)
await user.click(screen.getByRole('link', { name: /next page/i }))
expect(onChange).toHaveBeenCalledWith(currentValue + 1)
})

test('Min button sets value to min', () => {
test('Min control sets value to min', async () => {
const onChange = jest.fn()
const wrapper = mount(
const user = userEvent.setup()
render(
<Paginator value={5} min={1} max={10} onChange={onChange} />
)
wrapper.find('li > a').at(1).simulate('click')
await user.click(screen.getByRole('link', { name: /page 1$/ }))
expect(onChange).toHaveBeenCalledWith(1)
})

test('Max button sets value to max', () => {
test('Max control sets value to max', async () => {
const onChange = jest.fn()
const wrapper = mount(
const user = userEvent.setup()
render(
<Paginator value={5} min={1} max={10} onChange={onChange} />
)
wrapper.find('li > a').at(5).simulate('click')
await user.click(screen.getByRole('link', { name: /page 10$/ }))
expect(onChange).toHaveBeenCalledWith(10)
})

test('Current page is indicated via aria-current', () => {
const wrapper = mount(<Paginator value={5} min={1} max={10} />)
expect(wrapper.find('.active > a').prop('aria-current')).toBe('page')
expect(wrapper.find('a').not('.active').first().prop('aria-current')).toBe(
false
)
render(<Paginator value={5} min={1} max={10} />)
expect(screen.getByText(5)).toHaveAttribute('aria-current', 'page')
expect(screen.getByText(1)).toHaveAttribute('aria-current', 'false')
})

test('Destination is indicated via aria-label', () => {
const wrapper = mount(<Paginator value={5} min={1} max={10} />)
expect(wrapper.find('.active > a').prop('aria-label')).toBe('Go to page 5')
render(<Paginator value={5} min={1} max={10} />)
expect(screen.getByLabelText('Go to page 5')).toBeInTheDocument()
})

test('Page button is triggered via click or enter', () => {
test('Page control is triggered via click or enter', async () => {
const onChange = jest.fn()
const wrapper = mount(
const user = userEvent.setup()
render(
<Paginator value={5} min={1} max={10} onChange={onChange} />
)
const link = wrapper.find('li > a').at(2)
link.simulate('click')
link.simulate('keypress', { keyCode: 13 })

expect(onChange).toHaveBeenCalledTimes(2)
await user.click(screen.getByLabelText('Go to page 1'))
await user.keyboard('{Enter}')
expect(onChange).toHaveBeenNthCalledWith(1, 1)
expect(onChange).toHaveBeenNthCalledWith(2, 1)
})

test('Can accept custom delimiter', () => {
const wrapper = mount(
render(
<Paginator value={1} min={1} max={10} delimiter="foo" />
)
expect(wrapper.find('.delimiter').contains('foo')).toBe(true)
expect(screen.getByText('foo')).toBeInTheDocument()
})
100 changes: 44 additions & 56 deletions test/controls/tab-bar.test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React from 'react'
import { mount } from 'enzyme'
import { render, screen } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import { TabBar } from '../../src/'

const defaultOptions = ['Home', 'Account']
Expand All @@ -9,107 +10,94 @@ const objectOptions = [
]

test('TabBar defaults to horizontal alignment', () => {
const wrapper = mount(<TabBar options={defaultOptions} value="home" />)
expect(wrapper.find('ul').hasClass('horizontal-tabs')).toEqual(true)
render(<TabBar options={defaultOptions} value="home" />)
expect(screen.getByRole('tablist')).toHaveAttribute('aria-orientation', 'horizontal')
})

test('TabBar aligns vertically with vertical option', () => {
const wrapper = mount(
render(
<TabBar options={defaultOptions} vertical={true} value="home" />
)
expect(wrapper.find('ul').hasClass('vertical-tabs')).toEqual(true)
expect(screen.getByRole('tablist')).toHaveAttribute('aria-orientation', 'vertical')
})

test('TabBar renders defaultOptions', () => {
const wrapper = mount(<TabBar options={defaultOptions} value="home" />)
expect(wrapper.find('li').first().text()).toEqual('Home')
expect(wrapper.find('li').last().text()).toEqual('Account')
render(<TabBar options={defaultOptions} value="home" />)
expect(screen.getByText('Home')).toBeInTheDocument()
expect(screen.getByText('Account')).toBeInTheDocument()
})

test('TabBar renders objectOptions', () => {
const wrapper = mount(<TabBar options={objectOptions} value="home" />)
expect(wrapper.find('li').first().text()).toEqual('Home')
expect(wrapper.find('li').last().text()).toEqual('Account')
render(<TabBar options={objectOptions} value="home" />)
expect(screen.getByText('Home')).toBeInTheDocument()
expect(screen.getByText('Account')).toBeInTheDocument()
})

test('TabBar adds Active class', () => {
const wrapper = mount(<TabBar options={objectOptions} value="home" />)
expect(wrapper.find('li').first().hasClass('active')).toEqual(true)
render(<TabBar options={objectOptions} value="home" />)
expect(screen.getByText('Home').parentElement).toHaveClass('active')
})

test('TabBar calls onChange', () => {
test('TabBar calls onChange', async () => {
const onChange = jest.fn()
const wrapper = mount(
const user = userEvent.setup()
render(
<TabBar options={objectOptions} value="home" onChange={onChange} />
)
wrapper.find('li > a').first().simulate('click')
expect(onChange).toHaveBeenCalledWith('home')
await user.click(screen.getByText(objectOptions[0].key))
expect(onChange).toHaveBeenCalledWith(objectOptions[0].value)
})

test('TabBar passes down custom className to ul', () => {
const wrapper = mount(
render(
<TabBar options={objectOptions} value="home" className="custom" />
)
expect(wrapper.find('ul').hasClass('custom')).toEqual(true)
expect(screen.getByRole('tablist')).toHaveClass('tabs', 'custom')
})

test('TabBar passes down custom activeClassName to li', () => {
const wrapper = mount(
render(
<TabBar options={objectOptions} value="home" activeClassName="custom" />
)
expect(wrapper.find('li').first().hasClass('custom')).toEqual(true)
const homeTab = screen.getByText('Home')
expect(homeTab.parentElement).toHaveClass('custom')
expect(homeTab.parentElement).not.toHaveClass('active')
})

test('TabBar assigns appropriate aria roles', () => {
const wrapper = mount(<TabBar options={defaultOptions} value="home" />)
expect(wrapper.find('ul').prop('role')).toBe('tablist')
expect(wrapper.find('li > a').every('[role="tab"]')).toBe(true)
})

test('TabBar assigns appropriate aria orientation', () => {
const horizontalWrapper = mount(
<TabBar options={defaultOptions} vertical={false} value="home" />
)
const verticalWrapper = mount(
<TabBar options={defaultOptions} vertical value="home" />
)

expect(
horizontalWrapper.find('[role="tablist"]').prop('aria-orientation')
).toBe('horizontal')
expect(
verticalWrapper.find('[role="tablist"]').prop('aria-orientation')
).toBe('vertical')
chawes13 marked this conversation as resolved.
Show resolved Hide resolved
render(<TabBar options={defaultOptions} value="home" />)
expect(screen.getByRole('tablist')).toBeInTheDocument()
expect(screen.getAllByRole('tab').length).toBe(defaultOptions.length)
})

test('TabBar assigns unique id to tab', () => {
const wrapper = mount(<TabBar options={defaultOptions} value="home" />)
expect(wrapper.find('li > a').first().prop('id')).toContain(
defaultOptions[0].toLowerCase()
)
render(<TabBar options={defaultOptions} value="home" />)
expect(screen.getByText('Home')).toHaveAttribute('id', 'tab-' + defaultOptions[0].toLowerCase())
})

test('Inactive tabs are explicitly removed from the natural tab order', () => {
const wrapper = mount(<TabBar options={defaultOptions} value="home" />)
expect(
wrapper.find('li').not('.active').find('a').every('[tabIndex="-1"]')
).toBe(true)
render(<TabBar options={defaultOptions} value="home" />)
expect(screen.getByText('Account')).toHaveAttribute('tabIndex', '-1')
})

test('Tab to show is triggered via Enter', () => {
test('Tab to show is triggered via Enter', async () => {
const onChange = jest.fn()
const wrapper = mount(
const user = userEvent.setup()
render(
<TabBar options={objectOptions} value="home" onChange={onChange} />
)
wrapper.find('li > a').first().simulate('keyPress', { keyCode: 13 })
expect(onChange).toHaveBeenCalledWith('home')
screen.getByText(objectOptions[1].key).focus()
chawes13 marked this conversation as resolved.
Show resolved Hide resolved
await user.keyboard('{Enter}')
expect(onChange).toHaveBeenCalledWith(objectOptions[1].value)
})

test('Tab to show is triggered via Space', () => {
test('Tab to show is triggered via Space', async () => {
const onChange = jest.fn()
const wrapper = mount(
const user = userEvent.setup()
render(
<TabBar options={objectOptions} value="home" onChange={onChange} />
)
wrapper.find('li > a').first().simulate('keyPress', { keyCode: 32 })
expect(onChange).toHaveBeenCalledWith('home')
screen.getByText(objectOptions[1].key).focus()
await user.keyboard('[Space]')
expect(onChange).toHaveBeenCalledWith(objectOptions[1].value)
})