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,27 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`<CaptchaField /> renders null by default 1`] = `null`;
exports[`<NativeCaptchaField /> renders correctly 1`] = `
<div
className="captcha"
>
<img
alt="captcha"
src="data:image/png;base64,..."
/>
<div
className="input required"
>
<input
autoCapitalize="off"
autoComplete="off"
autoCorrect="off"
onChange={[Function]}
placeholder="Enter the pictured text"
required={true}
type="text"
/>
</div>
</div>
`;

View File

@ -1,267 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`<LoginForm /> renders for Mastodon 1`] = `
<div>
<div
className="pb-4 sm:pb-10 mb-4 border-b border-gray-200 border-solid -mx-4 sm:-mx-10"
>
<h1
className="text-center font-bold text-2xl"
>
Sign In
</h1>
</div>
<div
className="sm:pt-10 sm:w-2/3 md:w-1/2 mx-auto"
>
<form
className="space-y-4"
onSubmit={[Function]}
>
<div>
<label
className="block text-sm font-medium text-gray-700 dark:text-gray-400"
htmlFor="field-1"
>
Email address
</label>
<div
className="mt-1 dark:text-white"
>
<div
className="mt-1 relative rounded-md shadow-sm"
>
<input
aria-label="Email address"
autoCapitalize="off"
autoComplete="off"
autoCorrect="off"
className="dark:bg-slate-800 block w-full sm:text-sm border-gray-300 dark:border-gray-600 rounded-md focus:ring-indigo-500 focus:border-indigo-500"
id="field-1"
name="username"
placeholder="Email address"
required={true}
type="text"
/>
</div>
</div>
</div>
<div>
<label
className="block text-sm font-medium text-gray-700 dark:text-gray-400"
htmlFor="field-1"
>
Password
</label>
<div
className="mt-1 dark:text-white"
>
<div
className="mt-1 relative rounded-md shadow-sm"
>
<input
aria-label="Password"
autoCapitalize="off"
autoComplete="off"
autoCorrect="off"
className="dark:bg-slate-800 block w-full sm:text-sm border-gray-300 dark:border-gray-600 rounded-md focus:ring-indigo-500 focus:border-indigo-500 pr-7"
id="field-1"
name="password"
placeholder="Password"
required={true}
type="password"
/>
<div
className="absolute inset-y-0 right-0 flex items-center"
data-reach-tooltip-trigger=""
data-state="tooltip-hidden"
onBlur={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
onMouseDown={[Function]}
onMouseEnter={[Function]}
onMouseLeave={[Function]}
onMouseMove={[Function]}
onPointerDown={[Function]}
onPointerEnter={[Function]}
onPointerLeave={[Function]}
onPointerMove={[Function]}
>
<button
className="text-gray-400 hover:text-gray-500 h-full px-2 focus:ring-primary-500 focus:ring-2"
onClick={[Function]}
tabIndex={-1}
type="button"
>
<svg
id={
Object {
"process": [Function],
}
}
/>
</button>
</div>
</div>
<p
className="mt-0.5 text-xs text-gray-400"
>
<a
className="hover:underline"
href="/reset-password"
onClick={[Function]}
>
Trouble logging in?
</a>
</p>
</div>
</div>
<div
className="flex justify-end space-x-2"
>
<button
className="inline-flex items-center border font-medium rounded-full focus:outline-none appearance-none transition-all border-transparent text-white bg-primary-600 hover:bg-primary-700 focus:ring-primary-500 focus:ring-2 focus:ring-offset-2 px-4 py-2 text-sm"
disabled={false}
onClick={[Function]}
type="submit"
>
Sign in
</button>
</div>
</form>
</div>
</div>
`;
exports[`<LoginForm /> renders for Pleroma 1`] = `
<div>
<div
className="pb-4 sm:pb-10 mb-4 border-b border-gray-200 border-solid -mx-4 sm:-mx-10"
>
<h1
className="text-center font-bold text-2xl"
>
Sign In
</h1>
</div>
<div
className="sm:pt-10 sm:w-2/3 md:w-1/2 mx-auto"
>
<form
className="space-y-4"
onSubmit={[Function]}
>
<div>
<label
className="block text-sm font-medium text-gray-700 dark:text-gray-400"
htmlFor="field-1"
>
Email address
</label>
<div
className="mt-1 dark:text-white"
>
<div
className="mt-1 relative rounded-md shadow-sm"
>
<input
aria-label="Email address"
autoCapitalize="off"
autoComplete="off"
autoCorrect="off"
className="dark:bg-slate-800 block w-full sm:text-sm border-gray-300 dark:border-gray-600 rounded-md focus:ring-indigo-500 focus:border-indigo-500"
id="field-1"
name="username"
placeholder="Email address"
required={true}
type="text"
/>
</div>
</div>
</div>
<div>
<label
className="block text-sm font-medium text-gray-700 dark:text-gray-400"
htmlFor="field-1"
>
Password
</label>
<div
className="mt-1 dark:text-white"
>
<div
className="mt-1 relative rounded-md shadow-sm"
>
<input
aria-label="Password"
autoCapitalize="off"
autoComplete="off"
autoCorrect="off"
className="dark:bg-slate-800 block w-full sm:text-sm border-gray-300 dark:border-gray-600 rounded-md focus:ring-indigo-500 focus:border-indigo-500 pr-7"
id="field-1"
name="password"
placeholder="Password"
required={true}
type="password"
/>
<div
className="absolute inset-y-0 right-0 flex items-center"
data-reach-tooltip-trigger=""
data-state="tooltip-hidden"
onBlur={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
onMouseDown={[Function]}
onMouseEnter={[Function]}
onMouseLeave={[Function]}
onMouseMove={[Function]}
onPointerDown={[Function]}
onPointerEnter={[Function]}
onPointerLeave={[Function]}
onPointerMove={[Function]}
>
<button
className="text-gray-400 hover:text-gray-500 h-full px-2 focus:ring-primary-500 focus:ring-2"
onClick={[Function]}
tabIndex={-1}
type="button"
>
<svg
id={
Object {
"process": [Function],
}
}
/>
</button>
</div>
</div>
<p
className="mt-0.5 text-xs text-gray-400"
>
<a
className="hover:underline"
href="/reset-password"
onClick={[Function]}
>
Trouble logging in?
</a>
</p>
</div>
</div>
<div
className="flex justify-end space-x-2"
>
<button
className="inline-flex items-center border font-medium rounded-full focus:outline-none appearance-none transition-all border-transparent text-white bg-primary-600 hover:bg-primary-700 focus:ring-primary-500 focus:ring-2 focus:ring-offset-2 px-4 py-2 text-sm"
disabled={false}
onClick={[Function]}
type="submit"
>
Sign in
</button>
</div>
</form>
</div>
</div>
`;

