Convert old tests to use "react-testing-library"

This commit is contained in:
Justin
2022-04-04 11:53:47 -04:00
parent 9a099b3fa7
commit ed47cf5f09
71 changed files with 411 additions and 1515 deletions

View File

@ -1,72 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`<Button /> adds class "button-secondary" if props.theme="secondary" given 1`] = `
<button
className="inline-flex items-center border font-medium rounded-full focus:outline-none appearance-none transition-all border-transparent text-primary-700 bg-primary-100 hover:bg-primary-200 focus:ring-primary-500 focus:ring-2 focus:ring-offset-2 px-4 py-2 text-sm"
disabled={false}
onClick={[Function]}
type="button"
/>
`;
exports[`<Button /> renders a button element 1`] = `
<button
className="inline-flex items-center border font-medium rounded-full focus:outline-none appearance-none transition-all border-transparent text-white bg-accent-500 hover:bg-accent-300 focus:ring-pink-500 focus:ring-2 focus:ring-offset-2 px-4 py-2 text-sm"
disabled={false}
onClick={[Function]}
type="button"
/>
`;
exports[`<Button /> renders a disabled attribute if props.disabled given 1`] = `
<button
className="inline-flex items-center border font-medium rounded-full focus:outline-none appearance-none transition-all select-none disabled:opacity-50 disabled:cursor-default border-transparent text-white bg-accent-500 hover:bg-accent-300 focus:ring-pink-500 focus:ring-2 focus:ring-offset-2 px-4 py-2 text-sm"
disabled={true}
onClick={[Function]}
type="button"
/>
`;
exports[`<Button /> renders class="button--block" if props.block given 1`] = `
<button
className="inline-flex items-center border font-medium rounded-full focus:outline-none appearance-none transition-all border-transparent text-white bg-accent-500 hover:bg-accent-300 focus:ring-pink-500 focus:ring-2 focus:ring-offset-2 px-4 py-2 text-sm flex w-full justify-center"
disabled={false}
onClick={[Function]}
type="button"
/>
`;
exports[`<Button /> renders the children 1`] = `
<button
className="inline-flex items-center border font-medium rounded-full focus:outline-none appearance-none transition-all border-transparent text-white bg-accent-500 hover:bg-accent-300 focus:ring-pink-500 focus:ring-2 focus:ring-offset-2 px-4 py-2 text-sm"
disabled={false}
onClick={[Function]}
type="button"
>
<p>
children
</p>
</button>
`;
exports[`<Button /> renders the given text 1`] = `
<button
className="inline-flex items-center border font-medium rounded-full focus:outline-none appearance-none transition-all border-transparent text-white bg-accent-500 hover:bg-accent-300 focus:ring-pink-500 focus:ring-2 focus:ring-offset-2 px-4 py-2 text-sm"
disabled={false}
onClick={[Function]}
type="button"
>
foo
</button>
`;
exports[`<Button /> renders the props.text instead of children 1`] = `
<button
className="inline-flex items-center border font-medium rounded-full focus:outline-none appearance-none transition-all border-transparent text-white bg-accent-500 hover:bg-accent-300 focus:ring-pink-500 focus:ring-2 focus:ring-offset-2 px-4 py-2 text-sm"
disabled={false}
onClick={[Function]}
type="button"
>
foo
</button>
`;

View File

@ -1,76 +0,0 @@
import { shallow } from 'enzyme';
import React from 'react';
import renderer from 'react-test-renderer';
import Button from '../button';
describe('<Button />', () => {
it('renders a button element', () => {
const component = renderer.create(<Button />);
const tree = component.toJSON();
expect(tree).toMatchSnapshot();
});
it('renders the given text', () => {
const text = 'foo';
const component = renderer.create(<Button text={text} />);
const tree = component.toJSON();
expect(tree).toMatchSnapshot();
});
it('handles click events using the given handler', () => {
const handler = jest.fn();
const button = shallow(<Button onClick={handler} />);
button.find('button').simulate('click');
expect(handler.mock.calls.length).toEqual(1);
});
it('does not handle click events if props.disabled given', () => {
const handler = jest.fn();
const button = shallow(<Button onClick={handler} disabled />);
button.find('button').simulate('click');
expect(handler.mock.calls.length).toEqual(0);
});
it('renders a disabled attribute if props.disabled given', () => {
const component = renderer.create(<Button disabled />);
const tree = component.toJSON();
expect(tree).toMatchSnapshot();
});
it('renders the children', () => {
const children = <p>children</p>;
const component = renderer.create(<Button>{children}</Button>);
const tree = component.toJSON();
expect(tree).toMatchSnapshot();
});
it('renders the props.text instead of children', () => {
const text = 'foo';
const children = <p>children</p>;
const component = renderer.create(<Button text={text}>{children}</Button>);
const tree = component.toJSON();
expect(tree).toMatchSnapshot();
});
it('renders class="button--block" if props.block given', () => {
const component = renderer.create(<Button block />);
const tree = component.toJSON();
expect(tree).toMatchSnapshot();
});
it('adds class "button-secondary" if props.theme="secondary" given', () => {
const component = renderer.create(<Button theme='secondary' />);
const tree = component.toJSON();
expect(tree).toMatchSnapshot();
});
});

