Add tests for ChatPane component
This commit is contained in:
parent
e4ed68e070
commit
89af43df91
|
@ -21,6 +21,11 @@ export const getLinks = (response: AxiosResponse): LinkHeader => {
|
|||
return new LinkHeader(response.headers?.link);
|
||||
};
|
||||
|
||||
export const getNextLink = (response: AxiosResponse) => {
|
||||
const nextLink = new LinkHeader(response.headers?.link);
|
||||
return nextLink.refs.find((ref) => ref.uri)?.uri;
|
||||
};
|
||||
|
||||
export const baseClient = (...params: any[]) => {
|
||||
const axios = api.baseClient(...params);
|
||||
setupMock(axios);
|
||||
|
|
|
@ -82,7 +82,7 @@ const ChatListItem: React.FC<IChatListItemInterface> = ({ chat, chatSilence, onC
|
|||
key={chat.id}
|
||||
onClick={() => onClick(chat)}
|
||||
className='group px-2 py-3 w-full flex flex-col rounded-lg hover:bg-gray-100 dark:hover:bg-gray-800 focus:shadow-inset-ring'
|
||||
data-testid='chat'
|
||||
data-testid='chat-list-item'
|
||||
>
|
||||
<HStack alignItems='center' justifyContent='between' space={2} className='w-full'>
|
||||
<HStack alignItems='center' space={2} className='overflow-hidden'>
|
||||
|
|
|
@ -4,7 +4,7 @@ import { Virtuoso } from 'react-virtuoso';
|
|||
|
||||
import { fetchChats } from 'soapbox/actions/chats';
|
||||
import PullToRefresh from 'soapbox/components/pull-to-refresh';
|
||||
import { Stack } from 'soapbox/components/ui';
|
||||
import { Spinner, Stack } from 'soapbox/components/ui';
|
||||
import PlaceholderChat from 'soapbox/features/placeholder/components/placeholder-chat';
|
||||
import { useAppDispatch } from 'soapbox/hooks';
|
||||
import { useChats, useChatSilences } from 'soapbox/queries/chats';
|
||||
|
@ -29,15 +29,13 @@ const ChatList: React.FC<IChatList> = ({ onClickChat, useWindowScroll = false, s
|
|||
const [isNearBottom, setNearBottom] = useState<boolean>(false);
|
||||
const [isNearTop, setNearTop] = useState<boolean>(true);
|
||||
|
||||
const isEmpty = (!chats || chats.length === 0);
|
||||
|
||||
const handleLoadMore = () => {
|
||||
if (hasNextPage && !isFetching) {
|
||||
fetchNextPage();
|
||||
}
|
||||
};
|
||||
|
||||
const handleRefresh = () => dispatch(fetchChats()) as any;
|
||||
const handleRefresh = () => dispatch(fetchChats());
|
||||
|
||||
const renderEmpty = () => (
|
||||
<Stack space={2}>
|
||||
|
@ -50,29 +48,27 @@ const ChatList: React.FC<IChatList> = ({ onClickChat, useWindowScroll = false, s
|
|||
return (
|
||||
<div className='relative h-full'>
|
||||
<PullToRefresh onRefresh={handleRefresh}>
|
||||
{isEmpty ? renderEmpty() : (
|
||||
<Virtuoso
|
||||
ref={chatListRef}
|
||||
atTopStateChange={(atTop) => setNearTop(atTop)}
|
||||
atBottomStateChange={(atBottom) => setNearBottom(atBottom)}
|
||||
useWindowScroll={useWindowScroll}
|
||||
data={chats}
|
||||
endReached={handleLoadMore}
|
||||
itemContent={(_index, chat) => {
|
||||
const chatSilence = chatSilences?.find((chatSilence) => String(chatSilence.target_account_id) === chat.account.id);
|
||||
return (
|
||||
<div className='px-2'>
|
||||
<ChatListItem chat={chat} onClick={onClickChat} chatSilence={chatSilence} />
|
||||
</div>
|
||||
);
|
||||
}}
|
||||
components={{
|
||||
ScrollSeekPlaceholder: () => <PlaceholderChat />,
|
||||
// Footer: () => hasNextPage ? <Spinner withText={false} /> : null,
|
||||
EmptyPlaceholder: renderEmpty,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
<Virtuoso
|
||||
ref={chatListRef}
|
||||
atTopStateChange={(atTop) => setNearTop(atTop)}
|
||||
atBottomStateChange={(atBottom) => setNearBottom(atBottom)}
|
||||
useWindowScroll={useWindowScroll}
|
||||
data={chats}
|
||||
endReached={handleLoadMore}
|
||||
itemContent={(_index, chat) => {
|
||||
const chatSilence = chatSilences?.find((chatSilence) => String(chatSilence.target_account_id) === chat.account.id);
|
||||
return (
|
||||
<div className='px-2'>
|
||||
<ChatListItem chat={chat} onClick={onClickChat} chatSilence={chatSilence} />
|
||||
</div>
|
||||
);
|
||||
}}
|
||||
components={{
|
||||
ScrollSeekPlaceholder: () => <PlaceholderChat />,
|
||||
Footer: () => hasNextPage ? <Spinner withText={false} /> : null,
|
||||
EmptyPlaceholder: renderEmpty,
|
||||
}}
|
||||
/>
|
||||
</PullToRefresh>
|
||||
|
||||
<>
|
||||
|
|
|
@ -0,0 +1,102 @@
|
|||
import React from 'react';
|
||||
import { VirtuosoMockContext } from 'react-virtuoso';
|
||||
|
||||
import { __stub } from 'soapbox/api';
|
||||
import { ChatContext } from 'soapbox/contexts/chat-context';
|
||||
import { StatProvider } from 'soapbox/contexts/stat-context';
|
||||
import chats from 'soapbox/jest/fixtures/chats.json';
|
||||
import { render, rootState, screen, waitFor } from 'soapbox/jest/test-helpers';
|
||||
import { normalizeInstance } from 'soapbox/normalizers';
|
||||
|
||||
import ChatPane from '../chat-pane';
|
||||
|
||||
const renderComponentWithChatContext = (store = {}) => render(
|
||||
<VirtuosoMockContext.Provider value={{ viewportHeight: 300, itemHeight: 100 }}>
|
||||
<StatProvider>
|
||||
<ChatContext.Provider value={{ isOpen: true }}>
|
||||
<ChatPane />
|
||||
</ChatContext.Provider>
|
||||
</StatProvider>
|
||||
</VirtuosoMockContext.Provider>,
|
||||
undefined,
|
||||
store,
|
||||
);
|
||||
|
||||
const store = rootState
|
||||
.set('instance', normalizeInstance({
|
||||
version: '3.4.1 (compatible; TruthSocial 1.0.0)',
|
||||
}));
|
||||
|
||||
describe('<ChatPane />', () => {
|
||||
describe('when there are chats', () => {
|
||||
beforeEach(() => {
|
||||
__stub((mock) => {
|
||||
mock.onGet('/api/v1/pleroma/chats').reply(200, chats, {
|
||||
link: '<https://example.com/api/v1/pleroma/chats?since_id=2>; rel=\'prev\'',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('renders the chats', async () => {
|
||||
renderComponentWithChatContext();
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getAllByTestId('chat-list-item')).toHaveLength(chats.length);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when there are no chats', () => {
|
||||
beforeEach(() => {
|
||||
__stub((mock) => {
|
||||
mock.onGet('/api/v1/pleroma/chats').reply(200, [], {
|
||||
link: null,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('renders the blankslate', async () => {
|
||||
renderComponentWithChatContext();
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByTestId('chat-pane-blankslate')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the software is Truth Social', () => {
|
||||
beforeEach(() => {
|
||||
__stub((mock) => {
|
||||
mock.onGet('/api/v1/pleroma/chats').reply(200, chats, {
|
||||
link: '<https://example.com/api/v1/pleroma/chats?since_id=2>; rel=\'prev\'',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('renders the search input', async () => {
|
||||
renderComponentWithChatContext(store);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByTestId('chat-search-input')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the software is not Truth Social', () => {
|
||||
beforeEach(() => {
|
||||
__stub((mock) => {
|
||||
mock.onGet('/api/v1/pleroma/chats').reply(200, chats, {
|
||||
link: '<https://example.com/api/v1/pleroma/chats?since_id=2>; rel=\'prev\'',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('does not render the search input', async () => {
|
||||
renderComponentWithChatContext();
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.queryAllByTestId('chat-search-input')).toHaveLength(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -17,7 +17,12 @@ const Blankslate = ({ onSearch }: IBlankslate) => {
|
|||
const intl = useIntl();
|
||||
|
||||
return (
|
||||
<Stack alignItems='center' justifyContent='center' className='h-full flex-grow'>
|
||||
<Stack
|
||||
alignItems='center'
|
||||
justifyContent='center'
|
||||
className='h-full flex-grow'
|
||||
data-testid='chat-pane-blankslate'
|
||||
>
|
||||
<Stack space={4}>
|
||||
<Stack space={1} className='max-w-[80%] mx-auto'>
|
||||
<Text size='lg' weight='bold' align='center'>
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import sumBy from 'lodash/sumBy';
|
||||
import React, { useState } from 'react';
|
||||
|
||||
import { Stack } from 'soapbox/components/ui';
|
||||
|
|
|
@ -22,6 +22,7 @@ const ChatSearchInput: React.FC<IChatSearchInput> = ({ value, onChange, onClear
|
|||
|
||||
return (
|
||||
<Input
|
||||
data-testid='chat-search-input'
|
||||
type='text'
|
||||
autoFocus
|
||||
placeholder={intl.formatMessage(messages.searchPlaceholder)}
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
[
|
||||
{
|
||||
"id": "1",
|
||||
"unread": 0,
|
||||
"created_by_account": "2",
|
||||
"last_message": {
|
||||
"account_id": "2",
|
||||
"chat_id": "85",
|
||||
"content": "last message content",
|
||||
"created_at": "2022-09-28T17:43:01.432Z",
|
||||
"id": "1166",
|
||||
"unread": false,
|
||||
"discarded_at": "2022-09-29T19:09:30.253Z"
|
||||
},
|
||||
"created_at": "2022-08-26T14:49:16.360Z",
|
||||
"updated_at": "2022-09-29T19:09:30.257Z",
|
||||
"accepted": true,
|
||||
"discarded_at": null,
|
||||
"account": {
|
||||
"id": "2",
|
||||
"username": "leonard",
|
||||
"acct": "leonard",
|
||||
"display_name": "leonard",
|
||||
"created_at": "2021-10-19T00:00:00.000Z",
|
||||
"avatar": "original.jpg",
|
||||
"avatar_static": "original.jpg",
|
||||
"verified": false,
|
||||
"accepting_messages": true,
|
||||
"chats_onboarded": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "2",
|
||||
"unread": 0,
|
||||
"created_by_account": "3",
|
||||
"last_message": {
|
||||
"account_id": "3",
|
||||
"chat_id": "125",
|
||||
"content": "\u003cp\u003eInventore enim numquam nihil facilis nostrum eum natus provident quis veritatis esse dolorem praesentium rem cumque.\u003c/p\u003e",
|
||||
"created_at": "2022-09-23T14:09:29.625Z",
|
||||
"id": "1033",
|
||||
"unread": false,
|
||||
"discarded_at": null
|
||||
},
|
||||
"created_at": "2022-09-22T15:06:49.675Z",
|
||||
"updated_at": "2022-09-23T14:09:29.628Z",
|
||||
"accepted": true,
|
||||
"discarded_at": null,
|
||||
"account": {
|
||||
"id": "3",
|
||||
"username": "sheldon",
|
||||
"acct": "sheldon",
|
||||
"display_name": "sheldon",
|
||||
"created_at": "2022-09-22T00:00:00.000Z",
|
||||
"avatar": "original.jpg",
|
||||
"avatar_static": "original.jpg",
|
||||
"verified": false,
|
||||
"accepting_messages": true,
|
||||
"chats_onboarded": true
|
||||
}
|
||||
}
|
||||
]
|
Loading…
Reference in New Issue