Skip to content

Commit

Permalink
feat: add mutations to clear chat (#154)
Browse files Browse the repository at this point in the history
* feat: add mutations to clear chat

* refactor: rename "delete" to "clear"

* fix: clearChat route
  • Loading branch information
spaenleh authored Apr 19, 2022
1 parent 1a7a124 commit fe8a3fa
Show file tree
Hide file tree
Showing 8 changed files with 181 additions and 0 deletions.
9 changes: 9 additions & 0 deletions src/api/chat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import configureAxios, {
verifyAuthentication,
} from './axios';
import {
buildClearItemChatRoute,
buildDeleteItemChatMessageRoute,
buildGetItemChatRoute,
buildGetPublicItemChatRoute,
Expand Down Expand Up @@ -62,3 +63,11 @@ export const deleteItemChatMessage = async (
)
.then(({ data }) => data),
);

export const clearItemChat = async (id: UUID, { API_HOST }: QueryClientConfig,
) =>
verifyAuthentication(() =>
axios
.delete(`${API_HOST}/${buildClearItemChatRoute(id)}`)
.then(({ data }) => data),
);
3 changes: 3 additions & 0 deletions src/api/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ export const buildDeleteItemChatMessageRoute = (
chatId: UUID,
messageId: UUID,
) => `${ITEMS_ROUTE}/${chatId}/chat/${messageId}`;
export const buildClearItemChatRoute = (id: UUID) =>
`${ITEMS_ROUTE}/${id}/chat`;

export const buildGetMemberBy = (email: string) =>
`${MEMBERS_ROUTE}/search?email=${email.toLowerCase()}`;
Expand Down Expand Up @@ -296,6 +298,7 @@ export const API_ROUTES = {
buildPostItemChatMessageRoute,
buildPatchItemChatMessageRoute,
buildDeleteItemChatMessageRoute,
buildClearItemChatRoute,
buildRecycleItemRoute,
buildRecycleItemsRoute,
buildGetPublicItemsWithTag,
Expand Down
1 change: 1 addition & 0 deletions src/config/keys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ export const MUTATION_KEYS = {
POST_ITEM_CHAT_MESSAGE: 'postChatMessage',
PATCH_ITEM_CHAT_MESSAGE: 'patchChatMessage',
DELETE_ITEM_CHAT_MESSAGE: 'deleteChatMessage',
CLEAR_ITEM_CHAT: 'clearItemChat',
RECYCLE_ITEM: 'recycleItem',
RECYCLE_ITEMS: 'recycleItems',
RESTORE_ITEMS: 'restoreItems',
Expand Down
139 changes: 139 additions & 0 deletions src/mutations/chat.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import nock from 'nock';
import Cookies from 'js-cookie';
import { StatusCodes } from 'http-status-codes';
import {
buildClearItemChatRoute,
buildDeleteItemChatMessageRoute,
buildPatchItemChatMessageRoute,
buildPostItemChatMessageRoute,
Expand All @@ -19,6 +20,7 @@ import {
import { buildItemChatKey, MUTATION_KEYS } from '../config/keys';
import { REQUEST_METHODS } from '../api/utils';
import {
clearItemChatRoutine,
deleteItemChatMessageRoutine,
patchItemChatMessageRoutine,
postItemChatMessageRoutine,
Expand Down Expand Up @@ -228,6 +230,65 @@ describe('Chat Mutations', () => {
);
});
});

describe(MUTATION_KEYS.CLEAR_ITEM_CHAT, () => {
const route = `/${buildClearItemChatRoute(itemId)}`;
const mutation = () => useMutation(MUTATION_KEYS.CLEAR_ITEM_CHAT);

it(`Clear chat`, async () => {
const endpoints = [
{ route, response: OK_RESPONSE, method: REQUEST_METHODS.DELETE },
];
// set random data in cache
queryClient.setQueryData(chatKey, ITEM_CHAT);

const mockedMutation = await mockMutation({
endpoints,
mutation,
wrapper,
});

await act(async () => {
await mockedMutation.mutate(chatId);
await waitForMutation();
});

// verify cache keys
expect(queryClient.getQueryState(chatKey)?.isInvalidated).toBeTruthy();
});

it(`Unauthorized`, async () => {
const endpoints = [
{
route,
response: UNAUTHORIZED_RESPONSE,
method: REQUEST_METHODS.DELETE,
statusCode: StatusCodes.UNAUTHORIZED,
},
];
// set random data in cache
queryClient.setQueryData(chatKey, ITEM_CHAT);

const mockedMutation = await mockMutation({
endpoints,
mutation,
wrapper,
});

await act(async () => {
await mockedMutation.mutate(chatId);
await waitForMutation();
});

// verify cache keys
expect(queryClient.getQueryState(chatKey)?.isInvalidated).toBeTruthy();
expect(mockedNotifier).toHaveBeenCalledWith(
expect.objectContaining({
type: clearItemChatRoutine.FAILURE,
}),
);
});
});
});

describe('enableWebsockets = true', () => {
Expand Down Expand Up @@ -265,5 +326,83 @@ describe('Chat Mutations', () => {
expect(queryClient.getQueryState(chatKey)?.isInvalidated).toBeFalsy();
});
});

describe(MUTATION_KEYS.PATCH_ITEM_CHAT_MESSAGE, () => {
const route = `/${buildPatchItemChatMessageRoute(itemId, messageId)}`;
const mutation = () => useMutation(MUTATION_KEYS.PATCH_ITEM_CHAT_MESSAGE);
it(`Patch item chat message`, async () => {
const endpoints = [
{ route, response: OK_RESPONSE, method: REQUEST_METHODS.PATCH },
];
// set random data in cache
queryClient.setQueryData(chatKey, ITEM_CHAT);

const mockedMutation = await mockMutation({
endpoints,
mutation,
wrapper,
});

await act(async () => {
await mockedMutation.mutate({ chatId, body: 'new message content' });
await waitForMutation();
});

// verify cache keys
expect(queryClient.getQueryState(chatKey)?.isInvalidated).toBeFalsy();
});
});

describe(MUTATION_KEYS.DELETE_ITEM_CHAT_MESSAGE, () => {
const route = `/${buildDeleteItemChatMessageRoute(itemId, messageId)}`;
const mutation = () => useMutation(MUTATION_KEYS.DELETE_ITEM_CHAT_MESSAGE);
it(`Delete item chat message`, async () => {
const endpoints = [
{ route, response: OK_RESPONSE, method: REQUEST_METHODS.DELETE },
];
// set random data in cache
queryClient.setQueryData(chatKey, ITEM_CHAT);

const mockedMutation = await mockMutation({
endpoints,
mutation,
wrapper,
});

await act(async () => {
await mockedMutation.mutate({ chatId, body: 'message to remove' });
await waitForMutation();
});

// verify cache keys
expect(queryClient.getQueryState(chatKey)?.isInvalidated).toBeFalsy();
});
});

describe(MUTATION_KEYS.CLEAR_ITEM_CHAT, () => {
const route = `/${buildClearItemChatRoute(itemId)}`;
const mutation = () => useMutation(MUTATION_KEYS.CLEAR_ITEM_CHAT);
it(`Clear chat`, async () => {
const endpoints = [
{ route, response: OK_RESPONSE, method: REQUEST_METHODS.DELETE },
];
// set random data in cache
queryClient.setQueryData(chatKey, ITEM_CHAT);

const mockedMutation = await mockMutation({
endpoints,
mutation,
wrapper,
});

await act(async () => {
await mockedMutation.mutate(itemId);
await waitForMutation();
});

// verify cache keys
expect(queryClient.getQueryState(chatKey)?.isInvalidated).toBeFalsy();
});
});
});
});
19 changes: 19 additions & 0 deletions src/mutations/chat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { QueryClient } from 'react-query';
import * as Api from '../api';
import { buildItemChatKey, MUTATION_KEYS } from '../config/keys';
import {
clearItemChatRoutine,
deleteItemChatMessageRoutine,
patchItemChatMessageRoutine,
postItemChatMessageRoutine,
Expand All @@ -12,6 +13,7 @@ const {
POST_ITEM_CHAT_MESSAGE,
PATCH_ITEM_CHAT_MESSAGE,
DELETE_ITEM_CHAT_MESSAGE,
CLEAR_ITEM_CHAT,
} = MUTATION_KEYS;

export default (queryClient: QueryClient, queryConfig: QueryClientConfig) => {
Expand Down Expand Up @@ -65,4 +67,21 @@ export default (queryClient: QueryClient, queryConfig: QueryClientConfig) => {
}
},
});