View File

@ -0,0 +1,62 @@
import React from 'react';
import { fireEvent, render, screen } from '../../../../jest/test-helpers';
import Button from '../button';
describe('<Button />', () => {
it('renders the given text', () => {
const text = 'foo';
render(<Button text={text} />);
expect(screen.getByRole('button')).toHaveTextContent(text);
});
it('handles click events using the given handler', () => {
const handler = jest.fn();
render(<Button onClick={handler} />);
fireEvent.click(screen.getByRole('button'));
expect(handler.mock.calls.length).toEqual(1);
});
it('does not handle click events if props.disabled given', () => {
const handler = jest.fn();
render(<Button onClick={handler} disabled />);
fireEvent.click(screen.getByRole('button'));
expect(handler.mock.calls.length).toEqual(0);
});
it('renders a disabled attribute if props.disabled given', () => {
render(<Button disabled />);
expect(screen.getByRole('button')).toBeDisabled();
});
it('renders the children', () => {
render(<Button><p>children</p></Button>);
expect(screen.getByRole('button')).toHaveTextContent('children');
});
it('renders the props.text instead of children', () => {
const text = 'foo';
const children = <p>children</p>;
render(<Button text={text}>{children}</Button>);
expect(screen.getByRole('button')).toHaveTextContent('foo');
expect(screen.getByRole('button')).not.toHaveTextContent('children');
});
it('render full-width button if block prop given', () => {
render(<Button block />);
expect(screen.getByRole('button')).toHaveClass('w-full');
});
it('handles Theme properly', () => {
render(<Button theme='secondary' />);
expect(screen.getByRole('button')).toHaveClass('bg-primary-100');
});
});

View File

