diff --git a/src/api/action.ts b/src/api/action.ts index aa6bc977..4302754b 100644 --- a/src/api/action.ts +++ b/src/api/action.ts @@ -1,4 +1,4 @@ -import { ActionData, UUID } from '@graasp/sdk'; +import { Action, ActionData, UUID } from '@graasp/sdk'; import { QueryClientConfig } from '../types'; import { AggregateActionsArgs } from '../utils/action'; @@ -7,6 +7,7 @@ import { buildExportActions, buildGetActions, buildGetAggregateActions, + buildPostItemAction, } from './routes'; const axios = configureAxios(); @@ -34,3 +35,10 @@ export const exportActions = async ( { API_HOST }: QueryClientConfig, ): Promise => axios.post(`${API_HOST}/${buildExportActions(args.itemId)}`); + +export const postItemAction = async ( + itemId: UUID, + payload: { type: string; extra?: { [key: string]: unknown } }, + { API_HOST }: QueryClientConfig, +): Promise => + axios.post(`${API_HOST}/${buildPostItemAction(itemId)}`, payload); diff --git a/src/api/routes.ts b/src/api/routes.ts index 58fd277a..a2e00ec0 100644 --- a/src/api/routes.ts +++ b/src/api/routes.ts @@ -313,6 +313,8 @@ export const buildGetAggregateActions = (args: AggregateActionsArgs) => )}`; export const buildExportActions = (itemId: UUID) => `${ITEMS_ROUTE}/${itemId}/actions/export`; +export const buildPostItemAction = (itemId: UUID) => + `${ITEMS_ROUTE}/${itemId}/actions`; export const buildGetInvitationRoute = (id: UUID) => `${ITEMS_ROUTE}/${INVITATIONS_ROUTE}/${id}`; export const buildPatchInvitationRoute = (args: { itemId: UUID; id: UUID }) => @@ -410,7 +412,9 @@ export const API_ROUTES = { buildExportActions, buildExportItemChatRoute, buildExportItemRoute, + buildFavoriteItemRoute, buildGetActions, + buildGetAllPublishedItemsRoute, buildGetApiAccessTokenRoute, buildGetCategoriesRoute, buildGetCategoryRoute, @@ -426,7 +430,6 @@ export const API_ROUTES = { buildGetItemMembershipsForItemsRoute, buildGetItemPublishedInformationRoute, buildGetItemRoute, - SEARCH_PUBLISHED_ITEMS_ROUTE, buildGetItemsInCategoryRoute, buildGetItemTagsRoute, buildGetLastItemValidationGroupRoute, @@ -434,15 +437,15 @@ export const API_ROUTES = { buildGetMember, buildGetMembersBy, buildGetMembersRoute, - buildGetPlanRoute, - buildGetAllPublishedItemsRoute, buildGetMostLikedPublishedItemsRoute, buildGetMostRecentPublishedItemsRoute, + buildGetPlanRoute, buildGetPublishedItemsForMemberRoute, buildImportH5PRoute, buildImportZipRoute, buildItemPublishRoute, buildItemUnpublishRoute, + buildManyGetItemPublishedInformationsRoute, buildMoveItemRoute, buildMoveItemsRoute, buildPatchInvitationRoute, @@ -450,6 +453,7 @@ export const API_ROUTES = { buildPatchMember, buildPostEtherpadRoute, buildPostInvitationsRoute, + buildPostItemAction, buildPostItemCategoryRoute, buildPostItemChatMessageRoute, buildPostItemFlagRoute, @@ -470,18 +474,17 @@ export const API_ROUTES = { buildUploadAvatarRoute, buildUploadFilesRoute, buildUploadItemThumbnailRoute, - buildManyGetItemPublishedInformationsRoute, GET_CATEGORY_TYPES_ROUTE, GET_CURRENT_MEMBER_ROUTE, + GET_FAVORITE_ITEMS_ROUTE, GET_FLAGS_ROUTE, GET_ITEM_VALIDATION_REVIEWS_ROUTE, GET_ITEM_VALIDATION_STATUSES_ROUTE, GET_OWN_ITEMS_ROUTE, GET_RECYCLED_ITEMS_DATA_ROUTE, - GET_FAVORITE_ITEMS_ROUTE, - buildFavoriteItemRoute, GET_TAGS_ROUTE, ITEMS_ROUTE, + SEARCH_PUBLISHED_ITEMS_ROUTE, SHARED_ITEM_WITH_ROUTE, SIGN_IN_ROUTE, SIGN_IN_WITH_PASSWORD_ROUTE, diff --git a/src/mutations/action.test.ts b/src/mutations/action.test.ts index 9e27c798..d850d65c 100644 --- a/src/mutations/action.test.ts +++ b/src/mutations/action.test.ts @@ -11,8 +11,8 @@ import { UNAUTHORIZED_RESPONSE, } from '../../test/constants'; import { mockMutation, setUpTest, waitForMutation } from '../../test/utils'; -import { buildExportActions } from '../api/routes'; -import { exportActionsRoutine } from '../routines'; +import { buildExportActions, buildPostItemAction } from '../api/routes'; +import { exportActionsRoutine, postActionRoutine } from '../routines'; jest.spyOn(Cookies, 'get').mockReturnValue({ session: 'somesession' }); @@ -84,4 +84,61 @@ describe('Action Mutations', () => { ); }); }); + + describe('usePostItemAction', () => { + const route = `/${buildPostItemAction(itemId)}`; + const mutation = mutations.usePostItemAction; + const payload = { type: 'hello', extra: { to: 'me' } }; + + it(`Post Item Action`, async () => { + const endpoints = [ + { route, response: OK_RESPONSE, method: HttpMethod.POST }, + ]; + + const mockedMutation = await mockMutation({ + endpoints, + mutation, + wrapper, + }); + + await act(async () => { + await mockedMutation.mutate({ itemId, payload }); + await waitForMutation(); + }); + + expect(mockedNotifier).toHaveBeenCalledWith( + expect.objectContaining({ + type: postActionRoutine.SUCCESS, + }), + ); + }); + + it(`Unauthorized`, async () => { + const endpoints = [ + { + route, + response: UNAUTHORIZED_RESPONSE, + method: HttpMethod.POST, + statusCode: StatusCodes.UNAUTHORIZED, + }, + ]; + + const mockedMutation = await mockMutation({ + endpoints, + mutation, + wrapper, + }); + + await act(async () => { + await mockedMutation.mutate({ itemId, payload }); + await waitForMutation(); + }); + + expect(mockedNotifier).toHaveBeenCalledWith( + expect.objectContaining({ + type: postActionRoutine.FAILURE, + }), + ); + }); + }); }); diff --git a/src/mutations/action.ts b/src/mutations/action.ts index c5d87903..245675d5 100644 --- a/src/mutations/action.ts +++ b/src/mutations/action.ts @@ -2,11 +2,32 @@ import { UUID } from '@graasp/sdk'; import { useMutation } from 'react-query'; -import { exportActions } from '../api'; -import { exportActionsRoutine } from '../routines'; +import { exportActions, postItemAction } from '../api'; +import { exportActionsRoutine, postActionRoutine } from '../routines'; import { QueryClientConfig } from '../types'; export default (queryConfig: QueryClientConfig) => { + const usePostItemAction = () => + useMutation( + (args: { + itemId: UUID; + payload: { type: string; extra?: { [key: string]: unknown } }; + }) => postItemAction(args.itemId, args.payload, queryConfig), + { + onSuccess: () => { + queryConfig.notifier?.({ + type: postActionRoutine.SUCCESS, + }); + }, + onError: (error: Error) => { + queryConfig.notifier?.({ + type: postActionRoutine.FAILURE, + payload: { error }, + }); + }, + }, + ); + const useExportActions = () => useMutation((itemId: UUID) => exportActions({ itemId }, queryConfig), { onSuccess: () => { @@ -23,6 +44,7 @@ export default (queryConfig: QueryClientConfig) => { }); return { + usePostItemAction, useExportActions, }; }; diff --git a/src/routines/action.ts b/src/routines/action.ts index b08b670a..4eed39fb 100644 --- a/src/routines/action.ts +++ b/src/routines/action.ts @@ -1,4 +1,4 @@ import createRoutine from './utils'; -// eslint-disable-next-line import/prefer-default-export +export const postActionRoutine = createRoutine('POST_ACTION'); export const exportActionsRoutine = createRoutine('EXPORT_ACTIONS');