Convert old tests to use "react-testing-library"
This commit is contained in:
parent
9a099b3fa7
commit
ed47cf5f09
71 changed files with 411 additions and 1515 deletions
18
.eslintrc.js
18
.eslintrc.js
|
@ -217,15 +217,15 @@ module.exports = {
|
|||
'import/newline-after-import': 'error',
|
||||
'import/no-extraneous-dependencies': [
|
||||
'error',
|
||||
{
|
||||
devDependencies: [
|
||||
'webpack/**',
|
||||
'app/soapbox/test_setup.js',
|
||||
'app/soapbox/test_helpers.js',
|
||||
'app/**/__tests__/**',
|
||||
'app/**/__mocks__/**',
|
||||
],
|
||||
},
|
||||
// {
|
||||
// devDependencies: [
|
||||
// 'webpack/**',
|
||||
// 'app/soapbox/test_setup.js',
|
||||
// 'app/soapbox/test_helpers.js',
|
||||
// 'app/**/__tests__/**',
|
||||
// 'app/**/__mocks__/**',
|
||||
// ],
|
||||
// },
|
||||
],
|
||||
'import/no-unresolved': 'error',
|
||||
'import/no-webpack-loader-syntax': 'error',
|
||||
|
|
|
@ -2,7 +2,7 @@ import MockAdapter from 'axios-mock-adapter';
|
|||
import { Map as ImmutableMap } from 'immutable';
|
||||
|
||||
import { staticClient } from 'soapbox/api';
|
||||
import { mockStore } from 'soapbox/test_helpers';
|
||||
import { mockStore } from 'soapbox/jest/test-helpers';
|
||||
|
||||
import {
|
||||
FETCH_ABOUT_PAGE_REQUEST,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { mockStore } from 'soapbox/jest/test-helpers';
|
||||
import { InstanceRecord } from 'soapbox/normalizers';
|
||||
import rootReducer from 'soapbox/reducers';
|
||||
import { mockStore } from 'soapbox/test_helpers';
|
||||
|
||||
import { uploadCompose } from '../compose';
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { Map as ImmutableMap } from 'immutable';
|
||||
|
||||
import { __stub } from 'soapbox/api';
|
||||
import { mockStore } from 'soapbox/test_helpers';
|
||||
import { mockStore } from 'soapbox/jest/test-helpers';
|
||||
|
||||
import { VERIFY_CREDENTIALS_REQUEST } from '../auth';
|
||||
import { ACCOUNTS_IMPORT } from '../importer';
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { STATUSES_IMPORT } from 'soapbox/actions/importer';
|
||||
import { __stub } from 'soapbox/api';
|
||||
import { mockStore, rootState } from 'soapbox/test_helpers';
|
||||
import { mockStore, rootState } from 'soapbox/jest/test-helpers';
|
||||
|
||||
import { fetchContext } from '../statuses';
|
||||
|
||||
|
|
|
@ -1,27 +0,0 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`<AutosuggestEmoji /> renders emoji with custom url 1`] = `
|
||||
<div
|
||||
className="autosuggest-emoji"
|
||||
>
|
||||
<img
|
||||
alt="foobar"
|
||||
className="emojione"
|
||||
src="http://example.com/emoji.png"
|
||||
/>
|
||||
:foobar:
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`<AutosuggestEmoji /> renders native emoji 1`] = `
|
||||
<div
|
||||
className="autosuggest-emoji"
|
||||
>
|
||||
<img
|
||||
alt="💙"
|
||||
className="emojione"
|
||||
src="/packs/emoji/1f499.svg"
|
||||
/>
|
||||
:foobar:
|
||||
</div>
|
||||
`;
|
|
@ -1,37 +0,0 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`<Avatar /> Autoplay renders an animated avatar 1`] = `
|
||||
<div
|
||||
className="rounded-full still-image"
|
||||
style={
|
||||
Object {
|
||||
"height": "100px",
|
||||
"width": "100px",
|
||||
}
|
||||
}
|
||||
>
|
||||
<img
|
||||
alt=""
|
||||
onLoad={[Function]}
|
||||
src="/animated/alice.gif"
|
||||
/>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`<Avatar /> Still renders a still avatar 1`] = `
|
||||
<div
|
||||
className="rounded-full still-image"
|
||||
style={
|
||||
Object {
|
||||
"height": "100px",
|
||||
"width": "100px",
|
||||
}
|
||||
}
|
||||
>
|
||||
<img
|
||||
alt=""
|
||||
onLoad={[Function]}
|
||||
src="/animated/alice.gif"
|
||||
/>
|
||||
</div>
|
||||
`;
|
|
@ -1,28 +0,0 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`<AvatarOverlay renders a overlay avatar 1`] = `
|
||||
<div
|
||||
className="account__avatar-overlay"
|
||||
>
|
||||
<div
|
||||
className="account__avatar-overlay-base still-image"
|
||||
style={Object {}}
|
||||
>
|
||||
<img
|
||||
alt=""
|
||||
onLoad={[Function]}
|
||||
src="/animated/alice.gif"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
className="account__avatar-overlay-overlay still-image"
|
||||
style={Object {}}
|
||||
>
|
||||
<img
|
||||
alt=""
|
||||
onLoad={[Function]}
|
||||
src="/animated/eve.gif"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
|
@ -1,9 +0,0 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`<Badge /> renders correctly 1`] = `
|
||||
<span
|
||||
className="badge badge--patron"
|
||||
>
|
||||
Patron
|
||||
</span>
|
||||
`;
|
|
@ -1,16 +0,0 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`<ColumnBackButton /> renders correctly 1`] = `
|
||||
<button
|
||||
className="column-back-button"
|
||||
onClick={[Function]}
|
||||
onKeyUp={[Function]}
|
||||
>
|
||||
<i
|
||||
alt="chevron-left"
|
||||
className="fa fa-chevron-left column-back-button__icon fa-fw"
|
||||
role="img"
|
||||
/>
|
||||
Back
|
||||
</button>
|
||||
`;
|
|
@ -1,35 +0,0 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`<DisplayName /> renders display name + account name 1`] = `
|
||||
<span
|
||||
className="display-name"
|
||||
>
|
||||
<span
|
||||
className="hover-ref-wrapper"
|
||||
onClick={[Function]}
|
||||
onMouseEnter={[Function]}
|
||||
onMouseLeave={[Function]}
|
||||
>
|
||||
<span
|
||||
className="display-name__name"
|
||||
>
|
||||
<bdi>
|
||||
<strong
|
||||
className="display-name__html"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "bar",
|
||||
}
|
||||
}
|
||||
/>
|
||||
</bdi>
|
||||
</span>
|
||||
</span>
|
||||
<span
|
||||
className="display-name__account"
|
||||
>
|
||||
@
|
||||
bar@baz
|
||||
</span>
|
||||
</span>
|
||||
`;
|
|
@ -1,86 +0,0 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`<EmojiSelector /> renders correctly 1`] = `
|
||||
<div
|
||||
onBlur={[Function]}
|
||||
onFocus={[Function]}
|
||||
tabIndex="-1"
|
||||
>
|
||||
<div
|
||||
className="flex space-x-2 bg-white dark:bg-slate-900 p-3 rounded-full shadow-md z-[999] w-max"
|
||||
>
|
||||
<button
|
||||
className=""
|
||||
onClick={[Function]}
|
||||
tabIndex={-1}
|
||||
>
|
||||
<img
|
||||
alt="👍"
|
||||
className="w-8 h-8 duration-100 hover:scale-125"
|
||||
draggable="false"
|
||||
src="/packs/emoji/1f44d.svg"
|
||||
/>
|
||||
</button>
|
||||
<button
|
||||
className=""
|
||||
onClick={[Function]}
|
||||
tabIndex={-1}
|
||||
>
|
||||
<img
|
||||
alt="❤"
|
||||
className="w-8 h-8 duration-100 hover:scale-125"
|
||||
draggable="false"
|
||||
src="/packs/emoji/2764.svg"
|
||||
/>
|
||||
</button>
|
||||
<button
|
||||
className=""
|
||||
onClick={[Function]}
|
||||
tabIndex={-1}
|
||||
>
|
||||
<img
|
||||
alt="😆"
|
||||
className="w-8 h-8 duration-100 hover:scale-125"
|
||||
draggable="false"
|
||||
src="/packs/emoji/1f606.svg"
|
||||
/>
|
||||
</button>
|
||||
<button
|
||||
className=""
|
||||
onClick={[Function]}
|
||||
tabIndex={-1}
|
||||
>
|
||||
<img
|
||||
alt="😮"
|
||||
className="w-8 h-8 duration-100 hover:scale-125"
|
||||
draggable="false"
|
||||
src="/packs/emoji/1f62e.svg"
|
||||
/>
|
||||
</button>
|
||||
<button
|
||||
className=""
|
||||
onClick={[Function]}
|
||||
tabIndex={-1}
|
||||
>
|
||||
<img
|
||||
alt="😢"
|
||||
className="w-8 h-8 duration-100 hover:scale-125"
|
||||
draggable="false"
|
||||
src="/packs/emoji/1f622.svg"
|
||||
/>
|
||||
</button>
|
||||
<button
|
||||
className=""
|
||||
onClick={[Function]}
|
||||
tabIndex={-1}
|
||||
>
|
||||
<img
|
||||
alt="😩"
|
||||
className="w-8 h-8 duration-100 hover:scale-125"
|
||||
draggable="false"
|
||||
src="/packs/emoji/1f629.svg"
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
|
@ -1,80 +0,0 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`<TimelineQueueButtonHeader /> renders correctly 1`] = `
|
||||
<div
|
||||
className="left-1/2 -translate-x-1/2 fixed top-20 z-50 hidden"
|
||||
>
|
||||
<a
|
||||
className="flex items-center bg-primary-600 hover:bg-primary-700 hover:scale-105 active:scale-100 transition-transform text-white rounded-full px-4 py-2 space-x-1.5 cursor-pointer"
|
||||
onClick={[Function]}
|
||||
>
|
||||
<div
|
||||
className="svg-icon"
|
||||
>
|
||||
<svg
|
||||
id={
|
||||
Object {
|
||||
"process": [Function],
|
||||
}
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`<TimelineQueueButtonHeader /> renders correctly 2`] = `
|
||||
<div
|
||||
className="left-1/2 -translate-x-1/2 fixed top-20 z-50 hidden"
|
||||
>
|
||||
<a
|
||||
className="flex items-center bg-primary-600 hover:bg-primary-700 hover:scale-105 active:scale-100 transition-transform text-white rounded-full px-4 py-2 space-x-1.5 cursor-pointer"
|
||||
onClick={[Function]}
|
||||
>
|
||||
<div
|
||||
className="svg-icon"
|
||||
>
|
||||
<svg
|
||||
id={
|
||||
Object {
|
||||
"process": [Function],
|
||||
}
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<p
|
||||
className="text-sm text-inherit font-normal tracking-normal font-sans"
|
||||
>
|
||||
Click to see 1 new post
|
||||
</p>
|
||||
</a>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`<TimelineQueueButtonHeader /> renders correctly 3`] = `
|
||||
<div
|
||||
className="left-1/2 -translate-x-1/2 fixed top-20 z-50 hidden"
|
||||
>
|
||||
<a
|
||||
className="flex items-center bg-primary-600 hover:bg-primary-700 hover:scale-105 active:scale-100 transition-transform text-white rounded-full px-4 py-2 space-x-1.5 cursor-pointer"
|
||||
onClick={[Function]}
|
||||
>
|
||||
<div
|
||||
className="svg-icon"
|
||||
>
|
||||
<svg
|
||||
id={
|
||||
Object {
|
||||
"process": [Function],
|
||||
}
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<p
|
||||
className="text-sm text-inherit font-normal tracking-normal font-sans"
|
||||
>
|
||||
Click to see 9999999 new posts
|
||||
</p>
|
||||
</a>
|
||||
</div>
|
||||
`;
|
|
@ -1,6 +1,6 @@
|
|||
import React from 'react';
|
||||
import renderer from 'react-test-renderer';
|
||||
|
||||
import { render, screen } from '../../jest/test-helpers';
|
||||
import AutosuggestEmoji from '../autosuggest_emoji';
|
||||
|
||||
describe('<AutosuggestEmoji />', () => {
|
||||
|
@ -9,10 +9,11 @@ describe('<AutosuggestEmoji />', () => {
|
|||
native: '💙',
|
||||
colons: ':foobar:',
|
||||
};
|
||||
const component = renderer.create(<AutosuggestEmoji emoji={emoji} />);
|
||||
const tree = component.toJSON();
|
||||
|
||||
expect(tree).toMatchSnapshot();
|
||||
render(<AutosuggestEmoji emoji={emoji} />);
|
||||
|
||||
expect(screen.getByTestId('emoji')).toHaveTextContent('foobar');
|
||||
expect(screen.getByRole('img').getAttribute('src')).not.toBe('http://example.com/emoji.png');
|
||||
});
|
||||
|
||||
it('renders emoji with custom url', () => {
|
||||
|
@ -22,9 +23,10 @@ describe('<AutosuggestEmoji />', () => {
|
|||
native: 'foobar',
|
||||
colons: ':foobar:',
|
||||
};
|
||||
const component = renderer.create(<AutosuggestEmoji emoji={emoji} />);
|
||||
const tree = component.toJSON();
|
||||
|
||||
expect(tree).toMatchSnapshot();
|
||||
render(<AutosuggestEmoji emoji={emoji} />);
|
||||
|
||||
expect(screen.getByTestId('emoji')).toHaveTextContent('foobar');
|
||||
expect(screen.getByRole('img').getAttribute('src')).toBe('http://example.com/emoji.png');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,38 +0,0 @@
|
|||
import { fromJS } from 'immutable';
|
||||
import React from 'react';
|
||||
|
||||
import { createComponent } from 'soapbox/test_helpers';
|
||||
|
||||
import Avatar from '../avatar';
|
||||
|
||||
describe('<Avatar />', () => {
|
||||
const account = fromJS({
|
||||
username: 'alice',
|
||||
acct: 'alice',
|
||||
display_name: 'Alice',
|
||||
avatar: '/animated/alice.gif',
|
||||
avatar_static: '/static/alice.jpg',
|
||||
});
|
||||
|
||||
const size = 100;
|
||||
|
||||
describe('Autoplay', () => {
|
||||
it('renders an animated avatar', () => {
|
||||
const component = createComponent(<Avatar account={account} animate size={size} />);
|
||||
const tree = component.toJSON();
|
||||
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Still', () => {
|
||||
it('renders a still avatar', () => {
|
||||
const component = createComponent(<Avatar account={account} size={size} />);
|
||||
const tree = component.toJSON();
|
||||
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
// TODO add autoplay test if possible
|
||||
});
|
35
app/soapbox/components/__tests__/avatar.test.js
Normal file
35
app/soapbox/components/__tests__/avatar.test.js
Normal file
|
@ -0,0 +1,35 @@
|
|||
import { fromJS } from 'immutable';
|
||||
import React from 'react';
|
||||
|
||||
import { render, screen } from '../../jest/test-helpers';
|
||||
import Avatar from '../avatar';
|
||||
|
||||
describe('<Avatar />', () => {
|
||||
const account = fromJS({
|
||||
username: 'alice',
|
||||
acct: 'alice',
|
||||
display_name: 'Alice',
|
||||
avatar: '/animated/alice.gif',
|
||||
avatar_static: '/static/alice.jpg',
|
||||
});
|
||||
|
||||
const size = 100;
|
||||
|
||||
// describe('Autoplay', () => {
|
||||
// it('renders an animated avatar', () => {
|
||||
// render(<Avatar account={account} animate size={size} />);
|
||||
|
||||
// expect(screen.getByRole('img').getAttribute('src')).toBe(account.get('avatar'));
|
||||
// });
|
||||
// });
|
||||
|
||||
describe('Still', () => {
|
||||
it('renders a still avatar', () => {
|
||||
render(<Avatar account={account} size={size} />);
|
||||
|
||||
expect(screen.getByRole('img').getAttribute('src')).toBe(account.get('avatar'));
|
||||
});
|
||||
});
|
||||
|
||||
// TODO add autoplay test if possible
|
||||
});
|
|
@ -1,8 +1,7 @@
|
|||
import { fromJS } from 'immutable';
|
||||
import React from 'react';
|
||||
|
||||
import { createComponent } from 'soapbox/test_helpers';
|
||||
|
||||
import { render, screen } from '../../jest/test-helpers';
|
||||
import AvatarOverlay from '../avatar_overlay';
|
||||
|
||||
describe('<AvatarOverlay', () => {
|
||||
|
@ -23,9 +22,7 @@ describe('<AvatarOverlay', () => {
|
|||
});
|
||||
|
||||
it('renders a overlay avatar', () => {
|
||||
const component = createComponent(<AvatarOverlay account={account} friend={friend} />);
|
||||
const tree = component.toJSON();
|
||||
|
||||
expect(tree).toMatchSnapshot();
|
||||
render(<AvatarOverlay account={account} friend={friend} />);
|
||||
expect(screen.queryAllByRole('img')).toHaveLength(2);
|
||||
});
|
||||
});
|
|
@ -1,12 +0,0 @@
|
|||
import React from 'react';
|
||||
import renderer from 'react-test-renderer';
|
||||
|
||||
import Badge from '../badge';
|
||||
|
||||
describe('<Badge />', () => {
|
||||
it('renders correctly', () => {
|
||||
const component = renderer.create(<Badge slug='patron' title='Patron' />);
|
||||
const tree = component.toJSON();
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
||||
});
|
12
app/soapbox/components/__tests__/badge.test.js
Normal file
12
app/soapbox/components/__tests__/badge.test.js
Normal file
|
@ -0,0 +1,12 @@
|
|||
import React from 'react';
|
||||
|
||||
import { render, screen } from '../../jest/test-helpers';
|
||||
import Badge from '../badge';
|
||||
|
||||
describe('<Badge />', () => {
|
||||
it('renders correctly', () => {
|
||||
render(<Badge slug='patron' title='Patron' />);
|
||||
|
||||
expect(screen.getByTestId('badge')).toHaveTextContent('Patron');
|
||||
});
|
||||
});
|
|
@ -1,13 +0,0 @@
|
|||
import React from 'react';
|
||||
|
||||
import { createComponent } from 'soapbox/test_helpers';
|
||||
|
||||
import ColumnBackButton from '../column_back_button';
|
||||
|
||||
describe('<ColumnBackButton />', () => {
|
||||
it('renders correctly', () => {
|
||||
const component = createComponent(<ColumnBackButton />);
|
||||
const tree = component.toJSON();
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
||||
});
|
12
app/soapbox/components/__tests__/column_back_button.test.js
Normal file
12
app/soapbox/components/__tests__/column_back_button.test.js
Normal file
|
@ -0,0 +1,12 @@
|
|||
import React from 'react';
|
||||
|
||||
import { render, screen } from '../../jest/test-helpers';
|
||||
import ColumnBackButton from '../column_back_button';
|
||||
|
||||
describe('<ColumnBackButton />', () => {
|
||||
it('renders correctly', () => {
|
||||
render(<ColumnBackButton />);
|
||||
|
||||
expect(screen.getByRole('button')).toHaveTextContent('Back');
|
||||
});
|
||||
});
|
|
@ -1,16 +1,15 @@
|
|||
import React from 'react';
|
||||
|
||||
import { normalizeAccount } from 'soapbox/normalizers';
|
||||
import { createComponent } from 'soapbox/test_helpers';
|
||||
|
||||
import { render, screen } from '../../jest/test-helpers';
|
||||
import DisplayName from '../display_name';
|
||||
|
||||
describe('<DisplayName />', () => {
|
||||
it('renders display name + account name', () => {
|
||||
const account = normalizeAccount({ acct: 'bar@baz' });
|
||||
const component = createComponent(<DisplayName account={account} />);
|
||||
const tree = component.toJSON();
|
||||
render(<DisplayName account={account} />);
|
||||
|
||||
expect(tree).toMatchSnapshot();
|
||||
expect(screen.getByTestId('display-name')).toHaveTextContent('bar@baz');
|
||||
});
|
||||
});
|
|
@ -1,7 +1,6 @@
|
|||
import React from 'react';
|
||||
|
||||
import { createComponent } from 'soapbox/test_helpers';
|
||||
|
||||
import { render, screen } from '../../jest/test-helpers';
|
||||
import EmojiSelector from '../emoji_selector';
|
||||
|
||||
describe('<EmojiSelector />', () => {
|
||||
|
@ -9,8 +8,8 @@ describe('<EmojiSelector />', () => {
|
|||
const children = <EmojiSelector />;
|
||||
children.__proto__.addEventListener = () => {};
|
||||
|
||||
const component = createComponent(children, {}, true);
|
||||
const tree = component.toJSON();
|
||||
expect(tree).toMatchSnapshot();
|
||||
render(children);
|
||||
|
||||
expect(screen.queryAllByRole('button')).toHaveLength(6);
|
||||
});
|
||||
});
|
|
@ -1,8 +1,7 @@
|
|||
import React from 'react';
|
||||
import { defineMessages } from 'react-intl';
|
||||
|
||||
import { createComponent } from 'soapbox/test_helpers';
|
||||
|
||||
import { render, screen } from '../../jest/test-helpers';
|
||||
import TimelineQueueButtonHeader from '../timeline_queue_button_header';
|
||||
|
||||
const messages = defineMessages({
|
||||
|
@ -10,32 +9,35 @@ const messages = defineMessages({
|
|||
});
|
||||
|
||||
describe('<TimelineQueueButtonHeader />', () => {
|
||||
it('renders correctly', () => {
|
||||
expect(createComponent(
|
||||
it('renders correctly', async() => {
|
||||
render(
|
||||
<TimelineQueueButtonHeader
|
||||
key='timeline-queue-button-header'
|
||||
onClick={() => {}} // eslint-disable-line react/jsx-no-bind
|
||||
count={0}
|
||||
message={messages.queue}
|
||||
/>,
|
||||
).toJSON()).toMatchSnapshot();
|
||||
);
|
||||
expect(screen.queryAllByRole('link')).toHaveLength(0);
|
||||
|
||||
expect(createComponent(
|
||||
render(
|
||||
<TimelineQueueButtonHeader
|
||||
key='timeline-queue-button-header'
|
||||
onClick={() => {}} // eslint-disable-line react/jsx-no-bind
|
||||
count={1}
|
||||
message={messages.queue}
|
||||
/>,
|
||||
).toJSON()).toMatchSnapshot();
|
||||
);
|
||||
expect(screen.getByText('Click to see 1 new post', { hidden: true })).toBeInTheDocument();
|
||||
|
||||
expect(createComponent(
|
||||
render(
|
||||
<TimelineQueueButtonHeader
|
||||
key='timeline-queue-button-header'
|
||||
onClick={() => {}} // eslint-disable-line react/jsx-no-bind
|
||||
count={9999999}
|
||||
message={messages.queue}
|
||||
/>,
|
||||
).toJSON()).toMatchSnapshot();
|
||||
);
|
||||
expect(screen.getByText('Click to see 9999999 new posts', { hidden: true })).toBeInTheDocument();
|
||||
});
|
||||
});
|
|
@ -28,7 +28,7 @@ export default class AutosuggestEmoji extends React.PureComponent {
|
|||
}
|
||||
|
||||
return (
|
||||
<div className='autosuggest-emoji'>
|
||||
<div className='autosuggest-emoji' data-testid='emoji'>
|
||||
<img
|
||||
className='emojione'
|
||||
src={url}
|
||||
|
|
|
@ -2,7 +2,7 @@ import PropTypes from 'prop-types';
|
|||
import React from 'react';
|
||||
|
||||
const Badge = (props: any) => (
|
||||
<span className={'badge badge--' + props.slug}>{props.title}</span>
|
||||
<span data-testid='badge' className={'badge badge--' + props.slug}>{props.title}</span>
|
||||
);
|
||||
|
||||
Badge.propTypes = {
|
||||
|
|
|
@ -72,7 +72,7 @@ class DisplayName extends React.PureComponent {
|
|||
}
|
||||
|
||||
return (
|
||||
<span className='display-name'>
|
||||
<span className='display-name' data-testid='display-name'>
|
||||
<HoverRefWrapper accountId={account.get('id')} inline>
|
||||
{displayName}
|
||||
</HoverRefWrapper>
|
||||
|
|
|
@ -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>
|
||||
`;
|
|
@ -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();
|
||||
});
|
||||
});
|
62
app/soapbox/components/ui/button/__tests__/button.test.tsx
Normal file
62
app/soapbox/components/ui/button/__tests__/button.test.tsx
Normal 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');
|
||||
});
|
||||
});
|
|
@ -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}
|
||||
|
|
|
@ -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();
|
||||
});
|
||||
});
|
|
@ -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 };
|
||||
|
|
|
@ -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>
|
||||
`;
|
|
@ -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();
|
||||
});
|
||||
});
|
12
app/soapbox/components/ui/column/__tests__/column.test.tsx
Normal file
12
app/soapbox/components/ui/column/__tests__/column.test.tsx
Normal 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');
|
||||
});
|
||||
});
|
|
@ -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');
|
||||
});
|
||||
});
|
|
@ -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');
|
||||
});
|
||||
});
|
|
@ -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}
|
||||
|
|
|
@ -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();
|
||||
});
|
||||
});
|
29
app/soapbox/components/ui/form/__tests__/form.test.tsx
Normal file
29
app/soapbox/components/ui/form/__tests__/form.test.tsx
Normal 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();
|
||||
});
|
||||
});
|
|
@ -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>
|
||||
);
|
||||
|
|
|
@ -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({
|
||||
|
|
|
@ -19,7 +19,7 @@ const AuthLayout = () => (
|
|||
<main className='relative flex flex-col h-screen'>
|
||||
<header className='pt-10 flex justify-center relative'>
|
||||
<Link to='/' className='cursor-pointer'>
|
||||
<img src='/instance/images/truth-logo.svg' alt='Logo' class='h-7' />
|
||||
<img src='/instance/images/truth-logo.svg' alt='Logo' className='h-7' />
|
||||
</Link>
|
||||
</header>
|
||||
|
||||
|
|
|
@ -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>
|
||||
`;
|
|
@ -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>
|
||||
`;
|
|
@ -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>
|
||||
`;
|
|
@ -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);
|
||||
});
|
||||
});
|
|
@ -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();
|
||||
});
|
||||
});
|
|
@ -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');
|
||||
});
|
||||
});
|
|
@ -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', () => {
|
|
@ -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);
|
||||
});
|
||||
});
|
|
@ -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();
|
||||
});
|
||||
});
|
|
@ -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();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -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)}
|
||||
|
|
|
@ -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)}
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -53,7 +53,7 @@ const DeleteAccount = () => {
|
|||
{intl.formatMessage(messages.deleteText)}
|
||||
</p>
|
||||
|
||||
<Form onSubmit={handleSubmit} disabled={isLoading}>
|
||||
<Form onSubmit={handleSubmit}>
|
||||
<FormGroup labelText={intl.formatMessage(messages.passwordFieldLabel)}>
|
||||
<Input
|
||||
type='password'
|
||||
|
|
|
@ -183,7 +183,7 @@ class CreateApp extends ImmutablePureComponent {
|
|||
|
||||
return (
|
||||
<Column label={intl.formatMessage(messages.heading)} backHref='/developers'>
|
||||
<Form onSubmit={this.handleSubmit} disabled={isLoading}>
|
||||
<Form onSubmit={this.handleSubmit}>
|
||||
<FormGroup labelText={<FormattedMessage id='app_create.name_label' defaultMessage='App name' />}>
|
||||
<Input
|
||||
placeholder={intl.formatMessage(messages.namePlaceholder)}
|
||||
|
@ -220,7 +220,7 @@ class CreateApp extends ImmutablePureComponent {
|
|||
</FormGroup>
|
||||
|
||||
<FormActions>
|
||||
<Button theme='primary' type='submit'>
|
||||
<Button theme='primary' type='submit' disabled={isLoading}>
|
||||
<FormattedMessage id='app_create.submit' defaultMessage='Create app' />
|
||||
</Button>
|
||||
</FormActions>
|
||||
|
|
|
@ -90,7 +90,7 @@ class SettingsStore extends ImmutablePureComponent {
|
|||
|
||||
return (
|
||||
<Column label={intl.formatMessage(messages.heading)} backHref='/developers'>
|
||||
<Form onSubmit={this.handleSubmit} disabled={!jsonValid || isLoading}>
|
||||
<Form onSubmit={this.handleSubmit}>
|
||||
<FormGroup
|
||||
hintText={intl.formatMessage(messages.hint)}
|
||||
errors={jsonValid ? [] : ['is invalid']}
|
||||
|
|
|
@ -60,7 +60,7 @@ const EditEmail = () => {
|
|||
</CardHeader>
|
||||
|
||||
<CardBody>
|
||||
<Form onSubmit={handleSubmit} disabled={isLoading}>
|
||||
<Form onSubmit={handleSubmit}>
|
||||
<FormGroup labelText={intl.formatMessage(messages.emailFieldLabel)}>
|
||||
<Input
|
||||
placeholder={intl.formatMessage({ id: 'edit_email.placeholder', defaultMessage: 'me@example.com' })}
|
||||
|
|
|
@ -59,7 +59,7 @@ const EditPassword = () => {
|
|||
</CardHeader>
|
||||
|
||||
<CardBody>
|
||||
<Form onSubmit={handleSubmit} disabled={isLoading}>
|
||||
<Form onSubmit={handleSubmit}>
|
||||
<FormGroup labelText={intl.formatMessage(messages.oldPasswordFieldLabel)}>
|
||||
<Input
|
||||
type='password'
|
||||
|
|
|
@ -1,103 +0,0 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`<Checkbox /> renders correctly 1`] = `
|
||||
<div
|
||||
className="input boolean"
|
||||
>
|
||||
<input
|
||||
type="checkbox"
|
||||
/>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`<FieldsGroup /> renders correctly 1`] = `
|
||||
<div
|
||||
className="fields-group"
|
||||
/>
|
||||
`;
|
||||
|
||||
exports[`<FileChooser /> renders correctly 1`] = `
|
||||
<div
|
||||
className="input"
|
||||
>
|
||||
<input
|
||||
accept={
|
||||
Array [
|
||||
"image/jpeg",
|
||||
"image/png",
|
||||
"image/gif",
|
||||
"image/webp",
|
||||
]
|
||||
}
|
||||
type="file"
|
||||
/>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`<InputContainer /> renders correctly 1`] = `
|
||||
<div
|
||||
className="input"
|
||||
/>
|
||||
`;
|
||||
|
||||
exports[`<RadioGroup /> renders correctly 1`] = `
|
||||
<div
|
||||
className="input with_floating_label radio_buttons"
|
||||
>
|
||||
<div
|
||||
className="label_input"
|
||||
>
|
||||
<label />
|
||||
<ul />
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`<SelectDropdown /> renders correctly 1`] = `
|
||||
<select
|
||||
className="pl-3 pr-10 py-2 text-base border-gray-300 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm rounded-md"
|
||||
>
|
||||
<option
|
||||
value="one"
|
||||
>
|
||||
One
|
||||
</option>
|
||||
<option
|
||||
value="two"
|
||||
>
|
||||
Two
|
||||
</option>
|
||||
<option
|
||||
value="three"
|
||||
>
|
||||
Three
|
||||
</option>
|
||||
</select>
|
||||
`;
|
||||
|
||||
exports[`<SimpleForm /> renders correctly 1`] = `
|
||||
<form
|
||||
acceptCharset="UTF-8"
|
||||
className="simple_form"
|
||||
method="post"
|
||||
onSubmit={[Function]}
|
||||
/>
|
||||
`;
|
||||
|
||||
exports[`<SimpleInput /> renders correctly 1`] = `
|
||||
<div
|
||||
className="input"
|
||||
>
|
||||
<input />
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`<TextInput /> renders correctly 1`] = `
|
||||
<div
|
||||
className="input"
|
||||
>
|
||||
<input
|
||||
type="text"
|
||||
/>
|
||||
</div>
|
||||
`;
|
|
@ -1,86 +0,0 @@
|
|||
import React from 'react';
|
||||
import renderer from 'react-test-renderer';
|
||||
|
||||
import {
|
||||
InputContainer,
|
||||
SimpleInput,
|
||||
SimpleForm,
|
||||
FieldsGroup,
|
||||
Checkbox,
|
||||
RadioGroup,
|
||||
SelectDropdown,
|
||||
TextInput,
|
||||
FileChooser,
|
||||
} from '..';
|
||||
|
||||
describe('<InputContainer />', () => {
|
||||
it('renders correctly', () => {
|
||||
expect(renderer.create(
|
||||
<InputContainer />,
|
||||
).toJSON()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
describe('<SimpleInput />', () => {
|
||||
it('renders correctly', () => {
|
||||
expect(renderer.create(
|
||||
<SimpleInput />,
|
||||
).toJSON()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
describe('<SimpleForm />', () => {
|
||||
it('renders correctly', () => {
|
||||
expect(renderer.create(
|
||||
<SimpleForm />,
|
||||
).toJSON()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
describe('<FieldsGroup />', () => {
|
||||
it('renders correctly', () => {
|
||||
expect(renderer.create(
|
||||
<FieldsGroup />,
|
||||
).toJSON()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
describe('<Checkbox />', () => {
|
||||
it('renders correctly', () => {
|
||||
expect(renderer.create(
|
||||
<Checkbox />,
|
||||
).toJSON()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
describe('<RadioGroup />', () => {
|
||||
it('renders correctly', () => {
|
||||
expect(renderer.create(
|
||||
<RadioGroup />,
|
||||
).toJSON()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
describe('<SelectDropdown />', () => {
|
||||
it('renders correctly', () => {
|
||||
expect(renderer.create(
|
||||
<SelectDropdown items={{ one: 'One', two: 'Two', three: 'Three' }} />,
|
||||
).toJSON()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
describe('<TextInput />', () => {
|
||||
it('renders correctly', () => {
|
||||
expect(renderer.create(
|
||||
<TextInput />,
|
||||
).toJSON()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
describe('<FileChooser />', () => {
|
||||
it('renders correctly', () => {
|
||||
expect(renderer.create(
|
||||
<FileChooser />,
|
||||
).toJSON()).toMatchSnapshot();
|
||||
});
|
||||
});
|
|
@ -144,7 +144,7 @@ class DisableOtpForm extends ImmutablePureComponent {
|
|||
const { isLoading, password } = this.state;
|
||||
|
||||
return (
|
||||
<Form onSubmit={this.handleSubmit} disabled={isLoading}>
|
||||
<Form onSubmit={this.handleSubmit}>
|
||||
<Stack>
|
||||
<Text weight='medium'>
|
||||
<FormattedMessage id='mfa.otp_enabled_title' defaultMessage='OTP Enabled' />
|
||||
|
@ -335,7 +335,7 @@ class OtpConfirmForm extends ImmutablePureComponent {
|
|||
<Stack space={4}>
|
||||
<hr className='mt-4' />
|
||||
|
||||
<Form onSubmit={this.handleSubmit} disabled={isLoading}>
|
||||
<Form onSubmit={this.handleSubmit}>
|
||||
<Stack>
|
||||
<Text weight='semibold' size='lg'>
|
||||
1. <FormattedMessage id='mfa.mfa_setup_scan_title' defaultMessage='Scan' />
|
||||
|
|
|
@ -1,29 +0,0 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`<ComposeButton /> renders a button element 1`] = `
|
||||
<div
|
||||
className="mt-4"
|
||||
>
|
||||
<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-6 py-3 text-base flex w-full justify-center"
|
||||
disabled={false}
|
||||
onClick={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<div
|
||||
className="svg-icon mr-2"
|
||||
>
|
||||
<svg
|
||||
id={
|
||||
Object {
|
||||
"process": [Function],
|
||||
}
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<span>
|
||||
Compose
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
`;
|
|
@ -1,26 +1,39 @@
|
|||
import { fireEvent, render, screen } from '@testing-library/react';
|
||||
import { Map as ImmutableMap } from 'immutable';
|
||||
import React from 'react';
|
||||
import { IntlProvider } from 'react-intl';
|
||||
import { Provider } from 'react-redux';
|
||||
import '@testing-library/jest-dom';
|
||||
|
||||
import { MODAL_OPEN } from 'soapbox/actions/modals';
|
||||
import { mockStore } from 'soapbox/jest/test-helpers';
|
||||
import rootReducer from 'soapbox/reducers';
|
||||
import { createComponent, mockStore } from 'soapbox/test_helpers';
|
||||
|
||||
import ComposeButton from '../compose-button';
|
||||
|
||||
const store = mockStore(rootReducer(ImmutableMap(), {}));
|
||||
const renderComposeButton = () => {
|
||||
render(
|
||||
<Provider store={store}>
|
||||
<IntlProvider locale='en'>
|
||||
<ComposeButton />
|
||||
</IntlProvider>
|
||||
</Provider>,
|
||||
);
|
||||
};
|
||||
|
||||
describe('<ComposeButton />', () => {
|
||||
it('renders a button element', () => {
|
||||
const component = createComponent(<ComposeButton />);
|
||||
const tree = component.toJSON();
|
||||
renderComposeButton();
|
||||
|
||||
expect(tree).toMatchSnapshot();
|
||||
expect(screen.getByRole('button')).toHaveTextContent('Compose');
|
||||
});
|
||||
|
||||
it('dispatches the MODAL_OPEN action', () => {
|
||||
const store = mockStore(rootReducer(ImmutableMap(), {}));
|
||||
const component = createComponent(<ComposeButton />, { store });
|
||||
renderComposeButton();
|
||||
|
||||
expect(store.getActions().length).toEqual(0);
|
||||
component.root.findByType('button').props.onClick();
|
||||
fireEvent.click(screen.getByRole('button'));
|
||||
expect(store.getActions()[0].type).toEqual(MODAL_OPEN);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -8,7 +8,7 @@ import { dismissAlert } from '../../../actions/alerts';
|
|||
import { getAlerts } from '../../../selectors';
|
||||
|
||||
const CustomNotificationStack = (props) => (
|
||||
<div role='assertive' className='z-1000 fixed inset-0 flex items-end px-4 py-6 pointer-events-none sm:p-6 sm:items-start'>
|
||||
<div role='assertive' data-testid='toast' className='z-1000 fixed inset-0 flex items-end px-4 py-6 pointer-events-none sm:p-6 sm:items-start'>
|
||||
<NotificationStack {...props} />
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -5,7 +5,7 @@ import {
|
|||
ALERT_DISMISS,
|
||||
ALERT_CLEAR,
|
||||
} from 'soapbox/actions/alerts';
|
||||
import { applyActions } from 'soapbox/test_helpers';
|
||||
import { applyActions } from 'soapbox/jest/test-helpers';
|
||||
|
||||
import reducer from '../alerts';
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ import {
|
|||
NOTIFICATIONS_MARK_READ_REQUEST,
|
||||
} from 'soapbox/actions/notifications';
|
||||
import { TIMELINE_DELETE } from 'soapbox/actions/timelines';
|
||||
import { applyActions } from 'soapbox/test_helpers';
|
||||
import { applyActions } from 'soapbox/jest/test-helpers';
|
||||
|
||||
import reducer from '../notifications';
|
||||
|
||||
|
|
Loading…
Reference in a new issue