queryClient.setMutationDefaults(CLEAR_ITEM_CHAT, {
mutationFn: (chatId) => Api.clearItemChat(chatId, queryConfig),
onError: (error) => {
queryConfig.notifier?.({
type: clearItemChatRoutine.FAILURE,
payload: { error },
});
},
onSettled: (_data, _error, chatId) => {
// invalidate keys only if websockets are disabled
// otherwise the cache is updated automatically
if (!queryConfig.enableWebsocket) {
queryClient.invalidateQueries(buildItemChatKey(chatId));
}
},
});
};
4 changes: 4 additions & 0 deletions src/routines/chat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,7 @@ export const patchItemChatMessageRoutine = createRoutine(
export const deleteItemChatMessageRoutine = createRoutine(
'DELETE_ITEM_CHAT_MESSAGE',
);

export const clearItemChatRoutine = createRoutine(
'CLEAR_ITEM_CHAT',
);
1 change: 1 addition & 0 deletions src/ws/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export const OPS = {
PUBLISH: 'publish',
UPDATE: 'update',
DELETE: 'delete',
CLEAR: 'clear',
CREATE: 'create',
};

Expand Down
5 changes: 5 additions & 0 deletions src/ws/hooks/chat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,11 @@ export const configureWsChatHooks = (
queryClient.setQueryData(chatKey, mutation);
break;
}
case OPS.CLEAR: {
const mutation = current.update('messages', () => []);
queryClient.setQueryData(chatKey, mutation);
break;
}
default:
break;
}
Expand Down

0 comments on commit fe8a3fa

Please sign in to comment.