@ -64,6 +64,7 @@ const Button = React.forwardRef<HTMLButtonElement, IButton>((props, ref): JSX.El
onClick={handleClick}
ref={ref}
type={type}
data-testid='button'
>
{renderIcon()}
{text || children}

View File

@ -1,12 +1,11 @@
import React from 'react';
import { createShallowComponent } from 'soapbox/test_helpers';
import { render, screen } from '../../../../jest/test-helpers';
import { Card, CardBody, CardHeader, CardTitle } from '../card';
describe('<Card />', () => {
it('renders the CardTitle and CardBody', () => {
const component = createShallowComponent(
render(
<Card>
<CardHeader>
<CardTitle title='Card Title' />
@ -18,13 +17,13 @@ describe('<Card />', () => {
</Card>,
);
expect(component.text()).toContain('Card Title');
expect(component.text()).toContain('Card Body');
expect(component.text()).not.toContain('Back');
expect(screen.getByTestId('card-title')).toHaveTextContent('Card Title');
expect(screen.getByTestId('card-body')).toHaveTextContent('Card Body');
expect(screen.queryByTestId('back-button')).not.toBeInTheDocument();
});
it('renders the Back Button', () => {
const component = createShallowComponent(
render(
<Card>
<CardHeader backHref='/'>
<CardTitle title='Card Title' />
@ -32,6 +31,6 @@ describe('<Card />', () => {
</Card>,
);
expect(component.text()).toContain('Back');
expect(screen.getByTestId('back-button')).toBeInTheDocument();
});
});

View File

@ -55,7 +55,7 @@ const CardHeader: React.FC<ICardHeader> = ({ children, backHref, onBackClick }):
return (
<Comp {...backAttributes} className='mr-2 text-gray-900 dark:text-gray-100' aria-label={intl.formatMessage(messages.back)}>
<InlineSVG src={require('@tabler/icons/icons/arrow-left.svg')} className='h-6 w-6' />
<span className='sr-only'>Back</span>
<span className='sr-only' data-testid='back-button'>Back</span>
</Comp>
);
};
@ -74,11 +74,11 @@ interface ICardTitle {
}
const CardTitle = ({ title }: ICardTitle): JSX.Element => (
<Text size='xl' weight='bold' tag='h1'>{title}</Text>
<Text size='xl' weight='bold' tag='h1' data-testid='card-title'>{title}</Text>
);
const CardBody: React.FC = ({ children }): JSX.Element => (
<div>{children}</div>
<div data-testid='card-body'>{children}</div>
);
export { Card, CardHeader, CardTitle, CardBody };

View File

@ -1,40 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`<Column /> renders correctly with minimal props 1`] = `
<div
className="relative"
column-type="filled"
role="region"
>
<div
className="space-y-4 bg-white dark:bg-slate-800 sm:shadow-lg dark:sm:shadow-inset overflow-hidden p-4 sm:rounded-xl"
>
<div
className="mb-4 flex flex-row items-center"
>
<button
aria-label="Back"
className="mr-2 text-gray-900 dark:text-gray-100"
onClick={[Function]}
>
<svg
id={
Object {
"process": [Function],
}
}
/>
<span
className="sr-only"
>
Back
</span>
</button>
<h1
className="text-xl text-gray-900 dark:text-gray-100 font-bold tracking-normal font-sans"
/>
</div>
<div />
</div>
</div>
`;

View File

@ -1,13 +0,0 @@
import React from 'react';
import { createComponent } from 'soapbox/test_helpers';
import Column from '../column';
describe('<Column />', () => {
it('renders correctly with minimal props', () => {
const component = createComponent(<Column />);
const tree = component.toJSON();
expect(tree).toMatchSnapshot();
});
});

View File

@ -0,0 +1,12 @@
import React from 'react';
import { render, screen } from '../../../../jest/test-helpers';
import Column from '../column';
describe('<Column />', () => {
it('renders correctly with minimal props', () => {
render(<Column />);
expect(screen.getByRole('button')).toHaveTextContent('Back');
});
});

View File

@ -1,61 +0,0 @@
import React from 'react';
import { createShallowComponent } from 'soapbox/test_helpers';
jest.mock('uuid', () => ({
...jest.requireActual('uuid'),
}));
import FormGroup from '../form-group';
describe('<FormGroup />', () => {
it('connects the label and input', () => {
const component = createShallowComponent(
<FormGroup labelText='My label'>
<input type='text' />
</FormGroup>,
);
const otherComponent = createShallowComponent(
<FormGroup labelText='My other label'>
<input type='text' />
</FormGroup>,
);
const inputId = component.find('input').at(0).prop('id');
const labelId = component.find('label').at(0).prop('htmlFor');
expect(inputId).toBe(labelId);
const otherInputId = otherComponent.find('input').at(0).prop('id');
expect(otherInputId).not.toBe(inputId);
});
it('renders errors', () => {
const component = createShallowComponent(
<FormGroup labelText='My label' errors={['is invalid', 'is required']}>
<input type='text' />
</FormGroup>,
);
expect(component.text()).toContain('is invalid, is required');
});
it('renders label', () => {
const component = createShallowComponent(
<FormGroup labelText='My label'>
<input type='text' />
</FormGroup>,
);
expect(component.text()).toContain('My label');
});
it('renders hint', () => {
const component = createShallowComponent(
<FormGroup labelText='My label' hintText='My hint'>
<input type='text' />
</FormGroup>,
);
expect(component.text()).toContain('My hint');
});
});

View File

@ -0,0 +1,60 @@
import React from 'react';
import { render, screen } from '../../../../jest/test-helpers';
import FormGroup from '../form-group';
jest.mock('uuid', () => jest.requireActual('uuid'));
describe('<FormGroup />', () => {
it('connects the label and input', () => {
render(
<>
<div>
<FormGroup labelText='My label'>
<input type='text' data-testid='winner' />
</FormGroup>
</div>
<div>
<FormGroup labelText='My other label'>
<input type='text' />
</FormGroup>
</div>
</>,
);
expect(screen.getByLabelText('My label')).toHaveAttribute('data-testid');
expect(screen.getByLabelText('My other label')).not.toHaveAttribute('data-testid');
expect(screen.queryByTestId('form-group-error')).not.toBeInTheDocument();
});
it('renders errors', () => {
render(
<FormGroup labelText='My label' errors={['is invalid', 'is required']}>
<input type='text' />
</FormGroup>,
);
expect(screen.getByTestId('form-group-error')).toHaveTextContent('is invalid');
});
it('renders label', () => {
render(
<FormGroup labelText='My label'>
<input type='text' />
</FormGroup>,
);
expect(screen.getByTestId('form-group-label')).toHaveTextContent('My label');
});
it('renders hint', () => {
render(
<FormGroup labelText='My label' hintText='My hint'>
<input type='text' />
</FormGroup>,
);
expect(screen.getByTestId('form-group-hint')).toHaveTextContent('My hint');
});
});

View File

@ -24,6 +24,7 @@ const FormGroup: React.FC<IFormGroup> = (props) => {
<div>
<label
htmlFor={formFieldId}
data-testid='form-group-label'
className='block text-sm font-medium text-gray-700 dark:text-gray-400'
>
{labelText}
@ -34,13 +35,16 @@ const FormGroup: React.FC<IFormGroup> = (props) => {
{inputChildren.filter((_, i) => i !== 0)}
{errors?.length > 0 && (
<p className='mt-0.5 text-xs text-danger-900 bg-danger-200 rounded-md inline-block px-2 py-1 relative form-error'>
<p
data-testid='form-group-error'
className='mt-0.5 text-xs text-danger-900 bg-danger-200 rounded-md inline-block px-2 py-1 relative form-error'
>
{errors.join(', ')}
</p>
)}
{hintText ? (
<p className='mt-0.5 text-xs text-gray-400'>
<p data-testid='form-group-hint' className='mt-0.5 text-xs text-gray-400'>
{hintText}
</p>
) : null}

View File

@ -1,40 +0,0 @@
import React from 'react';
import { createShallowComponent } from 'soapbox/test_helpers';
import Form from '../form';
describe('<Form />', () => {
it('renders children', () => {
const onSubmitMock = jest.fn();
const component = createShallowComponent(
<Form onSubmit={onSubmitMock}>children</Form>,
);
expect(component.text()).toContain('children');
});
it('handles onSubmit prop', () => {
const onSubmitMock = jest.fn();
const component = createShallowComponent(
<Form onSubmit={onSubmitMock}>children</Form>,
);
component.find('form').at(0).simulate('submit', {
preventDefault: () => {},
});
expect(onSubmitMock).toHaveBeenCalled();
});
it('handles disabled prop', () => {
const onSubmitMock = jest.fn();
const component = createShallowComponent(
<Form onSubmit={onSubmitMock} disabled>
<button type='submit'>Submit</button>
</Form>,
);
component.find('button').at(0).simulate('click');
expect(onSubmitMock).not.toHaveBeenCalled();
});
});

View File

@ -0,0 +1,29 @@
import React from 'react';
import { fireEvent, render, screen } from '../../../../jest/test-helpers';
import Form from '../form';
describe('<Form />', () => {
it('renders children', () => {
const onSubmitMock = jest.fn();
render(
<Form onSubmit={onSubmitMock}>children</Form>,
);
expect(screen.getByTestId('form')).toHaveTextContent('children');
});
it('handles onSubmit prop', () => {
const onSubmitMock = jest.fn();
render(
<Form onSubmit={onSubmitMock}>children</Form>,
);
fireEvent.submit(
screen.getByTestId('form'), {
preventDefault: () => {},
},
);
expect(onSubmitMock).toHaveBeenCalled();
});
});

View File

@ -1,7 +1,6 @@
import * as React from 'react';
interface IForm {
disabled?: boolean,
onSubmit?: (event: React.FormEvent) => void,
}
@ -15,7 +14,7 @@ const Form: React.FC<IForm> = ({ onSubmit, children, ...filteredProps }) => {
}, [onSubmit]);
return (
<form onSubmit={handleSubmit} className='space-y-4' {...filteredProps}>
<form data-testid='form' onSubmit={handleSubmit} className='space-y-4' {...filteredProps}>
{children}
</form>
);

View File

@ -3,7 +3,7 @@ import React from 'react';
import InlineSVG from 'react-inlinesvg';
import { defineMessages, useIntl } from 'react-intl';
import Icon from '../../icon';
import Icon from '../icon/icon';
import Tooltip from '../tooltip/tooltip';
const messages = defineMessages({