Add tests for Groups discover components

environments/review-add-tests-rn4bon/deployments/3286
Chewbacca 1 year ago
parent 696e97bb19
commit 4d609b57d6

@ -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…
Cancel
Save