Skip to content
This repository was archived by the owner on Feb 12, 2025. It is now read-only.

Commit 3beb96c

Browse files
committed
feat: mutation for item publish
1 parent bac21c9 commit 3beb96c

File tree

9 files changed

+155
-0
lines changed

9 files changed

+155
-0
lines changed

src/api/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,4 @@ export * from './itemLike';
1414
export * from './itemValidation';
1515
export * from './action';
1616
export * from './invitation';
17+
export * from './itemPublish';

src/api/itemPublish.ts

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { QueryClientConfig, UUID } from '../types';
2+
import configureAxios, { verifyAuthentication } from './axios';
3+
import { buildItemPublishRoute } from './routes';
4+
5+
const axios = configureAxios();
6+
7+
/* eslint-disable import/prefer-default-export */
8+
export const publishItem = async (
9+
id: UUID,
10+
notification: boolean,
11+
{ API_HOST }: QueryClientConfig,
12+
) =>
13+
verifyAuthentication(() =>
14+
axios
15+
.get(`${API_HOST}/${buildItemPublishRoute(id, notification)}`)
16+
.then(({ data }) => data),
17+
);

src/api/routes.ts

+3
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,9 @@ export const buildPostInvitationsRoute = (itemId: UUID) =>
277277
export const buildResendInvitationRoute = (args: { itemId: UUID; id: UUID }) =>
278278
`${ITEMS_ROUTE}/${args.itemId}/${INVITATIONS_ROUTE}/${args.id}/send`;
279279

