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

fix(List, ListItem): Improve accessibility for List and migrate tests #949

Merged
merged 13 commits into from
May 15, 2023
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -237,9 +237,10 @@ exports[`AutosuggestDeprecated rendering should render all suggestions from the
className="ListItem ListItem--isHighlighted ListItem--clickable List__item"
id="downshift-5-item-0"
onClick={[Function]}
onKeyDown={[Function]}
onMouseDown={[Function]}
onMouseMove={[Function]}
role="presentation"
role="option"
>
<MarkedText
inline={true}
Expand Down Expand Up @@ -272,9 +273,10 @@ exports[`AutosuggestDeprecated rendering should render all suggestions from the
className="ListItem ListItem--clickable List__item"
id="downshift-5-item-1"
onClick={[Function]}
onKeyDown={[Function]}
onMouseDown={[Function]}
onMouseMove={[Function]}
role="presentation"
role="option"
>
<MarkedText
inline={true}
Expand Down Expand Up @@ -307,9 +309,10 @@ exports[`AutosuggestDeprecated rendering should render all suggestions from the
className="ListItem ListItem--clickable List__item"
id="downshift-5-item-2"
onClick={[Function]}
onKeyDown={[Function]}
onMouseDown={[Function]}
onMouseMove={[Function]}
role="presentation"
role="option"
>
<MarkedText
inline={true}
Expand Down Expand Up @@ -342,9 +345,10 @@ exports[`AutosuggestDeprecated rendering should render all suggestions from the
className="ListItem ListItem--clickable List__item"
id="downshift-5-item-3"
onClick={[Function]}
onKeyDown={[Function]}
onMouseDown={[Function]}
onMouseMove={[Function]}
role="presentation"
role="option"
>
<MarkedText
inline={true}
Expand Down Expand Up @@ -654,8 +658,9 @@ exports[`AutosuggestDeprecated rendering should render noSuggestions placeholder
key=".0"
>
<li
aria-selected={false}
className="ListItem ListItem--disabled List__item"
role="presentation"
role="option"
>
<Text
context="muted"
Expand Down Expand Up @@ -815,9 +820,10 @@ exports[`AutosuggestDeprecated rendering should render suggestions also if it pa
className="ListItem ListItem--isHighlighted ListItem--clickable List__item"
id="downshift-6-item-0"
onClick={[Function]}
onKeyDown={[Function]}
onMouseDown={[Function]}
onMouseMove={[Function]}
role="presentation"
role="option"
>
<MarkedText
inline={true}
Expand Down Expand Up @@ -850,9 +856,10 @@ exports[`AutosuggestDeprecated rendering should render suggestions also if it pa
className="ListItem ListItem--clickable List__item"
id="downshift-6-item-1"
onClick={[Function]}
onKeyDown={[Function]}
onMouseDown={[Function]}
onMouseMove={[Function]}
role="presentation"
role="option"
>
<MarkedText
inline={true}
Expand Down Expand Up @@ -885,9 +892,10 @@ exports[`AutosuggestDeprecated rendering should render suggestions also if it pa
className="ListItem ListItem--clickable List__item"
id="downshift-6-item-2"
onClick={[Function]}
onKeyDown={[Function]}
onMouseDown={[Function]}
onMouseMove={[Function]}
role="presentation"
role="option"
>
<MarkedText
inline={true}
Expand Down Expand Up @@ -920,9 +928,10 @@ exports[`AutosuggestDeprecated rendering should render suggestions also if it pa
className="ListItem ListItem--clickable List__item"
id="downshift-6-item-3"
onClick={[Function]}
onKeyDown={[Function]}
onMouseDown={[Function]}
onMouseMove={[Function]}
role="presentation"
role="option"
>
<MarkedText
inline={true}
Expand Down
67 changes: 39 additions & 28 deletions src/components/Dropdown/__tests__/Dropdown.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ describe('Dropdown', () => {
const mockOnDropdownStateChange = jest.fn();
let view;

const getListItemAt = (index) => screen.getAllByRole('option')[index];

beforeEach(() => {
view = render(
<Dropdown
Expand All @@ -39,16 +41,18 @@ describe('Dropdown', () => {

it('should render correctly closed', () => {
expect(view.container).toMatchSnapshot();
expect(screen.queryAllByRole('presentation')).toHaveLength(0);
expect(screen.queryAllByRole('option')).toHaveLength(0);
});

it('should render correctly opened', async () => {
await userEvent.click(screen.getByRole('button', { name: 'Click me!' }));
const user = userEvent.setup();
await user.click(screen.getByRole('button', { name: 'Click me!' }));
expect(view.container).toMatchSnapshot();
expect(screen.getAllByRole('listbox')).toHaveLength(1);
expect(screen.getAllByRole('presentation')).toHaveLength(2);
expect(screen.getAllByRole('option')).toHaveLength(2);
});
it('should downshift only by enabled items with value', async () => {
const user = userEvent.setup();
const { container } = render(
<Dropdown
button={<Button isPrimary>Click me!</Button>}
Expand All @@ -70,25 +74,26 @@ describe('Dropdown', () => {
</ListItem>
</Dropdown>
);
await userEvent.click(screen.getAllByRole('button', { name: 'Click me!' })[1]);
await user.click(screen.getAllByRole('button', { name: 'Click me!' })[1]);
expect(container).toMatchSnapshot();
const keyDown = () => userEvent.click(screen.getAllByRole('listbox')[1]);
const keyDown = () => user.click(screen.getAllByRole('listbox')[1]);

// 1 keydown
keyDown();
expect(screen.getAllByRole('presentation')[1].getAttribute('aria-selected')).toBeTruthy();
expect(screen.getAllByRole('presentation')[1]).toHaveTextContent('With value 1');
expect(getListItemAt(1).getAttribute('aria-selected')).toBeTruthy();
expect(getListItemAt(1)).toHaveTextContent('With value 1');
// 2 keydown
keyDown();
expect(screen.getAllByRole('presentation')[3].getAttribute('aria-selected')).toBeTruthy();
expect(screen.getAllByRole('presentation')[3]).toHaveTextContent('With value 2');
expect(getListItemAt(3).getAttribute('aria-selected')).toBeTruthy();
expect(getListItemAt(3)).toHaveTextContent('With value 2');
// 3 keydown. Should be again last not disabled with value item => 'With value 2'
keyDown();
expect(screen.getAllByRole('presentation')[3].getAttribute('aria-selected')).toBeTruthy();
expect(screen.getAllByRole('presentation')[3]).toHaveTextContent('With value 2');
expect(getListItemAt(3).getAttribute('aria-selected')).toBeTruthy();
expect(getListItemAt(3)).toHaveTextContent('With value 2');
});

it('onChange should return passed value', async () => {
const user = userEvent.setup();
render(
<Dropdown
button={<Button isPrimary>Click me!</Button>}
Expand All @@ -103,15 +108,16 @@ describe('Dropdown', () => {
</ListItem>
</Dropdown>
);
await userEvent.click(screen.getAllByRole('button', { name: 'Click me!' })[1]);
await user.click(screen.getAllByRole('button', { name: 'Click me!' })[1]);

await userEvent.keyboard('[ArrowDown]');
await userEvent.keyboard('[Enter]');
await user.keyboard('[ArrowDown]');
await user.keyboard('[Enter]');

expect(mockOnChange).toBeCalledWith('testValue');
});

it('should render correctly with mixed children: array and single ListItem', async () => {
const user = userEvent.setup();
const { container } = render(
<Dropdown
button={<Button isPrimary>Click me!</Button>}
Expand All @@ -128,49 +134,53 @@ describe('Dropdown', () => {
))}
</Dropdown>
);
await userEvent.click(screen.getAllByRole('button', { name: 'Click me!' })[1]);
await user.click(screen.getAllByRole('button', { name: 'Click me!' })[1]);
expect(container).toMatchSnapshot();
expect(screen.getAllByRole('presentation')).toHaveLength(3);
expect(screen.getAllByRole('option')).toHaveLength(3);
});

it('should call cb when button is clicked', async () => {
await userEvent.click(screen.getByRole('button', { name: 'Click me!' }));
const user = userEvent.setup();
await user.click(screen.getByRole('button', { name: 'Click me!' }));
expect(mockOnButtonClick).toHaveBeenCalledWith(false);
await userEvent.click(screen.getByRole('button', { name: 'Click me!' }));
await user.click(screen.getByRole('button', { name: 'Click me!' }));
expect(mockOnButtonClick).toHaveBeenCalledWith(true);
});

it('should call callback when menu is focused', async () => {
await userEvent.click(screen.getByRole('button', { name: 'Click me!' }));
await userEvent.click(screen.getByRole('listbox'));
const user = userEvent.setup();
await user.click(screen.getByRole('button', { name: 'Click me!' }));
await user.click(screen.getByRole('listbox'));

expect(mockOnMenuFocus).toHaveBeenCalled();
});

it('should call callback when menu is blurred', async () => {
await userEvent.click(screen.getByRole('button', { name: 'Click me!' }));
await userEvent.click(screen.getByRole('listbox'));
await userEvent.click(document.body);
const user = userEvent.setup();
await user.click(screen.getByRole('button', { name: 'Click me!' }));
await user.click(screen.getByRole('listbox'));
await user.click(document.body);

expect(mockOnMenuBlur).toHaveBeenCalled();
});

it('should call callback when menu state is changed', async () => {
await userEvent.click(screen.getByRole('button', { name: 'Click me!' }));
const user = userEvent.setup();
await user.click(screen.getByRole('button', { name: 'Click me!' }));
// Event for a successful mouse click on dropdown button
expect(mockOnDropdownStateChange).toHaveBeenCalledWith({
isOpen: true,
type: '__togglebutton_click__',
});

await userEvent.keyboard('[ArrowDown]');
await user.keyboard('[ArrowDown]');
// Event for a successful arrow down press when menu is opened
expect(mockOnDropdownStateChange).toHaveBeenCalledWith({
highlightedIndex: 0,
type: '__menu_keydown_arrow_down__',
});

await userEvent.click(document.body);
await user.click(document.body);
// Event for a successful dropdown blur
expect(mockOnDropdownStateChange).toHaveBeenCalledWith({
highlightedIndex: -1,
Expand Down Expand Up @@ -200,10 +210,11 @@ describe('Dropdown', () => {
</Dropdown>
);

expect(screen.getAllByRole('presentation')).toHaveLength(3);
expect(screen.getAllByRole('option')).toHaveLength(3);
});

it('should allow for conditional rendering of items', async () => {
const user = userEvent.setup();
const condition = false;
const { container } = render(
<Dropdown
Expand All @@ -222,7 +233,7 @@ describe('Dropdown', () => {
{condition ? <ListItem key="3">should not render</ListItem> : null}
</Dropdown>
);
await userEvent.click(screen.getAllByRole('button', { name: 'Click me!' })[1]);
await user.click(screen.getAllByRole('button', { name: 'Click me!' })[1]);

expect(container).toMatchSnapshot();
expect(screen.queryByText('false')).not.toBeInTheDocument();
Expand Down
Loading