Merge branch 'registration-tests' into 'next'
Add Registration Tests and Add React Testing Library See merge request soapbox-pub/soapbox-fe!1170
This commit is contained in:
commit
bacc34f872
18
.eslintrc.js
18
.eslintrc.js
|
@ -217,15 +217,15 @@ module.exports = {
|
||||||
'import/newline-after-import': 'error',
|
'import/newline-after-import': 'error',
|
||||||
'import/no-extraneous-dependencies': [
|
'import/no-extraneous-dependencies': [
|
||||||
'error',
|
'error',
|
||||||
{
|
// {
|
||||||
devDependencies: [
|
// devDependencies: [
|
||||||
'webpack/**',
|
// 'webpack/**',
|
||||||
'app/soapbox/test_setup.js',
|
// 'app/soapbox/test_setup.js',
|
||||||
'app/soapbox/test_helpers.js',
|
// 'app/soapbox/test_helpers.js',
|
||||||
'app/**/__tests__/**',
|
// 'app/**/__tests__/**',
|
||||||
'app/**/__mocks__/**',
|
// 'app/**/__mocks__/**',
|
||||||
],
|
// ],
|
||||||
},
|
// },
|
||||||
],
|
],
|
||||||
'import/no-unresolved': 'error',
|
'import/no-unresolved': 'error',
|
||||||
'import/no-webpack-loader-syntax': 'error',
|
'import/no-webpack-loader-syntax': 'error',
|
||||||
|
|
|
@ -22,7 +22,7 @@ before_script:
|
||||||
|
|
||||||
lint-js:
|
lint-js:
|
||||||
stage: lint
|
stage: lint
|
||||||
script: yarn test:lint:js
|
script: yarn lint:js
|
||||||
only:
|
only:
|
||||||
changes:
|
changes:
|
||||||
- "**/*.js"
|
- "**/*.js"
|
||||||
|
@ -34,7 +34,7 @@ lint-js:
|
||||||
|
|
||||||
lint-sass:
|
lint-sass:
|
||||||
stage: lint
|
stage: lint
|
||||||
script: yarn test:lint:sass
|
script: yarn lint:sass
|
||||||
only:
|
only:
|
||||||
changes:
|
changes:
|
||||||
- "**/*.scss"
|
- "**/*.scss"
|
||||||
|
@ -43,7 +43,7 @@ lint-sass:
|
||||||
|
|
||||||
jest:
|
jest:
|
||||||
stage: test
|
stage: test
|
||||||
script: yarn test:jest
|
script: yarn test:coverage
|
||||||
only:
|
only:
|
||||||
changes:
|
changes:
|
||||||
- "**/*.js"
|
- "**/*.js"
|
||||||
|
|
10
README.md
10
README.md
|
@ -153,15 +153,15 @@ NODE_ENV=development
|
||||||
- `yarn manage:translations` - Normalizes translation files. Should always be run after editing i18n strings.
|
- `yarn manage:translations` - Normalizes translation files. Should always be run after editing i18n strings.
|
||||||
|
|
||||||
#### Tests
|
#### Tests
|
||||||
- `yarn test` - Runs all tests.
|
- `yarn test:all` - Runs all tests and linters.
|
||||||
|
|
||||||
- `yarn test:lint` - Runs all linter tests.
|
- `yarn test` - Runs Jest for frontend unit tests.
|
||||||
|
|
||||||
- `yarn test:lint:js` - Runs only JavaScript linter.
|
- `yarn lint` - Runs all linters.
|
||||||
|
|
||||||
- `yarn test:lint:sass` - Runs only SASS linter.
|
- `yarn lint:js` - Runs only JavaScript linter.
|
||||||
|
|
||||||
- `yarn test:jest` - Frontend unit tests.
|
- `yarn lint:sass` - Runs only SASS linter.
|
||||||
|
|
||||||
# Contributing
|
# Contributing
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ import MockAdapter from 'axios-mock-adapter';
|
||||||
import { Map as ImmutableMap } from 'immutable';
|
import { Map as ImmutableMap } from 'immutable';
|
||||||
|
|
||||||
import { staticClient } from 'soapbox/api';
|
import { staticClient } from 'soapbox/api';
|
||||||
import { mockStore } from 'soapbox/test_helpers';
|
import { mockStore } from 'soapbox/jest/test-helpers';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
FETCH_ABOUT_PAGE_REQUEST,
|
FETCH_ABOUT_PAGE_REQUEST,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
|
import { mockStore } from 'soapbox/jest/test-helpers';
|
||||||
import { InstanceRecord } from 'soapbox/normalizers';
|
import { InstanceRecord } from 'soapbox/normalizers';
|
||||||
import rootReducer from 'soapbox/reducers';
|
import rootReducer from 'soapbox/reducers';
|
||||||
import { mockStore } from 'soapbox/test_helpers';
|
|
||||||
|
|
||||||
import { uploadCompose } from '../compose';
|
import { uploadCompose } from '../compose';
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { Map as ImmutableMap } from 'immutable';
|
import { Map as ImmutableMap } from 'immutable';
|
||||||
|
|
||||||
import { __stub } from 'soapbox/api';
|
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 { VERIFY_CREDENTIALS_REQUEST } from '../auth';
|
||||||
import { ACCOUNTS_IMPORT } from '../importer';
|
import { ACCOUNTS_IMPORT } from '../importer';
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { STATUSES_IMPORT } from 'soapbox/actions/importer';
|
import { STATUSES_IMPORT } from 'soapbox/actions/importer';
|
||||||
import { __stub } from 'soapbox/api';
|
import { __stub } from 'soapbox/api';
|
||||||
import { mockStore, rootState } from 'soapbox/test_helpers';
|
import { mockStore, rootState } from 'soapbox/jest/test-helpers';
|
||||||
|
|
||||||
import { fetchContext } from '../statuses';
|
import { fetchContext } from '../statuses';
|
||||||
|
|
||||||
|
|
|
@ -6,5 +6,5 @@ export default function InlineSVG({ src }) {
|
||||||
}
|
}
|
||||||
|
|
||||||
InlineSVG.propTypes = {
|
InlineSVG.propTypes = {
|
||||||
src: PropTypes.node.isRequired,
|
src: PropTypes.oneOfType([PropTypes.string, PropTypes.object]).isRequired,
|
||||||
};
|
};
|
||||||
|
|
|
@ -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 React from 'react';
|
||||||
import renderer from 'react-test-renderer';
|
|
||||||
|
|
||||||
|
import { render, screen } from '../../jest/test-helpers';
|
||||||
import AutosuggestEmoji from '../autosuggest_emoji';
|
import AutosuggestEmoji from '../autosuggest_emoji';
|
||||||
|
|
||||||
describe('<AutosuggestEmoji />', () => {
|
describe('<AutosuggestEmoji />', () => {
|
||||||
|
@ -9,10 +9,11 @@ describe('<AutosuggestEmoji />', () => {
|
||||||
native: '💙',
|
native: '💙',
|
||||||
colons: ':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')).not.toBe('http://example.com/emoji.png');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('renders emoji with custom url', () => {
|
it('renders emoji with custom url', () => {
|
||||||
|
@ -22,9 +23,10 @@ describe('<AutosuggestEmoji />', () => {
|
||||||
native: 'foobar',
|
native: 'foobar',
|
||||||
colons: ':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
|
|
||||||
});
|
|
|
@ -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 { fromJS } from 'immutable';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { createComponent } from 'soapbox/test_helpers';
|
import { render, screen } from '../../jest/test-helpers';
|
||||||
|
|
||||||
import AvatarOverlay from '../avatar_overlay';
|
import AvatarOverlay from '../avatar_overlay';
|
||||||
|
|
||||||
describe('<AvatarOverlay', () => {
|
describe('<AvatarOverlay', () => {
|
||||||
|
@ -23,9 +22,7 @@ describe('<AvatarOverlay', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('renders a overlay avatar', () => {
|
it('renders a overlay avatar', () => {
|
||||||
const component = createComponent(<AvatarOverlay account={account} friend={friend} />);
|
render(<AvatarOverlay account={account} friend={friend} />);
|
||||||
const tree = component.toJSON();
|
expect(screen.queryAllByRole('img')).toHaveLength(2);
|
||||||
|
|
||||||
expect(tree).toMatchSnapshot();
|
|
||||||
});
|
});
|
||||||
});
|
});
|
|
@ -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();
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -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();
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -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 React from 'react';
|
||||||
|
|
||||||
import { normalizeAccount } from 'soapbox/normalizers';
|
import { normalizeAccount } from 'soapbox/normalizers';
|
||||||
import { createComponent } from 'soapbox/test_helpers';
|
|
||||||
|
|
||||||
|
import { render, screen } from '../../jest/test-helpers';
|
||||||
import DisplayName from '../display_name';
|
import DisplayName from '../display_name';
|
||||||
|
|
||||||
describe('<DisplayName />', () => {
|
describe('<DisplayName />', () => {
|
||||||
it('renders display name + account name', () => {
|
it('renders display name + account name', () => {
|
||||||
const account = normalizeAccount({ acct: 'bar@baz' });
|
const account = normalizeAccount({ acct: 'bar@baz' });
|
||||||
const component = createComponent(<DisplayName account={account} />);
|
render(<DisplayName account={account} />);
|
||||||
const tree = component.toJSON();
|
|
||||||
|
|
||||||
expect(tree).toMatchSnapshot();
|
expect(screen.getByTestId('display-name')).toHaveTextContent('bar@baz');
|
||||||
});
|
});
|
||||||
});
|
});
|
|
@ -1,7 +1,6 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { createComponent } from 'soapbox/test_helpers';
|
import { render, screen } from '../../jest/test-helpers';
|
||||||
|
|
||||||
import EmojiSelector from '../emoji_selector';
|
import EmojiSelector from '../emoji_selector';
|
||||||
|
|
||||||
describe('<EmojiSelector />', () => {
|
describe('<EmojiSelector />', () => {
|
||||||
|
@ -9,8 +8,8 @@ describe('<EmojiSelector />', () => {
|
||||||
const children = <EmojiSelector />;
|
const children = <EmojiSelector />;
|
||||||
children.__proto__.addEventListener = () => {};
|
children.__proto__.addEventListener = () => {};
|
||||||
|
|
||||||
const component = createComponent(children, {}, true);
|
render(children);
|
||||||
const tree = component.toJSON();
|
|
||||||
expect(tree).toMatchSnapshot();
|
expect(screen.queryAllByRole('button')).toHaveLength(6);
|
||||||
});
|
});
|
||||||
});
|
});
|
|
@ -1,8 +1,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { defineMessages } from 'react-intl';
|
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';
|
import TimelineQueueButtonHeader from '../timeline_queue_button_header';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
|
@ -10,32 +9,35 @@ const messages = defineMessages({
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('<TimelineQueueButtonHeader />', () => {
|
describe('<TimelineQueueButtonHeader />', () => {
|
||||||
it('renders correctly', () => {
|
it('renders correctly', async() => {
|
||||||
expect(createComponent(
|
render(
|
||||||
<TimelineQueueButtonHeader
|
<TimelineQueueButtonHeader
|
||||||
key='timeline-queue-button-header'
|
key='timeline-queue-button-header'
|
||||||
onClick={() => {}} // eslint-disable-line react/jsx-no-bind
|
onClick={() => {}} // eslint-disable-line react/jsx-no-bind
|
||||||
count={0}
|
count={0}
|
||||||
message={messages.queue}
|
message={messages.queue}
|
||||||
/>,
|
/>,
|
||||||
).toJSON()).toMatchSnapshot();
|
);
|
||||||
|
expect(screen.queryAllByRole('link')).toHaveLength(0);
|
||||||
|
|
||||||
expect(createComponent(
|
render(
|
||||||
<TimelineQueueButtonHeader
|
<TimelineQueueButtonHeader
|
||||||
key='timeline-queue-button-header'
|
key='timeline-queue-button-header'
|
||||||
onClick={() => {}} // eslint-disable-line react/jsx-no-bind
|
onClick={() => {}} // eslint-disable-line react/jsx-no-bind
|
||||||
count={1}
|
count={1}
|
||||||
message={messages.queue}
|
message={messages.queue}
|
||||||
/>,
|
/>,
|
||||||
).toJSON()).toMatchSnapshot();
|
);
|
||||||
|
expect(screen.getByText('Click to see 1 new post', { hidden: true })).toBeInTheDocument();
|
||||||
|
|
||||||
expect(createComponent(
|
render(
|
||||||
<TimelineQueueButtonHeader
|
<TimelineQueueButtonHeader
|
||||||
key='timeline-queue-button-header'
|
key='timeline-queue-button-header'
|
||||||
onClick={() => {}} // eslint-disable-line react/jsx-no-bind
|
onClick={() => {}} // eslint-disable-line react/jsx-no-bind
|
||||||
count={9999999}
|
count={9999999}
|
||||||
message={messages.queue}
|
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 (
|
return (
|
||||||
<div className='autosuggest-emoji'>
|
<div className='autosuggest-emoji' data-testid='emoji'>
|
||||||
<img
|
<img
|
||||||
className='emojione'
|
className='emojione'
|
||||||
src={url}
|
src={url}
|
||||||
|
|
|
@ -2,7 +2,7 @@ import PropTypes from 'prop-types';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
const Badge = (props: any) => (
|
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 = {
|
Badge.propTypes = {
|
||||||
|
|
|
@ -72,7 +72,7 @@ class DisplayName extends React.PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<span className='display-name'>
|
<span className='display-name' data-testid='display-name'>
|
||||||
<HoverRefWrapper accountId={account.get('id')} inline>
|
<HoverRefWrapper accountId={account.get('id')} inline>
|
||||||
{displayName}
|
{displayName}
|
||||||
</HoverRefWrapper>
|
</HoverRefWrapper>
|
||||||
|
|
|
@ -15,7 +15,7 @@ export default class Icon extends React.PureComponent {
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
id: PropTypes.string,
|
id: PropTypes.string,
|
||||||
src: PropTypes.string,
|
src: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
|
||||||
className: PropTypes.string,
|
className: PropTypes.string,
|
||||||
fixedWidth: PropTypes.bool,
|
fixedWidth: PropTypes.bool,
|
||||||
};
|
};
|
||||||
|
|
|
@ -12,7 +12,7 @@ import InlineSVG from 'react-inlinesvg';
|
||||||
export default class SvgIcon extends React.PureComponent {
|
export default class SvgIcon extends React.PureComponent {
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
src: PropTypes.string.isRequired,
|
src: PropTypes.oneOfType([PropTypes.string, PropTypes.object]).isRequired,
|
||||||
alt: PropTypes.string,
|
alt: PropTypes.string,
|
||||||
className: PropTypes.string,
|
className: PropTypes.string,
|
||||||
};
|
};
|
||||||
|
|
|
@ -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();
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -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}
|
onClick={handleClick}
|
||||||
ref={ref}
|
ref={ref}
|
||||||
type={type}
|
type={type}
|
||||||
|
data-testid='button'
|
||||||
>
|
>
|
||||||
{renderIcon()}
|
{renderIcon()}
|
||||||
{text || children}
|
{text || children}
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { createShallowComponent } from 'soapbox/test_helpers';
|
import { render, screen } from '../../../../jest/test-helpers';
|
||||||
|
|
||||||
import { Card, CardBody, CardHeader, CardTitle } from '../card';
|
import { Card, CardBody, CardHeader, CardTitle } from '../card';
|
||||||
|
|
||||||
describe('<Card />', () => {
|
describe('<Card />', () => {
|
||||||
it('renders the CardTitle and CardBody', () => {
|
it('renders the CardTitle and CardBody', () => {
|
||||||
const component = createShallowComponent(
|
render(
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<CardTitle title='Card Title' />
|
<CardTitle title='Card Title' />
|
||||||
|
@ -18,13 +17,13 @@ describe('<Card />', () => {
|
||||||
</Card>,
|
</Card>,
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(component.text()).toContain('Card Title');
|
expect(screen.getByTestId('card-title')).toHaveTextContent('Card Title');
|
||||||
expect(component.text()).toContain('Card Body');
|
expect(screen.getByTestId('card-body')).toHaveTextContent('Card Body');
|
||||||
expect(component.text()).not.toContain('Back');
|
expect(screen.queryByTestId('back-button')).not.toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('renders the Back Button', () => {
|
it('renders the Back Button', () => {
|
||||||
const component = createShallowComponent(
|
render(
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader backHref='/'>
|
<CardHeader backHref='/'>
|
||||||
<CardTitle title='Card Title' />
|
<CardTitle title='Card Title' />
|
||||||
|
@ -32,6 +31,6 @@ describe('<Card />', () => {
|
||||||
</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 (
|
return (
|
||||||
<Comp {...backAttributes} className='mr-2 text-gray-900 dark:text-gray-100' aria-label={intl.formatMessage(messages.back)}>
|
<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' />
|
<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>
|
</Comp>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -74,11 +74,11 @@ interface ICardTitle {
|
||||||
}
|
}
|
||||||
|
|
||||||
const CardTitle = ({ title }: ICardTitle): JSX.Element => (
|
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 => (
|
const CardBody: React.FC = ({ children }): JSX.Element => (
|
||||||
<div>{children}</div>
|
<div data-testid='card-body'>{children}</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
export { Card, CardHeader, CardTitle, CardBody };
|
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();
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -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>
|
<div>
|
||||||
<label
|
<label
|
||||||
htmlFor={formFieldId}
|
htmlFor={formFieldId}
|
||||||
|
data-testid='form-group-label'
|
||||||
className='block text-sm font-medium text-gray-700 dark:text-gray-400'
|
className='block text-sm font-medium text-gray-700 dark:text-gray-400'
|
||||||
>
|
>
|
||||||
{labelText}
|
{labelText}
|
||||||
|
@ -34,13 +35,16 @@ const FormGroup: React.FC<IFormGroup> = (props) => {
|
||||||
{inputChildren.filter((_, i) => i !== 0)}
|
{inputChildren.filter((_, i) => i !== 0)}
|
||||||
|
|
||||||
{errors?.length > 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(', ')}
|
{errors.join(', ')}
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{hintText ? (
|
{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}
|
{hintText}
|
||||||
</p>
|
</p>
|
||||||
) : null}
|
) : 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();
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -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';
|
import * as React from 'react';
|
||||||
|
|
||||||
interface IForm {
|
interface IForm {
|
||||||
disabled?: boolean,
|
|
||||||
onSubmit?: (event: React.FormEvent) => void,
|
onSubmit?: (event: React.FormEvent) => void,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,7 +14,7 @@ const Form: React.FC<IForm> = ({ onSubmit, children, ...filteredProps }) => {
|
||||||
}, [onSubmit]);
|
}, [onSubmit]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form onSubmit={handleSubmit} className='space-y-4' {...filteredProps}>
|
<form data-testid='form' onSubmit={handleSubmit} className='space-y-4' {...filteredProps}>
|
||||||
{children}
|
{children}
|
||||||
</form>
|
</form>
|
||||||
);
|
);
|
||||||
|
|
|
@ -8,8 +8,7 @@ interface IIcon {
|
||||||
src: string,
|
src: string,
|
||||||
}
|
}
|
||||||
|
|
||||||
const Icon = ({ src, alt, count, ...filteredProps }: IIcon): JSX.Element => {
|
const Icon = ({ src, alt, count, ...filteredProps }: IIcon): JSX.Element => (
|
||||||
return (
|
|
||||||
<div className='relative'>
|
<div className='relative'>
|
||||||
{count ? (
|
{count ? (
|
||||||
<span className='absolute -top-2 -right-3 block px-1.5 py-0.5 bg-accent-500 text-xs text-white rounded-full ring-2 ring-white'>
|
<span className='absolute -top-2 -right-3 block px-1.5 py-0.5 bg-accent-500 text-xs text-white rounded-full ring-2 ring-white'>
|
||||||
|
@ -19,7 +18,6 @@ const Icon = ({ src, alt, count, ...filteredProps }: IIcon): JSX.Element => {
|
||||||
|
|
||||||
<InlineSVG src={src} title={alt} {...filteredProps} />
|
<InlineSVG src={src} title={alt} {...filteredProps} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
|
||||||
|
|
||||||
export default Icon;
|
export default Icon;
|
||||||
|
|
|
@ -3,7 +3,7 @@ import React from 'react';
|
||||||
import InlineSVG from 'react-inlinesvg';
|
import InlineSVG from 'react-inlinesvg';
|
||||||
import { defineMessages, useIntl } from 'react-intl';
|
import { defineMessages, useIntl } from 'react-intl';
|
||||||
|
|
||||||
import Icon from '../../icon';
|
import Icon from '../icon/icon';
|
||||||
import Tooltip from '../tooltip/tooltip';
|
import Tooltip from '../tooltip/tooltip';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
|
|
|
@ -19,7 +19,7 @@ const AuthLayout = () => (
|
||||||
<main className='relative flex flex-col h-screen'>
|
<main className='relative flex flex-col h-screen'>
|
||||||
<header className='pt-10 flex justify-center relative'>
|
<header className='pt-10 flex justify-center relative'>
|
||||||
<Link to='/' className='cursor-pointer'>
|
<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>
|
</Link>
|
||||||
</header>
|
</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 { Map as ImmutableMap } from 'immutable';
|
||||||
import React from 'react';
|
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';
|
import CaptchaField, { NativeCaptchaField } from '../captcha';
|
||||||
|
|
||||||
describe('<CaptchaField />', () => {
|
describe('<CaptchaField />', () => {
|
||||||
it('renders null by default', () => {
|
it('renders null by default', () => {
|
||||||
expect(createComponent(
|
render(<CaptchaField />);
|
||||||
<CaptchaField />,
|
|
||||||
).toJSON()).toMatchSnapshot();
|
expect(screen.queryAllByRole('textbox')).toHaveLength(0);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -23,11 +21,13 @@ describe('<NativeCaptchaField />', () => {
|
||||||
url: 'data:image/png;base64,...',
|
url: 'data:image/png;base64,...',
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(renderer.create(
|
render(
|
||||||
<NativeCaptchaField
|
<NativeCaptchaField
|
||||||
captcha={captcha}
|
captcha={captcha}
|
||||||
onChange={() => {}} // eslint-disable-line react/jsx-no-bind
|
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 React from 'react';
|
||||||
|
|
||||||
import rootReducer from 'soapbox/reducers';
|
import { render, screen } from '../../../../jest/test-helpers';
|
||||||
import { createComponent, mockStore } from 'soapbox/test_helpers';
|
|
||||||
|
|
||||||
import LoginPage from '../login_page';
|
import LoginPage from '../login_page';
|
||||||
|
|
||||||
describe('<LoginPage />', () => {
|
describe('<LoginPage />', () => {
|
||||||
it('renders correctly on load', () => {
|
it('renders correctly on load', () => {
|
||||||
const state = rootReducer(undefined, {})
|
const store = {
|
||||||
.set('me', '1234')
|
instance: ImmutableMap({
|
||||||
.update('instance', instance => instance.set('version', '2.7.2 (compatible; Pleroma 2.3.0)'));
|
version: '2.7.2 (compatible; Pleroma 2.3.0)',
|
||||||
const store = mockStore(state);
|
}),
|
||||||
|
};
|
||||||
|
|
||||||
expect(createComponent(
|
render(<LoginPage />, null, store);
|
||||||
<LoginPage />,
|
|
||||||
{ store },
|
expect(screen.getByRole('heading')).toHaveTextContent('Sign In');
|
||||||
).toJSON()).toMatchSnapshot();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// it('renders the OTP form when logIn returns with mfa_required', () => {
|
// 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 React from 'react';
|
||||||
import { act } from 'react-dom/test-utils';
|
|
||||||
import { Route, Switch } from 'react-router-dom';
|
import { Route, Switch } from 'react-router-dom';
|
||||||
|
|
||||||
import { __stub } from 'soapbox/api';
|
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';
|
import PasswordResetConfirm from '../password_reset_confirm';
|
||||||
|
|
||||||
const TestableComponent = () => (
|
const TestableComponent = () => (
|
||||||
<Switch>
|
<Switch>
|
||||||
<Route path='/edit' exact><PasswordResetConfirm /></Route>
|
<Route path='/edit' exact><PasswordResetConfirm /></Route>
|
||||||
<Route path='/' exact><span>Homepage</span></Route>
|
<Route path='/' exact><span data-testid='home'>Homepage</span></Route>
|
||||||
</Switch>
|
</Switch>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -22,24 +20,23 @@ describe('<PasswordResetConfirm />', () => {
|
||||||
.reply(200, {});
|
.reply(200, {});
|
||||||
});
|
});
|
||||||
|
|
||||||
const state = rootReducer(undefined, {});
|
render(
|
||||||
const store = mockStore(state);
|
|
||||||
const component = createShallowComponent(
|
|
||||||
<TestableComponent />,
|
<TestableComponent />,
|
||||||
{ store },
|
{},
|
||||||
|
null,
|
||||||
{ initialEntries: ['/edit'] },
|
{ initialEntries: ['/edit'] },
|
||||||
);
|
);
|
||||||
|
|
||||||
await component.find('form').at(0).simulate('submit', {
|
fireEvent.submit(
|
||||||
|
screen.getByTestId('form'), {
|
||||||
preventDefault: () => {},
|
preventDefault: () => {},
|
||||||
});
|
},
|
||||||
await act(async() => {
|
);
|
||||||
await new Promise(resolve => setTimeout(resolve, 0));
|
|
||||||
component.update();
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(component.text()).toContain('Homepage');
|
await waitFor(() => {
|
||||||
expect(component.text()).not.toContain('Expired token');
|
expect(screen.getByTestId('home')).toHaveTextContent('Homepage');
|
||||||
|
expect(screen.queryByTestId('form-group-error')).not.toBeInTheDocument();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('handles failed responses from the API', async() => {
|
it('handles failed responses from the API', async() => {
|
||||||
|
@ -48,23 +45,22 @@ describe('<PasswordResetConfirm />', () => {
|
||||||
.reply(403, {});
|
.reply(403, {});
|
||||||
});
|
});
|
||||||
|
|
||||||
const state = rootReducer(undefined, {});
|
render(
|
||||||
const store = mockStore(state);
|
|
||||||
const component = createShallowComponent(
|
|
||||||
<TestableComponent />,
|
<TestableComponent />,
|
||||||
{ store },
|
{},
|
||||||
|
null,
|
||||||
{ initialEntries: ['/edit'] },
|
{ initialEntries: ['/edit'] },
|
||||||
);
|
);
|
||||||
|
|
||||||
await component.find('form').at(0).simulate('submit', {
|
await fireEvent.submit(
|
||||||
|
screen.getByTestId('form'), {
|
||||||
preventDefault: () => {},
|
preventDefault: () => {},
|
||||||
});
|
},
|
||||||
await act(async() => {
|
);
|
||||||
await new Promise(resolve => setTimeout(resolve, 0));
|
|
||||||
component.update();
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(component.text()).toContain('Expired token');
|
await waitFor(() => {
|
||||||
expect(component.text()).not.toContain('Homepage');
|
expect(screen.queryByTestId('home')).not.toBeInTheDocument();
|
||||||
|
expect(screen.queryByTestId('form-group-error')).toBeInTheDocument();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -30,7 +30,7 @@ const LoginForm = ({ isLoading, handleSubmit }) => {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='sm:pt-10 sm:w-2/3 md:w-1/2 mx-auto'>
|
<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)}>
|
<FormGroup labelText={intl.formatMessage(messages.email)}>
|
||||||
<Input
|
<Input
|
||||||
aria-label={intl.formatMessage(messages.email)}
|
aria-label={intl.formatMessage(messages.email)}
|
||||||
|
|
|
@ -66,7 +66,7 @@ class OtpAuthForm extends ImmutablePureComponent {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='sm:pt-10 sm:w-2/3 md:w-1/2 mx-auto'>
|
<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
|
<FormGroup
|
||||||
labelText={intl.formatMessage(messages.otpCodeLabel)}
|
labelText={intl.formatMessage(messages.otpCodeLabel)}
|
||||||
hintText={intl.formatMessage(messages.otpCodeHint)}
|
hintText={intl.formatMessage(messages.otpCodeHint)}
|
||||||
|
|
|
@ -49,7 +49,7 @@ class PasswordReset extends ImmutablePureComponent {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='sm:pt-10 sm:w-2/3 md:w-1/2 mx-auto'>
|
<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)}>
|
<FormGroup labelText={intl.formatMessage(messages.nicknameOrEmail)}>
|
||||||
<Input
|
<Input
|
||||||
name='nickname_or_email'
|
name='nickname_or_email'
|
||||||
|
|
|
@ -62,7 +62,7 @@ const PasswordResetConfirm = ({ resetPasswordConfirm }) => {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='sm:pt-10 sm:w-2/3 md:w-1/2 mx-auto'>
|
<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()}>
|
<FormGroup labelText='Password' errors={renderErrors()}>
|
||||||
<Input
|
<Input
|
||||||
type='password'
|
type='password'
|
||||||
|
|
|
@ -53,7 +53,7 @@ const DeleteAccount = () => {
|
||||||
{intl.formatMessage(messages.deleteText)}
|
{intl.formatMessage(messages.deleteText)}
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<Form onSubmit={handleSubmit} disabled={isLoading}>
|
<Form onSubmit={handleSubmit}>
|
||||||
<FormGroup labelText={intl.formatMessage(messages.passwordFieldLabel)}>
|
<FormGroup labelText={intl.formatMessage(messages.passwordFieldLabel)}>
|
||||||
<Input
|
<Input
|
||||||
type='password'
|
type='password'
|
||||||
|
|
|
@ -183,7 +183,7 @@ class CreateApp extends ImmutablePureComponent {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Column label={intl.formatMessage(messages.heading)} backHref='/developers'>
|
<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' />}>
|
<FormGroup labelText={<FormattedMessage id='app_create.name_label' defaultMessage='App name' />}>
|
||||||
<Input
|
<Input
|
||||||
placeholder={intl.formatMessage(messages.namePlaceholder)}
|
placeholder={intl.formatMessage(messages.namePlaceholder)}
|
||||||
|
@ -220,7 +220,7 @@ class CreateApp extends ImmutablePureComponent {
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
|
|
||||||
<FormActions>
|
<FormActions>
|
||||||
<Button theme='primary' type='submit'>
|
<Button theme='primary' type='submit' disabled={isLoading}>
|
||||||
<FormattedMessage id='app_create.submit' defaultMessage='Create app' />
|
<FormattedMessage id='app_create.submit' defaultMessage='Create app' />
|
||||||
</Button>
|
</Button>
|
||||||
</FormActions>
|
</FormActions>
|
||||||
|
|
|
@ -90,7 +90,7 @@ class SettingsStore extends ImmutablePureComponent {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Column label={intl.formatMessage(messages.heading)} backHref='/developers'>
|
<Column label={intl.formatMessage(messages.heading)} backHref='/developers'>
|
||||||
<Form onSubmit={this.handleSubmit} disabled={!jsonValid || isLoading}>
|
<Form onSubmit={this.handleSubmit}>
|
||||||
<FormGroup
|
<FormGroup
|
||||||
hintText={intl.formatMessage(messages.hint)}
|
hintText={intl.formatMessage(messages.hint)}
|
||||||
errors={jsonValid ? [] : ['is invalid']}
|
errors={jsonValid ? [] : ['is invalid']}
|
||||||
|
|
|
@ -60,7 +60,7 @@ const EditEmail = () => {
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
|
|
||||||
<CardBody>
|
<CardBody>
|
||||||
<Form onSubmit={handleSubmit} disabled={isLoading}>
|
<Form onSubmit={handleSubmit}>
|
||||||
<FormGroup labelText={intl.formatMessage(messages.emailFieldLabel)}>
|
<FormGroup labelText={intl.formatMessage(messages.emailFieldLabel)}>
|
||||||
<Input
|
<Input
|
||||||
placeholder={intl.formatMessage({ id: 'edit_email.placeholder', defaultMessage: 'me@example.com' })}
|
placeholder={intl.formatMessage({ id: 'edit_email.placeholder', defaultMessage: 'me@example.com' })}
|
||||||
|
|
|
@ -59,7 +59,7 @@ const EditPassword = () => {
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
|
|
||||||
<CardBody>
|
<CardBody>
|
||||||
<Form onSubmit={handleSubmit} disabled={isLoading}>
|
<Form onSubmit={handleSubmit}>
|
||||||
<FormGroup labelText={intl.formatMessage(messages.oldPasswordFieldLabel)}>
|
<FormGroup labelText={intl.formatMessage(messages.oldPasswordFieldLabel)}>
|
||||||
<Input
|
<Input
|
||||||
type='password'
|
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;
|
const { isLoading, password } = this.state;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Form onSubmit={this.handleSubmit} disabled={isLoading}>
|
<Form onSubmit={this.handleSubmit}>
|
||||||
<Stack>
|
<Stack>
|
||||||
<Text weight='medium'>
|
<Text weight='medium'>
|
||||||
<FormattedMessage id='mfa.otp_enabled_title' defaultMessage='OTP Enabled' />
|
<FormattedMessage id='mfa.otp_enabled_title' defaultMessage='OTP Enabled' />
|
||||||
|
@ -335,7 +335,7 @@ class OtpConfirmForm extends ImmutablePureComponent {
|
||||||
<Stack space={4}>
|
<Stack space={4}>
|
||||||
<hr className='mt-4' />
|
<hr className='mt-4' />
|
||||||
|
|
||||||
<Form onSubmit={this.handleSubmit} disabled={isLoading}>
|
<Form onSubmit={this.handleSubmit}>
|
||||||
<Stack>
|
<Stack>
|
||||||
<Text weight='semibold' size='lg'>
|
<Text weight='semibold' size='lg'>
|
||||||
1. <FormattedMessage id='mfa.mfa_setup_scan_title' defaultMessage='Scan' />
|
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 { Map as ImmutableMap } from 'immutable';
|
||||||
import React from 'react';
|
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 { MODAL_OPEN } from 'soapbox/actions/modals';
|
||||||
|
import { mockStore } from 'soapbox/jest/test-helpers';
|
||||||
import rootReducer from 'soapbox/reducers';
|
import rootReducer from 'soapbox/reducers';
|
||||||
import { createComponent, mockStore } from 'soapbox/test_helpers';
|
|
||||||
|
|
||||||
import ComposeButton from '../compose-button';
|
import ComposeButton from '../compose-button';
|
||||||
|
|
||||||
|
const store = mockStore(rootReducer(ImmutableMap(), {}));
|
||||||
|
const renderComposeButton = () => {
|
||||||
|
render(
|
||||||
|
<Provider store={store}>
|
||||||
|
<IntlProvider locale='en'>
|
||||||
|
<ComposeButton />
|
||||||
|
</IntlProvider>
|
||||||
|
</Provider>,
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
describe('<ComposeButton />', () => {
|
describe('<ComposeButton />', () => {
|
||||||
it('renders a button element', () => {
|
it('renders a button element', () => {
|
||||||
const component = createComponent(<ComposeButton />);
|
renderComposeButton();
|
||||||
const tree = component.toJSON();
|
|
||||||
|
|
||||||
expect(tree).toMatchSnapshot();
|
expect(screen.getByRole('button')).toHaveTextContent('Compose');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('dispatches the MODAL_OPEN action', () => {
|
it('dispatches the MODAL_OPEN action', () => {
|
||||||
const store = mockStore(rootReducer(ImmutableMap(), {}));
|
renderComposeButton();
|
||||||
const component = createComponent(<ComposeButton />, { store });
|
|
||||||
|
|
||||||
expect(store.getActions().length).toEqual(0);
|
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);
|
expect(store.getActions()[0].type).toEqual(MODAL_OPEN);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -8,7 +8,7 @@ import { dismissAlert } from '../../../actions/alerts';
|
||||||
import { getAlerts } from '../../../selectors';
|
import { getAlerts } from '../../../selectors';
|
||||||
|
|
||||||
const CustomNotificationStack = (props) => (
|
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} />
|
<NotificationStack {...props} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -0,0 +1,100 @@
|
||||||
|
import { Map as ImmutableMap } from 'immutable';
|
||||||
|
import React from 'react';
|
||||||
|
import { Route, Switch } from 'react-router-dom';
|
||||||
|
|
||||||
|
import { __stub } from '../../../__mocks__/api';
|
||||||
|
import { render, screen } from '../../../jest/test-helpers';
|
||||||
|
import Verification from '../index';
|
||||||
|
|
||||||
|
const TestableComponent = () => (
|
||||||
|
<Switch>
|
||||||
|
<Route path='/auth/verify' exact><Verification /></Route>
|
||||||
|
<Route path='/' exact><span data-testid='home'>Homepage</span></Route>
|
||||||
|
</Switch>
|
||||||
|
);
|
||||||
|
|
||||||
|
const renderComponent = (store) => render(
|
||||||
|
<TestableComponent />,
|
||||||
|
{},
|
||||||
|
store,
|
||||||
|
{ initialEntries: ['/auth/verify'] },
|
||||||
|
);
|
||||||
|
|
||||||
|
describe('<Verification />', () => {
|
||||||
|
let store;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
store = {
|
||||||
|
verification: ImmutableMap({
|
||||||
|
instance: {
|
||||||
|
isReady: true,
|
||||||
|
registrations: true,
|
||||||
|
},
|
||||||
|
isComplete: false,
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
|
||||||
|
__stub(mock => {
|
||||||
|
mock.onGet('/api/v1/pepe/instance')
|
||||||
|
.reply(200, {
|
||||||
|
age_minimum: 18,
|
||||||
|
approval_required: true,
|
||||||
|
challenges: ['age', 'email', 'sms'],
|
||||||
|
});
|
||||||
|
|
||||||
|
mock.onPost('/api/v1/pepe/registrations')
|
||||||
|
.reply(200, {
|
||||||
|
access_token: 'N-dZmNqNSmTutJLsGjZ5AnJL4sLw_y-N3pn2acSqJY8',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('When registration is closed', () => {
|
||||||
|
it('successfully redirects to the homepage', () => {
|
||||||
|
const verification = store.verification.setIn(['instance', 'registrations'], false);
|
||||||
|
store.verification = verification;
|
||||||
|
|
||||||
|
renderComponent(store);
|
||||||
|
expect(screen.getByTestId('home')).toHaveTextContent('Homepage');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('When verification is complete', () => {
|
||||||
|
it('successfully renders the Registration component', () => {
|
||||||
|
const verification = store.verification.set('isComplete', true);
|
||||||
|
store.verification = verification;
|
||||||
|
|
||||||
|
renderComponent(store);
|
||||||
|
expect(screen.getByRole('heading')).toHaveTextContent('Register your account');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Switching verification steps', () => {
|
||||||
|
it('successfully renders the Birthday step', () => {
|
||||||
|
const verification = store.verification.set('currentChallenge', 'age');
|
||||||
|
store.verification = verification;
|
||||||
|
|
||||||
|
renderComponent(store);
|
||||||
|
|
||||||
|
expect(screen.getByRole('heading')).toHaveTextContent('Enter your birth date');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('successfully renders the Email step', () => {
|
||||||
|
const verification = store.verification.set('currentChallenge', 'email');
|
||||||
|
store.verification = verification;
|
||||||
|
|
||||||
|
renderComponent(store);
|
||||||
|
|
||||||
|
expect(screen.getByRole('heading')).toHaveTextContent('Enter your email address');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('successfully renders the SMS step', () => {
|
||||||
|
const verification = store.verification.set('currentChallenge', 'sms');
|
||||||
|
store.verification = verification;
|
||||||
|
|
||||||
|
renderComponent(store);
|
||||||
|
|
||||||
|
expect(screen.getByRole('heading')).toHaveTextContent('Enter your phone number');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,67 @@
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import { __stub } from 'soapbox/api';
|
||||||
|
|
||||||
|
import { fireEvent, render, screen, waitFor } from '../../../jest/test-helpers';
|
||||||
|
import Registration from '../registration';
|
||||||
|
|
||||||
|
describe('<Registration />', () => {
|
||||||
|
it('renders', () => {
|
||||||
|
render(<Registration />);
|
||||||
|
|
||||||
|
expect(screen.getByRole('heading')).toHaveTextContent(/register your account/i);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('with valid data', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
__stub(mock => {
|
||||||
|
mock.onPost('/api/v1/pepe/accounts').reply(200, {});
|
||||||
|
mock.onPost('/api/v1/apps').reply(200, {});
|
||||||
|
mock.onPost('/oauth/token').reply(200, {});
|
||||||
|
mock.onPost('/api/v1/accounts/verify_credentials').reply(200, {});
|
||||||
|
mock.onGet('/api/v1/instance').reply(200, {});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('handles successful submission', async() => {
|
||||||
|
render(<Registration />);
|
||||||
|
|
||||||
|
await waitFor(() => {
|
||||||
|
fireEvent.submit(screen.getByTestId('button'), { preventDefault: () => {} });
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(screen.getByTestId('toast')).toHaveTextContent(/welcome to/i);
|
||||||
|
expect(screen.queryAllByRole('heading')).toHaveLength(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('with invalid data', () => {
|
||||||
|
it('handles 422 errors', async() => {
|
||||||
|
__stub(mock => {
|
||||||
|
mock.onPost('/api/v1/pepe/accounts').reply(422, {});
|
||||||
|
});
|
||||||
|
|
||||||
|
render(<Registration />);
|
||||||
|
|
||||||
|
await waitFor(() => {
|
||||||
|
fireEvent.submit(screen.getByTestId('button'), { preventDefault: () => {} });
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(screen.getByTestId('toast')).toHaveTextContent(/this username has already been taken/i);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('handles generic errors', async() => {
|
||||||
|
__stub(mock => {
|
||||||
|
mock.onPost('/api/v1/pepe/accounts').reply(500, {});
|
||||||
|
});
|
||||||
|
|
||||||
|
render(<Registration />);
|
||||||
|
|
||||||
|
await waitFor(() => {
|
||||||
|
fireEvent.submit(screen.getByTestId('button'), { preventDefault: () => {} });
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(screen.getByTestId('toast')).toHaveTextContent(/failed to register your account/i);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -1,50 +0,0 @@
|
||||||
import * as React from 'react';
|
|
||||||
import { useDispatch, useSelector } from 'react-redux';
|
|
||||||
import { Redirect } from 'react-router-dom';
|
|
||||||
|
|
||||||
import { fetchVerificationConfig } from 'soapbox/actions/verification';
|
|
||||||
|
|
||||||
import Registration from './registration';
|
|
||||||
import AgeVerification from './steps/age_verification';
|
|
||||||
import EmailVerification from './steps/email_verification';
|
|
||||||
import SmsVerification from './steps/sms_verification';
|
|
||||||
|
|
||||||
const verificationSteps = {
|
|
||||||
email: EmailVerification,
|
|
||||||
sms: SmsVerification,
|
|
||||||
age: AgeVerification,
|
|
||||||
};
|
|
||||||
|
|
||||||
const Verification = () => {
|
|
||||||
const dispatch = useDispatch();
|
|
||||||
|
|
||||||
const isInstanceReady = useSelector((state) => state.getIn(['verification', 'instance', 'isReady'], false) === true);
|
|
||||||
const isRegistrationOpen = useSelector(state => state.getIn(['verification', 'instance', 'registrations'], false) === true);
|
|
||||||
const currentChallenge = useSelector((state) => state.getIn(['verification', 'currentChallenge']));
|
|
||||||
const isVerificationComplete = useSelector((state) => state.getIn(['verification', 'isComplete']));
|
|
||||||
const StepToRender = verificationSteps[currentChallenge];
|
|
||||||
|
|
||||||
React.useEffect(() => {
|
|
||||||
dispatch(fetchVerificationConfig());
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
if (isInstanceReady && !isRegistrationOpen) {
|
|
||||||
return <Redirect to='/' />;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isVerificationComplete) {
|
|
||||||
return (
|
|
||||||
<Registration />
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!currentChallenge) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<StepToRender />
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Verification;
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
import * as React from 'react';
|
||||||
|
import { useDispatch } from 'react-redux';
|
||||||
|
import { Redirect } from 'react-router-dom';
|
||||||
|
|
||||||
|
import { fetchVerificationConfig } from 'soapbox/actions/verification';
|
||||||
|
import { useAppSelector } from 'soapbox/hooks';
|
||||||
|
|
||||||
|
import Registration from './registration';
|
||||||
|
import AgeVerification from './steps/age-verification';
|
||||||
|
import EmailVerification from './steps/email-verification';
|
||||||
|
import SmsVerification from './steps/sms-verification';
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
|
enum ChallengeTypes {
|
||||||
|
EMAIL = 'email', // eslint-disable-line no-unused-vars
|
||||||
|
SMS = 'sms', // eslint-disable-line no-unused-vars
|
||||||
|
AGE = 'age', // eslint-disable-line no-unused-vars
|
||||||
|
}
|
||||||
|
|
||||||
|
const verificationSteps = {
|
||||||
|
email: EmailVerification,
|
||||||
|
sms: SmsVerification,
|
||||||
|
age: AgeVerification,
|
||||||
|
};
|
||||||
|
|
||||||
|
const Verification = () => {
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
|
||||||
|
const isInstanceReady = useAppSelector((state) => state.verification.getIn(['instance', 'isReady'], false) === true);
|
||||||
|
const isRegistrationOpen = useAppSelector(state => state.verification.getIn(['instance', 'registrations'], false) === true);
|
||||||
|
const currentChallenge = useAppSelector((state) => state.verification.getIn(['currentChallenge']) as ChallengeTypes);
|
||||||
|
const isVerificationComplete = useAppSelector((state) => state.verification.get('isComplete'));
|
||||||
|
const StepToRender = verificationSteps[currentChallenge];
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
dispatch(fetchVerificationConfig());
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
if (isInstanceReady && !isRegistrationOpen) {
|
||||||
|
return <Redirect to='/' />;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isVerificationComplete) {
|
||||||
|
return (
|
||||||
|
<Registration />
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!currentChallenge) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<StepToRender />
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Verification;
|
|
@ -20,7 +20,7 @@ const Registration = () => {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
|
||||||
const isLoading = useSelector((state) => state.getIn(['verification', 'isLoading']));
|
const isLoading = useSelector((state) => state.verification.get('isLoading'));
|
||||||
const siteTitle = useSelector((state) => state.instance.title);
|
const siteTitle = useSelector((state) => state.instance.title);
|
||||||
|
|
||||||
const [state, setState] = React.useState(initialState);
|
const [state, setState] = React.useState(initialState);
|
||||||
|
@ -89,7 +89,7 @@ const Registration = () => {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='sm:pt-10 sm:w-2/3 md:w-1/2 mx-auto space-y-4'>
|
<div className='sm:pt-10 sm:w-2/3 md:w-1/2 mx-auto space-y-4'>
|
||||||
<Form onSubmit={handleSubmit} disabled={isLoading}>
|
<Form onSubmit={handleSubmit}>
|
||||||
<FormGroup labelText='Your username'>
|
<FormGroup labelText='Your username'>
|
||||||
<Input
|
<Input
|
||||||
name='username'
|
name='username'
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
import userEvent from '@testing-library/user-event';
|
||||||
|
import { Map as ImmutableMap } from 'immutable';
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import { __stub } from 'soapbox/api';
|
||||||
|
import { fireEvent, render, screen } from 'soapbox/jest/test-helpers';
|
||||||
|
|
||||||
|
import AgeVerification from '../age-verification';
|
||||||
|
|
||||||
|
describe('<AgeVerification />', () => {
|
||||||
|
let store;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
store = {
|
||||||
|
verification: ImmutableMap({
|
||||||
|
ageMinimum: 13,
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
|
||||||
|
__stub(mock => {
|
||||||
|
mock.onPost('/api/v1/pepe/verify_age/confirm')
|
||||||
|
.reply(200, {});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('successfully renders the Birthday step', async() => {
|
||||||
|
render(
|
||||||
|
<AgeVerification />,
|
||||||
|
{},
|
||||||
|
store,
|
||||||
|
);
|
||||||
|
expect(screen.getByRole('heading')).toHaveTextContent('Enter your birth date');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('selects a date', async() => {
|
||||||
|
render(
|
||||||
|
<AgeVerification />,
|
||||||
|
{},
|
||||||
|
store,
|
||||||
|
);
|
||||||
|
|
||||||
|
await userEvent.type(screen.getByLabelText('Birth Date'), '{enter}');
|
||||||
|
|
||||||
|
fireEvent.submit(
|
||||||
|
screen.getByRole('button'), {
|
||||||
|
preventDefault: () => {},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,66 @@
|
||||||
|
import userEvent from '@testing-library/user-event';
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import { __stub } from 'soapbox/api';
|
||||||
|
import { fireEvent, render, screen, waitFor } from 'soapbox/jest/test-helpers';
|
||||||
|
|
||||||
|
import EmailVerification from '../email-verification';
|
||||||
|
|
||||||
|
describe('<EmailVerification />', () => {
|
||||||
|
it('successfully renders the Email step', async() => {
|
||||||
|
render(<EmailVerification />);
|
||||||
|
expect(screen.getByRole('heading')).toHaveTextContent('Enter your email address');
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('with valid data', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
__stub(mock => {
|
||||||
|
mock.onPost('/api/v1/pepe/verify_email/request')
|
||||||
|
.reply(200, {});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('successfully submits', async() => {
|
||||||
|
render(<EmailVerification />);
|
||||||
|
|
||||||
|
await userEvent.type(screen.getByLabelText('Email Address'), 'foo@bar.com{enter}');
|
||||||
|
|
||||||
|
await waitFor(() => {
|
||||||
|
fireEvent.submit(
|
||||||
|
screen.getByRole('button'), {
|
||||||
|
preventDefault: () => {},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(screen.getByRole('button')).toHaveTextContent('Resend verification email');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('with invalid data', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
__stub(mock => {
|
||||||
|
mock.onPost('/api/v1/pepe/verify_email/request')
|
||||||
|
.reply(422, {
|
||||||
|
error: 'email_taken',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders errors', async() => {
|
||||||
|
render(<EmailVerification />);
|
||||||
|
|
||||||
|
await userEvent.type(screen.getByLabelText('Email Address'), 'foo@bar.com{enter}');
|
||||||
|
|
||||||
|
await waitFor(() => {
|
||||||
|
fireEvent.submit(
|
||||||
|
screen.getByRole('button'), {
|
||||||
|
preventDefault: () => {},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(screen.getByTestId('form-group-error')).toHaveTextContent('is taken');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,102 @@
|
||||||
|
import userEvent from '@testing-library/user-event';
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import { __stub } from 'soapbox/api';
|
||||||
|
import { fireEvent, render, screen, waitFor } from 'soapbox/jest/test-helpers';
|
||||||
|
|
||||||
|
import SmsVerification from '../sms-verification';
|
||||||
|
|
||||||
|
describe('<SmsVerification />', () => {
|
||||||
|
it('successfully renders the SMS step', async() => {
|
||||||
|
render(<SmsVerification />);
|
||||||
|
expect(screen.getByRole('heading')).toHaveTextContent('Enter your phone number');
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('with valid data', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
__stub(mock => {
|
||||||
|
mock.onPost('/api/v1/pepe/verify_sms/request').reply(200, {});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('successfully submits', async() => {
|
||||||
|
__stub(mock => {
|
||||||
|
mock.onPost('/api/v1/pepe/verify_sms/confirm').reply(200, {});
|
||||||
|
});
|
||||||
|
|
||||||
|
render(<SmsVerification />);
|
||||||
|
|
||||||
|
await userEvent.type(screen.getByLabelText('Phone Number'), '+1 (555) 555-5555');
|
||||||
|
await waitFor(() => {
|
||||||
|
fireEvent.submit(
|
||||||
|
screen.getByRole('button'), {
|
||||||
|
preventDefault: () => {},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(screen.getByRole('heading')).toHaveTextContent('Verification code');
|
||||||
|
expect(screen.getByTestId('toast')).toHaveTextContent('A verification code has been sent to your phone number.');
|
||||||
|
|
||||||
|
await userEvent.type(screen.getByLabelText('Please enter verification code. Digit 1'), '1');
|
||||||
|
await userEvent.type(screen.getByLabelText('Digit 2'), '2');
|
||||||
|
await userEvent.type(screen.getByLabelText('Digit 3'), '3');
|
||||||
|
await userEvent.type(screen.getByLabelText('Digit 4'), '4');
|
||||||
|
await userEvent.type(screen.getByLabelText('Digit 5'), '5');
|
||||||
|
await userEvent.type(screen.getByLabelText('Digit 6'), '6');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('handle expired tokens', async() => {
|
||||||
|
__stub(mock => {
|
||||||
|
mock.onPost('/api/v1/pepe/verify_sms/confirm').reply(422, {});
|
||||||
|
});
|
||||||
|
|
||||||
|
render(<SmsVerification />);
|
||||||
|
|
||||||
|
await userEvent.type(screen.getByLabelText('Phone Number'), '+1 (555) 555-5555');
|
||||||
|
await waitFor(() => {
|
||||||
|
fireEvent.submit(
|
||||||
|
screen.getByRole('button'), {
|
||||||
|
preventDefault: () => {},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(screen.getByRole('heading')).toHaveTextContent('Verification code');
|
||||||
|
expect(screen.getByTestId('toast')).toHaveTextContent('A verification code has been sent to your phone number.');
|
||||||
|
|
||||||
|
await userEvent.type(screen.getByLabelText('Please enter verification code. Digit 1'), '1');
|
||||||
|
await userEvent.type(screen.getByLabelText('Digit 2'), '2');
|
||||||
|
await userEvent.type(screen.getByLabelText('Digit 3'), '3');
|
||||||
|
await userEvent.type(screen.getByLabelText('Digit 4'), '4');
|
||||||
|
await userEvent.type(screen.getByLabelText('Digit 5'), '5');
|
||||||
|
await userEvent.type(screen.getByLabelText('Digit 6'), '6');
|
||||||
|
|
||||||
|
expect(screen.getByTestId('toast')).toHaveTextContent('Your SMS token has expired.');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('with invalid data', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
__stub(mock => {
|
||||||
|
mock.onPost('/api/v1/pepe/verify_sms/request')
|
||||||
|
.reply(422, {});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders errors', async() => {
|
||||||
|
render(<SmsVerification />);
|
||||||
|
|
||||||
|
await userEvent.type(screen.getByLabelText('Phone Number'), '+1 (555) 555-5555');
|
||||||
|
await waitFor(() => {
|
||||||
|
fireEvent.submit(
|
||||||
|
screen.getByRole('button'), {
|
||||||
|
preventDefault: () => {},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(screen.getByTestId('toast')).toHaveTextContent('Failed to send SMS message to your phone number.');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -28,9 +28,9 @@ const AgeVerification = () => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
|
|
||||||
const isLoading = useSelector((state) => state.getIn(['verification', 'isLoading']));
|
const isLoading = useSelector((state) => state.verification.get('isLoading'));
|
||||||
const ageMinimum = useSelector((state) => state.getIn(['verification', 'ageMinimum']));
|
const ageMinimum = useSelector((state) => state.verification.get('ageMinimum'));
|
||||||
const siteTitle = useSelector((state) => state.instance.title);
|
const siteTitle = useSelector((state) => state.instance.get('title'));
|
||||||
|
|
||||||
const [date, setDate] = React.useState('');
|
const [date, setDate] = React.useState('');
|
||||||
const isValid = typeof date === 'object';
|
const isValid = typeof date === 'object';
|
||||||
|
@ -65,7 +65,7 @@ const AgeVerification = () => {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='sm:pt-10 sm:w-2/3 md:w-1/2 mx-auto'>
|
<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='Birth Date'>
|
<FormGroup labelText='Birth Date'>
|
||||||
<DatePicker
|
<DatePicker
|
||||||
selected={date}
|
selected={date}
|
|
@ -50,7 +50,7 @@ const EmailVerification = () => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
|
|
||||||
const isLoading = useSelector((state) => state.getIn(['verification', 'isLoading']));
|
const isLoading = useSelector((state) => state.verification.get('isLoading'));
|
||||||
|
|
||||||
const [email, setEmail] = React.useState('');
|
const [email, setEmail] = React.useState('');
|
||||||
const [status, setStatus] = React.useState(Statuses.IDLE);
|
const [status, setStatus] = React.useState(Statuses.IDLE);
|
||||||
|
@ -110,7 +110,7 @@ const EmailVerification = () => {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='sm:pt-10 sm:w-2/3 md:w-1/2 mx-auto'>
|
<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='Email Address' errors={errors}>
|
<FormGroup labelText='Email Address' errors={errors}>
|
||||||
<Input
|
<Input
|
||||||
type='email'
|
type='email'
|
|
@ -21,7 +21,7 @@ const SmsVerification = () => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
|
|
||||||
const isLoading = useSelector((state) => state.getIn(['verification', 'isLoading']));
|
const isLoading = useSelector((state) => state.verification.get('isLoading'));
|
||||||
|
|
||||||
const [phone, setPhone] = React.useState('');
|
const [phone, setPhone] = React.useState('');
|
||||||
const [status, setStatus] = React.useState(Statuses.IDLE);
|
const [status, setStatus] = React.useState(Statuses.IDLE);
|
||||||
|
@ -147,7 +147,7 @@ const SmsVerification = () => {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='sm:pt-10 sm:w-2/3 md:w-1/2 mx-auto'>
|
<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='Phone Number'>
|
<FormGroup labelText='Phone Number'>
|
||||||
<Input
|
<Input
|
||||||
type='text'
|
type='text'
|
|
@ -0,0 +1,72 @@
|
||||||
|
import { render, RenderOptions } from '@testing-library/react';
|
||||||
|
import { merge } from 'immutable';
|
||||||
|
import React, { FC, ReactElement } from 'react';
|
||||||
|
import { IntlProvider } from 'react-intl';
|
||||||
|
import { Provider } from 'react-redux';
|
||||||
|
import { MemoryRouter } from 'react-router-dom';
|
||||||
|
import { Action, applyMiddleware, createStore } from 'redux';
|
||||||
|
import configureMockStore from 'redux-mock-store';
|
||||||
|
import thunk from 'redux-thunk';
|
||||||
|
import '@testing-library/jest-dom';
|
||||||
|
|
||||||
|
import NotificationsContainer from '../features/ui/containers/notifications_container';
|
||||||
|
import { default as rootReducer } from '../reducers';
|
||||||
|
|
||||||
|
// Mock Redux
|
||||||
|
// https://redux.js.org/recipes/writing-tests/
|
||||||
|
const middlewares = [thunk];
|
||||||
|
const mockStore = configureMockStore(middlewares);
|
||||||
|
let rootState = rootReducer(undefined, {} as Action);
|
||||||
|
|
||||||
|
// Apply actions to the state, one at a time
|
||||||
|
const applyActions = (state: any, actions: any, reducer: any) => {
|
||||||
|
return actions.reduce((state: any, action: any) => reducer(state, action), state);
|
||||||
|
};
|
||||||
|
|
||||||
|
const createTestStore = (initialState: any) => createStore(rootReducer, initialState, applyMiddleware(thunk));
|
||||||
|
|
||||||
|
const TestApp: FC<any> = ({ children, storeProps, routerProps = {} }) => {
|
||||||
|
let store: any;
|
||||||
|
|
||||||
|
if (storeProps) {
|
||||||
|
rootState = merge(rootState, storeProps);
|
||||||
|
store = createTestStore(rootState);
|
||||||
|
} else {
|
||||||
|
store = createTestStore(rootState);
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = {
|
||||||
|
locale: 'en',
|
||||||
|
store,
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Provider store={props.store}>
|
||||||
|
<IntlProvider locale={props.locale}>
|
||||||
|
<MemoryRouter {...routerProps}>
|
||||||
|
{children}
|
||||||
|
|
||||||
|
<NotificationsContainer />
|
||||||
|
</MemoryRouter>
|
||||||
|
</IntlProvider>
|
||||||
|
</Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const customRender = (
|
||||||
|
ui: ReactElement,
|
||||||
|
options?: Omit<RenderOptions, 'wrapper'>,
|
||||||
|
store?: any,
|
||||||
|
routerProps?: any,
|
||||||
|
) => render(ui, {
|
||||||
|
wrapper: () => <TestApp children={ui} storeProps={store} routerProps={routerProps} />,
|
||||||
|
...options,
|
||||||
|
});
|
||||||
|
|
||||||
|
export * from '@testing-library/react';
|
||||||
|
export {
|
||||||
|
customRender as render,
|
||||||
|
mockStore,
|
||||||
|
applyActions,
|
||||||
|
rootState,
|
||||||
|
};
|
|
@ -0,0 +1,10 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
import { __clear as clearApiMocks } from '../__mocks__/api';
|
||||||
|
|
||||||
|
// API mocking
|
||||||
|
jest.mock('soapbox/api');
|
||||||
|
afterEach(() => clearApiMocks());
|
||||||
|
|
||||||
|
// Mock external dependencies
|
||||||
|
jest.mock('uuid', () => ({ v4: jest.fn(() => 1) }));
|
|
@ -5,7 +5,7 @@ import {
|
||||||
ALERT_DISMISS,
|
ALERT_DISMISS,
|
||||||
ALERT_CLEAR,
|
ALERT_CLEAR,
|
||||||
} from 'soapbox/actions/alerts';
|
} from 'soapbox/actions/alerts';
|
||||||
import { applyActions } from 'soapbox/test_helpers';
|
import { applyActions } from 'soapbox/jest/test-helpers';
|
||||||
|
|
||||||
import reducer from '../alerts';
|
import reducer from '../alerts';
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@ import {
|
||||||
NOTIFICATIONS_MARK_READ_REQUEST,
|
NOTIFICATIONS_MARK_READ_REQUEST,
|
||||||
} from 'soapbox/actions/notifications';
|
} from 'soapbox/actions/notifications';
|
||||||
import { TIMELINE_DELETE } from 'soapbox/actions/timelines';
|
import { TIMELINE_DELETE } from 'soapbox/actions/timelines';
|
||||||
import { applyActions } from 'soapbox/test_helpers';
|
import { applyActions } from 'soapbox/jest/test-helpers';
|
||||||
|
|
||||||
import reducer from '../notifications';
|
import reducer from '../notifications';
|
||||||
|
|
||||||
|
|
|
@ -1,61 +0,0 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
import { mount } from 'enzyme';
|
|
||||||
import { Map as ImmutableMap } from 'immutable';
|
|
||||||
import React from 'react';
|
|
||||||
import { IntlProvider } from 'react-intl';
|
|
||||||
import { Provider } from 'react-redux';
|
|
||||||
import { BrowserRouter, MemoryRouter } from 'react-router-dom';
|
|
||||||
import renderer from 'react-test-renderer';
|
|
||||||
import configureMockStore from 'redux-mock-store';
|
|
||||||
import thunk from 'redux-thunk';
|
|
||||||
|
|
||||||
import rootReducer from 'soapbox/reducers';
|
|
||||||
|
|
||||||
export const rootState = rootReducer(undefined, {});
|
|
||||||
export const getState = () => rootState;
|
|
||||||
|
|
||||||
// Mock Redux
|
|
||||||
// https://redux.js.org/recipes/writing-tests/
|
|
||||||
const middlewares = [thunk];
|
|
||||||
export const mockStore = configureMockStore(middlewares);
|
|
||||||
|
|
||||||
// Create test component with i18n and Redux store, etc
|
|
||||||
export const createComponent = (children, props = {}) => {
|
|
||||||
props = ImmutableMap({
|
|
||||||
locale: 'en',
|
|
||||||
store: mockStore(rootState),
|
|
||||||
}).merge(props);
|
|
||||||
|
|
||||||
return renderer.create(
|
|
||||||
<Provider store={props.get('store')}>
|
|
||||||
<IntlProvider locale={props.get('locale')}>
|
|
||||||
<BrowserRouter>
|
|
||||||
{children}
|
|
||||||
</BrowserRouter>
|
|
||||||
</IntlProvider>
|
|
||||||
</Provider>,
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export const createShallowComponent = (children, props = {}, routerProps = {}) => {
|
|
||||||
props = ImmutableMap({
|
|
||||||
locale: 'en',
|
|
||||||
store: mockStore(rootReducer(ImmutableMap(), {})),
|
|
||||||
}).merge(props);
|
|
||||||
|
|
||||||
return mount(
|
|
||||||
<Provider store={props.get('store')}>
|
|
||||||
<IntlProvider locale={props.get('locale')}>
|
|
||||||
<MemoryRouter {...routerProps}>
|
|
||||||
{children}
|
|
||||||
</MemoryRouter>
|
|
||||||
</IntlProvider>
|
|
||||||
</Provider>,
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Apply actions to the state, one at a time
|
|
||||||
export const applyActions = (state, actions, reducer) => {
|
|
||||||
return actions.reduce((state, action) => reducer(state, action), state);
|
|
||||||
};
|
|
|
@ -1,16 +0,0 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
import { configure } from 'enzyme';
|
|
||||||
import Adapter from 'enzyme-adapter-react-16';
|
|
||||||
|
|
||||||
import { __clear as clearApiMocks } from 'soapbox/api';
|
|
||||||
|
|
||||||
// Enzyme
|
|
||||||
const adapter = new Adapter();
|
|
||||||
configure({ adapter });
|
|
||||||
|
|
||||||
// API mocking
|
|
||||||
jest.mock('soapbox/api');
|
|
||||||
afterEach(() => clearApiMocks());
|
|
||||||
|
|
||||||
jest.mock('uuid', () => ({ v4: jest.fn(() => 1) }));
|
|
|
@ -18,12 +18,12 @@ NODE_ENV=development
|
||||||
- `yarn manage:translations` - Normalizes translation files. Should always be run after editing i18n strings.
|
- `yarn manage:translations` - Normalizes translation files. Should always be run after editing i18n strings.
|
||||||
|
|
||||||
## Tests
|
## Tests
|
||||||
- `yarn test` - Runs all tests.
|
- `yarn test:all` - Runs all tests and linters.
|
||||||
|
|
||||||
- `yarn test:lint` - Runs all linter tests.
|
- `yarn test` - Runs Jest for frontend unit tests.
|
||||||
|
|
||||||
- `yarn test:lint:js` - Runs only JavaScript linter.
|
- `yarn lint` - Runs all linters.
|
||||||
|
|
||||||
- `yarn test:lint:sass` - Runs only SASS linter.
|
- `yarn lint:js` - Runs only JavaScript linter.
|
||||||
|
|
||||||
- `yarn test:jest` - Frontend unit tests.
|
- `yarn lint:sass` - Runs only SASS linter.
|
||||||
|
|
|
@ -12,15 +12,17 @@ module.exports = {
|
||||||
'raf/polyfill',
|
'raf/polyfill',
|
||||||
],
|
],
|
||||||
'setupFilesAfterEnv': [
|
'setupFilesAfterEnv': [
|
||||||
'<rootDir>/app/soapbox/test_setup.js',
|
'<rootDir>/app/soapbox/jest/test-setup.ts',
|
||||||
],
|
],
|
||||||
'collectCoverageFrom': [
|
'collectCoverageFrom': [
|
||||||
'app/soapbox/**/*.js',
|
'app/soapbox/**/*.js',
|
||||||
|
'app/soapbox/**/*.ts',
|
||||||
|
'app/soapbox/**/*.tsx',
|
||||||
'!app/soapbox/features/emoji/emoji_compressed.js',
|
'!app/soapbox/features/emoji/emoji_compressed.js',
|
||||||
'!app/soapbox/locales/locale-data/*.js',
|
'!app/soapbox/locales/locale-data/*.js',
|
||||||
'!app/soapbox/service_worker/entry.js',
|
'!app/soapbox/service_worker/entry.js',
|
||||||
'!app/soapbox/test_setup.js',
|
'!app/soapbox/jest/test-setup.ts',
|
||||||
'!app/soapbox/test_helpers.js',
|
'!app/soapbox/jest/test-helpers.ts',
|
||||||
],
|
],
|
||||||
'coverageDirectory': '<rootDir>/coverage',
|
'coverageDirectory': '<rootDir>/coverage',
|
||||||
'moduleDirectories': [
|
'moduleDirectories': [
|
||||||
|
|
23
package.json
23
package.json
|
@ -21,11 +21,12 @@
|
||||||
"build": "npx webpack",
|
"build": "npx webpack",
|
||||||
"jsdoc": "npx jsdoc -c jsdoc.conf.js",
|
"jsdoc": "npx jsdoc -c jsdoc.conf.js",
|
||||||
"manage:translations": "node ./webpack/translationRunner.js",
|
"manage:translations": "node ./webpack/translationRunner.js",
|
||||||
"test": "${npm_execpath} run test:lint && ${npm_execpath} run test:jest",
|
"test": "npx jest",
|
||||||
"test:lint": "${npm_execpath} run test:lint:js && ${npm_execpath} run test:lint:sass",
|
"test:coverage": "npx jest --coverage",
|
||||||
"test:lint:js": "npx eslint --ext .js,.jsx,.ts,.tsx . --cache",
|
"test:all": "${npm_execpath} run test:coverage && ${npm_execpath} run lint",
|
||||||
"test:lint:sass": "npx stylelint app/styles/**/*.scss",
|
"lint": "${npm_execpath} run lint:js && ${npm_execpath} run lint:sass",
|
||||||
"test:jest": "npx jest --coverage",
|
"lint:js": "npx eslint --ext .js,.jsx,.ts,.tsx . --cache",
|
||||||
|
"lint:sass": "npx stylelint app/styles/**/*.scss",
|
||||||
"prepare": "husky install"
|
"prepare": "husky install"
|
||||||
},
|
},
|
||||||
"license": "AGPL-3.0-or-later",
|
"license": "AGPL-3.0-or-later",
|
||||||
|
@ -52,6 +53,7 @@
|
||||||
"@fontsource/inter": "^4.5.1",
|
"@fontsource/inter": "^4.5.1",
|
||||||
"@fontsource/roboto": "^4.5.0",
|
"@fontsource/roboto": "^4.5.0",
|
||||||
"@gamestdio/websocket": "^0.3.2",
|
"@gamestdio/websocket": "^0.3.2",
|
||||||
|
"@jest/globals": "^27.5.1",
|
||||||
"@lcdp/offline-plugin": "^5.1.0",
|
"@lcdp/offline-plugin": "^5.1.0",
|
||||||
"@popperjs/core": "^2.4.4",
|
"@popperjs/core": "^2.4.4",
|
||||||
"@reach/menu-button": "^0.16.2",
|
"@reach/menu-button": "^0.16.2",
|
||||||
|
@ -67,19 +69,23 @@
|
||||||
"@tabler/icons": "^1.53.0",
|
"@tabler/icons": "^1.53.0",
|
||||||
"@tailwindcss/forms": "^0.4.0",
|
"@tailwindcss/forms": "^0.4.0",
|
||||||
"@tailwindcss/typography": "^0.5.1",
|
"@tailwindcss/typography": "^0.5.1",
|
||||||
|
"@testing-library/react": "^12.1.4",
|
||||||
"@types/escape-html": "^1.0.1",
|
"@types/escape-html": "^1.0.1",
|
||||||
"@types/http-link-header": "^1.0.3",
|
"@types/http-link-header": "^1.0.3",
|
||||||
|
"@types/jest": "^27.4.1",
|
||||||
"@types/lodash": "^4.14.180",
|
"@types/lodash": "^4.14.180",
|
||||||
"@types/qrcode.react": "^1.0.2",
|
"@types/qrcode.react": "^1.0.2",
|
||||||
"@types/react-helmet": "^6.1.5",
|
"@types/react-helmet": "^6.1.5",
|
||||||
"@types/react-motion": "^0.0.32",
|
"@types/react-motion": "^0.0.32",
|
||||||
"@types/react-router-dom": "^5.3.3",
|
"@types/react-router-dom": "^5.3.3",
|
||||||
"@types/react-toggle": "^4.0.3",
|
"@types/react-toggle": "^4.0.3",
|
||||||
|
"@types/redux-mock-store": "^1.0.3",
|
||||||
"@types/semver": "^7.3.9",
|
"@types/semver": "^7.3.9",
|
||||||
"@types/uuid": "^8.3.4",
|
"@types/uuid": "^8.3.4",
|
||||||
"array-includes": "^3.0.3",
|
"array-includes": "^3.0.3",
|
||||||
"autoprefixer": "^10.4.2",
|
"autoprefixer": "^10.4.2",
|
||||||
"axios": "^0.21.4",
|
"axios": "^0.21.4",
|
||||||
|
"axios-mock-adapter": "^1.18.1",
|
||||||
"babel-loader": "^8.2.2",
|
"babel-loader": "^8.2.2",
|
||||||
"babel-plugin-lodash": "^3.3.4",
|
"babel-plugin-lodash": "^3.3.4",
|
||||||
"babel-plugin-preval": "^5.0.0",
|
"babel-plugin-preval": "^5.0.0",
|
||||||
|
@ -189,14 +195,12 @@
|
||||||
"wicg-inert": "^3.1.1"
|
"wicg-inert": "^3.1.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@jest/globals": "^27.5.1",
|
"@testing-library/jest-dom": "^5.16.3",
|
||||||
|
"@testing-library/user-event": "^14.0.3",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.15.0",
|
"@typescript-eslint/eslint-plugin": "^5.15.0",
|
||||||
"@typescript-eslint/parser": "^5.15.0",
|
"@typescript-eslint/parser": "^5.15.0",
|
||||||
"axios-mock-adapter": "^1.18.1",
|
|
||||||
"babel-eslint": "^10.1.0",
|
"babel-eslint": "^10.1.0",
|
||||||
"babel-jest": "^27.1.0",
|
"babel-jest": "^27.1.0",
|
||||||
"enzyme": "^3.11.0",
|
|
||||||
"enzyme-adapter-react-16": "^1.15.6",
|
|
||||||
"eslint": "^7.0.0",
|
"eslint": "^7.0.0",
|
||||||
"eslint-plugin-import": "^2.25.4",
|
"eslint-plugin-import": "^2.25.4",
|
||||||
"eslint-plugin-jsx-a11y": "^6.4.1",
|
"eslint-plugin-jsx-a11y": "^6.4.1",
|
||||||
|
@ -208,7 +212,6 @@
|
||||||
"lint-staged": ">=10",
|
"lint-staged": ">=10",
|
||||||
"raf": "^3.4.1",
|
"raf": "^3.4.1",
|
||||||
"react-intl-translations-manager": "^5.0.3",
|
"react-intl-translations-manager": "^5.0.3",
|
||||||
"react-test-renderer": "^16.13.1",
|
|
||||||
"redux-mock-store": "^1.5.4",
|
"redux-mock-store": "^1.5.4",
|
||||||
"stylelint": "^13.7.2",
|
"stylelint": "^13.7.2",
|
||||||
"stylelint-config-standard": "^22.0.0",
|
"stylelint-config-standard": "^22.0.0",
|
||||||
|
|
436
yarn.lock
436
yarn.lock
|
@ -16,7 +16,7 @@
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/highlight" "^7.14.5"
|
"@babel/highlight" "^7.14.5"
|
||||||
|
|
||||||
"@babel/code-frame@^7.16.7", "@babel/code-frame@^7.8.3":
|
"@babel/code-frame@^7.10.4", "@babel/code-frame@^7.16.7", "@babel/code-frame@^7.8.3":
|
||||||
version "7.16.7"
|
version "7.16.7"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.16.7.tgz#44416b6bd7624b998f5b1af5d470856c40138789"
|
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.16.7.tgz#44416b6bd7624b998f5b1af5d470856c40138789"
|
||||||
integrity sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==
|
integrity sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==
|
||||||
|
@ -1141,7 +1141,7 @@
|
||||||
dependencies:
|
dependencies:
|
||||||
regenerator-runtime "^0.13.4"
|
regenerator-runtime "^0.13.4"
|
||||||
|
|
||||||
"@babel/runtime@^7.12.13", "@babel/runtime@^7.17.0":
|
"@babel/runtime@^7.12.13", "@babel/runtime@^7.12.5", "@babel/runtime@^7.17.0":
|
||||||
version "7.17.8"
|
version "7.17.8"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.17.8.tgz#3e56e4aff81befa55ac3ac6a0967349fd1c5bca2"
|
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.17.8.tgz#3e56e4aff81befa55ac3ac6a0967349fd1c5bca2"
|
||||||
integrity sha512-dQpEpK0O9o6lj6oPu0gRDbbnk+4LeHlNcBpspf6Olzt3GIX4P1lWF1gS+pHLDFlaJvbR6q7jCfQ08zA4QJBnmA==
|
integrity sha512-dQpEpK0O9o6lj6oPu0gRDbbnk+4LeHlNcBpspf6Olzt3GIX4P1lWF1gS+pHLDFlaJvbR6q7jCfQ08zA4QJBnmA==
|
||||||
|
@ -1904,11 +1904,59 @@
|
||||||
lodash.isplainobject "^4.0.6"
|
lodash.isplainobject "^4.0.6"
|
||||||
lodash.merge "^4.6.2"
|
lodash.merge "^4.6.2"
|
||||||
|
|
||||||
|
"@testing-library/dom@^8.0.0":
|
||||||
|
version "8.12.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-8.12.0.tgz#fef5e545533fb084175dda6509ee71d7d2f72e23"
|
||||||
|
integrity sha512-rBrJk5WjI02X1edtiUcZhgyhgBhiut96r5Jp8J5qktKdcvLcZpKDW8i2hkGMMItxrghjXuQ5AM6aE0imnFawaw==
|
||||||
|
dependencies:
|
||||||
|
"@babel/code-frame" "^7.10.4"
|
||||||
|
"@babel/runtime" "^7.12.5"
|
||||||
|
"@types/aria-query" "^4.2.0"
|
||||||
|
aria-query "^5.0.0"
|
||||||
|
chalk "^4.1.0"
|
||||||
|
dom-accessibility-api "^0.5.9"
|
||||||
|
lz-string "^1.4.4"
|
||||||
|
pretty-format "^27.0.2"
|
||||||
|
|
||||||
|
"@testing-library/jest-dom@^5.16.3":
|
||||||
|
version "5.16.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/@testing-library/jest-dom/-/jest-dom-5.16.3.tgz#b76851a909586113c20486f1679ffb4d8ec27bfa"
|
||||||
|
integrity sha512-u5DfKj4wfSt6akfndfu1eG06jsdyA/IUrlX2n3pyq5UXgXMhXY+NJb8eNK/7pqPWAhCKsCGWDdDO0zKMKAYkEA==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.9.2"
|
||||||
|
"@types/testing-library__jest-dom" "^5.9.1"
|
||||||
|
aria-query "^5.0.0"
|
||||||
|
chalk "^3.0.0"
|
||||||
|
css "^3.0.0"
|
||||||
|
css.escape "^1.5.1"
|
||||||
|
dom-accessibility-api "^0.5.6"
|
||||||
|
lodash "^4.17.15"
|
||||||
|
redent "^3.0.0"
|
||||||
|
|
||||||
|
"@testing-library/react@^12.1.4":
|
||||||
|
version "12.1.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-12.1.4.tgz#09674b117e550af713db3f4ec4c0942aa8bbf2c0"
|
||||||
|
integrity sha512-jiPKOm7vyUw311Hn/HlNQ9P8/lHNtArAx0PisXyFixDDvfl8DbD6EUdbshK5eqauvBSvzZd19itqQ9j3nferJA==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.12.5"
|
||||||
|
"@testing-library/dom" "^8.0.0"
|
||||||
|
"@types/react-dom" "*"
|
||||||
|
|
||||||
|
"@testing-library/user-event@^14.0.3":
|
||||||
|
version "14.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/@testing-library/user-event/-/user-event-14.0.3.tgz#463667596122c13d997f70b73426947ab71de962"
|
||||||
|
integrity sha512-zIgBG5CxfXbMsm4wBS6iQC3TBNMZk16O25i4shS9MM+eSG7PZHrsBF6LFIesUkepkZ3QKKgstB2/Nola6nvy4A==
|
||||||
|
|
||||||
"@tootallnate/once@1":
|
"@tootallnate/once@1":
|
||||||
version "1.1.2"
|
version "1.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82"
|
resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82"
|
||||||
integrity sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==
|
integrity sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==
|
||||||
|
|
||||||
|
"@types/aria-query@^4.2.0":
|
||||||
|
version "4.2.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/aria-query/-/aria-query-4.2.2.tgz#ed4e0ad92306a704f9fb132a0cfcf77486dbe2bc"
|
||||||
|
integrity sha512-HnYpAE1Y6kRyKM/XkEuiRQhTHvkzMBurTHnpFLYLBGPIylZNPs9jJcuOOYWxPLJCSEtmZT0Y8rHDokKN7rRTig==
|
||||||
|
|
||||||
"@types/babel__core@^7.0.0", "@types/babel__core@^7.1.14", "@types/babel__core@^7.1.7":
|
"@types/babel__core@^7.0.0", "@types/babel__core@^7.1.14", "@types/babel__core@^7.1.7":
|
||||||
version "7.1.16"
|
version "7.1.16"
|
||||||
resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.16.tgz#bc12c74b7d65e82d29876b5d0baf5c625ac58702"
|
resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.16.tgz#bc12c74b7d65e82d29876b5d0baf5c625ac58702"
|
||||||
|
@ -2033,6 +2081,14 @@
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/istanbul-lib-report" "*"
|
"@types/istanbul-lib-report" "*"
|
||||||
|
|
||||||
|
"@types/jest@*", "@types/jest@^27.4.1":
|
||||||
|
version "27.4.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/jest/-/jest-27.4.1.tgz#185cbe2926eaaf9662d340cc02e548ce9e11ab6d"
|
||||||
|
integrity sha512-23iPJADSmicDVrWk+HT58LMJtzLAnB2AgIzplQuq/bSrGaxCrlvRFjGbXmamnnk/mAmCdLStiGqggu28ocUyiw==
|
||||||
|
dependencies:
|
||||||
|
jest-matcher-utils "^27.0.0"
|
||||||
|
pretty-format "^27.0.0"
|
||||||
|
|
||||||
"@types/json-schema@*", "@types/json-schema@^7.0.4", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.8":
|
"@types/json-schema@*", "@types/json-schema@^7.0.4", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.8":
|
||||||
version "7.0.9"
|
version "7.0.9"
|
||||||
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.9.tgz#97edc9037ea0c38585320b28964dde3b39e4660d"
|
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.9.tgz#97edc9037ea0c38585320b28964dde3b39e4660d"
|
||||||
|
@ -2102,6 +2158,13 @@
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/react" "*"
|
"@types/react" "*"
|
||||||
|
|
||||||
|
"@types/react-dom@*":
|
||||||
|
version "17.0.14"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-17.0.14.tgz#c8f917156b652ddf807711f5becbd2ab018dea9f"
|
||||||
|
integrity sha512-H03xwEP1oXmSfl3iobtmQ/2dHF5aBHr8aUMwyGZya6OW45G+xtdzmq6HkncefiBt5JU8DVyaWl/nWZbjZCnzAQ==
|
||||||
|
dependencies:
|
||||||
|
"@types/react" "*"
|
||||||
|
|
||||||
"@types/react-helmet@^6.1.5":
|
"@types/react-helmet@^6.1.5":
|
||||||
version "6.1.5"
|
version "6.1.5"
|
||||||
resolved "https://registry.yarnpkg.com/@types/react-helmet/-/react-helmet-6.1.5.tgz#35f89a6b1646ee2bc342a33a9a6c8777933f9083"
|
resolved "https://registry.yarnpkg.com/@types/react-helmet/-/react-helmet-6.1.5.tgz#35f89a6b1646ee2bc342a33a9a6c8777933f9083"
|
||||||
|
@ -2159,6 +2222,13 @@
|
||||||
"@types/scheduler" "*"
|
"@types/scheduler" "*"
|
||||||
csstype "^3.0.2"
|
csstype "^3.0.2"
|
||||||
|
|
||||||
|
"@types/redux-mock-store@^1.0.3":
|
||||||
|
version "1.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/redux-mock-store/-/redux-mock-store-1.0.3.tgz#895de4a364bc4836661570aec82f2eef5989d1fb"
|
||||||
|
integrity sha512-Wqe3tJa6x9MxMN4DJnMfZoBRBRak1XTPklqj4qkVm5VBpZnC8PSADf4kLuFQ9NAdHaowfWoEeUMz7NWc2GMtnA==
|
||||||
|
dependencies:
|
||||||
|
redux "^4.0.5"
|
||||||
|
|
||||||
"@types/retry@^0.12.0":
|
"@types/retry@^0.12.0":
|
||||||
version "0.12.1"
|
version "0.12.1"
|
||||||
resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.1.tgz#d8f1c0d0dc23afad6dc16a9e993a0865774b4065"
|
resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.1.tgz#d8f1c0d0dc23afad6dc16a9e993a0865774b4065"
|
||||||
|
@ -2186,6 +2256,13 @@
|
||||||
resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.1.tgz#20f18294f797f2209b5f65c8e3b5c8e8261d127c"
|
resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.1.tgz#20f18294f797f2209b5f65c8e3b5c8e8261d127c"
|
||||||
integrity sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==
|
integrity sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==
|
||||||
|
|
||||||
|
"@types/testing-library__jest-dom@^5.9.1":
|
||||||
|
version "5.14.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.14.3.tgz#ee6c7ffe9f8595882ee7bda8af33ae7b8789ef17"
|
||||||
|
integrity sha512-oKZe+Mf4ioWlMuzVBaXQ9WDnEm1+umLx0InILg+yvZVBBDmzV5KfZyLrCvadtWcx8+916jLmHafcmqqffl+iIw==
|
||||||
|
dependencies:
|
||||||
|
"@types/jest" "*"
|
||||||
|
|
||||||
"@types/unist@*", "@types/unist@^2.0.0", "@types/unist@^2.0.2":
|
"@types/unist@*", "@types/unist@^2.0.0", "@types/unist@^2.0.2":
|
||||||
version "2.0.6"
|
version "2.0.6"
|
||||||
resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.6.tgz#250a7b16c3b91f672a24552ec64678eeb1d3a08d"
|
resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.6.tgz#250a7b16c3b91f672a24552ec64678eeb1d3a08d"
|
||||||
|
@ -2511,21 +2588,6 @@ aggregate-error@^3.0.0:
|
||||||
clean-stack "^2.0.0"
|
clean-stack "^2.0.0"
|
||||||
indent-string "^4.0.0"
|
indent-string "^4.0.0"
|
||||||
|
|
||||||
airbnb-prop-types@^2.16.0:
|
|
||||||
version "2.16.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/airbnb-prop-types/-/airbnb-prop-types-2.16.0.tgz#b96274cefa1abb14f623f804173ee97c13971dc2"
|
|
||||||
integrity sha512-7WHOFolP/6cS96PhKNrslCLMYAI8yB1Pp6u6XmxozQOiZbsI5ycglZr5cHhBFfuRcQQjzCMith5ZPZdYiJCxUg==
|
|
||||||
dependencies:
|
|
||||||
array.prototype.find "^2.1.1"
|
|
||||||
function.prototype.name "^1.1.2"
|
|
||||||
is-regex "^1.1.0"
|
|
||||||
object-is "^1.1.2"
|
|
||||||
object.assign "^4.1.0"
|
|
||||||
object.entries "^1.1.2"
|
|
||||||
prop-types "^15.7.2"
|
|
||||||
prop-types-exact "^1.2.0"
|
|
||||||
react-is "^16.13.1"
|
|
||||||
|
|
||||||
ajv-keywords@^3.4.1, ajv-keywords@^3.5.2:
|
ajv-keywords@^3.4.1, ajv-keywords@^3.5.2:
|
||||||
version "3.5.2"
|
version "3.5.2"
|
||||||
resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d"
|
resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d"
|
||||||
|
@ -2640,6 +2702,11 @@ aria-query@^4.2.2:
|
||||||
"@babel/runtime" "^7.10.2"
|
"@babel/runtime" "^7.10.2"
|
||||||
"@babel/runtime-corejs3" "^7.10.2"
|
"@babel/runtime-corejs3" "^7.10.2"
|
||||||
|
|
||||||
|
aria-query@^5.0.0:
|
||||||
|
version "5.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-5.0.0.tgz#210c21aaf469613ee8c9a62c7f86525e058db52c"
|
||||||
|
integrity sha512-V+SM7AbUwJ+EBnB8+DXs0hPZHO0W6pqBcc0dW90OwtVG02PswOu/teuARoLQjdDOH+t9pJgGnW5/Qmouf3gPJg==
|
||||||
|
|
||||||
array-flatten@1.1.1:
|
array-flatten@1.1.1:
|
||||||
version "1.1.1"
|
version "1.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2"
|
resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2"
|
||||||
|
@ -2677,34 +2744,6 @@ array-union@^2.1.0:
|
||||||
resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d"
|
resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d"
|
||||||
integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==
|
integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==
|
||||||
|
|
||||||
array.prototype.filter@^1.0.0:
|
|
||||||
version "1.0.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/array.prototype.filter/-/array.prototype.filter-1.0.0.tgz#24d63e38983cdc6bf023a3c574b2f2a3f384c301"
|
|
||||||
integrity sha512-TfO1gz+tLm+Bswq0FBOXPqAchtCr2Rn48T8dLJoRFl8NoEosjZmzptmuo1X8aZBzZcqsR1W8U761tjACJtngTQ==
|
|
||||||
dependencies:
|
|
||||||
call-bind "^1.0.2"
|
|
||||||
define-properties "^1.1.3"
|
|
||||||
es-abstract "^1.18.0"
|
|
||||||
es-array-method-boxes-properly "^1.0.0"
|
|
||||||
is-string "^1.0.5"
|
|
||||||
|
|
||||||
array.prototype.find@^2.1.1:
|
|
||||||
version "2.1.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/array.prototype.find/-/array.prototype.find-2.1.1.tgz#3baca26108ca7affb08db06bf0be6cb3115a969c"
|
|
||||||
integrity sha512-mi+MYNJYLTx2eNYy+Yh6raoQacCsNeeMUaspFPh9Y141lFSsWxxB8V9mM2ye+eqiRs917J6/pJ4M9ZPzenWckA==
|
|
||||||
dependencies:
|
|
||||||
define-properties "^1.1.3"
|
|
||||||
es-abstract "^1.17.4"
|
|
||||||
|
|
||||||
array.prototype.flat@^1.2.3:
|
|
||||||
version "1.2.4"
|
|
||||||
resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.2.4.tgz#6ef638b43312bd401b4c6199fdec7e2dc9e9a123"
|
|
||||||
integrity sha512-4470Xi3GAPAjZqFcljX2xzckv1qeKPizoNkiS0+O4IoPR2ZNpcjE0pkhdihlDouK+x6QOast26B4Q/O9DJnwSg==
|
|
||||||
dependencies:
|
|
||||||
call-bind "^1.0.0"
|
|
||||||
define-properties "^1.1.3"
|
|
||||||
es-abstract "^1.18.0-next.1"
|
|
||||||
|
|
||||||
array.prototype.flat@^1.2.5:
|
array.prototype.flat@^1.2.5:
|
||||||
version "1.2.5"
|
version "1.2.5"
|
||||||
resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.2.5.tgz#07e0975d84bbc7c48cd1879d609e682598d33e13"
|
resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.2.5.tgz#07e0975d84bbc7c48cd1879d609e682598d33e13"
|
||||||
|
@ -2756,6 +2795,11 @@ at-least-node@^1.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2"
|
resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2"
|
||||||
integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==
|
integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==
|
||||||
|
|
||||||
|
atob@^2.1.2:
|
||||||
|
version "2.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9"
|
||||||
|
integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==
|
||||||
|
|
||||||
autoprefixer@^10.4.2:
|
autoprefixer@^10.4.2:
|
||||||
version "10.4.2"
|
version "10.4.2"
|
||||||
resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.2.tgz#25e1df09a31a9fba5c40b578936b90d35c9d4d3b"
|
resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.2.tgz#25e1df09a31a9fba5c40b578936b90d35c9d4d3b"
|
||||||
|
@ -3261,6 +3305,14 @@ chalk@^2.0.0, chalk@^2.3.2, chalk@^2.4.1, chalk@^2.4.2:
|
||||||
escape-string-regexp "^1.0.5"
|
escape-string-regexp "^1.0.5"
|
||||||
supports-color "^5.3.0"
|
supports-color "^5.3.0"
|
||||||
|
|
||||||
|
chalk@^3.0.0:
|
||||||
|
version "3.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4"
|
||||||
|
integrity sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==
|
||||||
|
dependencies:
|
||||||
|
ansi-styles "^4.1.0"
|
||||||
|
supports-color "^7.1.0"
|
||||||
|
|
||||||
chalk@^4.0, chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.1, chalk@^4.1.2:
|
chalk@^4.0, chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.1, chalk@^4.1.2:
|
||||||
version "4.1.2"
|
version "4.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01"
|
resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01"
|
||||||
|
@ -3300,7 +3352,7 @@ cheerio-select@^1.5.0:
|
||||||
domhandler "^4.2.0"
|
domhandler "^4.2.0"
|
||||||
domutils "^2.7.0"
|
domutils "^2.7.0"
|
||||||
|
|
||||||
cheerio@^1.0.0-rc.10, cheerio@^1.0.0-rc.3:
|
cheerio@^1.0.0-rc.10:
|
||||||
version "1.0.0-rc.10"
|
version "1.0.0-rc.10"
|
||||||
resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-1.0.0-rc.10.tgz#2ba3dcdfcc26e7956fc1f440e61d51c643379f3e"
|
resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-1.0.0-rc.10.tgz#2ba3dcdfcc26e7956fc1f440e61d51c643379f3e"
|
||||||
integrity sha512-g0J0q/O6mW8z5zxQ3A8E8J1hUgp4SMOvEoW/x84OwyHKe/Zccz83PVT4y5Crcr530FV6NgmKI1qvGTKVl9XXVw==
|
integrity sha512-g0J0q/O6mW8z5zxQ3A8E8J1hUgp4SMOvEoW/x84OwyHKe/Zccz83PVT4y5Crcr530FV6NgmKI1qvGTKVl9XXVw==
|
||||||
|
@ -3491,7 +3543,7 @@ combined-stream@^1.0.8:
|
||||||
dependencies:
|
dependencies:
|
||||||
delayed-stream "~1.0.0"
|
delayed-stream "~1.0.0"
|
||||||
|
|
||||||
commander@^2.19.0, commander@^2.20.0:
|
commander@^2.20.0:
|
||||||
version "2.20.3"
|
version "2.20.3"
|
||||||
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
|
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
|
||||||
integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
|
integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
|
||||||
|
@ -3780,6 +3832,20 @@ css-what@^5.0.0, css-what@^5.0.1:
|
||||||
resolved "https://registry.yarnpkg.com/css-what/-/css-what-5.0.1.tgz#3efa820131f4669a8ac2408f9c32e7c7de9f4cad"
|
resolved "https://registry.yarnpkg.com/css-what/-/css-what-5.0.1.tgz#3efa820131f4669a8ac2408f9c32e7c7de9f4cad"
|
||||||
integrity sha512-FYDTSHb/7KXsWICVsxdmiExPjCfRC4qRFBdVwv7Ax9hMnvMmEjP9RfxTEZ3qPZGmADDn2vAKSo9UcN1jKVYscg==
|
integrity sha512-FYDTSHb/7KXsWICVsxdmiExPjCfRC4qRFBdVwv7Ax9hMnvMmEjP9RfxTEZ3qPZGmADDn2vAKSo9UcN1jKVYscg==
|
||||||
|
|
||||||
|
css.escape@^1.5.1:
|
||||||
|
version "1.5.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/css.escape/-/css.escape-1.5.1.tgz#42e27d4fa04ae32f931a4b4d4191fa9cddee97cb"
|
||||||
|
integrity sha1-QuJ9T6BK4y+TGktNQZH6nN3ul8s=
|
||||||
|
|
||||||
|
css@^3.0.0:
|
||||||
|
version "3.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/css/-/css-3.0.0.tgz#4447a4d58fdd03367c516ca9f64ae365cee4aa5d"
|
||||||
|
integrity sha512-DG9pFfwOrzc+hawpmqX/dHYHJG+Bsdb0klhyi1sDneOgGOXy9wQIC8hzyVp1e4NRYDBdxcylvywPkkXCHAzTyQ==
|
||||||
|
dependencies:
|
||||||
|
inherits "^2.0.4"
|
||||||
|
source-map "^0.6.1"
|
||||||
|
source-map-resolve "^0.6.0"
|
||||||
|
|
||||||
cssesc@^3.0.0:
|
cssesc@^3.0.0:
|
||||||
version "3.0.0"
|
version "3.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee"
|
resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee"
|
||||||
|
@ -3955,6 +4021,11 @@ decimal.js@^10.2.1:
|
||||||
resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.3.1.tgz#d8c3a444a9c6774ba60ca6ad7261c3a94fd5e783"
|
resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.3.1.tgz#d8c3a444a9c6774ba60ca6ad7261c3a94fd5e783"
|
||||||
integrity sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ==
|
integrity sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ==
|
||||||
|
|
||||||
|
decode-uri-component@^0.2.0:
|
||||||
|
version "0.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545"
|
||||||
|
integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=
|
||||||
|
|
||||||
dedent@^0.7.0:
|
dedent@^0.7.0:
|
||||||
version "0.7.0"
|
version "0.7.0"
|
||||||
resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c"
|
resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c"
|
||||||
|
@ -4093,11 +4164,6 @@ dir-glob@^3.0.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
path-type "^4.0.0"
|
path-type "^4.0.0"
|
||||||
|
|
||||||
discontinuous-range@1.0.0:
|
|
||||||
version "1.0.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/discontinuous-range/-/discontinuous-range-1.0.0.tgz#e38331f0844bba49b9a9cb71c771585aab1bc65a"
|
|
||||||
integrity sha1-44Mx8IRLukm5qctxx3FYWqsbxlo=
|
|
||||||
|
|
||||||
dlv@^1.1.3:
|
dlv@^1.1.3:
|
||||||
version "1.1.3"
|
version "1.1.3"
|
||||||
resolved "https://registry.yarnpkg.com/dlv/-/dlv-1.1.3.tgz#5c198a8a11453596e751494d49874bc7732f2e79"
|
resolved "https://registry.yarnpkg.com/dlv/-/dlv-1.1.3.tgz#5c198a8a11453596e751494d49874bc7732f2e79"
|
||||||
|
@ -4137,6 +4203,11 @@ doctrine@^3.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
esutils "^2.0.2"
|
esutils "^2.0.2"
|
||||||
|
|
||||||
|
dom-accessibility-api@^0.5.6, dom-accessibility-api@^0.5.9:
|
||||||
|
version "0.5.13"
|
||||||
|
resolved "https://registry.yarnpkg.com/dom-accessibility-api/-/dom-accessibility-api-0.5.13.tgz#102ee5f25eacce09bdf1cfa5a298f86da473be4b"
|
||||||
|
integrity sha512-R305kwb5CcMDIpSHUnLyIAp7SrSPBx6F0VfQFB3M75xVMHhXJJIdePYgbPPh1o57vCHNu5QztokWUPsLjWzFqw==
|
||||||
|
|
||||||
dom-converter@^0.2.0:
|
dom-converter@^0.2.0:
|
||||||
version "0.2.0"
|
version "0.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/dom-converter/-/dom-converter-0.2.0.tgz#6721a9daee2e293682955b6afe416771627bb768"
|
resolved "https://registry.yarnpkg.com/dom-converter/-/dom-converter-0.2.0.tgz#6721a9daee2e293682955b6afe416771627bb768"
|
||||||
|
@ -4353,70 +4424,6 @@ envinfo@^7.7.3:
|
||||||
resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.8.1.tgz#06377e3e5f4d379fea7ac592d5ad8927e0c4d475"
|
resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.8.1.tgz#06377e3e5f4d379fea7ac592d5ad8927e0c4d475"
|
||||||
integrity sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw==
|
integrity sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw==
|
||||||
|
|
||||||
enzyme-adapter-react-16@^1.15.6:
|
|
||||||
version "1.15.6"
|
|
||||||
resolved "https://registry.yarnpkg.com/enzyme-adapter-react-16/-/enzyme-adapter-react-16-1.15.6.tgz#fd677a658d62661ac5afd7f7f541f141f8085901"
|
|
||||||
integrity sha512-yFlVJCXh8T+mcQo8M6my9sPgeGzj85HSHi6Apgf1Cvq/7EL/J9+1JoJmJsRxZgyTvPMAqOEpRSu/Ii/ZpyOk0g==
|
|
||||||
dependencies:
|
|
||||||
enzyme-adapter-utils "^1.14.0"
|
|
||||||
enzyme-shallow-equal "^1.0.4"
|
|
||||||
has "^1.0.3"
|
|
||||||
object.assign "^4.1.2"
|
|
||||||
object.values "^1.1.2"
|
|
||||||
prop-types "^15.7.2"
|
|
||||||
react-is "^16.13.1"
|
|
||||||
react-test-renderer "^16.0.0-0"
|
|
||||||
semver "^5.7.0"
|
|
||||||
|
|
||||||
enzyme-adapter-utils@^1.14.0:
|
|
||||||
version "1.14.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/enzyme-adapter-utils/-/enzyme-adapter-utils-1.14.0.tgz#afbb0485e8033aa50c744efb5f5711e64fbf1ad0"
|
|
||||||
integrity sha512-F/z/7SeLt+reKFcb7597IThpDp0bmzcH1E9Oabqv+o01cID2/YInlqHbFl7HzWBl4h3OdZYedtwNDOmSKkk0bg==
|
|
||||||
dependencies:
|
|
||||||
airbnb-prop-types "^2.16.0"
|
|
||||||
function.prototype.name "^1.1.3"
|
|
||||||
has "^1.0.3"
|
|
||||||
object.assign "^4.1.2"
|
|
||||||
object.fromentries "^2.0.3"
|
|
||||||
prop-types "^15.7.2"
|
|
||||||
semver "^5.7.1"
|
|
||||||
|
|
||||||
enzyme-shallow-equal@^1.0.1, enzyme-shallow-equal@^1.0.4:
|
|
||||||
version "1.0.4"
|
|
||||||
resolved "https://registry.yarnpkg.com/enzyme-shallow-equal/-/enzyme-shallow-equal-1.0.4.tgz#b9256cb25a5f430f9bfe073a84808c1d74fced2e"
|
|
||||||
integrity sha512-MttIwB8kKxypwHvRynuC3ahyNc+cFbR8mjVIltnmzQ0uKGqmsfO4bfBuLxb0beLNPhjblUEYvEbsg+VSygvF1Q==
|
|
||||||
dependencies:
|
|
||||||
has "^1.0.3"
|
|
||||||
object-is "^1.1.2"
|
|
||||||
|
|
||||||
enzyme@^3.11.0:
|
|
||||||
version "3.11.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/enzyme/-/enzyme-3.11.0.tgz#71d680c580fe9349f6f5ac6c775bc3e6b7a79c28"
|
|
||||||
integrity sha512-Dw8/Gs4vRjxY6/6i9wU0V+utmQO9kvh9XLnz3LIudviOnVYDEe2ec+0k+NQoMamn1VrjKgCUOWj5jG/5M5M0Qw==
|
|
||||||
dependencies:
|
|
||||||
array.prototype.flat "^1.2.3"
|
|
||||||
cheerio "^1.0.0-rc.3"
|
|
||||||
enzyme-shallow-equal "^1.0.1"
|
|
||||||
function.prototype.name "^1.1.2"
|
|
||||||
has "^1.0.3"
|
|
||||||
html-element-map "^1.2.0"
|
|
||||||
is-boolean-object "^1.0.1"
|
|
||||||
is-callable "^1.1.5"
|
|
||||||
is-number-object "^1.0.4"
|
|
||||||
is-regex "^1.0.5"
|
|
||||||
is-string "^1.0.5"
|
|
||||||
is-subset "^0.1.1"
|
|
||||||
lodash.escape "^4.0.1"
|
|
||||||
lodash.isequal "^4.5.0"
|
|
||||||
object-inspect "^1.7.0"
|
|
||||||
object-is "^1.0.2"
|
|
||||||
object.assign "^4.1.0"
|
|
||||||
object.entries "^1.1.1"
|
|
||||||
object.values "^1.1.1"
|
|
||||||
raf "^3.4.1"
|
|
||||||
rst-selector-parser "^2.2.3"
|
|
||||||
string.prototype.trim "^1.2.1"
|
|
||||||
|
|
||||||
error-ex@^1.3.1:
|
error-ex@^1.3.1:
|
||||||
version "1.3.2"
|
version "1.3.2"
|
||||||
resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf"
|
resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf"
|
||||||
|
@ -4424,7 +4431,7 @@ error-ex@^1.3.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
is-arrayish "^0.2.1"
|
is-arrayish "^0.2.1"
|
||||||
|
|
||||||
es-abstract@^1.17.2, es-abstract@^1.17.4, es-abstract@^1.18.0, es-abstract@^1.18.0-next.1, es-abstract@^1.18.0-next.2, es-abstract@^1.18.2, es-abstract@^1.18.5:
|
es-abstract@^1.17.2, es-abstract@^1.18.0-next.1, es-abstract@^1.18.0-next.2, es-abstract@^1.18.2, es-abstract@^1.18.5:
|
||||||
version "1.18.6"
|
version "1.18.6"
|
||||||
resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.18.6.tgz#2c44e3ea7a6255039164d26559777a6d978cb456"
|
resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.18.6.tgz#2c44e3ea7a6255039164d26559777a6d978cb456"
|
||||||
integrity sha512-kAeIT4cku5eNLNuUKhlmtuk1/TRZvQoYccn6TO0cSVdf1kzB0T7+dYuVK9MWM7l+/53W2Q8M7N2c6MQvhXFcUQ==
|
integrity sha512-kAeIT4cku5eNLNuUKhlmtuk1/TRZvQoYccn6TO0cSVdf1kzB0T7+dYuVK9MWM7l+/53W2Q8M7N2c6MQvhXFcUQ==
|
||||||
|
@ -4474,11 +4481,6 @@ es-abstract@^1.19.0, es-abstract@^1.19.1:
|
||||||
string.prototype.trimstart "^1.0.4"
|
string.prototype.trimstart "^1.0.4"
|
||||||
unbox-primitive "^1.0.1"
|
unbox-primitive "^1.0.1"
|
||||||
|
|
||||||
es-array-method-boxes-properly@^1.0.0:
|
|
||||||
version "1.0.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz#873f3e84418de4ee19c5be752990b2e44718d09e"
|
|
||||||
integrity sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==
|
|
||||||
|
|
||||||
es-module-lexer@^0.7.1:
|
es-module-lexer@^0.7.1:
|
||||||
version "0.7.1"
|
version "0.7.1"
|
||||||
resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.7.1.tgz#c2c8e0f46f2df06274cdaf0dd3f3b33e0a0b267d"
|
resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.7.1.tgz#c2c8e0f46f2df06274cdaf0dd3f3b33e0a0b267d"
|
||||||
|
@ -5117,26 +5119,11 @@ function-bind@^1.1.1:
|
||||||
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
|
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
|
||||||
integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
|
integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
|
||||||
|
|
||||||
function.prototype.name@^1.1.2, function.prototype.name@^1.1.3:
|
|
||||||
version "1.1.4"
|
|
||||||
resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.4.tgz#e4ea839b9d3672ae99d0efd9f38d9191c5eaac83"
|
|
||||||
integrity sha512-iqy1pIotY/RmhdFZygSSlW0wko2yxkSCKqsuv4pr8QESohpYyG/Z7B/XXvPRKTJS//960rgguE5mSRUsDdaJrQ==
|
|
||||||
dependencies:
|
|
||||||
call-bind "^1.0.2"
|
|
||||||
define-properties "^1.1.3"
|
|
||||||
es-abstract "^1.18.0-next.2"
|
|
||||||
functions-have-names "^1.2.2"
|
|
||||||
|
|
||||||
functional-red-black-tree@^1.0.1:
|
functional-red-black-tree@^1.0.1:
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327"
|
resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327"
|
||||||
integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=
|
integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=
|
||||||
|
|
||||||
functions-have-names@^1.2.2:
|
|
||||||
version "1.2.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.2.tgz#98d93991c39da9361f8e50b337c4f6e41f120e21"
|
|
||||||
integrity sha512-bLgc3asbWdwPbx2mNk2S49kmJCuQeu0nfmaOgbs8WIyzzkw3r4htszdIi9Q9EMezDPTYuJx2wvjZ/EwgAthpnA==
|
|
||||||
|
|
||||||
gensync@^1.0.0-beta.2:
|
gensync@^1.0.0-beta.2:
|
||||||
version "1.0.0-beta.2"
|
version "1.0.0-beta.2"
|
||||||
resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0"
|
resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0"
|
||||||
|
@ -5432,14 +5419,6 @@ hsla-regex@^1.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/hsla-regex/-/hsla-regex-1.0.0.tgz#c1ce7a3168c8c6614033a4b5f7877f3b225f9c38"
|
resolved "https://registry.yarnpkg.com/hsla-regex/-/hsla-regex-1.0.0.tgz#c1ce7a3168c8c6614033a4b5f7877f3b225f9c38"
|
||||||
integrity sha1-wc56MWjIxmFAM6S194d/OyJfnDg=
|
integrity sha1-wc56MWjIxmFAM6S194d/OyJfnDg=
|
||||||
|
|
||||||
html-element-map@^1.2.0:
|
|
||||||
version "1.3.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/html-element-map/-/html-element-map-1.3.1.tgz#44b2cbcfa7be7aa4ff59779e47e51012e1c73c08"
|
|
||||||
integrity sha512-6XMlxrAFX4UEEGxctfFnmrFaaZFNf9i5fNuV5wZ3WWQ4FVaNP1aX1LkX9j2mfEx1NpjeE/rL3nmgEn23GdFmrg==
|
|
||||||
dependencies:
|
|
||||||
array.prototype.filter "^1.0.0"
|
|
||||||
call-bind "^1.0.2"
|
|
||||||
|
|
||||||
html-encoding-sniffer@^2.0.1:
|
html-encoding-sniffer@^2.0.1:
|
||||||
version "2.0.1"
|
version "2.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz#42a6dc4fd33f00281176e8b23759ca4e4fa185f3"
|
resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz#42a6dc4fd33f00281176e8b23759ca4e4fa185f3"
|
||||||
|
@ -5706,7 +5685,7 @@ inflight@^1.0.4:
|
||||||
once "^1.3.0"
|
once "^1.3.0"
|
||||||
wrappy "1"
|
wrappy "1"
|
||||||
|
|
||||||
inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.3:
|
inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3:
|
||||||
version "2.0.4"
|
version "2.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
|
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
|
||||||
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
|
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
|
||||||
|
@ -5874,7 +5853,7 @@ is-blob@^2.1.0:
|
||||||
resolved "https://registry.yarnpkg.com/is-blob/-/is-blob-2.1.0.tgz#e36cd82c90653f1e1b930f11baf9c64216a05385"
|
resolved "https://registry.yarnpkg.com/is-blob/-/is-blob-2.1.0.tgz#e36cd82c90653f1e1b930f11baf9c64216a05385"
|
||||||
integrity sha512-SZ/fTft5eUhQM6oF/ZaASFDEdbFVe89Imltn9uZr03wdKMcWNVYSMjQPFtg05QuNkt5l5c135ElvXEQG0rk4tw==
|
integrity sha512-SZ/fTft5eUhQM6oF/ZaASFDEdbFVe89Imltn9uZr03wdKMcWNVYSMjQPFtg05QuNkt5l5c135ElvXEQG0rk4tw==
|
||||||
|
|
||||||
is-boolean-object@^1.0.1, is-boolean-object@^1.1.0:
|
is-boolean-object@^1.1.0:
|
||||||
version "1.1.2"
|
version "1.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719"
|
resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719"
|
||||||
integrity sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==
|
integrity sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==
|
||||||
|
@ -5887,7 +5866,7 @@ is-buffer@^2.0.0, is-buffer@^2.0.5:
|
||||||
resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191"
|
resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191"
|
||||||
integrity sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==
|
integrity sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==
|
||||||
|
|
||||||
is-callable@^1.1.4, is-callable@^1.1.5, is-callable@^1.2.4:
|
is-callable@^1.1.4, is-callable@^1.2.4:
|
||||||
version "1.2.4"
|
version "1.2.4"
|
||||||
resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.4.tgz#47301d58dd0259407865547853df6d61fe471945"
|
resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.4.tgz#47301d58dd0259407865547853df6d61fe471945"
|
||||||
integrity sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==
|
integrity sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==
|
||||||
|
@ -6067,7 +6046,7 @@ is-potential-custom-element-name@^1.0.1:
|
||||||
resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz#171ed6f19e3ac554394edf78caa05784a45bebb5"
|
resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz#171ed6f19e3ac554394edf78caa05784a45bebb5"
|
||||||
integrity sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==
|
integrity sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==
|
||||||
|
|
||||||
is-regex@^1.0.4, is-regex@^1.0.5, is-regex@^1.1.0, is-regex@^1.1.4:
|
is-regex@^1.0.4, is-regex@^1.1.4:
|
||||||
version "1.1.4"
|
version "1.1.4"
|
||||||
resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958"
|
resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958"
|
||||||
integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==
|
integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==
|
||||||
|
@ -6107,11 +6086,6 @@ is-string@^1.0.5, is-string@^1.0.7:
|
||||||
dependencies:
|
dependencies:
|
||||||
has-tostringtag "^1.0.0"
|
has-tostringtag "^1.0.0"
|
||||||
|
|
||||||
is-subset@^0.1.1:
|
|
||||||
version "0.1.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/is-subset/-/is-subset-0.1.1.tgz#8a59117d932de1de00f245fcdd39ce43f1e939a6"
|
|
||||||
integrity sha1-ilkRfZMt4d4A8kX83TnOQ/HpOaY=
|
|
||||||
|
|
||||||
is-symbol@^1.0.2, is-symbol@^1.0.3:
|
is-symbol@^1.0.2, is-symbol@^1.0.3:
|
||||||
version "1.0.4"
|
version "1.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c"
|
resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c"
|
||||||
|
@ -6419,6 +6393,16 @@ jest-leak-detector@^27.2.0:
|
||||||
jest-get-type "^27.0.6"
|
jest-get-type "^27.0.6"
|
||||||
pretty-format "^27.2.0"
|
pretty-format "^27.2.0"
|
||||||
|
|
||||||
|
jest-matcher-utils@^27.0.0, jest-matcher-utils@^27.5.1:
|
||||||
|
version "27.5.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz#9c0cdbda8245bc22d2331729d1091308b40cf8ab"
|
||||||
|
integrity sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw==
|
||||||
|
dependencies:
|
||||||
|
chalk "^4.0.0"
|
||||||
|
jest-diff "^27.5.1"
|
||||||
|
jest-get-type "^27.5.1"
|
||||||
|
pretty-format "^27.5.1"
|
||||||
|
|
||||||
jest-matcher-utils@^27.2.0:
|
jest-matcher-utils@^27.2.0:
|
||||||
version "27.2.0"
|
version "27.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-27.2.0.tgz#b4d224ab88655d5fab64b96b989ac349e2f5da43"
|
resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-27.2.0.tgz#b4d224ab88655d5fab64b96b989ac349e2f5da43"
|
||||||
|
@ -6429,16 +6413,6 @@ jest-matcher-utils@^27.2.0:
|
||||||
jest-get-type "^27.0.6"
|
jest-get-type "^27.0.6"
|
||||||
pretty-format "^27.2.0"
|
pretty-format "^27.2.0"
|
||||||
|
|
||||||
jest-matcher-utils@^27.5.1:
|
|
||||||
version "27.5.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz#9c0cdbda8245bc22d2331729d1091308b40cf8ab"
|
|
||||||
integrity sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw==
|
|
||||||
dependencies:
|
|
||||||
chalk "^4.0.0"
|
|
||||||
jest-diff "^27.5.1"
|
|
||||||
jest-get-type "^27.5.1"
|
|
||||||
pretty-format "^27.5.1"
|
|
||||||
|
|
||||||
jest-message-util@^27.2.0:
|
jest-message-util@^27.2.0:
|
||||||
version "27.2.0"
|
version "27.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-27.2.0.tgz#2f65c71df55267208686b1d7514e18106c91ceaf"
|
resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-27.2.0.tgz#2f65c71df55267208686b1d7514e18106c91ceaf"
|
||||||
|
@ -7077,16 +7051,6 @@ lodash.debounce@^4.0.8:
|
||||||
resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af"
|
resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af"
|
||||||
integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168=
|
integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168=
|
||||||
|
|
||||||
lodash.escape@^4.0.1:
|
|
||||||
version "4.0.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/lodash.escape/-/lodash.escape-4.0.1.tgz#c9044690c21e04294beaa517712fded1fa88de98"
|
|
||||||
integrity sha1-yQRGkMIeBClL6qUXcS/e0fqI3pg=
|
|
||||||
|
|
||||||
lodash.flattendeep@^4.4.0:
|
|
||||||
version "4.4.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz#fb030917f86a3134e5bc9bec0d69e0013ddfedb2"
|
|
||||||
integrity sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=
|
|
||||||
|
|
||||||
lodash.get@^4.0:
|
lodash.get@^4.0:
|
||||||
version "4.4.2"
|
version "4.4.2"
|
||||||
resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99"
|
resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99"
|
||||||
|
@ -7191,6 +7155,11 @@ lru-cache@^6.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
yallist "^4.0.0"
|
yallist "^4.0.0"
|
||||||
|
|
||||||
|
lz-string@^1.4.4:
|
||||||
|
version "1.4.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/lz-string/-/lz-string-1.4.4.tgz#c0d8eaf36059f705796e1e344811cf4c498d3a26"
|
||||||
|
integrity sha1-wNjq82BZ9wV5bh40SBHPTEmNOiY=
|
||||||
|
|
||||||
make-dir@^3.0.0, make-dir@^3.0.2, make-dir@^3.1.0:
|
make-dir@^3.0.0, make-dir@^3.0.2, make-dir@^3.1.0:
|
||||||
version "3.1.0"
|
version "3.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f"
|
resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f"
|
||||||
|
@ -7474,11 +7443,6 @@ mkdirp@^1.0.4:
|
||||||
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e"
|
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e"
|
||||||
integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==
|
integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==
|
||||||
|
|
||||||
moo@^0.5.0:
|
|
||||||
version "0.5.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/moo/-/moo-0.5.1.tgz#7aae7f384b9b09f620b6abf6f74ebbcd1b65dbc4"
|
|
||||||
integrity sha512-I1mnb5xn4fO80BH9BLcF0yLypy2UKl+Cb01Fu0hJRkJjlCRtxZMWkTdAtDd5ZqCOxtCkhmRwyI57vWT+1iZ67w==
|
|
||||||
|
|
||||||
mousetrap@^1.5.2:
|
mousetrap@^1.5.2:
|
||||||
version "1.6.5"
|
version "1.6.5"
|
||||||
resolved "https://registry.yarnpkg.com/mousetrap/-/mousetrap-1.6.5.tgz#8a766d8c272b08393d5f56074e0b5ec183485bf9"
|
resolved "https://registry.yarnpkg.com/mousetrap/-/mousetrap-1.6.5.tgz#8a766d8c272b08393d5f56074e0b5ec183485bf9"
|
||||||
|
@ -7532,16 +7496,6 @@ natural-compare@^1.4.0:
|
||||||
resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
|
resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
|
||||||
integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=
|
integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=
|
||||||
|
|
||||||
nearley@^2.7.10:
|
|
||||||
version "2.20.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/nearley/-/nearley-2.20.1.tgz#246cd33eff0d012faf197ff6774d7ac78acdd474"
|
|
||||||
integrity sha512-+Mc8UaAebFzgV+KpI5n7DasuuQCHA89dmwm7JXw3TV43ukfNQ9DnBH3Mdb2g/I4Fdxc26pwimBWvjIw0UAILSQ==
|
|
||||||
dependencies:
|
|
||||||
commander "^2.19.0"
|
|
||||||
moo "^0.5.0"
|
|
||||||
railroad-diagrams "^1.0.0"
|
|
||||||
randexp "0.4.6"
|
|
||||||
|
|
||||||
negotiator@0.6.2:
|
negotiator@0.6.2:
|
||||||
version "0.6.2"
|
version "0.6.2"
|
||||||
resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb"
|
resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb"
|
||||||
|
@ -7676,12 +7630,12 @@ object-hash@^2.2.0:
|
||||||
resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-2.2.0.tgz#5ad518581eefc443bd763472b8ff2e9c2c0d54a5"
|
resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-2.2.0.tgz#5ad518581eefc443bd763472b8ff2e9c2c0d54a5"
|
||||||
integrity sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==
|
integrity sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==
|
||||||
|
|
||||||
object-inspect@^1.11.0, object-inspect@^1.7.0, object-inspect@^1.9.0:
|
object-inspect@^1.11.0, object-inspect@^1.9.0:
|
||||||
version "1.11.0"
|
version "1.11.0"
|
||||||
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.11.0.tgz#9dceb146cedd4148a0d9e51ab88d34cf509922b1"
|
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.11.0.tgz#9dceb146cedd4148a0d9e51ab88d34cf509922b1"
|
||||||
integrity sha512-jp7ikS6Sd3GxQfZJPyH3cjcbJF6GZPClgdV+EFygjFLQ5FmW/dRUnTd9PQ9k0JhoNDabWFbpF1yCdSWCC6gexg==
|
integrity sha512-jp7ikS6Sd3GxQfZJPyH3cjcbJF6GZPClgdV+EFygjFLQ5FmW/dRUnTd9PQ9k0JhoNDabWFbpF1yCdSWCC6gexg==
|
||||||
|
|
||||||
object-is@^1.0.1, object-is@^1.0.2, object-is@^1.1.2:
|
object-is@^1.0.1:
|
||||||
version "1.1.5"
|
version "1.1.5"
|
||||||
resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.5.tgz#b9deeaa5fc7f1846a0faecdceec138e5778f53ac"
|
resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.5.tgz#b9deeaa5fc7f1846a0faecdceec138e5778f53ac"
|
||||||
integrity sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==
|
integrity sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==
|
||||||
|
@ -7704,7 +7658,7 @@ object.assign@^4.1.0, object.assign@^4.1.2:
|
||||||
has-symbols "^1.0.1"
|
has-symbols "^1.0.1"
|
||||||
object-keys "^1.1.1"
|
object-keys "^1.1.1"
|
||||||
|
|
||||||
object.entries@^1.1.1, object.entries@^1.1.2, object.entries@^1.1.4:
|
object.entries@^1.1.4:
|
||||||
version "1.1.4"
|
version "1.1.4"
|
||||||
resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.4.tgz#43ccf9a50bc5fd5b649d45ab1a579f24e088cafd"
|
resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.4.tgz#43ccf9a50bc5fd5b649d45ab1a579f24e088cafd"
|
||||||
integrity sha512-h4LWKWE+wKQGhtMjZEBud7uLGhqyLwj8fpHOarZhD2uY3C9cRtk57VQ89ke3moByLXMedqs3XCHzyb4AmA2DjA==
|
integrity sha512-h4LWKWE+wKQGhtMjZEBud7uLGhqyLwj8fpHOarZhD2uY3C9cRtk57VQ89ke3moByLXMedqs3XCHzyb4AmA2DjA==
|
||||||
|
@ -7713,7 +7667,7 @@ object.entries@^1.1.1, object.entries@^1.1.2, object.entries@^1.1.4:
|
||||||
define-properties "^1.1.3"
|
define-properties "^1.1.3"
|
||||||
es-abstract "^1.18.2"
|
es-abstract "^1.18.2"
|
||||||
|
|
||||||
object.fromentries@^2.0.3, object.fromentries@^2.0.4:
|
object.fromentries@^2.0.4:
|
||||||
version "2.0.4"
|
version "2.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.4.tgz#26e1ba5c4571c5c6f0890cef4473066456a120b8"
|
resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.4.tgz#26e1ba5c4571c5c6f0890cef4473066456a120b8"
|
||||||
integrity sha512-EsFBshs5RUUpQEY1D4q/m59kMfz4YJvxuNCJcv/jWwOJr34EaVnG11ZrZa0UHB3wnzV1wx8m58T4hQL8IuNXlQ==
|
integrity sha512-EsFBshs5RUUpQEY1D4q/m59kMfz4YJvxuNCJcv/jWwOJr34EaVnG11ZrZa0UHB3wnzV1wx8m58T4hQL8IuNXlQ==
|
||||||
|
@ -7732,7 +7686,7 @@ object.getownpropertydescriptors@^2.1.0:
|
||||||
define-properties "^1.1.3"
|
define-properties "^1.1.3"
|
||||||
es-abstract "^1.18.0-next.2"
|
es-abstract "^1.18.0-next.2"
|
||||||
|
|
||||||
object.values@^1.1.0, object.values@^1.1.1, object.values@^1.1.2, object.values@^1.1.4:
|
object.values@^1.1.0, object.values@^1.1.4:
|
||||||
version "1.1.4"
|
version "1.1.4"
|
||||||
resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.4.tgz#0d273762833e816b693a637d30073e7051535b30"
|
resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.4.tgz#0d273762833e816b693a637d30073e7051535b30"
|
||||||
integrity sha512-TnGo7j4XSnKQoK3MfvkzqKCi0nVe/D9I9IjwTNYdb/fxYHpjrluHVOgw0AF6jrRFGMPHdfuidR09tIDiIvnaSg==
|
integrity sha512-TnGo7j4XSnKQoK3MfvkzqKCi0nVe/D9I9IjwTNYdb/fxYHpjrluHVOgw0AF6jrRFGMPHdfuidR09tIDiIvnaSg==
|
||||||
|
@ -8547,6 +8501,15 @@ pretty-error@^3.0.4:
|
||||||
lodash "^4.17.20"
|
lodash "^4.17.20"
|
||||||
renderkid "^2.0.6"
|
renderkid "^2.0.6"
|
||||||
|
|
||||||
|
pretty-format@^27.0.0, pretty-format@^27.0.2, pretty-format@^27.5.1:
|
||||||
|
version "27.5.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.5.1.tgz#2181879fdea51a7a5851fb39d920faa63f01d88e"
|
||||||
|
integrity sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==
|
||||||
|
dependencies:
|
||||||
|
ansi-regex "^5.0.1"
|
||||||
|
ansi-styles "^5.0.0"
|
||||||
|
react-is "^17.0.1"
|
||||||
|
|
||||||
pretty-format@^27.2.0:
|
pretty-format@^27.2.0:
|
||||||
version "27.2.0"
|
version "27.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.2.0.tgz#ee37a94ce2a79765791a8649ae374d468c18ef19"
|
resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.2.0.tgz#ee37a94ce2a79765791a8649ae374d468c18ef19"
|
||||||
|
@ -8557,15 +8520,6 @@ pretty-format@^27.2.0:
|
||||||
ansi-styles "^5.0.0"
|
ansi-styles "^5.0.0"
|
||||||
react-is "^17.0.1"
|
react-is "^17.0.1"
|
||||||
|
|
||||||
pretty-format@^27.5.1:
|
|
||||||
version "27.5.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.5.1.tgz#2181879fdea51a7a5851fb39d920faa63f01d88e"
|
|
||||||
integrity sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==
|
|
||||||
dependencies:
|
|
||||||
ansi-regex "^5.0.1"
|
|
||||||
ansi-styles "^5.0.0"
|
|
||||||
react-is "^17.0.1"
|
|
||||||
|
|
||||||
process-nextick-args@~2.0.0:
|
process-nextick-args@~2.0.0:
|
||||||
version "2.0.1"
|
version "2.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
|
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
|
||||||
|
@ -8589,15 +8543,6 @@ prompts@^2.0.1:
|
||||||
kleur "^3.0.3"
|
kleur "^3.0.3"
|
||||||
sisteransi "^1.0.5"
|
sisteransi "^1.0.5"
|
||||||
|
|
||||||
prop-types-exact@^1.2.0:
|
|
||||||
version "1.2.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/prop-types-exact/-/prop-types-exact-1.2.0.tgz#825d6be46094663848237e3925a98c6e944e9869"
|
|
||||||
integrity sha512-K+Tk3Kd9V0odiXFP9fwDHUYRyvK3Nun3GVyPapSIs5OBkITAm15W0CPFD/YKTkMUAbc0b9CUwRQp2ybiBIq+eA==
|
|
||||||
dependencies:
|
|
||||||
has "^1.0.3"
|
|
||||||
object.assign "^4.1.0"
|
|
||||||
reflect.ownkeys "^0.2.0"
|
|
||||||
|
|
||||||
prop-types-extra@^1.0.1:
|
prop-types-extra@^1.0.1:
|
||||||
version "1.1.1"
|
version "1.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/prop-types-extra/-/prop-types-extra-1.1.1.tgz#58c3b74cbfbb95d304625975aa2f0848329a010b"
|
resolved "https://registry.yarnpkg.com/prop-types-extra/-/prop-types-extra-1.1.1.tgz#58c3b74cbfbb95d304625975aa2f0848329a010b"
|
||||||
|
@ -8694,19 +8639,6 @@ raf@^3.0.0, raf@^3.1.0, raf@^3.4.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
performance-now "^2.1.0"
|
performance-now "^2.1.0"
|
||||||
|
|
||||||
railroad-diagrams@^1.0.0:
|
|
||||||
version "1.0.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz#eb7e6267548ddedfb899c1b90e57374559cddb7e"
|
|
||||||
integrity sha1-635iZ1SN3t+4mcG5Dlc3RVnN234=
|
|
||||||
|
|
||||||
randexp@0.4.6:
|
|
||||||
version "0.4.6"
|
|
||||||
resolved "https://registry.yarnpkg.com/randexp/-/randexp-0.4.6.tgz#e986ad5e5e31dae13ddd6f7b3019aa7c87f60ca3"
|
|
||||||
integrity sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==
|
|
||||||
dependencies:
|
|
||||||
discontinuous-range "1.0.0"
|
|
||||||
ret "~0.1.10"
|
|
||||||
|
|
||||||
randombytes@^2.1.0:
|
randombytes@^2.1.0:
|
||||||
version "2.1.0"
|
version "2.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a"
|
resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a"
|
||||||
|
@ -8850,7 +8782,7 @@ react-intl@^5.0.0:
|
||||||
intl-messageformat "9.9.1"
|
intl-messageformat "9.9.1"
|
||||||
tslib "^2.1.0"
|
tslib "^2.1.0"
|
||||||
|
|
||||||
react-is@^16.13.1, react-is@^16.3.2, react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.6:
|
react-is@^16.13.1, react-is@^16.3.2, react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1:
|
||||||
version "16.13.1"
|
version "16.13.1"
|
||||||
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
|
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
|
||||||
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
|
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
|
||||||
|
@ -9027,16 +8959,6 @@ react-swipeable-views@^0.14.0:
|
||||||
react-swipeable-views-utils "^0.14.0"
|
react-swipeable-views-utils "^0.14.0"
|
||||||
warning "^4.0.1"
|
warning "^4.0.1"
|
||||||
|
|
||||||
react-test-renderer@^16.0.0-0, react-test-renderer@^16.13.1:
|
|
||||||
version "16.14.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-16.14.0.tgz#e98360087348e260c56d4fe2315e970480c228ae"
|
|
||||||
integrity sha512-L8yPjqPE5CZO6rKsKXRO/rVPiaCOy0tQQJbC+UjPNlobl5mad59lvPjwFsQHTvL03caVDIVr9x9/OSgDe6I5Eg==
|
|
||||||
dependencies:
|
|
||||||
object-assign "^4.1.1"
|
|
||||||
prop-types "^15.6.2"
|
|
||||||
react-is "^16.8.6"
|
|
||||||
scheduler "^0.19.1"
|
|
||||||
|
|
||||||
react-textarea-autosize@^8.3.3:
|
react-textarea-autosize@^8.3.3:
|
||||||
version "8.3.3"
|
version "8.3.3"
|
||||||
resolved "https://registry.yarnpkg.com/react-textarea-autosize/-/react-textarea-autosize-8.3.3.tgz#f70913945369da453fd554c168f6baacd1fa04d8"
|
resolved "https://registry.yarnpkg.com/react-textarea-autosize/-/react-textarea-autosize-8.3.3.tgz#f70913945369da453fd554c168f6baacd1fa04d8"
|
||||||
|
@ -9166,10 +9088,12 @@ redux@^4.0.0, redux@^4.1.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/runtime" "^7.9.2"
|
"@babel/runtime" "^7.9.2"
|
||||||
|
|
||||||
reflect.ownkeys@^0.2.0:
|
redux@^4.0.5:
|
||||||
version "0.2.0"
|
version "4.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/reflect.ownkeys/-/reflect.ownkeys-0.2.0.tgz#749aceec7f3fdf8b63f927a04809e90c5c0b3460"
|
resolved "https://registry.yarnpkg.com/redux/-/redux-4.1.2.tgz#140f35426d99bb4729af760afcf79eaaac407104"
|
||||||
integrity sha1-dJrO7H8/34tj+SegSAnpDFwLNGA=
|
integrity sha512-SH8PglcebESbd/shgf6mii6EIoRM0zrQyjcuQ+ojmfxjTtE0z9Y8pa62iA/OJ58qjP6j27uyW4kUF4jl/jd6sw==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.9.2"
|
||||||
|
|
||||||
regenerate-unicode-properties@^9.0.0:
|
regenerate-unicode-properties@^9.0.0:
|
||||||
version "9.0.0"
|
version "9.0.0"
|
||||||
|
@ -9383,11 +9307,6 @@ restore-cursor@^3.1.0:
|
||||||
onetime "^5.1.0"
|
onetime "^5.1.0"
|
||||||
signal-exit "^3.0.2"
|
signal-exit "^3.0.2"
|
||||||
|
|
||||||
ret@~0.1.10:
|
|
||||||
version "0.1.15"
|
|
||||||
resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc"
|
|
||||||
integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==
|
|
||||||
|
|
||||||
retry@^0.13.1:
|
retry@^0.13.1:
|
||||||
version "0.13.1"
|
version "0.13.1"
|
||||||
resolved "https://registry.yarnpkg.com/retry/-/retry-0.13.1.tgz#185b1587acf67919d63b357349e03537b2484658"
|
resolved "https://registry.yarnpkg.com/retry/-/retry-0.13.1.tgz#185b1587acf67919d63b357349e03537b2484658"
|
||||||
|
@ -9415,14 +9334,6 @@ rimraf@^3.0.0, rimraf@^3.0.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
glob "^7.1.3"
|
glob "^7.1.3"
|
||||||
|
|
||||||
rst-selector-parser@^2.2.3:
|
|
||||||
version "2.2.3"
|
|
||||||
resolved "https://registry.yarnpkg.com/rst-selector-parser/-/rst-selector-parser-2.2.3.tgz#81b230ea2fcc6066c89e3472de794285d9b03d91"
|
|
||||||
integrity sha1-gbIw6i/MYGbInjRy3nlChdmwPZE=
|
|
||||||
dependencies:
|
|
||||||
lodash.flattendeep "^4.4.0"
|
|
||||||
nearley "^2.7.10"
|
|
||||||
|
|
||||||
run-parallel@^1.1.9:
|
run-parallel@^1.1.9:
|
||||||
version "1.2.0"
|
version "1.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee"
|
resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee"
|
||||||
|
@ -9542,7 +9453,7 @@ semver-compare@^1.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc"
|
resolved "https://registry.yarnpkg.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc"
|
||||||
integrity sha1-De4hahyUGrN+nvsXiPavxf9VN/w=
|
integrity sha1-De4hahyUGrN+nvsXiPavxf9VN/w=
|
||||||
|
|
||||||
"semver@2 || 3 || 4 || 5", semver@^5.7.0, semver@^5.7.1:
|
"semver@2 || 3 || 4 || 5":
|
||||||
version "5.7.1"
|
version "5.7.1"
|
||||||
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
|
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
|
||||||
integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
|
integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
|
||||||
|
@ -9739,6 +9650,14 @@ source-map-js@^1.0.1:
|
||||||
resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c"
|
resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c"
|
||||||
integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==
|
integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==
|
||||||
|
|
||||||
|
source-map-resolve@^0.6.0:
|
||||||
|
version "0.6.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.6.0.tgz#3d9df87e236b53f16d01e58150fc7711138e5ed2"
|
||||||
|
integrity sha512-KXBr9d/fO/bWo97NXsPIAW1bFSBOuCnjbNTBMO7N59hsv5i9yzRDfcYwwt0l04+VqnKC+EwzvJZIP/qkuMgR/w==
|
||||||
|
dependencies:
|
||||||
|
atob "^2.1.2"
|
||||||
|
decode-uri-component "^0.2.0"
|
||||||
|
|
||||||
source-map-support@^0.5.20, source-map-support@^0.5.6, source-map-support@~0.5.12, source-map-support@~0.5.20:
|
source-map-support@^0.5.20, source-map-support@^0.5.6, source-map-support@~0.5.12, source-map-support@~0.5.20:
|
||||||
version "0.5.20"
|
version "0.5.20"
|
||||||
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.20.tgz#12166089f8f5e5e8c56926b377633392dd2cb6c9"
|
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.20.tgz#12166089f8f5e5e8c56926b377633392dd2cb6c9"
|
||||||
|
@ -9875,15 +9794,6 @@ string.prototype.matchall@^4.0.5:
|
||||||
regexp.prototype.flags "^1.3.1"
|
regexp.prototype.flags "^1.3.1"
|
||||||
side-channel "^1.0.4"
|
side-channel "^1.0.4"
|
||||||
|
|
||||||
string.prototype.trim@^1.2.1:
|
|
||||||
version "1.2.4"
|
|
||||||
resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.4.tgz#6014689baf5efaf106ad031a5fa45157666ed1bd"
|
|
||||||
integrity sha512-hWCk/iqf7lp0/AgTF7/ddO1IWtSNPASjlzCicV5irAVdE1grjsneK26YG6xACMBEdCvO8fUST0UzDMh/2Qy+9Q==
|
|
||||||
dependencies:
|
|
||||||
call-bind "^1.0.2"
|
|
||||||
define-properties "^1.1.3"
|
|
||||||
es-abstract "^1.18.0-next.2"
|
|
||||||
|
|
||||||
string.prototype.trimend@^1.0.4:
|
string.prototype.trimend@^1.0.4:
|
||||||
version "1.0.4"
|
version "1.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz#e75ae90c2942c63504686c18b287b4a0b1a45f80"
|
resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz#e75ae90c2942c63504686c18b287b4a0b1a45f80"
|
||||||
|
|
Loading…
Reference in New Issue