280+
export const buildItemPublishRoute = (itemId: UUID, notification: boolean) =>
281+
`${ITEMS_ROUTE}/${itemId}/publish${qs.stringify(notification)}`;
282+
280283
export const API_ROUTES = {
281284
APPS_ROUTE,
282285
ITEMS_ROUTE,

src/config/keys.ts

+1
Original file line numberDiff line numberDiff line change
@@ -233,4 +233,5 @@ export const MUTATION_KEYS = {
233233
PATCH_INVITATION: 'patchInvitation',
234234
DELETE_INVITATION: 'deleteInvitation',
235235
RESEND_INVITATION: 'resendInvitation',
236+
PUBLISH_ITEM: 'publishItem',
236237
};

src/mutations/index.ts

+2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import itemValidationMutations from './itemValidation';
1414
import actionMutations from './action';
1515
import invitationMutations from './invitation';
1616
import authenticationMutations from './authentication';
17+
import itemPublishMutations from './itemPublish';
1718

1819
const configureMutations = (
1920
queryClient: QueryClient,
@@ -33,6 +34,7 @@ const configureMutations = (
3334
actionMutations(queryClient, queryConfig);
3435
invitationMutations(queryClient, queryConfig);
3536
authenticationMutations(queryClient, queryConfig);
37+
itemPublishMutations(queryClient, queryConfig);
3638
};
3739

3840
export default configureMutations;

src/mutations/itemPublish.test.ts

+101
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
/* eslint-disable import/no-extraneous-dependencies */
2+
import nock from 'nock';
3+
import Cookies from 'js-cookie';
4+
import { act } from 'react-test-renderer';
5+
import { StatusCodes } from 'http-status-codes';
6+
import { mockMutation, setUpTest, waitForMutation } from '../../test/utils';
7+
import { REQUEST_METHODS } from '../api/utils';
8+
import { buildItemTagsKey, MUTATION_KEYS } from '../config/keys';
9+
import {
10+
buildItemPublishRoute,
11+
} from '../api/routes';
12+
import { publishItemRoutine } from '../routines';
13+
import { ITEMS, ITEM_TAGS, UNAUTHORIZED_RESPONSE } from '../../test/constants';
14+
15+
const mockedNotifier = jest.fn();
16+
const { wrapper, queryClient, useMutation } = setUpTest({
17+
notifier: mockedNotifier,
18+
});
19+
20+
jest.spyOn(Cookies, 'get').mockReturnValue({ session: 'somesession' });
21+
22+
describe('Publish Item', () => {
23+
afterEach(() => {
24+
queryClient.clear();
25+
nock.cleanAll();
26+
});
27+
28+
describe(MUTATION_KEYS.PUBLISH_ITEM, () => {
29+
const item = ITEMS[0];
30+
const itemId = item.id;
31+
const notification = true;
32+
const route = `/${buildItemPublishRoute(itemId, notification)}`;
33+
const mutation = () => useMutation(MUTATION_KEYS.PUBLISH_ITEM);
34+
const itemTagKey = buildItemTagsKey(itemId);
35+
36+
it('Publish Item', async () => {
37+
queryClient.setQueryData(itemTagKey, ITEM_TAGS);
38+
39+
const endpoints = [
40+
{
41+
response: { item },
42+
method: REQUEST_METHODS.GET,
43+
route,
44+
},
45+
];
46+
47+
const mockedMutation = await mockMutation({
48+
endpoints,
49+
mutation,
50+
wrapper,
51+
});
52+
53+
await act(async () => {
54+
await mockedMutation.mutate({
55+
id: itemId,
56+
notification,
57+
});
58+
await waitForMutation();
59+
});
60+
61+
expect(queryClient.getQueryState(itemTagKey)?.isInvalidated).toBeTruthy();
62+
expect(mockedNotifier).toHaveBeenCalledWith({
63+
type: publishItemRoutine.SUCCESS,
64+
});
65+
});
66+
67+
it('Unauthorized to publish item', async () => {
68+
queryClient.setQueryData(itemTagKey, ITEM_TAGS);
69+
70+
const endpoints = [
71+
{
72+
response: UNAUTHORIZED_RESPONSE,
73+
statusCode: StatusCodes.UNAUTHORIZED,
74+
method: REQUEST_METHODS.GET,
75+
route,
76+
},
77+
];
78+
79+
const mockedMutation = await mockMutation({
80+
endpoints,
81+
mutation,
82+
wrapper,
83+
});
84+
85+
await act(async () => {
86+
await mockedMutation.mutate({
87+
id: itemId,
88+
notification,
89+
});
90+
await waitForMutation();
91+
});
92+
93+
// expect(queryClient.getQueryState(itemTagKey)?.isInvalidated).toBeTruthy();
94+
expect(mockedNotifier).toHaveBeenCalledWith(
95+
expect.objectContaining({
96+
type: publishItemRoutine.FAILURE,
97+
}),
98+
);
99+
});
100+
});
101+
});

src/mutations/itemPublish.ts

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { QueryClient } from 'react-query';
2+
import * as Api from '../api';
3+
import { MUTATION_KEYS, buildItemTagsKey } from '../config/keys';
4+
import { publishItemRoutine } from '../routines';
5+
import { QueryClientConfig } from '../types';
6+
7+
export default (queryClient: QueryClient, queryConfig: QueryClientConfig) => {
8+
const { notifier } = queryConfig;
9+
10+
/**
11+
* @param notification {boolean} send out email notification
12+
*/
13+
queryClient.setMutationDefaults(MUTATION_KEYS.PUBLISH_ITEM, {
14+
mutationFn: ({ id, notification }) => Api.publishItem(id, notification, queryConfig ),
15+
onSuccess: () => {
16+
notifier?.({ type: publishItemRoutine.SUCCESS });
17+
},
18+
onError: (error) => {
19+
notifier?.({ type: publishItemRoutine.FAILURE, payload: { error } });
20+
},
21+
onSettled: (_data, _error, { id }) => {
22+
queryClient.invalidateQueries(buildItemTagsKey(id));
23+
},
24+
});
25+
};

src/routines/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@ export * from './itemValidation';
1212
export * from './action';
1313
export * from './invitation';
1414
export * from './authentication';
15+
export * from './itemPublish';

src/routines/itemPublish.ts

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import createRoutine from './utils';
2+
3+
/* eslint-disable import/prefer-default-export */
4+
export const publishItemRoutine = createRoutine('PUBLISH_ITEM');

0 commit comments

Comments
 (0)