View File

@ -1,135 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`<LoginPage /> renders correctly on load 1`] = `
<div>
<div
className="pb-4 sm:pb-10 mb-4 border-b border-gray-200 border-solid -mx-4 sm:-mx-10"
>
<h1
className="text-center font-bold text-2xl"
>
Sign In
</h1>
</div>
<div
className="sm:pt-10 sm:w-2/3 md:w-1/2 mx-auto"
>
<form
className="space-y-4"
disabled={false}
onSubmit={[Function]}
>
<div>
<label
className="block text-sm font-medium text-gray-700 dark:text-gray-400"
htmlFor="field-1"
>
Email address
</label>
<div
className="mt-1 dark:text-white"
>
<div
className="mt-1 relative rounded-md shadow-sm"
>
<input
aria-label="Email address"
autoCapitalize="off"
autoComplete="off"
autoCorrect="off"
className="dark:bg-slate-800 block w-full sm:text-sm border-gray-300 dark:border-gray-600 rounded-md focus:ring-indigo-500 focus:border-indigo-500"
id="field-1"
name="username"
placeholder="Email address"
required={true}
type="text"
/>
</div>
</div>
</div>
<div>
<label
className="block text-sm font-medium text-gray-700 dark:text-gray-400"
htmlFor="field-1"
>
Password
</label>
<div
className="mt-1 dark:text-white"
>
<div
className="mt-1 relative rounded-md shadow-sm"
>
<input
aria-label="Password"
autoCapitalize="off"
autoComplete="off"
autoCorrect="off"
className="dark:bg-slate-800 block w-full sm:text-sm border-gray-300 dark:border-gray-600 rounded-md focus:ring-indigo-500 focus:border-indigo-500 pr-7"
id="field-1"
name="password"
placeholder="Password"
required={true}
type="password"
/>
<div
className="absolute inset-y-0 right-0 flex items-center"
data-reach-tooltip-trigger=""
data-state="tooltip-hidden"
onBlur={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
onMouseDown={[Function]}
onMouseEnter={[Function]}
onMouseLeave={[Function]}
onMouseMove={[Function]}
onPointerDown={[Function]}
onPointerEnter={[Function]}
onPointerLeave={[Function]}
onPointerMove={[Function]}
>
<button
className="text-gray-400 hover:text-gray-500 h-full px-2 focus:ring-primary-500 focus:ring-2"
onClick={[Function]}
tabIndex={-1}
type="button"
>
<svg
id={
Object {
"process": [Function],
}
}
/>
</button>
</div>
</div>
<p
className="mt-0.5 text-xs text-gray-400"
>
<a
className="hover:underline"
href="/reset-password"
onClick={[Function]}
>
Trouble logging in?
</a>
</p>
</div>
</div>
<div
className="flex justify-end space-x-2"
>
<button
className="inline-flex items-center border font-medium rounded-full focus:outline-none appearance-none transition-all border-transparent text-white bg-primary-600 hover:bg-primary-700 focus:ring-primary-500 focus:ring-2 focus:ring-offset-2 px-4 py-2 text-sm"
disabled={false}
onClick={[Function]}
type="submit"
>
Sign in
</button>
</div>
</form>
</div>
</div>
`;

