mirror of
https://github.com/shlinkio/shlink-web-client.git
synced 2024-12-23 17:40:23 +03:00
Migrated remaining tags-related elements to TS
This commit is contained in:
parent
18883caa6d
commit
f8ea1ae3d5
8 changed files with 198 additions and 225 deletions
|
@ -1,21 +0,0 @@
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
|
|
||||||
const regularServerType = PropTypes.shape({
|
|
||||||
id: PropTypes.string,
|
|
||||||
name: PropTypes.string,
|
|
||||||
url: PropTypes.string,
|
|
||||||
apiKey: PropTypes.string,
|
|
||||||
version: PropTypes.string,
|
|
||||||
printableVersion: PropTypes.string,
|
|
||||||
serverNotReachable: PropTypes.bool,
|
|
||||||
});
|
|
||||||
|
|
||||||
const notFoundServerType = PropTypes.shape({
|
|
||||||
serverNotFound: PropTypes.bool.isRequired,
|
|
||||||
});
|
|
||||||
|
|
||||||
/** @deprecated Use SelectedServer type instead */
|
|
||||||
export const serverType = PropTypes.oneOfType([
|
|
||||||
regularServerType,
|
|
||||||
notFoundServerType,
|
|
||||||
]);
|
|
|
@ -1,84 +0,0 @@
|
||||||
import { Card, CardHeader, CardBody, Button, Collapse } from 'reactstrap';
|
|
||||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
|
||||||
import { faTrash as deleteIcon, faPencilAlt as editIcon, faLink, faEye } from '@fortawesome/free-solid-svg-icons';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import React from 'react';
|
|
||||||
import { Link } from 'react-router-dom';
|
|
||||||
import { serverType } from '../servers/prop-types';
|
|
||||||
import { prettify } from '../utils/helpers/numbers';
|
|
||||||
import { useToggle } from '../utils/helpers/hooks';
|
|
||||||
import TagBullet from './helpers/TagBullet';
|
|
||||||
import './TagCard.scss';
|
|
||||||
|
|
||||||
const propTypes = {
|
|
||||||
tag: PropTypes.string,
|
|
||||||
tagStats: PropTypes.shape({
|
|
||||||
shortUrlsCount: PropTypes.number,
|
|
||||||
visitsCount: PropTypes.number,
|
|
||||||
}),
|
|
||||||
selectedServer: serverType,
|
|
||||||
displayed: PropTypes.bool,
|
|
||||||
toggle: PropTypes.func,
|
|
||||||
};
|
|
||||||
|
|
||||||
const TagCard = (DeleteTagConfirmModal, EditTagModal, ForServerVersion, colorGenerator) => {
|
|
||||||
const TagCardComp = ({ tag, tagStats, selectedServer, displayed, toggle }) => {
|
|
||||||
const [ isDeleteModalOpen, toggleDelete ] = useToggle();
|
|
||||||
const [ isEditModalOpen, toggleEdit ] = useToggle();
|
|
||||||
|
|
||||||
const { id } = selectedServer;
|
|
||||||
const shortUrlsLink = `/server/${id}/list-short-urls/1?tag=${tag}`;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Card className="tag-card">
|
|
||||||
<CardHeader className="tag-card__header">
|
|
||||||
<Button color="light" size="sm" className="tag-card__btn tag-card__btn--last" onClick={toggleDelete}>
|
|
||||||
<FontAwesomeIcon icon={deleteIcon} />
|
|
||||||
</Button>
|
|
||||||
<Button color="light" size="sm" className="tag-card__btn" onClick={toggleEdit}>
|
|
||||||
<FontAwesomeIcon icon={editIcon} />
|
|
||||||
</Button>
|
|
||||||
<h5 className="tag-card__tag-title text-ellipsis">
|
|
||||||
<TagBullet tag={tag} colorGenerator={colorGenerator} />
|
|
||||||
<ForServerVersion minVersion="2.2.0">
|
|
||||||
<span className="tag-card__tag-name" onClick={toggle}>{tag}</span>
|
|
||||||
</ForServerVersion>
|
|
||||||
<ForServerVersion maxVersion="2.1.*">
|
|
||||||
<Link to={shortUrlsLink}>{tag}</Link>
|
|
||||||
</ForServerVersion>
|
|
||||||
</h5>
|
|
||||||
</CardHeader>
|
|
||||||
|
|
||||||
{tagStats && (
|
|
||||||
<Collapse isOpen={displayed}>
|
|
||||||
<CardBody className="tag-card__body">
|
|
||||||
<Link
|
|
||||||
to={shortUrlsLink}
|
|
||||||
className="btn btn-light btn-block d-flex justify-content-between align-items-center mb-1"
|
|
||||||
>
|
|
||||||
<span className="text-ellipsis"><FontAwesomeIcon icon={faLink} className="mr-2" />Short URLs</span>
|
|
||||||
<b>{prettify(tagStats.shortUrlsCount)}</b>
|
|
||||||
</Link>
|
|
||||||
<Link
|
|
||||||
to={`/server/${id}/tag/${tag}/visits`}
|
|
||||||
className="btn btn-light btn-block d-flex justify-content-between align-items-center"
|
|
||||||
>
|
|
||||||
<span className="text-ellipsis"><FontAwesomeIcon icon={faEye} className="mr-2" />Visits</span>
|
|
||||||
<b>{prettify(tagStats.visitsCount)}</b>
|
|
||||||
</Link>
|
|
||||||
</CardBody>
|
|
||||||
</Collapse>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<DeleteTagConfirmModal tag={tag} toggle={toggleDelete} isOpen={isDeleteModalOpen} />
|
|
||||||
<EditTagModal tag={tag} toggle={toggleEdit} isOpen={isEditModalOpen} />
|
|
||||||
</Card>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
TagCardComp.propTypes = propTypes;
|
|
||||||
|
|
||||||
return TagCardComp;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default TagCard;
|
|
82
src/tags/TagCard.tsx
Normal file
82
src/tags/TagCard.tsx
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
import { Card, CardHeader, CardBody, Button, Collapse } from 'reactstrap';
|
||||||
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
|
import { faTrash as deleteIcon, faPencilAlt as editIcon, faLink, faEye } from '@fortawesome/free-solid-svg-icons';
|
||||||
|
import React, { FC } from 'react';
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
|
import { prettify } from '../utils/helpers/numbers';
|
||||||
|
import { useToggle } from '../utils/helpers/hooks';
|
||||||
|
import { Versions } from '../utils/helpers/version';
|
||||||
|
import ColorGenerator from '../utils/services/ColorGenerator';
|
||||||
|
import { isServerWithId, SelectedServer } from '../servers/data';
|
||||||
|
import TagBullet from './helpers/TagBullet';
|
||||||
|
import { TagModalProps, TagStats } from './data';
|
||||||
|
import './TagCard.scss';
|
||||||
|
|
||||||
|
export interface TagCardProps {
|
||||||
|
tag: string;
|
||||||
|
tagStats?: TagStats;
|
||||||
|
selectedServer: SelectedServer;
|
||||||
|
displayed: boolean;
|
||||||
|
toggle: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const TagCard = (
|
||||||
|
DeleteTagConfirmModal: FC<TagModalProps>,
|
||||||
|
EditTagModal: FC<TagModalProps>,
|
||||||
|
ForServerVersion: FC<Versions>,
|
||||||
|
colorGenerator: ColorGenerator,
|
||||||
|
) => ({ tag, tagStats, selectedServer, displayed, toggle }: TagCardProps) => {
|
||||||
|
const [ isDeleteModalOpen, toggleDelete ] = useToggle();
|
||||||
|
const [ isEditModalOpen, toggleEdit ] = useToggle();
|
||||||
|
|
||||||
|
const serverId = isServerWithId(selectedServer) ? selectedServer.id : '';
|
||||||
|
const shortUrlsLink = `/server/${serverId}/list-short-urls/1?tag=${tag}`;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Card className="tag-card">
|
||||||
|
<CardHeader className="tag-card__header">
|
||||||
|
<Button color="light" size="sm" className="tag-card__btn tag-card__btn--last" onClick={toggleDelete}>
|
||||||
|
<FontAwesomeIcon icon={deleteIcon} />
|
||||||
|
</Button>
|
||||||
|
<Button color="light" size="sm" className="tag-card__btn" onClick={toggleEdit}>
|
||||||
|
<FontAwesomeIcon icon={editIcon} />
|
||||||
|
</Button>
|
||||||
|
<h5 className="tag-card__tag-title text-ellipsis">
|
||||||
|
<TagBullet tag={tag} colorGenerator={colorGenerator} />
|
||||||
|
<ForServerVersion minVersion="2.2.0">
|
||||||
|
<span className="tag-card__tag-name" onClick={toggle}>{tag}</span>
|
||||||
|
</ForServerVersion>
|
||||||
|
<ForServerVersion maxVersion="2.1.*">
|
||||||
|
<Link to={shortUrlsLink}>{tag}</Link>
|
||||||
|
</ForServerVersion>
|
||||||
|
</h5>
|
||||||
|
</CardHeader>
|
||||||
|
|
||||||
|
{tagStats && (
|
||||||
|
<Collapse isOpen={displayed}>
|
||||||
|
<CardBody className="tag-card__body">
|
||||||
|
<Link
|
||||||
|
to={shortUrlsLink}
|
||||||
|
className="btn btn-light btn-block d-flex justify-content-between align-items-center mb-1"
|
||||||
|
>
|
||||||
|
<span className="text-ellipsis"><FontAwesomeIcon icon={faLink} className="mr-2" />Short URLs</span>
|
||||||
|
<b>{prettify(tagStats.shortUrlsCount)}</b>
|
||||||
|
</Link>
|
||||||
|
<Link
|
||||||
|
to={`/server/${serverId}/tag/${tag}/visits`}
|
||||||
|
className="btn btn-light btn-block d-flex justify-content-between align-items-center"
|
||||||
|
>
|
||||||
|
<span className="text-ellipsis"><FontAwesomeIcon icon={faEye} className="mr-2" />Visits</span>
|
||||||
|
<b>{prettify(tagStats.visitsCount)}</b>
|
||||||
|
</Link>
|
||||||
|
</CardBody>
|
||||||
|
</Collapse>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<DeleteTagConfirmModal tag={tag} toggle={toggleDelete} isOpen={isDeleteModalOpen} />
|
||||||
|
<EditTagModal tag={tag} toggle={toggleEdit} isOpen={isEditModalOpen} />
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default TagCard;
|
|
@ -1,91 +0,0 @@
|
||||||
import React, { useEffect, useState } from 'react';
|
|
||||||
import { splitEvery } from 'ramda';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import Message from '../utils/Message';
|
|
||||||
import SearchField from '../utils/SearchField';
|
|
||||||
import { serverType } from '../servers/prop-types';
|
|
||||||
import { MercureInfoType } from '../mercure/reducers/mercureInfo';
|
|
||||||
import { useMercureTopicBinding } from '../mercure/helpers';
|
|
||||||
import { TagsListType } from './reducers/tagsList';
|
|
||||||
|
|
||||||
const { ceil } = Math;
|
|
||||||
const TAGS_GROUPS_AMOUNT = 4;
|
|
||||||
|
|
||||||
const propTypes = {
|
|
||||||
filterTags: PropTypes.func,
|
|
||||||
forceListTags: PropTypes.func,
|
|
||||||
tagsList: TagsListType,
|
|
||||||
selectedServer: serverType,
|
|
||||||
createNewVisit: PropTypes.func,
|
|
||||||
loadMercureInfo: PropTypes.func,
|
|
||||||
mercureInfo: MercureInfoType,
|
|
||||||
};
|
|
||||||
|
|
||||||
const TagsList = (TagCard) => {
|
|
||||||
const TagListComp = (
|
|
||||||
{ filterTags, forceListTags, tagsList, selectedServer, createNewVisit, loadMercureInfo, mercureInfo },
|
|
||||||
) => {
|
|
||||||
const [ displayedTag, setDisplayedTag ] = useState();
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
forceListTags();
|
|
||||||
}, []);
|
|
||||||
useMercureTopicBinding(mercureInfo, 'https://shlink.io/new-visit', createNewVisit, loadMercureInfo);
|
|
||||||
|
|
||||||
const renderContent = () => {
|
|
||||||
if (tagsList.loading) {
|
|
||||||
return <Message noMargin loading />;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tagsList.error) {
|
|
||||||
return (
|
|
||||||
<div className="col-12">
|
|
||||||
<div className="bg-danger p-2 text-white text-center">Error loading tags :(</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const tagsCount = tagsList.filteredTags.length;
|
|
||||||
|
|
||||||
if (tagsCount < 1) {
|
|
||||||
return <Message>No tags found</Message>;
|
|
||||||
}
|
|
||||||
|
|
||||||
const tagsGroups = splitEvery(ceil(tagsCount / TAGS_GROUPS_AMOUNT), tagsList.filteredTags);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<React.Fragment>
|
|
||||||
{tagsGroups.map((group, index) => (
|
|
||||||
<div key={index} className="col-md-6 col-xl-3">
|
|
||||||
{group.map((tag) => (
|
|
||||||
<TagCard
|
|
||||||
key={tag}
|
|
||||||
tag={tag}
|
|
||||||
tagStats={tagsList.stats[tag]}
|
|
||||||
selectedServer={selectedServer}
|
|
||||||
displayed={displayedTag === tag}
|
|
||||||
toggle={() => setDisplayedTag(displayedTag !== tag ? tag : undefined)}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</React.Fragment>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<React.Fragment>
|
|
||||||
{!tagsList.loading && <SearchField className="mb-3" placeholder="Search tags..." onChange={filterTags} />}
|
|
||||||
<div className="row">
|
|
||||||
{renderContent()}
|
|
||||||
</div>
|
|
||||||
</React.Fragment>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
TagListComp.propTypes = propTypes;
|
|
||||||
|
|
||||||
return TagListComp;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default TagsList;
|
|
85
src/tags/TagsList.tsx
Normal file
85
src/tags/TagsList.tsx
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
import React, { FC, useEffect, useState } from 'react';
|
||||||
|
import { splitEvery } from 'ramda';
|
||||||
|
import Message from '../utils/Message';
|
||||||
|
import SearchField from '../utils/SearchField';
|
||||||
|
import { MercureInfo } from '../mercure/reducers/mercureInfo';
|
||||||
|
import { useMercureTopicBinding } from '../mercure/helpers';
|
||||||
|
import { SelectedServer } from '../servers/data';
|
||||||
|
import { TagsList as TagsListState } from './reducers/tagsList';
|
||||||
|
import { TagCardProps } from './TagCard';
|
||||||
|
|
||||||
|
const { ceil } = Math;
|
||||||
|
const TAGS_GROUPS_AMOUNT = 4;
|
||||||
|
|
||||||
|
export interface TagsListProps {
|
||||||
|
filterTags: (searchTerm: string) => void;
|
||||||
|
forceListTags: Function;
|
||||||
|
tagsList: TagsListState;
|
||||||
|
selectedServer: SelectedServer;
|
||||||
|
createNewVisit: () => void;
|
||||||
|
loadMercureInfo: Function;
|
||||||
|
mercureInfo: MercureInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
const TagsList = (TagCard: FC<TagCardProps>) => (
|
||||||
|
{ filterTags, forceListTags, tagsList, selectedServer, createNewVisit, loadMercureInfo, mercureInfo }: TagsListProps,
|
||||||
|
) => {
|
||||||
|
const [ displayedTag, setDisplayedTag ] = useState<string | undefined>();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
forceListTags();
|
||||||
|
}, []);
|
||||||
|
useMercureTopicBinding(mercureInfo, 'https://shlink.io/new-visit', createNewVisit, loadMercureInfo);
|
||||||
|
|
||||||
|
const renderContent = () => {
|
||||||
|
if (tagsList.loading) {
|
||||||
|
return <Message noMargin loading />;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tagsList.error) {
|
||||||
|
return (
|
||||||
|
<div className="col-12">
|
||||||
|
<div className="bg-danger p-2 text-white text-center">Error loading tags :(</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const tagsCount = tagsList.filteredTags.length;
|
||||||
|
|
||||||
|
if (tagsCount < 1) {
|
||||||
|
return <Message>No tags found</Message>;
|
||||||
|
}
|
||||||
|
|
||||||
|
const tagsGroups = splitEvery(ceil(tagsCount / TAGS_GROUPS_AMOUNT), tagsList.filteredTags);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<React.Fragment>
|
||||||
|
{tagsGroups.map((group, index) => (
|
||||||
|
<div key={index} className="col-md-6 col-xl-3">
|
||||||
|
{group.map((tag) => (
|
||||||
|
<TagCard
|
||||||
|
key={tag}
|
||||||
|
tag={tag}
|
||||||
|
tagStats={tagsList.stats[tag]}
|
||||||
|
selectedServer={selectedServer}
|
||||||
|
displayed={displayedTag === tag}
|
||||||
|
toggle={() => setDisplayedTag(displayedTag !== tag ? tag : undefined)}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<React.Fragment>
|
||||||
|
{!tagsList.loading && <SearchField className="mb-3" placeholder="Search tags..." onChange={filterTags} />}
|
||||||
|
<div className="row">
|
||||||
|
{renderContent()}
|
||||||
|
</div>
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default TagsList;
|
|
@ -1,5 +1,4 @@
|
||||||
import { isEmpty, reject } from 'ramda';
|
import { isEmpty, reject } from 'ramda';
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import { Action, Dispatch } from 'redux';
|
import { Action, Dispatch } from 'redux';
|
||||||
import { CREATE_VISIT, CreateVisitAction } from '../../visits/reducers/visitCreation';
|
import { CREATE_VISIT, CreateVisitAction } from '../../visits/reducers/visitCreation';
|
||||||
import { buildReducer } from '../../utils/helpers/redux';
|
import { buildReducer } from '../../utils/helpers/redux';
|
||||||
|
@ -17,18 +16,6 @@ export const LIST_TAGS = 'shlink/tagsList/LIST_TAGS';
|
||||||
export const FILTER_TAGS = 'shlink/tagsList/FILTER_TAGS';
|
export const FILTER_TAGS = 'shlink/tagsList/FILTER_TAGS';
|
||||||
/* eslint-enable padding-line-between-statements */
|
/* eslint-enable padding-line-between-statements */
|
||||||
|
|
||||||
/** @deprecated Use TagsList interface instead */
|
|
||||||
export const TagsListType = PropTypes.shape({
|
|
||||||
tags: PropTypes.arrayOf(PropTypes.string),
|
|
||||||
filteredTags: PropTypes.arrayOf(PropTypes.string),
|
|
||||||
stats: PropTypes.objectOf(PropTypes.shape({
|
|
||||||
shortUrlsCount: PropTypes.number,
|
|
||||||
visitsCount: PropTypes.number,
|
|
||||||
})), // Record
|
|
||||||
loading: PropTypes.bool,
|
|
||||||
error: PropTypes.bool,
|
|
||||||
});
|
|
||||||
|
|
||||||
type TagsStatsMap = Record<string, TagStats>;
|
type TagsStatsMap = Record<string, TagStats>;
|
||||||
|
|
||||||
export interface TagsList {
|
export interface TagsList {
|
||||||
|
|
|
@ -1,11 +1,14 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { shallow } from 'enzyme';
|
import { shallow, ShallowWrapper } from 'enzyme';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
|
import { Mock } from 'ts-mockery';
|
||||||
import createTagCard from '../../src/tags/TagCard';
|
import createTagCard from '../../src/tags/TagCard';
|
||||||
import TagBullet from '../../src/tags/helpers/TagBullet';
|
import TagBullet from '../../src/tags/helpers/TagBullet';
|
||||||
|
import ColorGenerator from '../../src/utils/services/ColorGenerator';
|
||||||
|
import { ReachableServer } from '../../src/servers/data';
|
||||||
|
|
||||||
describe('<TagCard />', () => {
|
describe('<TagCard />', () => {
|
||||||
let wrapper;
|
let wrapper: ShallowWrapper;
|
||||||
const tagStats = {
|
const tagStats = {
|
||||||
shortUrlsCount: 48,
|
shortUrlsCount: 48,
|
||||||
visitsCount: 23257,
|
visitsCount: 23257,
|
||||||
|
@ -14,9 +17,17 @@ describe('<TagCard />', () => {
|
||||||
const EditTagModal = jest.fn();
|
const EditTagModal = jest.fn();
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
const TagCard = createTagCard(DeleteTagConfirmModal, EditTagModal, () => '', {});
|
const TagCard = createTagCard(DeleteTagConfirmModal, EditTagModal, () => null, Mock.all<ColorGenerator>());
|
||||||
|
|
||||||
wrapper = shallow(<TagCard tag="ssr" selectedServer={{ id: 1, serverNotFound: false }} tagStats={tagStats} />);
|
wrapper = shallow(
|
||||||
|
<TagCard
|
||||||
|
tag="ssr"
|
||||||
|
selectedServer={Mock.of<ReachableServer>({ id: '1' })}
|
||||||
|
tagStats={tagStats}
|
||||||
|
displayed={true}
|
||||||
|
toggle={() => {}}
|
||||||
|
/>,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => wrapper.unmount());
|
afterEach(() => wrapper.unmount());
|
|
@ -1,30 +1,34 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { shallow } from 'enzyme';
|
import { shallow, ShallowWrapper } from 'enzyme';
|
||||||
import { identity } from 'ramda';
|
import { identity } from 'ramda';
|
||||||
import createTagsList from '../../src/tags/TagsList';
|
import { Mock } from 'ts-mockery';
|
||||||
|
import createTagsList, { TagsListProps } from '../../src/tags/TagsList';
|
||||||
import Message from '../../src/utils/Message';
|
import Message from '../../src/utils/Message';
|
||||||
import SearchField from '../../src/utils/SearchField';
|
import SearchField from '../../src/utils/SearchField';
|
||||||
import { rangeOf } from '../../src/utils/utils';
|
import { rangeOf } from '../../src/utils/utils';
|
||||||
|
import { TagsList } from '../../src/tags/reducers/tagsList';
|
||||||
|
|
||||||
describe('<TagsList />', () => {
|
describe('<TagsList />', () => {
|
||||||
let wrapper;
|
let wrapper: ShallowWrapper;
|
||||||
const filterTags = jest.fn();
|
const filterTags = jest.fn();
|
||||||
const TagCard = () => '';
|
const TagCard = () => null;
|
||||||
const createWrapper = (tagsList) => {
|
const createWrapper = (tagsList: Partial<TagsList>) => {
|
||||||
const params = { serverId: '1' };
|
const TagsListComp = createTagsList(TagCard);
|
||||||
const TagsList = createTagsList(TagCard);
|
|
||||||
|
|
||||||
wrapper = shallow(
|
wrapper = shallow(
|
||||||
<TagsList forceListTags={identity} filterTags={filterTags} match={{ params }} tagsList={tagsList} />,
|
<TagsListComp
|
||||||
|
{...Mock.all<TagsListProps>()}
|
||||||
|
forceListTags={identity}
|
||||||
|
filterTags={filterTags}
|
||||||
|
tagsList={Mock.of<TagsList>(tagsList)}
|
||||||
|
/>,
|
||||||
);
|
);
|
||||||
|
|
||||||
return wrapper;
|
return wrapper;
|
||||||
};
|
};
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => wrapper?.unmount());
|
||||||
wrapper && wrapper.unmount();
|
afterEach(jest.clearAllMocks);
|
||||||
filterTags.mockReset();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('shows a loading message when tags are being loaded', () => {
|
it('shows a loading message when tags are being loaded', () => {
|
||||||
const wrapper = createWrapper({ loading: true });
|
const wrapper = createWrapper({ loading: true });
|
Loading…
Reference in a new issue