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

test: update Checkbox tests to use react testing library #1341

Merged
merged 5 commits into from
Feb 9, 2024
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
140 changes: 0 additions & 140 deletions packages/react/__tests__/src/components/Checkbox/index.js

This file was deleted.

1 change: 1 addition & 0 deletions packages/react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
"@svgr/rollup": "^6.1.2",
"@testing-library/jest-dom": "^6.1.3",
"@testing-library/react": "11.1.2",
"@testing-library/user-event": "^14.5.2",
"@types/classnames": "^2.2.10",
"@types/enzyme-adapter-react-16": "^1.0.9",
"@types/jest": "^29.5.11",
Expand Down
187 changes: 187 additions & 0 deletions packages/react/src/components/Checkbox/Checkbox.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
import React, { createRef } from 'react';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { spy } from 'sinon';
import { axe } from 'jest-axe';
import Checkbox from './';

type SetOptional<T, Keys extends keyof T> = Pick<Partial<T>, Keys> &
Omit<T, Keys>;
type CheckboxProps = SetOptional<
React.ComponentProps<typeof Checkbox>,
'label' | 'id'
>;

const renderCheckbox = ({
label,
...props
}: CheckboxProps = {}): HTMLInputElement => {
render(<Checkbox id="checkbox-id" label={label || 'checkbox'} {...props} />);
// no individual assertions needed, as this should throw if the element does not exist
return screen.getByRole('checkbox', {
name: label as string
}) as HTMLInputElement;
};

test('should render unchecked checkbox', () => {
const input = renderCheckbox({ label: 'this is a checkbox' });
expect(input).not.toBeChecked();
expect(screen.queryByText('this is a checkbox')).toBeInTheDocument();
});

test('should render checked checkbox', () => {
const input = renderCheckbox({ checked: true });
expect(input).toBeChecked();
});

test('should render disabled unchecked checkbox', () => {
const input = renderCheckbox({ disabled: true });
expect(input).toBeDisabled();
expect(input).not.toBeChecked();
});

test('should render disabled checked checkbox', () => {
const input = renderCheckbox({ disabled: true, checked: true });
expect(input).toBeDisabled();
expect(input).toBeChecked();
});

test('should render error checkbox', () => {
const input = renderCheckbox({ error: 'you should check this checkbox' });
expect(input).toHaveAccessibleDescription('you should check this checkbox');
expect(
screen.queryByText('you should check this checkbox')
).toBeInTheDocument();
});

test('should toggle checkbox correctly', async () => {
const user = userEvent.setup();
const input = renderCheckbox();
const checkboxIcon = input.parentElement!.querySelector(
'.Checkbox__overlay'
) as HTMLElement;
expect(checkboxIcon).toHaveClass('Icon--checkbox-unchecked');
expect(checkboxIcon).not.toHaveClass('Icon--checkbox-checked');
expect(input).not.toBeChecked();

await user.click(checkboxIcon);
expect(checkboxIcon).not.toHaveClass('Icon--checkbox-unchecked');
expect(checkboxIcon).toHaveClass('Icon--checkbox-checked');
});

test('should handle focus correctly', () => {
const onFocus = spy();
const input = renderCheckbox({ onFocus });
const checkboxIcon = input.parentElement!.querySelector(
'.Checkbox__overlay'
) as HTMLElement;
expect(checkboxIcon).not.toHaveClass('.Checkbox__overlay--focused');
expect(onFocus.notCalled).toBeTruthy();

input.focus();
expect(input).toHaveFocus();
expect(checkboxIcon).toHaveClass('Checkbox__overlay--focused');
expect(onFocus.calledOnce).toBeTruthy();
});

test('should handle blur correctly', () => {
const onBlur = spy();
const input = renderCheckbox({ onBlur, checked: true });
const checkboxIcon = input.parentElement!.querySelector(
'.Checkbox__overlay'
) as HTMLElement;
expect(checkboxIcon).not.toHaveClass('.Checkbox__overlay--focused');
scurker marked this conversation as resolved.
Show resolved Hide resolved
expect(onBlur.notCalled).toBeTruthy();

input.focus();
input.blur();
expect(input).not.toHaveFocus();
expect(checkboxIcon).not.toHaveClass('Checkbox__overlay--focused');
expect(onBlur.calledOnce).toBeTruthy();
});

test('should handle onChange correctly', async () => {
const user = userEvent.setup();
const onChange = spy();
const input = renderCheckbox({ onChange });

expect(onChange.notCalled).toBeTruthy();
await user.click(input);
expect(onChange.calledOnce).toBeTruthy();
});

test('should support ref prop', () => {
const ref = createRef<HTMLInputElement>();
render(<Checkbox id="id" label="checkbox" ref={ref} />);
expect(ref.current).toBeInstanceOf(HTMLInputElement);
expect(ref.current).toEqual(
screen.queryByRole('checkbox', { name: 'checkbox' })
);
});

test('should support checkboxRef prop', () => {
const ref = createRef<HTMLInputElement>();
render(<Checkbox id="id" label="checkbox" checkboxRef={ref} />);
expect(ref.current).toBeInstanceOf(HTMLInputElement);
expect(ref.current).toEqual(
screen.queryByRole('checkbox', { name: 'checkbox' })
);
});

test('should support className prop', () => {
const input = renderCheckbox({ className: 'banana' });
expect(input.parentElement).toHaveClass('Checkbox', 'banana');
});

test('should support value prop', () => {
render(
<form data-testid="form">
<Checkbox id="id-1" name="checkbox" label="checkbox" value="apples" />
<Checkbox
id="id-2"
name="checkbox"
label="checkbox"
value="bananas"
checked
/>
</form>
);
const form = screen.getByTestId('form');
expect(form).toHaveFormValues({ checkbox: ['bananas'] });
});

test('should support labelDescription prop', () => {
const input = renderCheckbox({
labelDescription: 'more stuff and things you should know'
});
expect(input).toHaveAccessibleDescription(
/more stuff and things you should know/
);
expect(
screen.queryByText('more stuff and things you should know')
).toBeInTheDocument();
});

test('should have no axe violations with unchecked checkbox', async () => {
const input = renderCheckbox();
const results = await axe(input);
expect(results).toHaveNoViolations();
});

test('should have no axe violations with checked checkbox', async () => {
const input = renderCheckbox({ checked: true });
const results = await axe(input);
expect(results).toHaveNoViolations();
});

test('should have no axe violations with disabled checkbox', async () => {
const input = renderCheckbox({ disabled: true });
const results = await axe(input);
expect(results).toHaveNoViolations();
});

test('should have no axe violations when checkbox has errors', async () => {
const input = renderCheckbox({ error: 'you should check this checkbox' });
const results = await axe(input);
expect(results).toHaveNoViolations();
});
5 changes: 5 additions & 0 deletions packages/react/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1789,6 +1789,11 @@
"@babel/runtime" "^7.12.1"
"@testing-library/dom" "^7.26.6"

"@testing-library/user-event@^14.5.2":
version "14.5.2"
resolved "https://registry.yarnpkg.com/@testing-library/user-event/-/user-event-14.5.2.tgz#db7257d727c891905947bd1c1a99da20e03c2ebd"
integrity sha512-YAh82Wh4TIrxYLmfGcixwD18oIjyC1pFQC2Y01F2lzV2HTMiYrI0nze0FD0ocB//CKS/7jIUgae+adPqxK5yCQ==

"@tootallnate/once@2":
version "2.0.0"
resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-2.0.0.tgz#f544a148d3ab35801c1f633a7441fd87c2e484bf"
Expand Down
Loading