View File

@ -1,16 +1,14 @@
import { Map as ImmutableMap } from 'immutable';
import React from 'react';
import renderer from 'react-test-renderer';
import { createComponent } from 'soapbox/test_helpers';
import { render, screen } from '../../../../jest/test-helpers';
import CaptchaField, { NativeCaptchaField } from '../captcha';
describe('<CaptchaField />', () => {
it('renders null by default', () => {
expect(createComponent(
<CaptchaField />,
).toJSON()).toMatchSnapshot();
render(<CaptchaField />);
expect(screen.queryAllByRole('textbox')).toHaveLength(0);
});
});
@ -23,11 +21,13 @@ describe('<NativeCaptchaField />', () => {
url: 'data:image/png;base64,...',
});
expect(renderer.create(
render(
<NativeCaptchaField
captcha={captcha}
onChange={() => {}} // eslint-disable-line react/jsx-no-bind
/>,
).toJSON()).toMatchSnapshot();
);
expect(screen.queryAllByRole('textbox')).toHaveLength(1);
});
});

View File

@ -1,31 +0,0 @@
import React from 'react';
import rootReducer from 'soapbox/reducers';
import { createComponent, mockStore } from 'soapbox/test_helpers';
import LoginForm from '../login_form';
describe('<LoginForm />', () => {
it('renders for Pleroma', () => {
const state = rootReducer(undefined, {})
.update('instance', instance => instance.set('version', '2.7.2 (compatible; Pleroma 2.3.0)'));
const store = mockStore(state);
expect(createComponent(
<LoginForm />,
{ store },
).toJSON()).toMatchSnapshot();
});
it('renders for Mastodon', () => {
const state = rootReducer(undefined, {})
.update('instance', instance => instance.set('version', '3.0.0'));
const store = mockStore(state);
expect(createComponent(
<LoginForm />,
{ store },
).toJSON()).toMatchSnapshot();
});
});

View File

@ -0,0 +1,31 @@
import { Map as ImmutableMap } from 'immutable';
import React from 'react';
import { render, screen } from '../../../../jest/test-helpers';
import LoginForm from '../login_form';
describe('<LoginForm />', () => {
it('renders for Pleroma', () => {
const store = {
instance: ImmutableMap({
version: '2.7.2 (compatible; Pleroma 2.3.0)',
}),
};
render(<LoginForm />, null, store);
expect(screen.getByRole('heading')).toHaveTextContent('Sign In');
});
it('renders for Mastodon', () => {
const store = {
instance: ImmutableMap({
version: '3.0.0',
}),
};
render(<LoginForm />, null, store);
expect(screen.getByRole('heading')).toHaveTextContent('Sign In');
});
});

View File

