Add tests for ChatPane component
This commit is contained in:
@ -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)}
|
||||
|
||||
Reference in New Issue
Block a user