-
Notifications
You must be signed in to change notification settings - Fork 352
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chore(Dropdown next): add testing (#8640)
* add integration tests, issue with keypress tests * use shared mocks * fix integration tests * temporarily remove onOpenChange test * default behavior tests, small changes
- Loading branch information
1 parent
d557fbd
commit c29744e
Showing
20 changed files
with
698 additions
and
0 deletions.
There are no files selected for viewing
12 changes: 12 additions & 0 deletions
12
packages/react-core/src/components/Menu/__mocks__/Menu.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import React from 'react'; | ||
import { MenuProps } from '../Menu'; | ||
|
||
export const Menu = ({ className, isPlain, isScrollable, style, onSelect, ...props }: MenuProps) => ( | ||
<> | ||
<div className={className} data-testid="menu-mock" {...props}></div> | ||
<div onClick={onSelect}>{'Mock item'}</div> | ||
<p>{`isPlain: ${isPlain}`}</p> | ||
<p>{`isScrollable: ${isScrollable}`}</p> | ||
<p>{`minWidth: ${style?.['--pf-c-menu--MinWidth']}`}</p> | ||
</> | ||
); |
3 changes: 3 additions & 0 deletions
3
packages/react-core/src/components/Menu/__mocks__/MenuContent.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
import React from 'react'; | ||
|
||
export const MenuContent = ({ children }) => <div>{children}</div>; |
12 changes: 12 additions & 0 deletions
12
packages/react-core/src/components/Menu/__mocks__/MenuGroup.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import React from 'react'; | ||
import { MenuGroupProps } from '../MenuGroup'; | ||
|
||
export const MenuGroup = ({ className, children, label, labelHeadingLevel }: MenuGroupProps) => ( | ||
<> | ||
<div className={className} data-testid="menu-group-mock"> | ||
{children} | ||
</div> | ||
<p>{`label: ${label}`}</p> | ||
<p>{`labelHeadingLevel: ${labelHeadingLevel}`}</p> | ||
</> | ||
); |
12 changes: 12 additions & 0 deletions
12
packages/react-core/src/components/Menu/__mocks__/MenuItem.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import React from 'react'; | ||
import { MenuItemProps } from '../MenuItem'; | ||
|
||
export const MenuItem = ({ className, children, description, itemId }: MenuItemProps) => ( | ||
<> | ||
<div className={className} data-testid="menu-item-mock"> | ||
{children} | ||
</div> | ||
<p>{`description: ${description}`}</p> | ||
<p>{`itemId: ${itemId}`}</p> | ||
</> | ||
); |
10 changes: 10 additions & 0 deletions
10
packages/react-core/src/components/Menu/__mocks__/MenuList.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import React from 'react'; | ||
import { MenuListProps } from '../MenuList'; | ||
|
||
export const MenuList = ({ className, children }: MenuListProps) => ( | ||
<> | ||
<div className={className} data-testid="menu-list-mock"> | ||
{children} | ||
</div> | ||
</> | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
export * from './Menu'; | ||
export * from './MenuContent'; | ||
export * from './MenuGroup'; | ||
export * from './MenuItem'; | ||
export * from './MenuList'; |
11 changes: 11 additions & 0 deletions
11
packages/react-core/src/helpers/Popper/__mocks__/Popper.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import React from 'react'; | ||
import { PopperProps } from '../Popper'; | ||
|
||
export const Popper = ({ popper, zIndex, isVisible, trigger }: PopperProps) => ( | ||
<> | ||
<div>{popper}</div> | ||
<p>{`zIndex: ${zIndex}`}</p> | ||
<p>{`isOpen: ${isVisible}`}</p> | ||
<div>{trigger}</div> | ||
</> | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * from './Popper'; |
236 changes: 236 additions & 0 deletions
236
packages/react-core/src/next/components/Dropdown/__tests__/Dropdown.test.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,236 @@ | ||
import React from 'react'; | ||
import { Dropdown } from '../../Dropdown'; | ||
import { render, screen, waitFor } from '@testing-library/react'; | ||
import userEvent from '@testing-library/user-event'; | ||
|
||
jest.mock('../../../../components/Menu'); | ||
|
||
jest.mock('../../../../helpers/Popper/Popper'); | ||
|
||
const toggle = (ref: React.RefObject<any>) => <button ref={ref}>Dropdown</button>; | ||
|
||
const dropdownChildren = <div>Dropdown children</div>; | ||
|
||
test('renders dropdown', () => { | ||
render( | ||
<div data-testid="dropdown"> | ||
<Dropdown toggle={toggleRef => toggle(toggleRef)}>{dropdownChildren}</Dropdown> | ||
</div> | ||
); | ||
|
||
expect(screen.getByTestId('dropdown').children[0]).toBeVisible(); | ||
}); | ||
|
||
test('passes children', () => { | ||
render(<Dropdown toggle={toggleRef => toggle(toggleRef)}>{dropdownChildren}</Dropdown>); | ||
|
||
expect(screen.getByText('Dropdown children')).toBeVisible(); | ||
}); | ||
|
||
test('renders passed toggle element', () => { | ||
render(<Dropdown toggle={toggleRef => toggle(toggleRef)}>{dropdownChildren}</Dropdown>); | ||
|
||
expect(screen.getByRole('button', { name: 'Dropdown' })).toBeVisible(); | ||
}); | ||
|
||
test('passes no class name by default', () => { | ||
render( | ||
<Dropdown isOpen={true} toggle={toggleRef => toggle(toggleRef)}> | ||
{dropdownChildren} | ||
</Dropdown> | ||
); | ||
|
||
expect(screen.getByTestId('menu-mock')).not.toHaveClass(); | ||
}); | ||
|
||
test('passes custom class name', () => { | ||
render( | ||
<Dropdown className="custom-class" isOpen={true} toggle={toggleRef => toggle(toggleRef)}> | ||
{dropdownChildren} | ||
</Dropdown> | ||
); | ||
|
||
expect(screen.getByTestId('menu-mock')).toHaveClass('custom-class'); | ||
}); | ||
|
||
test('does not pass isPlain to Menu by default', () => { | ||
render( | ||
<Dropdown isOpen={true} toggle={toggleRef => toggle(toggleRef)}> | ||
{dropdownChildren} | ||
</Dropdown> | ||
); | ||
|
||
expect(screen.getByText('isPlain: undefined')).toBeVisible(); | ||
}); | ||
|
||
test('passes isPlain to Menu', () => { | ||
render( | ||
<Dropdown isPlain isOpen={true} toggle={toggleRef => toggle(toggleRef)}> | ||
{dropdownChildren} | ||
</Dropdown> | ||
); | ||
|
||
expect(screen.getByText('isPlain: true')).toBeVisible(); | ||
}); | ||
|
||
test('does not pass isScrollable to Menu by default', () => { | ||
render( | ||
<Dropdown isOpen={true} toggle={toggleRef => toggle(toggleRef)}> | ||
{dropdownChildren} | ||
</Dropdown> | ||
); | ||
|
||
expect(screen.getByText('isScrollable: undefined')).toBeVisible(); | ||
}); | ||
|
||
test('passes isScrollable to Menu', () => { | ||
render( | ||
<Dropdown isScrollable isOpen={true} toggle={toggleRef => toggle(toggleRef)}> | ||
{dropdownChildren} | ||
</Dropdown> | ||
); | ||
|
||
expect(screen.getByText('isScrollable: true')).toBeVisible(); | ||
}); | ||
|
||
test('does not pass minWidth to Menu by default', () => { | ||
render( | ||
<Dropdown isOpen={true} toggle={toggleRef => toggle(toggleRef)}> | ||
{dropdownChildren} | ||
</Dropdown> | ||
); | ||
|
||
expect(screen.getByText('minWidth: undefined')).toBeVisible(); | ||
}); | ||
|
||
test('passes minWidth to Menu', () => { | ||
render( | ||
<Dropdown minWidth="100px" isOpen={true} toggle={toggleRef => toggle(toggleRef)}> | ||
{dropdownChildren} | ||
</Dropdown> | ||
); | ||
|
||
expect(screen.getByText('minWidth: 100px')).toBeVisible(); | ||
}); | ||
|
||
test('passes default zIndex to popper', () => { | ||
render(<Dropdown toggle={toggleRef => toggle(toggleRef)}>{dropdownChildren}</Dropdown>); | ||
|
||
expect(screen.getByText('zIndex: 9999')).toBeVisible(); | ||
}); | ||
|
||
test('passes zIndex to popper', () => { | ||
render( | ||
<Dropdown zIndex={100} toggle={toggleRef => toggle(toggleRef)}> | ||
{dropdownChildren} | ||
</Dropdown> | ||
); | ||
|
||
expect(screen.getByText('zIndex: 100')).toBeVisible(); | ||
}); | ||
|
||
test('does not pass isOpen to popper by default', () => { | ||
render(<Dropdown toggle={toggleRef => toggle(toggleRef)}>{dropdownChildren}</Dropdown>); | ||
|
||
expect(screen.getByText('isOpen: undefined')).toBeVisible(); | ||
}); | ||
|
||
test('passes isOpen to popper', () => { | ||
render( | ||
<Dropdown isOpen toggle={toggleRef => toggle(toggleRef)}> | ||
{dropdownChildren} | ||
</Dropdown> | ||
); | ||
|
||
expect(screen.getByText('isOpen: true')).toBeVisible(); | ||
}); | ||
|
||
/* no default tests for callback props | ||
since there is no way to test that the | ||
function doesn`t get passed */ | ||
|
||
test('passes onSelect callback', async () => { | ||
const user = userEvent.setup(); | ||
|
||
const onSelect = jest.fn(); | ||
render( | ||
<Dropdown onSelect={onSelect} toggle={toggleRef => toggle(toggleRef)}> | ||
{dropdownChildren} | ||
</Dropdown> | ||
); | ||
|
||
const trigger = await screen.findByText('Mock item'); | ||
await user.click(trigger); | ||
|
||
expect(onSelect).toBeCalledTimes(1); | ||
}); | ||
|
||
test('onOpenChange is called when passed and user clicks outside of dropdown', async () => { | ||
const user = userEvent.setup(); | ||
const onOpenChange = jest.fn(); | ||
|
||
render( | ||
<Dropdown isOpen={true} onOpenChange={onOpenChange} toggle={toggleRef => toggle(toggleRef)}> | ||
{dropdownChildren} | ||
</Dropdown> | ||
); | ||
|
||
const dropdown = screen.getByRole('button', { name: 'Dropdown' }); | ||
await user.click(dropdown); | ||
await user.click(document.body); | ||
|
||
expect(onOpenChange).toBeCalledTimes(1); | ||
}); | ||
|
||
test('onOpenChange is called when passed and user presses tab key', async () => { | ||
const user = userEvent.setup(); | ||
const onOpenChange = jest.fn(); | ||
|
||
render( | ||
<Dropdown isOpen={true} onOpenChange={onOpenChange} toggle={toggleRef => toggle(toggleRef)}> | ||
{dropdownChildren} | ||
</Dropdown> | ||
); | ||
|
||
//focus dropdown | ||
const dropdown = screen.getByRole('button', { name: 'Dropdown' }); | ||
await user.click(dropdown); | ||
await user.keyboard('{Tab}'); | ||
|
||
expect(onOpenChange).toBeCalledTimes(1); | ||
}); | ||
|
||
test('onOpenChange is called when passed and user presses esc key', async () => { | ||
const user = userEvent.setup(); | ||
const onOpenChange = jest.fn(); | ||
|
||
render( | ||
<Dropdown isOpen={true} onOpenChange={onOpenChange} toggle={toggleRef => toggle(toggleRef)}> | ||
{dropdownChildren} | ||
</Dropdown> | ||
); | ||
|
||
//focus dropdown | ||
const dropdown = screen.getByRole('button', { name: 'Dropdown' }); | ||
await user.click(dropdown); | ||
await user.keyboard('{Escape}'); | ||
|
||
expect(onOpenChange).toBeCalledTimes(1); | ||
}); | ||
|
||
test('match snapshot', () => { | ||
const { asFragment } = render( | ||
<Dropdown | ||
ouiaId={'dropdown'} | ||
isOpen | ||
isScrollable | ||
isPlain | ||
className={'customClass'} | ||
toggle={toggleRef => toggle(toggleRef)} | ||
> | ||
{dropdownChildren} | ||
</Dropdown> | ||
); | ||
|
||
expect(asFragment()).toMatchSnapshot(); | ||
}); |
69 changes: 69 additions & 0 deletions
69
packages/react-core/src/next/components/Dropdown/__tests__/DropdownGroup.test.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
import { DropdownGroup } from '../../Dropdown'; | ||
import { render, screen } from '@testing-library/react'; | ||
import React from 'react'; | ||
|
||
jest.mock('../../../../components/Menu'); | ||
|
||
const dropdownGroupChildren = <div>Dropdown Group children</div>; | ||
|
||
test('renders dropdown group', () => { | ||
render( | ||
<div data-testid="dropdown-group"> | ||
<DropdownGroup>{dropdownGroupChildren}</DropdownGroup> | ||
</div> | ||
); | ||
|
||
expect(screen.getByTestId('dropdown-group').children[0]).toBeVisible(); | ||
}); | ||
|
||
test('passes children', () => { | ||
render(<DropdownGroup>{dropdownGroupChildren}</DropdownGroup>); | ||
|
||
expect(screen.getByText('Dropdown Group children')).toBeVisible(); | ||
}); | ||
|
||
test('passes no class name by default', () => { | ||
render(<DropdownGroup>{dropdownGroupChildren}</DropdownGroup>); | ||
|
||
expect(screen.getByTestId('menu-group-mock')).not.toHaveClass(); | ||
}); | ||
|
||
test('passes custom class name to MenuGroup', () => { | ||
render(<DropdownGroup className="custom-class">{dropdownGroupChildren}</DropdownGroup>); | ||
|
||
expect(screen.getByTestId('menu-group-mock')).toHaveClass('custom-class'); | ||
}); | ||
|
||
test('passes no label by default', () => { | ||
render(<DropdownGroup>{dropdownGroupChildren}</DropdownGroup>); | ||
|
||
expect(screen.getByText('label: undefined')).toBeVisible(); | ||
}); | ||
|
||
test('passes custom label to MenuGroup', () => { | ||
render(<DropdownGroup label="Test label">{dropdownGroupChildren}</DropdownGroup>); | ||
|
||
expect(screen.getByText('label: Test label')).toBeVisible(); | ||
}); | ||
|
||
test('passes h1 as labelHeadingLevel to MenuGroup by default', () => { | ||
render(<DropdownGroup>{dropdownGroupChildren}</DropdownGroup>); | ||
|
||
expect(screen.getByText('labelHeadingLevel: h1')).toBeVisible(); | ||
}); | ||
|
||
test('passes custom labelHeadingLevel to MenuGroup', () => { | ||
render(<DropdownGroup labelHeadingLevel="h2">{dropdownGroupChildren}</DropdownGroup>); | ||
|
||
expect(screen.getByText('labelHeadingLevel: h2')).toBeVisible(); | ||
}); | ||
|
||
test('matches snapshot', () => { | ||
const { asFragment } = render( | ||
<DropdownGroup className="custom-class" label="Test label" labelHeadingLevel="h2"> | ||
{dropdownGroupChildren} | ||
</DropdownGroup> | ||
); | ||
|
||
expect(asFragment()).toMatchSnapshot(); | ||
}); |
Oops, something went wrong.