@ -1,21 +1,20 @@
import { Map as ImmutableMap } from 'immutable';
import React from 'react';
import rootReducer from 'soapbox/reducers';
import { createComponent, mockStore } from 'soapbox/test_helpers';
import { render, screen } from '../../../../jest/test-helpers';
import LoginPage from '../login_page';
describe('<LoginPage />', () => {
it('renders correctly on load', () => {
const state = rootReducer(undefined, {})
.set('me', '1234')
.update('instance', instance => instance.set('version', '2.7.2 (compatible; Pleroma 2.3.0)'));
const store = mockStore(state);
const store = {
instance: ImmutableMap({
version: '2.7.2 (compatible; Pleroma 2.3.0)',
}),
};
expect(createComponent(
<LoginPage />,
{ store },
).toJSON()).toMatchSnapshot();
render(<LoginPage />, null, store);
expect(screen.getByRole('heading')).toHaveTextContent('Sign In');
});
// it('renders the OTP form when logIn returns with mfa_required', () => {

View File

@ -1,19 +0,0 @@
import { Map as ImmutableMap } from 'immutable';
import React from 'react';
import { createShallowComponent, mockStore } from 'soapbox/test_helpers';
import OtpAuthForm from '../otp_auth_form';
describe('<OtpAuthForm />', () => {
it('renders correctly', () => {
const store = mockStore(ImmutableMap({ mfa_auth_needed: true }));
const component = createShallowComponent(
<OtpAuthForm mfa_token={'12345'} />,
{ store },
);
expect(component.text()).toContain('OTP Login');
expect(component.exists('form')).toBe(true);
});
});

View File

@ -0,0 +1,13 @@
import React from 'react';
import { render, screen } from '../../../../jest/test-helpers';
import OtpAuthForm from '../otp_auth_form';
describe('<OtpAuthForm />', () => {
it('renders correctly', () => {
render(<OtpAuthForm mfa_token={'12345'} />);
expect(screen.getByRole('heading')).toHaveTextContent('OTP Login');
expect(screen.getByTestId('form')).toBeInTheDocument();
});
});

View File

@ -1,17 +1,15 @@
import React from 'react';
import { act } from 'react-dom/test-utils';
import { Route, Switch } from 'react-router-dom';
import { __stub } from 'soapbox/api';
import rootReducer from 'soapbox/reducers';
import { createShallowComponent, mockStore } from 'soapbox/test_helpers';
import { fireEvent, render, screen, waitFor } from '../../../../jest/test-helpers';
import PasswordResetConfirm from '../password_reset_confirm';
const TestableComponent = () => (
<Switch>
<Route path='/edit' exact><PasswordResetConfirm /></Route>
<Route path='/' exact><span>Homepage</span></Route>
<Route path='/' exact><span data-testid='home'>Homepage</span></Route>
</Switch>
);
@ -22,24 +20,23 @@ describe('<PasswordResetConfirm />', () => {
.reply(200, {});
});
const state = rootReducer(undefined, {});
const store = mockStore(state);
const component = createShallowComponent(
render(
<TestableComponent />,
{ store },
{},
null,
{ initialEntries: ['/edit'] },
);
await component.find('form').at(0).simulate('submit', {
preventDefault: () => {},
});
await act(async() => {
await new Promise(resolve => setTimeout(resolve, 0));
component.update();
});
fireEvent.submit(
screen.getByTestId('form'), {
preventDefault: () => {},
},
);
expect(component.text()).toContain('Homepage');
expect(component.text()).not.toContain('Expired token');
await waitFor(() => {
expect(screen.getByTestId('home')).toHaveTextContent('Homepage');
expect(screen.queryByTestId('form-group-error')).not.toBeInTheDocument();
});
});
it('handles failed responses from the API', async() => {
@ -48,23 +45,22 @@ describe('<PasswordResetConfirm />', () => {
.reply(403, {});
});
const state = rootReducer(undefined, {});
const store = mockStore(state);
const component = createShallowComponent(
render(
<TestableComponent />,
{ store },
{},
null,
{ initialEntries: ['/edit'] },
);
await component.find('form').at(0).simulate('submit', {
preventDefault: () => {},
});
await act(async() => {
await new Promise(resolve => setTimeout(resolve, 0));
component.update();
});
await fireEvent.submit(
screen.getByTestId('form'), {
preventDefault: () => {},
},
);
expect(component.text()).toContain('Expired token');
expect(component.text()).not.toContain('Homepage');
await waitFor(() => {
expect(screen.queryByTestId('home')).not.toBeInTheDocument();
expect(screen.queryByTestId('form-group-error')).toBeInTheDocument();
});
});
});

View File

@ -30,7 +30,7 @@ const LoginForm = ({ isLoading, handleSubmit }) => {
</div>
<div className='sm:pt-10 sm:w-2/3 md:w-1/2 mx-auto'>
<Form onSubmit={handleSubmit} disabled={isLoading}>
<Form onSubmit={handleSubmit}>
<FormGroup labelText={intl.formatMessage(messages.email)}>
<Input
aria-label={intl.formatMessage(messages.email)}

View File

@ -66,7 +66,7 @@ class OtpAuthForm extends ImmutablePureComponent {
</div>
<div className='sm:pt-10 sm:w-2/3 md:w-1/2 mx-auto'>
<Form onSubmit={this.handleSubmit} disabled={this.state.isLoading}>
<Form onSubmit={this.handleSubmit}>
<FormGroup
labelText={intl.formatMessage(messages.otpCodeLabel)}
hintText={intl.formatMessage(messages.otpCodeHint)}

View File

@ -49,7 +49,7 @@ class PasswordReset extends ImmutablePureComponent {
</div>
<div className='sm:pt-10 sm:w-2/3 md:w-1/2 mx-auto'>
<Form onSubmit={this.handleSubmit} disabled={this.state.isLoading}>
<Form onSubmit={this.handleSubmit}>
<FormGroup labelText={intl.formatMessage(messages.nicknameOrEmail)}>
<Input
name='nickname_or_email'

View File

@ -62,7 +62,7 @@ const PasswordResetConfirm = ({ resetPasswordConfirm }) => {
</div>
<div className='sm:pt-10 sm:w-2/3 md:w-1/2 mx-auto'>
<Form onSubmit={handleSubmit} disabled={isLoading}>
<Form onSubmit={handleSubmit}>
<FormGroup labelText='Password' errors={renderErrors()}>
<Input
type='password'