Fixed all tests to work with new tags sorting approach

This commit is contained in:
Alejandro Celaya 2021-11-06 11:30:42 +01:00
parent e6737ff1f2
commit 765c4713a2
5 changed files with 37 additions and 47 deletions

View File

@ -1,4 +1,4 @@
import { FC, useEffect, useMemo, useState } from 'react'; import { FC, useEffect, useState } from 'react';
import { Row } from 'reactstrap'; import { Row } from 'reactstrap';
import { pipe } from 'ramda'; import { pipe } from 'ramda';
import Message from '../utils/Message'; import Message from '../utils/Message';
@ -30,16 +30,13 @@ const TagsList = (TagsCards: FC<TagsListChildrenProps>, TagsTable: FC<TagsTableP
) => { ) => {
const [ mode, setMode ] = useState<TagsMode>(settings.ui?.tagsMode ?? 'cards'); const [ mode, setMode ] = useState<TagsMode>(settings.ui?.tagsMode ?? 'cards');
const [ order, setOrder ] = useState<TagsOrder>({}); const [ order, setOrder ] = useState<TagsOrder>({});
const sortedTags = useMemo( const resolveSortedTags = pipe(
pipe( () => tagsList.filteredTags.map((tag): NormalizedTag => ({
() => tagsList.filteredTags.map((tag): NormalizedTag => ({ tag,
tag, shortUrls: tagsList.stats[tag]?.shortUrlsCount ?? 0,
shortUrls: tagsList.stats[tag]?.shortUrlsCount ?? 0, visits: tagsList.stats[tag]?.visitsCount ?? 0,
visits: tagsList.stats[tag]?.visitsCount ?? 0, })),
})), (normalizedTags) => sortList<NormalizedTag>(normalizedTags, order),
(normalizedTags) => sortList<NormalizedTag>(normalizedTags, order),
),
[ tagsList.filteredTags, order ],
); );
useEffect(() => { useEffect(() => {
@ -50,22 +47,24 @@ const TagsList = (TagsCards: FC<TagsListChildrenProps>, TagsTable: FC<TagsTableP
return <Message loading />; return <Message loading />;
} }
if (tagsList.error) {
return (
<Result type="error">
<ShlinkApiError errorData={tagsList.errorData} fallbackMessage="Error loading tags :(" />
</Result>
);
}
const orderByColumn = (field: OrderableFields) => const orderByColumn = (field: OrderableFields) =>
() => setOrder({ field, dir: determineOrderDir(field, order.field, order.dir) }); () => setOrder({ field, dir: determineOrderDir(field, order.field, order.dir) });
const renderContent = () => { const renderContent = () => {
if (tagsList.error) {
return (
<Result type="error">
<ShlinkApiError errorData={tagsList.errorData} fallbackMessage="Error loading tags :(" />
</Result>
);
}
if (tagsList.filteredTags.length < 1) { if (tagsList.filteredTags.length < 1) {
return <Message>No tags found</Message>; return <Message>No tags found</Message>;
} }
const sortedTags = resolveSortedTags();
return mode === 'cards' return mode === 'cards'
? <TagsCards sortedTags={sortedTags} selectedServer={selectedServer} /> ? <TagsCards sortedTags={sortedTags} selectedServer={selectedServer} />
: ( : (

View File

@ -8,19 +8,14 @@ import { ReachableServer } from '../../src/servers/data';
describe('<TagCard />', () => { describe('<TagCard />', () => {
let wrapper: ShallowWrapper; let wrapper: ShallowWrapper;
const tagStats = {
shortUrlsCount: 48,
visitsCount: 23257,
};
const DeleteTagConfirmModal = jest.fn(); const DeleteTagConfirmModal = jest.fn();
const EditTagModal = jest.fn(); const EditTagModal = jest.fn();
const TagCard = createTagCard(DeleteTagConfirmModal, EditTagModal, Mock.all<ColorGenerator>()); const TagCard = createTagCard(DeleteTagConfirmModal, EditTagModal, Mock.all<ColorGenerator>());
const createWrapper = (tag = 'ssr') => { const createWrapper = (tag = 'ssr') => {
wrapper = shallow( wrapper = shallow(
<TagCard <TagCard
tag={tag} tag={{ tag, visits: 23257, shortUrls: 48 }}
selectedServer={Mock.of<ReachableServer>({ id: '1' })} selectedServer={Mock.of<ReachableServer>({ id: '1' })}
tagStats={tagStats}
displayed={true} displayed={true}
toggle={() => {}} toggle={() => {}}
/>, />,

View File

@ -1,19 +1,19 @@
import { shallow, ShallowWrapper } from 'enzyme'; import { shallow, ShallowWrapper } from 'enzyme';
import { Mock } from 'ts-mockery'; import { Mock } from 'ts-mockery';
import { TagsCards as createTagsCards } from '../../src/tags/TagsCards'; import { TagsCards as createTagsCards } from '../../src/tags/TagsCards';
import { TagsList } from '../../src/tags/reducers/tagsList';
import { SelectedServer } from '../../src/servers/data'; import { SelectedServer } from '../../src/servers/data';
import { rangeOf } from '../../src/utils/utils'; import { rangeOf } from '../../src/utils/utils';
import { NormalizedTag } from '../../src/tags/data';
describe('<TagsCards />', () => { describe('<TagsCards />', () => {
const amountOfTags = 10; const amountOfTags = 10;
const tagsList = Mock.of<TagsList>({ filteredTags: rangeOf(amountOfTags, (i) => `tag_${i}`), stats: {} }); const sortedTags = rangeOf(amountOfTags, (i) => Mock.of<NormalizedTag>({ tag: `tag_${i}` }));
const TagCard = () => null; const TagCard = () => null;
const TagsCards = createTagsCards(TagCard); const TagsCards = createTagsCards(TagCard);
let wrapper: ShallowWrapper; let wrapper: ShallowWrapper;
beforeEach(() => { beforeEach(() => {
wrapper = shallow(<TagsCards tagsList={tagsList} selectedServer={Mock.all<SelectedServer>()} />); wrapper = shallow(<TagsCards sortedTags={sortedTags} selectedServer={Mock.all<SelectedServer>()} />);
}); });
afterEach(() => wrapper?.unmount()); afterEach(() => wrapper?.unmount());

View File

@ -37,17 +37,21 @@ describe('<TagsList />', () => {
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 });
const loadingMsg = wrapper.find(Message); const loadingMsg = wrapper.find(Message);
const searchField = wrapper.find(SearchField);
expect(loadingMsg).toHaveLength(1); expect(loadingMsg).toHaveLength(1);
expect(loadingMsg.html()).toContain('Loading...'); expect(loadingMsg.html()).toContain('Loading...');
expect(searchField).toHaveLength(0);
}); });
it('shows an error when tags failed to be loaded', () => { it('shows an error when tags failed to be loaded', () => {
const wrapper = createWrapper({ error: true }); const wrapper = createWrapper({ error: true });
const errorMsg = wrapper.find(Result).filterWhere((result) => result.prop('type') === 'error'); const errorMsg = wrapper.find(Result).filterWhere((result) => result.prop('type') === 'error');
const searchField = wrapper.find(SearchField);
expect(errorMsg).toHaveLength(1); expect(errorMsg).toHaveLength(1);
expect(errorMsg.html()).toContain('Error loading tags :('); expect(errorMsg.html()).toContain('Error loading tags :(');
expect(searchField).toHaveLength(0);
}); });
it('shows a message when the list of tags is empty', () => { it('shows a message when the list of tags is empty', () => {

View File

@ -4,24 +4,26 @@ import { match } from 'react-router';
import { Location, History } from 'history'; import { Location, History } from 'history';
import { TagsTable as createTagsTable } from '../../src/tags/TagsTable'; import { TagsTable as createTagsTable } from '../../src/tags/TagsTable';
import { SelectedServer } from '../../src/servers/data'; import { SelectedServer } from '../../src/servers/data';
import { TagsList } from '../../src/tags/reducers/tagsList';
import { rangeOf } from '../../src/utils/utils'; import { rangeOf } from '../../src/utils/utils';
import SimplePaginator from '../../src/common/SimplePaginator'; import SimplePaginator from '../../src/common/SimplePaginator';
import { NormalizedTag } from '../../src/tags/data'; import { NormalizedTag } from '../../src/tags/data';
describe('<TagsTable />', () => { describe('<TagsTable />', () => {
const TagsTableRow = () => null; const TagsTableRow = () => null;
const orderByColumn = jest.fn();
const TagsTable = createTagsTable(TagsTableRow); const TagsTable = createTagsTable(TagsTableRow);
const tags = (amount: number) => rangeOf(amount, (i) => `tag_${i}`); const tags = (amount: number) => rangeOf(amount, (i) => `tag_${i}`);
let wrapper: ShallowWrapper; let wrapper: ShallowWrapper;
const createWrapper = (filteredTags: string[] = [], search = '') => { const createWrapper = (sortedTags: string[] = [], search = '') => {
wrapper = shallow( wrapper = shallow(
<TagsTable <TagsTable
tagsList={Mock.of<TagsList>({ stats: {}, filteredTags })} sortedTags={sortedTags.map((tag) => Mock.of<NormalizedTag>({ tag }))}
selectedServer={Mock.all<SelectedServer>()} selectedServer={Mock.all<SelectedServer>()}
currentOrder={{}}
history={Mock.all<History>()} history={Mock.all<History>()}
location={Mock.of<Location>({ search })} location={Mock.of<Location>({ search })}
match={Mock.all<match>()} match={Mock.all<match>()}
orderByColumn={() => orderByColumn}
/>, />,
); );
@ -33,6 +35,7 @@ describe('<TagsTable />', () => {
(global as any).history = { pushState: jest.fn() }; (global as any).history = { pushState: jest.fn() };
}); });
afterEach(jest.clearAllMocks);
afterEach(() => wrapper?.unmount()); afterEach(() => wrapper?.unmount());
it('renders empty result if there are no tags', () => { it('renders empty result if there are no tags', () => {
@ -99,22 +102,11 @@ describe('<TagsTable />', () => {
it('orders tags when column is clicked', () => { it('orders tags when column is clicked', () => {
const wrapper = createWrapper(tags(100)); const wrapper = createWrapper(tags(100));
const firstRowText = () => (wrapper.find('tbody').find(TagsTableRow).first().prop('tag') as NormalizedTag).tag;
expect(firstRowText()).toEqual('tag_1'); expect(orderByColumn).not.toHaveBeenCalled();
wrapper.find('thead').find('th').first().simulate('click'); // Tag column ASC wrapper.find('thead').find('th').first().simulate('click');
expect(firstRowText()).toEqual('tag_1'); wrapper.find('thead').find('th').at(2).simulate('click');
wrapper.find('thead').find('th').first().simulate('click'); // Tag column DESC wrapper.find('thead').find('th').at(1).simulate('click');
expect(firstRowText()).toEqual('tag_99'); expect(orderByColumn).toHaveBeenCalledTimes(3);
wrapper.find('thead').find('th').at(2).simulate('click'); // Visits column - ASC
expect(firstRowText()).toEqual('tag_100');
wrapper.find('thead').find('th').at(2).simulate('click'); // Visits column - DESC
expect(firstRowText()).toEqual('tag_1');
wrapper.find('thead').find('th').at(2).simulate('click'); // Visits column - reset
expect(firstRowText()).toEqual('tag_1');
wrapper.find('thead').find('th').at(1).simulate('click'); // Short URLs column - ASC
expect(firstRowText()).toEqual('tag_100');
wrapper.find('thead').find('th').at(1).simulate('click'); // Short URLs column - DESC
expect(firstRowText()).toEqual('tag_1');
}); });
}); });