kopia lustrzana https://gitlab.com/soapbox-pub/soapbox
Add tests for ChatPane component
rodzic
e4ed68e070
commit
89af43df91
|
@ -21,6 +21,11 @@ export const getLinks = (response: AxiosResponse): LinkHeader => {
|
||||||
return new LinkHeader(response.headers?.link);
|
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[]) => {
|
export const baseClient = (...params: any[]) => {
|
||||||
const axios = api.baseClient(...params);
|
const axios = api.baseClient(...params);
|
||||||
setupMock(axios);
|
setupMock(axios);
|
||||||
|
|
|
@ -82,7 +82,7 @@ const ChatListItem: React.FC<IChatListItemInterface> = ({ chat, chatSilence, onC
|
||||||
key={chat.id}
|
key={chat.id}
|
||||||
onClick={() => onClick(chat)}
|
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'
|
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' justifyContent='between' space={2} className='w-full'>
|
||||||
<HStack alignItems='center' space={2} className='overflow-hidden'>
|
<HStack alignItems='center' space={2} className='overflow-hidden'>
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { Virtuoso } from 'react-virtuoso';
|
||||||
|
|
||||||
import { fetchChats } from 'soapbox/actions/chats';
|
import { fetchChats } from 'soapbox/actions/chats';
|
||||||
import PullToRefresh from 'soapbox/components/pull-to-refresh';
|
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 PlaceholderChat from 'soapbox/features/placeholder/components/placeholder-chat';
|
||||||
import { useAppDispatch } from 'soapbox/hooks';
|
import { useAppDispatch } from 'soapbox/hooks';
|
||||||
import { useChats, useChatSilences } from 'soapbox/queries/chats';
|
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 [isNearBottom, setNearBottom] = useState<boolean>(false);
|
||||||
const [isNearTop, setNearTop] = useState<boolean>(true);
|
const [isNearTop, setNearTop] = useState<boolean>(true);
|
||||||
|
|
||||||
const isEmpty = (!chats || chats.length === 0);
|
|
||||||
|
|
||||||
const handleLoadMore = () => {
|
const handleLoadMore = () => {
|
||||||
if (hasNextPage && !isFetching) {
|
if (hasNextPage && !isFetching) {
|
||||||
fetchNextPage();
|
fetchNextPage();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleRefresh = () => dispatch(fetchChats()) as any;
|
const handleRefresh = () => dispatch(fetchChats());
|
||||||
|
|
||||||
const renderEmpty = () => (
|
const renderEmpty = () => (
|
||||||
<Stack space={2}>
|
<Stack space={2}>
|
||||||
|
@ -50,7 +48,6 @@ const ChatList: React.FC<IChatList> = ({ onClickChat, useWindowScroll = false, s
|
||||||
return (
|
return (
|
||||||
<div className='relative h-full'>
|
<div className='relative h-full'>
|
||||||
<PullToRefresh onRefresh={handleRefresh}>
|
<PullToRefresh onRefresh={handleRefresh}>
|
||||||
{isEmpty ? renderEmpty() : (
|
|
||||||
<Virtuoso
|
<Virtuoso
|
||||||
ref={chatListRef}
|
ref={chatListRef}
|
||||||
atTopStateChange={(atTop) => setNearTop(atTop)}
|
atTopStateChange={(atTop) => setNearTop(atTop)}
|
||||||
|
@ -68,11 +65,10 @@ const ChatList: React.FC<IChatList> = ({ onClickChat, useWindowScroll = false, s
|
||||||
}}
|
}}
|
||||||
components={{
|
components={{
|
||||||
ScrollSeekPlaceholder: () => <PlaceholderChat />,
|
ScrollSeekPlaceholder: () => <PlaceholderChat />,
|
||||||
// Footer: () => hasNextPage ? <Spinner withText={false} /> : null,
|
Footer: () => hasNextPage ? <Spinner withText={false} /> : null,
|
||||||
EmptyPlaceholder: renderEmpty,
|
EmptyPlaceholder: renderEmpty,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
|
||||||
</PullToRefresh>
|
</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();
|
const intl = useIntl();
|
||||||
|
|
||||||
return (
|
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={4}>
|
||||||
<Stack space={1} className='max-w-[80%] mx-auto'>
|
<Stack space={1} className='max-w-[80%] mx-auto'>
|
||||||
<Text size='lg' weight='bold' align='center'>
|
<Text size='lg' weight='bold' align='center'>
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import sumBy from 'lodash/sumBy';
|
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
|
|
||||||
import { Stack } from 'soapbox/components/ui';
|
import { Stack } from 'soapbox/components/ui';
|
||||||
|
|
|
@ -22,6 +22,7 @@ const ChatSearchInput: React.FC<IChatSearchInput> = ({ value, onChange, onClear
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Input
|
<Input
|
||||||
|
data-testid='chat-search-input'
|
||||||
type='text'
|
type='text'
|
||||||
autoFocus
|
autoFocus
|
||||||
placeholder={intl.formatMessage(messages.searchPlaceholder)}
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
Ładowanie…
Reference in New Issue