Fetch relationships everytime we fetch a single chat

This commit is contained in:
Chewbacca 2022-11-10 11:56:36 -05:00
parent 98b2fdf9a4
commit 15c22863d7
5 changed files with 157 additions and 7 deletions

View file

@ -36,7 +36,9 @@ const TestApp: FC<any> = ({ children, storeProps, routerProps = {} }) => {
let store: ReturnType<typeof createTestStore>;
let appState = rootState;
if (storeProps) {
if (storeProps && typeof storeProps.getState !== 'undefined') { // storeProps is a store
store = storeProps;
} else if (storeProps) { // storeProps is state
appState = merge(rootState, storeProps);
store = createTestStore(appState);
} else {

View file

@ -3,8 +3,9 @@ import sumBy from 'lodash/sumBy';
import { useEffect } from 'react';
import { __stub } from 'soapbox/api';
import { mockStore, queryClient, renderHook, rootState, waitFor } from 'soapbox/jest/test-helpers';
import { createTestStore, mockStore, queryClient, renderHook, rootState, waitFor } from 'soapbox/jest/test-helpers';
import { normalizeRelationship } from 'soapbox/normalizers';
import { Store } from 'soapbox/store';
import { flattenPages } from 'soapbox/utils/queries';
import { IAccount } from '../accounts';
@ -179,7 +180,7 @@ describe('useChats', () => {
describe('with a successful request', () => {
beforeEach(() => {
store = mockStore(ImmutableMap());
store = mockStore(rootState);
__stub((mock) => {
mock.onGet('/api/v1/pleroma/chats')
@ -218,7 +219,13 @@ describe('useChats', () => {
});
describe('useChat()', () => {
const relationshipId = '123';
let store: Store;
beforeEach(() => {
const state = rootState;
store = createTestStore(state);
queryClient.clear();
});
@ -226,14 +233,21 @@ describe('useChat()', () => {
beforeEach(() => {
__stub((mock) => {
mock.onGet(`/api/v1/pleroma/chats/${chat.id}`).reply(200, chat);
mock
.onGet(`/api/v1/accounts/relationships?id[]=${chat.account.id}`)
.reply(200, [normalizeRelationship({ id: relationshipId, blocked_by: true })]);
});
});
it('is successful', async () => {
const { result } = renderHook(() => useChat(chat.id));
expect(store.getState().relationships.getIn([relationshipId, 'blocked_by'])).toBeUndefined();
const { result } = renderHook(() => useChat(chat.id), undefined, store);
await waitFor(() => expect(result.current.isFetching).toBe(false));
expect(store.getState().relationships.getIn([relationshipId, 'id'])).toBe(relationshipId);
expect(store.getState().relationships.getIn([relationshipId, 'blocked_by'])).toBe(true);
expect(result.current.data.id).toBe(chat.id);
});
});

View file

@ -0,0 +1,107 @@
import { useEffect } from 'react';
import { __stub } from 'soapbox/api';
import { createTestStore, queryClient, renderHook, rootState, waitFor } from 'soapbox/jest/test-helpers';
import { normalizeRelationship } from 'soapbox/normalizers';
import { Store } from 'soapbox/store';
import { useFetchRelationships } from '../relationships';
describe('useFetchRelationships()', () => {
let store: Store;
beforeEach(() => {
const state = rootState;
store = createTestStore(state);
queryClient.clear();
});
describe('with a successful query', () => {
describe('with one relationship', () => {
const id = '123';
beforeEach(() => {
__stub((mock) => {
mock
.onGet(`/api/v1/accounts/relationships?id[]=${id}`)
.reply(200, [normalizeRelationship({ id, blocked_by: true })]);
});
});
it('is successful', async() => {
const { result } = renderHook(() => {
const fetchRelationships = useFetchRelationships();
useEffect(() => {
fetchRelationships.mutate({ accountIds: [id] });
}, []);
return fetchRelationships;
}, undefined, store);
await waitFor(() => expect(result.current.isLoading).toBe(false));
expect(store.getState().relationships.size).toBe(1);
expect(store.getState().relationships.getIn([id, 'id'])).toBe(id);
expect(store.getState().relationships.getIn([id, 'blocked_by'])).toBe(true);
});
});
describe('with multiple relationships', () => {
const ids = ['123', '456'];
beforeEach(() => {
__stub((mock) => {
mock
.onGet(`/api/v1/accounts/relationships?id[]=${ids[0]}&id[]=${ids[1]}`)
.reply(200, ids.map((id) => normalizeRelationship({ id, blocked_by: true })));
});
});
it('is successful', async() => {
const { result } = renderHook(() => {
const fetchRelationships = useFetchRelationships();
useEffect(() => {
fetchRelationships.mutate({ accountIds: ids });
}, []);
return fetchRelationships;
}, undefined, store);
await waitFor(() => expect(result.current.isLoading).toBe(false));
expect(store.getState().relationships.size).toBe(2);
expect(store.getState().relationships.getIn([ids[0], 'id'])).toBe(ids[0]);
expect(store.getState().relationships.getIn([ids[1], 'id'])).toBe(ids[1]);
});
});
});
describe('with an unsuccessful query', () => {
const id = '123';
beforeEach(() => {
__stub((mock) => {
mock.onGet(`/api/v1/accounts/relationships?id[]=${id}`).networkError();
});
});
it('is successful', async() => {
const { result } = renderHook(() => {
const fetchRelationships = useFetchRelationships();
useEffect(() => {
fetchRelationships.mutate({ accountIds: [id] });
}, []);
return fetchRelationships;
}, undefined, store);
await waitFor(() => expect(result.current.isLoading).toBe(false));
expect(result.current.error).toBeDefined();
});
});
});

View file

@ -1,7 +1,6 @@
import { InfiniteData, useInfiniteQuery, useMutation, useQuery } from '@tanstack/react-query';
import sumBy from 'lodash/sumBy';
import { fetchRelationships } from 'soapbox/actions/accounts';
import { importFetchedAccount, importFetchedAccounts } from 'soapbox/actions/importer';
import snackbar from 'soapbox/actions/snackbar';
import { getNextLink } from 'soapbox/api';
@ -13,6 +12,7 @@ import { normalizeChatMessage } from 'soapbox/normalizers';
import { flattenPages, PaginatedResult, updatePageItem } from 'soapbox/utils/queries';
import { queryClient } from './client';
import { useFetchRelationships } from './relationships';
import type { IAccount } from './accounts';
@ -129,6 +129,7 @@ const useChats = (search?: string) => {
const dispatch = useAppDispatch();
const features = useFeatures();
const { setUnreadChatsCount } = useStatContext();
const fetchRelationships = useFetchRelationships();
const getChats = async (pageParam?: any): Promise<PaginatedResult<IChat>> => {
const endpoint = features.chatsV2 ? '/api/v2/pleroma/chats' : '/api/v1/pleroma/chats';
@ -147,7 +148,7 @@ const useChats = (search?: string) => {
setUnreadChatsCount(Number(response.headers['x-unread-messages-count']) || sumBy(data, (chat) => chat.unread));
// Set the relationships to these users in the redux store.
dispatch(fetchRelationships(data.map((item) => item.account.id)));
fetchRelationships.mutate({ accountIds: data.map((item) => item.account.id) });
dispatch(importFetchedAccounts(data.map((item) => item.account)));
return {
@ -183,12 +184,13 @@ const useChats = (search?: string) => {
const useChat = (chatId?: string) => {
const api = useApi();
const dispatch = useAppDispatch();
const fetchRelationships = useFetchRelationships();
const getChat = async () => {
if (chatId) {
const { data } = await api.get<IChat>(`/api/v1/pleroma/chats/${chatId}`);
dispatch(fetchRelationships([data.account.id]));
fetchRelationships.mutate({ accountIds: [data.account.id] });
dispatch(importFetchedAccount(data.account));
return data;

View file

@ -0,0 +1,25 @@
import { useMutation } from '@tanstack/react-query';
import { AxiosError } from 'axios';
import { fetchRelationshipsFail, fetchRelationshipsSuccess } from 'soapbox/actions/accounts';
import { useApi, useAppDispatch } from 'soapbox/hooks';
const useFetchRelationships = () => {
const api = useApi();
const dispatch = useAppDispatch();
return useMutation(({ accountIds }: { accountIds: string[]}) => {
const ids = accountIds.map((id) => `id[]=${id}`).join('&');
return api.get(`/api/v1/accounts/relationships?${ids}`);
}, {
onSuccess(response) {
dispatch(fetchRelationshipsSuccess(response.data));
},
onError(error: AxiosError) {
dispatch(fetchRelationshipsFail(error));
},
});
};
export { useFetchRelationships };