Add tests for Groups discover components
This commit is contained in:
parent
696e97bb19
commit
4d609b57d6
16 changed files with 304 additions and 8 deletions
77
app/soapbox/features/groups/__tests__/discover.test.tsx
Normal file
77
app/soapbox/features/groups/__tests__/discover.test.tsx
Normal file
|
@ -0,0 +1,77 @@
|
|||
import userEvent from '@testing-library/user-event';
|
||||
import { Map as ImmutableMap } from 'immutable';
|
||||
import React from 'react';
|
||||
|
||||
import { render, screen, waitFor } from 'soapbox/jest/test-helpers';
|
||||
import { normalizeAccount, normalizeInstance } from 'soapbox/normalizers';
|
||||
|
||||
import Discover from '../discover';
|
||||
|
||||
jest.mock('../../../hooks/useDimensions', () => ({
|
||||
useDimensions: () => [{ scrollWidth: 190 }, null, { width: 300 }],
|
||||
}));
|
||||
|
||||
(window as any).ResizeObserver = class ResizeObserver {
|
||||
|
||||
observe() { }
|
||||
disconnect() { }
|
||||
|
||||
};
|
||||
|
||||
const userId = '1';
|
||||
const store: any = {
|
||||
me: userId,
|
||||
accounts: ImmutableMap({
|
||||
[userId]: normalizeAccount({
|
||||
id: userId,
|
||||
acct: 'justin-username',
|
||||
display_name: 'Justin L',
|
||||
avatar: 'test.jpg',
|
||||
chats_onboarded: false,
|
||||
}),
|
||||
}),
|
||||
instance: normalizeInstance({
|
||||
version: '3.4.1 (compatible; TruthSocial 1.0.0)',
|
||||
software: 'TRUTHSOCIAL',
|
||||
}),
|
||||
};
|
||||
|
||||
const renderApp = () => (
|
||||
render(
|
||||
<Discover />,
|
||||
undefined,
|
||||
store,
|
||||
)
|
||||
);
|
||||
|
||||
describe('<Discover />', () => {
|
||||
describe('before the user starts searching', () => {
|
||||
it('it should render popular groups', async () => {
|
||||
renderApp();
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByTestId('popular-groups')).toBeInTheDocument();
|
||||
expect(screen.getByTestId('suggested-groups')).toBeInTheDocument();
|
||||
expect(screen.getByTestId('popular-tags')).toBeInTheDocument();
|
||||
expect(screen.queryAllByTestId('recent-searches')).toHaveLength(0);
|
||||
expect(screen.queryAllByTestId('group-search-icon')).toHaveLength(0);
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the user focuses on the input', () => {
|
||||
it('should render the search experience', async () => {
|
||||
const user = userEvent.setup();
|
||||
renderApp();
|
||||
|
||||
await user.click(screen.getByTestId('search'));
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByTestId('group-search-icon')).toBeInTheDocument();
|
||||
expect(screen.getByTestId('recent-searches')).toBeInTheDocument();
|
||||
expect(screen.queryAllByTestId('popular-groups')).toHaveLength(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,21 @@
|
|||
import React from 'react';
|
||||
|
||||
import { buildGroup } from 'soapbox/jest/factory';
|
||||
import { render, screen } from 'soapbox/jest/test-helpers';
|
||||
|
||||
import GroupGridItem from '../group-grid-item';
|
||||
|
||||
describe('<GroupGridItem', () => {
|
||||
it('should render correctly', () => {
|
||||
const group = buildGroup({
|
||||
display_name: 'group name here',
|
||||
locked: false,
|
||||
members_count: 6,
|
||||
});
|
||||
render(<GroupGridItem group={group} />);
|
||||
|
||||
expect(screen.getByTestId('group-grid-item')).toHaveTextContent(group.display_name);
|
||||
expect(screen.getByTestId('group-grid-item')).toHaveTextContent('Public');
|
||||
expect(screen.getByTestId('group-grid-item')).toHaveTextContent('6 members');
|
||||
});
|
||||
});
|
|
@ -0,0 +1,21 @@
|
|||
import React from 'react';
|
||||
|
||||
import { buildGroup } from 'soapbox/jest/factory';
|
||||
import { render, screen } from 'soapbox/jest/test-helpers';
|
||||
|
||||
import GroupListItem from '../group-list-item';
|
||||
|
||||
describe('<GroupListItem', () => {
|
||||
it('should render correctly', () => {
|
||||
const group = buildGroup({
|
||||
display_name: 'group name here',
|
||||
locked: false,
|
||||
members_count: 6,
|
||||
});
|
||||
render(<GroupListItem group={group} />);
|
||||
|
||||
expect(screen.getByTestId('group-list-item')).toHaveTextContent(group.display_name);
|
||||
expect(screen.getByTestId('group-list-item')).toHaveTextContent('Public');
|
||||
expect(screen.getByTestId('group-list-item')).toHaveTextContent('6 members');
|
||||
});
|
||||
});
|
|
@ -0,0 +1,38 @@
|
|||
import userEvent from '@testing-library/user-event';
|
||||
import React from 'react';
|
||||
|
||||
import { render, screen, within } from 'soapbox/jest/test-helpers';
|
||||
|
||||
import LayoutButtons, { GroupLayout } from '../layout-buttons';
|
||||
|
||||
describe('<LayoutButtons', () => {
|
||||
describe('when LIST view', () => {
|
||||
it('should render correctly', async () => {
|
||||
const onSelectFn = jest.fn();
|
||||
const user = userEvent.setup();
|
||||
|
||||
render(<LayoutButtons layout={GroupLayout.LIST} onSelect={onSelectFn} />);
|
||||
|
||||
expect(within(screen.getByTestId('layout-list-action')).getByTestId('svg-icon-loader')).toHaveClass('text-primary-600');
|
||||
expect(within(screen.getByTestId('layout-grid-action')).getByTestId('svg-icon-loader')).not.toHaveClass('text-primary-600');
|
||||
|
||||
await user.click(screen.getByTestId('layout-grid-action'));
|
||||
expect(onSelectFn).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('when GRID view', () => {
|
||||
it('should render correctly', async () => {
|
||||
const onSelectFn = jest.fn();
|
||||
const user = userEvent.setup();
|
||||
|
||||
render(<LayoutButtons layout={GroupLayout.GRID} onSelect={onSelectFn} />);
|
||||
|
||||
expect(within(screen.getByTestId('layout-list-action')).getByTestId('svg-icon-loader')).not.toHaveClass('text-primary-600');
|
||||
expect(within(screen.getByTestId('layout-grid-action')).getByTestId('svg-icon-loader')).toHaveClass('text-primary-600');
|
||||
|
||||
await user.click(screen.getByTestId('layout-grid-action'));
|
||||
expect(onSelectFn).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,16 @@
|
|||
import React from 'react';
|
||||
|
||||
import { buildGroupTag } from 'soapbox/jest/factory';
|
||||
import { render, screen } from 'soapbox/jest/test-helpers';
|
||||
|
||||
import TagListItem from '../tag-list-item';
|
||||
|
||||
describe('<TagListItem', () => {
|
||||
it('should render correctly', () => {
|
||||
const tag = buildGroupTag({ name: 'tag 1', groups: 5 });
|
||||
render(<TagListItem tag={tag} />);
|
||||
|
||||
expect(screen.getByTestId('tag-list-item')).toHaveTextContent(tag.name);
|
||||
expect(screen.getByTestId('tag-list-item')).toHaveTextContent('Number of groups: 5');
|
||||
});
|
||||
});
|
|
@ -25,6 +25,7 @@ const GroupGridItem = forwardRef((props: IGroup, ref: React.ForwardedRef<HTMLDiv
|
|||
style={{
|
||||
width,
|
||||
}}
|
||||
data-testid='group-grid-item'
|
||||
>
|
||||
<Link to={`/group/${group.slug}`}>
|
||||
<Stack
|
||||
|
|
|
@ -20,6 +20,7 @@ const GroupListItem = (props: IGroup) => {
|
|||
<HStack
|
||||
alignItems='center'
|
||||
justifyContent='between'
|
||||
data-testid='group-list-item'
|
||||
>
|
||||
<Link key={group.id} to={`/group/${group.slug}`}>
|
||||
<HStack alignItems='center' space={2}>
|
||||
|
|
|
@ -15,7 +15,10 @@ interface ILayoutButtons {
|
|||
|
||||
const LayoutButtons = ({ layout, onSelect }: ILayoutButtons) => (
|
||||
<HStack alignItems='center' space={1}>
|
||||
<button onClick={() => onSelect(GroupLayout.LIST)}>
|
||||
<button
|
||||
data-testid='layout-list-action'
|
||||
onClick={() => onSelect(GroupLayout.LIST)}
|
||||
>
|
||||
<Icon
|
||||
src={require('@tabler/icons/layout-list.svg')}
|
||||
className={
|
||||
|
@ -26,7 +29,10 @@ const LayoutButtons = ({ layout, onSelect }: ILayoutButtons) => (
|
|||
/>
|
||||
</button>
|
||||
|
||||
<button onClick={() => onSelect(GroupLayout.GRID)}>
|
||||
<button
|
||||
data-testid='layout-grid-action'
|
||||
onClick={() => onSelect(GroupLayout.GRID)}
|
||||
>
|
||||
<Icon
|
||||
src={require('@tabler/icons/layout-grid.svg')}
|
||||
className={
|
||||
|
|
|
@ -15,7 +15,7 @@ const PopularGroups = () => {
|
|||
const [groupCover, setGroupCover] = useState<HTMLDivElement | null>(null);
|
||||
|
||||
return (
|
||||
<Stack space={4}>
|
||||
<Stack space={4} data-testid='popular-groups'>
|
||||
<HStack alignItems='center' justifyContent='between'>
|
||||
<Text size='xl' weight='bold'>
|
||||
<FormattedMessage
|
||||
|
|
|
@ -12,7 +12,7 @@ const PopularTags = () => {
|
|||
const isEmpty = (isFetched && tags.length === 0) || isError;
|
||||
|
||||
return (
|
||||
<Stack space={4}>
|
||||
<Stack space={4} data-testid='popular-tags'>
|
||||
<HStack alignItems='center' justifyContent='between'>
|
||||
<Text size='xl' weight='bold'>
|
||||
<FormattedMessage
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
import React from 'react';
|
||||
|
||||
import { render, screen } from 'soapbox/jest/test-helpers';
|
||||
|
||||
import Blankslate from '../blankslate';
|
||||
|
||||
|
||||
describe('<Blankslate />', () => {
|
||||
describe('with string props', () => {
|
||||
it('should render correctly', () => {
|
||||
render(<Blankslate title='Title' subtitle='Subtitle' />);
|
||||
|
||||
expect(screen.getByTestId('no-results')).toHaveTextContent('Title');
|
||||
expect(screen.getByTestId('no-results')).toHaveTextContent('Subtitle');
|
||||
});
|
||||
});
|
||||
|
||||
describe('with node props', () => {
|
||||
it('should render correctly', () => {
|
||||
render(
|
||||
<Blankslate
|
||||
title={<span>Title</span>}
|
||||
subtitle={<span>Subtitle</span>}
|
||||
/>);
|
||||
|
||||
expect(screen.getByTestId('no-results')).toHaveTextContent('Title');
|
||||
expect(screen.getByTestId('no-results')).toHaveTextContent('Subtitle');
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,67 @@
|
|||
import userEvent from '@testing-library/user-event';
|
||||
import { Map as ImmutableMap } from 'immutable';
|
||||
import React from 'react';
|
||||
import { VirtuosoGridMockContext, VirtuosoMockContext } from 'react-virtuoso';
|
||||
|
||||
import { buildGroup } from 'soapbox/jest/factory';
|
||||
import { render, screen, waitFor } from 'soapbox/jest/test-helpers';
|
||||
import { normalizeAccount } from 'soapbox/normalizers';
|
||||
|
||||
import Results from '../results';
|
||||
|
||||
const userId = '1';
|
||||
const store = {
|
||||
me: userId,
|
||||
accounts: ImmutableMap({
|
||||
[userId]: normalizeAccount({
|
||||
id: userId,
|
||||
acct: 'justin-username',
|
||||
display_name: 'Justin L',
|
||||
avatar: 'test.jpg',
|
||||
chats_onboarded: false,
|
||||
}),
|
||||
}),
|
||||
};
|
||||
|
||||
const renderApp = (children: React.ReactNode) => (
|
||||
render(
|
||||
<VirtuosoMockContext.Provider value={{ viewportHeight: 300, itemHeight: 100 }}>
|
||||
<VirtuosoGridMockContext.Provider value={{ viewportHeight: 300, viewportWidth: 300, itemHeight: 100, itemWidth: 100 }}>
|
||||
{children}
|
||||
</VirtuosoGridMockContext.Provider>
|
||||
</VirtuosoMockContext.Provider>,
|
||||
undefined,
|
||||
store,
|
||||
)
|
||||
);
|
||||
|
||||
const groupSearchResult = {
|
||||
groups: [buildGroup()],
|
||||
hasNextPage: false,
|
||||
isFetching: false,
|
||||
fetchNextPage: jest.fn(),
|
||||
} as any;
|
||||
|
||||
describe('<Results />', () => {
|
||||
describe('with a list layout', () => {
|
||||
it('should render the GroupListItem components', async () => {
|
||||
renderApp(<Results groupSearchResult={groupSearchResult} />);
|
||||
await waitFor(() => {
|
||||
expect(screen.getByTestId('group-list-item')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('with a grid layout', () => {
|
||||
it('should render the GroupGridItem components', async () => {
|
||||
const user = userEvent.setup();
|
||||
renderApp(<Results groupSearchResult={groupSearchResult} />);
|
||||
|
||||
await user.click(screen.getByTestId('layout-grid-action'));
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByTestId('group-grid-item')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -15,7 +15,7 @@ const SuggestedGroups = () => {
|
|||
const [groupCover, setGroupCover] = useState<HTMLDivElement | null>(null);
|
||||
|
||||
return (
|
||||
<Stack space={4}>
|
||||
<Stack space={4} data-testid='suggested-groups'>
|
||||
<HStack alignItems='center' justifyContent='between'>
|
||||
<Text size='xl' weight='bold'>
|
||||
<FormattedMessage
|
||||
|
|
|
@ -14,7 +14,11 @@ const TagListItem = (props: ITagListItem) => {
|
|||
const { tag } = props;
|
||||
|
||||
return (
|
||||
<Link to={`/groups/discover/tags/${tag.id}`} className='group'>
|
||||
<Link
|
||||
to={`/groups/discover/tags/${tag.id}`}
|
||||
className='group'
|
||||
data-testid='tag-list-item'
|
||||
>
|
||||
<Stack>
|
||||
<Text
|
||||
weight='bold'
|
||||
|
|
|
@ -39,6 +39,7 @@ const Discover: React.FC = () => {
|
|||
src={require('@tabler/icons/arrow-left.svg')}
|
||||
iconClassName='mr-2 h-5 w-5 fill-current text-gray-600'
|
||||
onClick={cancelSearch}
|
||||
data-testid='group-search-icon'
|
||||
/>
|
||||
) : null}
|
||||
|
||||
|
|
|
@ -1,6 +1,13 @@
|
|||
import { v4 as uuidv4 } from 'uuid';
|
||||
|
||||
import { groupSchema, Group, groupRelationshipSchema, GroupRelationship } from 'soapbox/schemas';
|
||||
import {
|
||||
groupSchema,
|
||||
groupRelationshipSchema,
|
||||
groupTagSchema,
|
||||
type Group,
|
||||
type GroupRelationship,
|
||||
type GroupTag,
|
||||
} from 'soapbox/schemas';
|
||||
|
||||
// TODO: there's probably a better way to create these factory functions.
|
||||
// This looks promising but didn't work on my first attempt: https://github.com/anatine/zod-plugins/tree/main/packages/zod-mock
|
||||
|
@ -17,4 +24,10 @@ function buildGroupRelationship(props: Record<string, any> = {}): GroupRelations
|
|||
}, props));
|
||||
}
|
||||
|
||||
export { buildGroup, buildGroupRelationship };
|
||||
function buildGroupTag(props: Record<string, any> = {}): GroupTag {
|
||||
return groupTagSchema.parse(Object.assign({
|
||||
id: uuidv4(),
|
||||
}, props));
|
||||
}
|
||||
|
||||
export { buildGroup, buildGroupRelationship, buildGroupTag };
|
Loading…
Reference in a new issue