mirror of
https://github.com/shlinkio/shlink-web-client.git
synced 2025-01-09 17:57:26 +03:00
Migrated TagsList to react testing library
This commit is contained in:
parent
744cea1f11
commit
27a05e55c9
3 changed files with 33 additions and 80 deletions
|
@ -30,7 +30,7 @@ export interface TagsListProps {
|
||||||
settings: Settings;
|
settings: Settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
const TagsList = (TagsCards: FC<TagsListChildrenProps>, TagsTable: FC<TagsTableProps>) => boundToMercureHub((
|
export const TagsList = (TagsCards: FC<TagsListChildrenProps>, TagsTable: FC<TagsTableProps>) => boundToMercureHub((
|
||||||
{ filterTags, forceListTags, tagsList, selectedServer, settings }: TagsListProps,
|
{ filterTags, forceListTags, tagsList, selectedServer, settings }: TagsListProps,
|
||||||
) => {
|
) => {
|
||||||
const [mode, setMode] = useState<TagsMode>(settings.tags?.defaultMode ?? 'cards');
|
const [mode, setMode] = useState<TagsMode>(settings.tags?.defaultMode ?? 'cards');
|
||||||
|
@ -104,5 +104,3 @@ const TagsList = (TagsCards: FC<TagsListChildrenProps>, TagsTable: FC<TagsTableP
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}, () => [Topics.visits]);
|
}, () => [Topics.visits]);
|
||||||
|
|
||||||
export default TagsList;
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ import TagsSelector from '../helpers/TagsSelector';
|
||||||
import TagCard from '../TagCard';
|
import TagCard from '../TagCard';
|
||||||
import DeleteTagConfirmModal from '../helpers/DeleteTagConfirmModal';
|
import DeleteTagConfirmModal from '../helpers/DeleteTagConfirmModal';
|
||||||
import EditTagModal from '../helpers/EditTagModal';
|
import EditTagModal from '../helpers/EditTagModal';
|
||||||
import TagsList from '../TagsList';
|
import { TagsList } from '../TagsList';
|
||||||
import { filterTags, listTags } from '../reducers/tagsList';
|
import { filterTags, listTags } from '../reducers/tagsList';
|
||||||
import { deleteTag, tagDeleted } from '../reducers/tagDelete';
|
import { deleteTag, tagDeleted } from '../reducers/tagDelete';
|
||||||
import { editTag, tagEdited } from '../reducers/tagEdit';
|
import { editTag, tagEdited } from '../reducers/tagEdit';
|
||||||
|
|
|
@ -1,25 +1,18 @@
|
||||||
import { shallow, ShallowWrapper } from 'enzyme';
|
import { render, screen, waitFor } from '@testing-library/react';
|
||||||
|
import userEvent from '@testing-library/user-event';
|
||||||
import { identity } from 'ramda';
|
import { identity } from 'ramda';
|
||||||
import { Mock } from 'ts-mockery';
|
import { Mock } from 'ts-mockery';
|
||||||
import createTagsList, { TagsListProps } from '../../src/tags/TagsList';
|
import { TagsList as createTagsList, TagsListProps } from '../../src/tags/TagsList';
|
||||||
import Message from '../../src/utils/Message';
|
|
||||||
import { TagsList } from '../../src/tags/reducers/tagsList';
|
import { TagsList } from '../../src/tags/reducers/tagsList';
|
||||||
import { MercureBoundProps } from '../../src/mercure/helpers/boundToMercureHub';
|
import { MercureBoundProps } from '../../src/mercure/helpers/boundToMercureHub';
|
||||||
import { Result } from '../../src/utils/Result';
|
|
||||||
import { TagsModeDropdown } from '../../src/tags/TagsModeDropdown';
|
|
||||||
import { SearchField } from '../../src/utils/SearchField';
|
|
||||||
import { Settings } from '../../src/settings/reducers/settings';
|
import { Settings } from '../../src/settings/reducers/settings';
|
||||||
import { TagsOrderableFields } from '../../src/tags/data/TagsListChildrenProps';
|
|
||||||
import { OrderingDropdown } from '../../src/utils/OrderingDropdown';
|
|
||||||
|
|
||||||
describe('<TagsList />', () => {
|
describe('<TagsList />', () => {
|
||||||
let wrapper: ShallowWrapper;
|
|
||||||
const filterTags = jest.fn();
|
const filterTags = jest.fn();
|
||||||
const TagsCards = () => null;
|
const TagsListComp = createTagsList(() => <>TagsCards</>, () => <>TagsTable</>);
|
||||||
const TagsTable = () => null;
|
const setUp = (tagsList: Partial<TagsList>) => ({
|
||||||
const TagsListComp = createTagsList(TagsCards, TagsTable);
|
user: userEvent.setup(),
|
||||||
const createWrapper = (tagsList: Partial<TagsList>) => {
|
...render(
|
||||||
wrapper = shallow(
|
|
||||||
<TagsListComp
|
<TagsListComp
|
||||||
{...Mock.all<TagsListProps>()}
|
{...Mock.all<TagsListProps>()}
|
||||||
{...Mock.of<MercureBoundProps>({ mercureInfo: {} })}
|
{...Mock.of<MercureBoundProps>({ mercureInfo: {} })}
|
||||||
|
@ -28,89 +21,51 @@ describe('<TagsList />', () => {
|
||||||
tagsList={Mock.of<TagsList>(tagsList)}
|
tagsList={Mock.of<TagsList>(tagsList)}
|
||||||
settings={Mock.all<Settings>()}
|
settings={Mock.all<Settings>()}
|
||||||
/>,
|
/>,
|
||||||
).dive(); // Dive is needed as this component is wrapped in a HOC
|
),
|
||||||
|
});
|
||||||
|
|
||||||
return wrapper;
|
|
||||||
};
|
|
||||||
|
|
||||||
afterEach(() => wrapper?.unmount());
|
|
||||||
afterEach(jest.clearAllMocks);
|
afterEach(jest.clearAllMocks);
|
||||||
|
|
||||||
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 });
|
setUp({ loading: true });
|
||||||
const loadingMsg = wrapper.find(Message);
|
|
||||||
const searchField = wrapper.find(SearchField);
|
|
||||||
|
|
||||||
expect(loadingMsg).toHaveLength(1);
|
expect(screen.getByText('Loading...')).toBeInTheDocument();
|
||||||
expect(loadingMsg.html()).toContain('Loading...');
|
expect(screen.queryByText('Error loading tags :(')).not.toBeInTheDocument();
|
||||||
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 });
|
setUp({ error: true });
|
||||||
const errorMsg = wrapper.find(Result).filterWhere((result) => result.prop('type') === 'error');
|
|
||||||
const searchField = wrapper.find(SearchField);
|
|
||||||
|
|
||||||
expect(errorMsg).toHaveLength(1);
|
expect(screen.getByText('Error loading tags :(')).toBeInTheDocument();
|
||||||
expect(errorMsg.html()).toContain('Error loading tags :(');
|
expect(screen.queryByText('Loading')).not.toBeInTheDocument();
|
||||||
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', () => {
|
||||||
const wrapper = createWrapper({ filteredTags: [] });
|
setUp({ filteredTags: [] });
|
||||||
const msg = wrapper.find(Message);
|
|
||||||
|
|
||||||
expect(msg).toHaveLength(1);
|
expect(screen.getByText('No tags found')).toBeInTheDocument();
|
||||||
expect(msg.html()).toContain('No tags found');
|
expect(screen.queryByText('Error loading tags :(')).not.toBeInTheDocument();
|
||||||
|
expect(screen.queryByText('Loading')).not.toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('renders proper component based on the display mode', () => {
|
it('renders proper component based on the display mode', async () => {
|
||||||
const wrapper = createWrapper({ filteredTags: ['foo', 'bar'], stats: {} });
|
const { user } = setUp({ filteredTags: ['foo', 'bar'], stats: {} });
|
||||||
|
|
||||||
expect(wrapper.find(TagsCards)).toHaveLength(1);
|
expect(screen.getByText('TagsCards')).toBeInTheDocument();
|
||||||
expect(wrapper.find(TagsTable)).toHaveLength(0);
|
expect(screen.queryByText('TagsTable')).not.toBeInTheDocument();
|
||||||
|
|
||||||
wrapper.find(TagsModeDropdown).simulate('change');
|
await user.click(screen.getByRole('button', { name: /^Display mode/ }));
|
||||||
|
await user.click(screen.getByRole('menuitem', { name: /List/ }));
|
||||||
|
|
||||||
expect(wrapper.find(TagsCards)).toHaveLength(0);
|
expect(screen.queryByText('TagsCards')).not.toBeInTheDocument();
|
||||||
expect(wrapper.find(TagsTable)).toHaveLength(1);
|
expect(screen.getByText('TagsTable')).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('triggers tags filtering when search field changes', () => {
|
it('triggers tags filtering when search field changes', async () => {
|
||||||
const wrapper = createWrapper({ filteredTags: [] });
|
const { user } = setUp({ filteredTags: [] });
|
||||||
const searchField = wrapper.find(SearchField);
|
|
||||||
|
|
||||||
expect(searchField).toHaveLength(1);
|
|
||||||
expect(filterTags).not.toHaveBeenCalled();
|
expect(filterTags).not.toHaveBeenCalled();
|
||||||
searchField.simulate('change');
|
await user.type(screen.getByPlaceholderText('Search...'), 'Hello');
|
||||||
expect(filterTags).toHaveBeenCalledTimes(1);
|
await waitFor(() => expect(filterTags).toHaveBeenCalledTimes(1));
|
||||||
});
|
|
||||||
|
|
||||||
it('triggers ordering when sorting dropdown changes', () => {
|
|
||||||
const wrapper = createWrapper({ filteredTags: [] });
|
|
||||||
|
|
||||||
expect(wrapper.find(OrderingDropdown).prop('order')).toEqual({});
|
|
||||||
wrapper.find(OrderingDropdown).simulate('change', 'tag', 'DESC');
|
|
||||||
expect(wrapper.find(OrderingDropdown).prop('order')).toEqual({ field: 'tag', dir: 'DESC' });
|
|
||||||
wrapper.find(OrderingDropdown).simulate('change', 'visits', 'ASC');
|
|
||||||
expect(wrapper.find(OrderingDropdown).prop('order')).toEqual({ field: 'visits', dir: 'ASC' });
|
|
||||||
});
|
|
||||||
|
|
||||||
it('can update current order via orderByColumn from table component', () => {
|
|
||||||
const wrapper = createWrapper({ filteredTags: ['foo', 'bar'], stats: {} });
|
|
||||||
const callOrderBy = (field: TagsOrderableFields) => {
|
|
||||||
((wrapper.find(TagsTable).prop('orderByColumn') as Function)(field) as Function)();
|
|
||||||
};
|
|
||||||
|
|
||||||
wrapper.find(TagsModeDropdown).simulate('change'); // Make sure table is rendered
|
|
||||||
|
|
||||||
callOrderBy('visits');
|
|
||||||
expect(wrapper.find(TagsTable).prop('currentOrder')).toEqual({ field: 'visits', dir: 'ASC' });
|
|
||||||
callOrderBy('visits');
|
|
||||||
expect(wrapper.find(TagsTable).prop('currentOrder')).toEqual({ field: 'visits', dir: 'DESC' });
|
|
||||||
callOrderBy('tag');
|
|
||||||
expect(wrapper.find(TagsTable).prop('currentOrder')).toEqual({ field: 'tag', dir: 'ASC' });
|
|
||||||
callOrderBy('shortUrls');
|
|
||||||
expect(wrapper.find(TagsTable).prop('currentOrder')).toEqual({ field: 'shortUrls', dir: 'ASC' });
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue