diff --git a/packages/marketplace/src/actions/__tests__/webhook-edit-modal.ts b/packages/marketplace/src/actions/__tests__/webhook-edit-modal.ts index 22377fa93d..73d09bcf1b 100644 --- a/packages/marketplace/src/actions/__tests__/webhook-edit-modal.ts +++ b/packages/marketplace/src/actions/__tests__/webhook-edit-modal.ts @@ -1,7 +1,6 @@ import { requestWebhookSubcriptionData, requestWebhookSubcriptionReceiveData, - webhookEditLoading, createWebhook, CreateWebhookParams, requestWebhookData, @@ -11,11 +10,6 @@ import ActionTypes from '../../constants/action-types' import { webhookDataStub } from '@/sagas/__stubs__/webhook-edit' describe('developer webhook actions', () => { - it('should create a developerWebhookLoading action', () => { - expect(webhookEditLoading.type).toEqual(ActionTypes.WEBHOOK_EDIT_LOADING) - expect(webhookEditLoading(true).data).toEqual(true) - }) - it('should create a requestDeveloperWebhookData action', () => { expect(requestWebhookSubcriptionData.type).toEqual(ActionTypes.WEBHOOK_EDIT_SUBCRIPTION_REQUEST_DATA) }) diff --git a/packages/marketplace/src/actions/webhook-edit-modal.ts b/packages/marketplace/src/actions/webhook-edit-modal.ts index 18f75199b9..703ef8999e 100644 --- a/packages/marketplace/src/actions/webhook-edit-modal.ts +++ b/packages/marketplace/src/actions/webhook-edit-modal.ts @@ -1,23 +1,19 @@ import { actionCreator } from '../utils/actions' import ActionTypes from '../constants/action-types' import { WebhookModal, WebhookSubscription } from '@/reducers/webhook-edit-modal' -import { StringMap } from '../../../elements/src/types/core' export interface SubscriptionCustomersRequestParams { AppId: string } export interface SubscriptionTopicsRequestParams { applicationId: string - headers: StringMap } export interface FetchWebhookRequestParams { - headers: StringMap webhookId: string } export interface DeleteWebhookRequestParams { - headers: StringMap webhookId: string } @@ -52,7 +48,6 @@ export interface EditWebhookParams { active: boolean } -export const webhookEditLoading = actionCreator(ActionTypes.WEBHOOK_EDIT_LOADING) export const requestWebhookSubcriptionData = actionCreator(ActionTypes.WEBHOOK_EDIT_SUBCRIPTION_REQUEST_DATA) export const requestWebhookSubcriptionReceiveData = actionCreator( ActionTypes.WEBHOOK_EDIT_SUBCRIPTION_RECEIVE_DATA, diff --git a/packages/marketplace/src/actions/webhook-subscriptions.ts b/packages/marketplace/src/actions/webhook-subscriptions.ts index de6dca945e..004ae16f0e 100644 --- a/packages/marketplace/src/actions/webhook-subscriptions.ts +++ b/packages/marketplace/src/actions/webhook-subscriptions.ts @@ -6,6 +6,6 @@ export const webhookSubscriptionsRequestData = actionCreator(ActionTypes export const webhookSubscriptionsReceiveData = actionCreator( ActionTypes.WEBHOOK_SUBSCRIPTION_RECEIVE_DATA, ) -export const webhookTopicsRequestData = actionCreator(ActionTypes.WEBHOOK_TOPICS_REQUEST_DATA) +export const webhookTopicsRequestData = actionCreator(ActionTypes.WEBHOOK_TOPICS_REQUEST_DATA) export const webhookTopicsReceiveData = actionCreator(ActionTypes.WEBHOOK_TOPICS_RECEIVE_DATA) export const setApplicationId = actionCreator(ActionTypes.WEBHOOK_SET_APPLICATION_ID) diff --git a/packages/marketplace/src/components/pages/__tests__/__snapshots__/developer-webhooks.tsx.snap b/packages/marketplace/src/components/pages/__tests__/__snapshots__/developer-webhooks.tsx.snap index a77d67bc35..a6b8eeacbb 100644 --- a/packages/marketplace/src/components/pages/__tests__/__snapshots__/developer-webhooks.tsx.snap +++ b/packages/marketplace/src/components/pages/__tests__/__snapshots__/developer-webhooks.tsx.snap @@ -28,16 +28,7 @@ exports[`DeveloperWebHooks should match a snapshot 1`] = ` - - - Add New Webhook - - + { describe('mapDispatchToProps', () => { it('should call dispatch correctly', () => { const mockDispatch = jest.fn() - const { fetchTopics } = mapDispatchToProps(mockDispatch) + const { fetchTopics, fetchSubscriptions, setApplicationId, webhookSetOpenModal } = mapDispatchToProps( + mockDispatch, + ) + fetchSubscriptions('applicationId') fetchTopics('applicationId') + setApplicationId('applicationId') + webhookSetOpenModal('applicationId') expect(mockDispatch).toBeCalled() }) }) @@ -101,18 +112,74 @@ describe('DeveloperWebHooks', () => { describe('handleSubscriptionChange', () => { it('should run correctly', () => { const fetchTopics = jest.fn() + const fetchSubscriptions = jest.fn() const values = { applicationId: '123' } - handleSubscriptionChange(fetchTopics)(values) + handleSubscriptionChange({ fetchTopics, fetchSubscriptions })(values) expect(fetchTopics).toHaveBeenCalledWith(values.applicationId) + expect(fetchSubscriptions).toHaveBeenCalledWith(values.applicationId) }) }) + describe('renderTopicName', () => { + it('should run correctly', () => { + const topics: TopicModel[] = [ + { + id: 'XXX', + created: '', + modified: '', + name: 'xxx', + description: '', + url: '', + active: false, + associatedScope: '', + example: '', + }, + { + id: 'YYY', + created: '', + modified: '', + name: 'yyy', + description: '', + url: '', + active: false, + associatedScope: '', + example: '', + }, + ] + const subscriptionTopicIds: string[] = ['XXX', 'YYY'] + const result = renderTopicName(topics, subscriptionTopicIds) + const expected = ['xxx', 'yyy'] + expect(result).toEqual(expected) + }) + }) + describe('renderCustomerName', () => { + it('should run correctly', () => { + const subscriptionCustomerIds = ['XXX', 'yyy'] + const subscriptionCustomerIdsEmpty = [] + const result = renderCustomerName(subscriptionCustomerIds) + const expected = ['XXX', 'yyy'] + expect(result).toEqual(expected) - describe('getTableTopicsData', () => { + const emptyResult = renderCustomerName(subscriptionCustomerIdsEmpty) + expect(emptyResult).toEqual(['All Customers (*)']) + }) + }) + describe('openEditModal', () => { it('should run correctly', () => { - const fetchTopics = jest.fn() - const values = { applicationId: '123' } - handleSubscriptionChange(fetchTopics)(values) - expect(fetchTopics).toHaveBeenCalledWith(values.applicationId) + const webhookSetOpenModal = jest.fn() + const setWebhookId = jest.fn() + const webhookId = 'webhookId' + + openEditModal({ webhookSetOpenModal, setWebhookId })(webhookId) + expect(webhookSetOpenModal).toBeCalledWith(MODAL_TYPE.EDIT) + expect(setWebhookId).toBeCalledWith(webhookId) + }) + }) + describe('openCreateModal', () => { + it('should run correctly', () => { + const webhookSetOpenModal = jest.fn() + + openCreateModal(webhookSetOpenModal)() + expect(webhookSetOpenModal).toBeCalledWith(MODAL_TYPE.CREATE) }) }) }) diff --git a/packages/marketplace/src/components/pages/developer-webhooks.tsx b/packages/marketplace/src/components/pages/developer-webhooks.tsx index 7754d06ead..0309f868a6 100644 --- a/packages/marketplace/src/components/pages/developer-webhooks.tsx +++ b/packages/marketplace/src/components/pages/developer-webhooks.tsx @@ -1,4 +1,4 @@ -import React from 'react' +import React, { ReactElement } from 'react' import { Loader, SelectBoxOptions } from '@reapit/elements' import { ReduxState } from '@/types/core' import { DeveloperState } from '@/reducers/developer' @@ -18,7 +18,11 @@ import { import { AppSummaryModel } from '@reapit/foundations-ts-definitions' import { compose, Dispatch } from 'redux' import { Form, Formik } from 'formik' -import { webhookSubscriptionsRequestData, setApplicationId } from '@/actions/webhook-subscriptions' +import { + webhookSubscriptionsRequestData, + setApplicationId, + webhookTopicsRequestData, +} from '@/actions/webhook-subscriptions' import { webhookSetOpenModal } from '@/actions/webhook-edit-modal' import { WebhookModel, TopicModel } from '@/reducers/webhook-subscriptions' import { @@ -31,6 +35,10 @@ import FormikAutoSave from '@/components/hocs/formik-auto-save' import WebhookEditModal from '../ui/webhook-edit-modal' import { selectDeveloperApps } from '@/selector/developer' +export const CreatedCell = ({ cell: { value } }): ReactElement[] => { + return value.map((line, index) =>

{line}

) +} + export const columns = [ { Header: 'URL', @@ -39,10 +47,12 @@ export const columns = [ { Header: 'Topics', accessor: 'topics', + Cell: CreatedCell, }, { Header: 'Customer', accessor: 'customer', + Cell: CreatedCell, }, { Header: 'Test Webhook', @@ -54,12 +64,13 @@ export const columns = [ }, ] -const MODAL_TYPE = { +export const MODAL_TYPE = { EDIT: 'EDIT', CREATE: 'CREATE', } -export const handleSubscriptionChange = fetchTopics => (values): void => { +export const handleSubscriptionChange = ({ fetchTopics, fetchSubscriptions }) => (values): void => { + fetchSubscriptions(values.applicationId) fetchTopics(values.applicationId) } @@ -78,20 +89,30 @@ export const openEditModal = ({ webhookSetOpenModal, setWebhookId }: OpenEditMod setWebhookId(webhookId) } -export const renderTopicName = (subscriptionTopicIds: string[]) => { - return subscriptionTopicIds.join('\n') +export const renderTopicName = (topics: TopicModel[], subscriptionTopicIds: string[]) => { + const subscriptionTopics = topics.filter(topic => subscriptionTopicIds.includes(topic.id)) + const subscriptionTopicsName = subscriptionTopics.map(topic => topic.name) + return subscriptionTopicsName +} + +export const renderCustomerName = (subscriptionCustomerIds: string[]) => { + if (subscriptionCustomerIds.length) { + return subscriptionCustomerIds + } + return ['All Customers (*)'] } type GetTableTopicsDataParams = { subscriptions: WebhookModel[] + topics: TopicModel[] handleOpenEditModal: (webhookId: string) => void } -export const getTableTopicsData = ({ subscriptions, handleOpenEditModal }: GetTableTopicsDataParams) => { +export const getTableTopicsData = ({ subscriptions, topics, handleOpenEditModal }: GetTableTopicsDataParams) => { return subscriptions?.map((subscription: WebhookModel) => ({ url: subscription.url, - topics: renderTopicName(subscription.topicIds), - customer: 'All Customers (*)', + topics: renderTopicName(topics, subscription.topicIds), + customer: renderCustomerName(subscription.customerIds), test: 'Ping', edit: ( + {applicationId && ( + + )} {unfetched || loading || subscriptionsLoading ? ( @@ -189,7 +214,7 @@ export const DeveloperWebhooks = ({ )} @@ -208,6 +233,7 @@ export const DeveloperWebhooks = ({ } export type DispatchProps = { + fetchSubscriptions: (applicationId: string) => void fetchTopics: (applicationId: string) => void setApplicationId: (applicationId: string) => void webhookSetOpenModal: (type: string) => void @@ -225,7 +251,8 @@ export const mapStateToProps = (state: ReduxState): StateProps => ({ export const mapDispatchToProps = (dispatch: Dispatch): DispatchProps => { return { - fetchTopics: (applicationId: string) => dispatch(webhookSubscriptionsRequestData(applicationId)), + fetchSubscriptions: (applicationId: string) => dispatch(webhookSubscriptionsRequestData(applicationId)), + fetchTopics: (applicationId: string) => dispatch(webhookTopicsRequestData(applicationId)), setApplicationId: (applicationId: string) => dispatch(setApplicationId(applicationId)), webhookSetOpenModal: (type: string) => dispatch(webhookSetOpenModal(type)), } diff --git a/packages/marketplace/src/components/ui/__tests__/__snapshots__/webhook-edit-modal.tsx.snap b/packages/marketplace/src/components/ui/__tests__/__snapshots__/webhook-edit-modal.tsx.snap index a3fbd9b47b..76d7e06f97 100644 --- a/packages/marketplace/src/components/ui/__tests__/__snapshots__/webhook-edit-modal.tsx.snap +++ b/packages/marketplace/src/components/ui/__tests__/__snapshots__/webhook-edit-modal.tsx.snap @@ -100,7 +100,6 @@ exports[`WebhookEditModal should match a snapshot 5`] = ` ] } placeholder="All Customers who have installed your application (default)" - required={true} /> { describe('mapDispatchToProps', () => { it('should run correctly', () => { const mockDispatch = jest.fn() - const { requestWebhookSubcriptionData, createWebhook, editWebhook, requestWebhookData } = mapDispatchToProps( - mockDispatch, - ) + const { + requestWebhookSubcriptionData, + createWebhook, + editWebhook, + requestWebhookData, + webhookDataClear, + deleteWebhook, + } = mapDispatchToProps(mockDispatch) requestWebhookSubcriptionData('1') requestWebhookData('1') const values = { @@ -95,6 +100,8 @@ describe('WebhookEditModal', () => { } createWebhook(values) editWebhook(values) + webhookDataClear() + deleteWebhook(values) expect(mockDispatch).toBeCalled() }) }) diff --git a/packages/marketplace/src/components/ui/webhook-edit-modal.tsx b/packages/marketplace/src/components/ui/webhook-edit-modal.tsx index 6eb717b195..0483b723b1 100644 --- a/packages/marketplace/src/components/ui/webhook-edit-modal.tsx +++ b/packages/marketplace/src/components/ui/webhook-edit-modal.tsx @@ -226,7 +226,6 @@ export const WebhookModalInner: React.FunctionComponent labelText="Subscription Customers" options={customerOptions} dropdownStyle={{ zIndex: 41 }} - required /> diff --git a/packages/marketplace/src/reducers/__tests__/webhook-edit-modal.ts b/packages/marketplace/src/reducers/__tests__/webhook-edit-modal.ts index 73f7f9ba0c..7d84e6db37 100644 --- a/packages/marketplace/src/reducers/__tests__/webhook-edit-modal.ts +++ b/packages/marketplace/src/reducers/__tests__/webhook-edit-modal.ts @@ -21,17 +21,6 @@ describe('developer webhook reducer', () => { expect(newState).toEqual(expected) }) - it('should set loading to test when WEBHOOK_EDIT_LOADING action is called with true', () => { - const newState = DeveloperWebhookReducer(undefined, { - type: ActionTypes.WEBHOOK_EDIT_LOADING as ActionType, - data: true, - }) - const expected = { - ...defaultState, - loading: true, - } - expect(newState).toEqual(expected) - }) it('should set loading to test when WEBHOOK_EDIT_SUBCRIPTION_REQUEST_DATA_FAILURE action is called with true', () => { const newState = DeveloperWebhookReducer(undefined, { type: ActionTypes.WEBHOOK_EDIT_SUBCRIPTION_REQUEST_DATA_FAILURE as ActionType, @@ -51,6 +40,7 @@ describe('developer webhook reducer', () => { const expected = { ...defaultState, webhookData: webhookItemDataStub, + loading: false, } expect(newState).toEqual(expected) }) diff --git a/packages/marketplace/src/reducers/webhook-edit-modal.ts b/packages/marketplace/src/reducers/webhook-edit-modal.ts index afcf75092d..d76f780e75 100644 --- a/packages/marketplace/src/reducers/webhook-edit-modal.ts +++ b/packages/marketplace/src/reducers/webhook-edit-modal.ts @@ -3,10 +3,11 @@ import { isType } from '../utils/actions' import { requestWebhookSubcriptionReceiveData, requestWebhookSubcriptionReceiveFailure, - webhookEditLoading, requestWebhookReceiveData, webhookDataClear, webhookSetOpenModal, + requestWebhookSubcriptionData, + requestWebhookData, } from '../actions/webhook-edit-modal' export interface WebhookModal { @@ -97,23 +98,23 @@ export const defaultState: WebhookEditState = { } const WebhookEditReducer = (state: WebhookEditState = defaultState, action: Action): WebhookEditState => { - if (isType(action, requestWebhookSubcriptionReceiveData)) { + if (isType(action, requestWebhookSubcriptionData) || isType(action, requestWebhookData)) { return { ...state, - loading: false, - ...action.data, + loading: true, } } - if (isType(action, requestWebhookSubcriptionReceiveFailure)) { + if (isType(action, requestWebhookSubcriptionReceiveData)) { return { ...state, loading: false, + ...action.data, } } - if (isType(action, webhookEditLoading)) { + if (isType(action, requestWebhookSubcriptionReceiveFailure)) { return { ...state, - loading: action.data, + loading: false, } } if (isType(action, requestWebhookReceiveData)) { diff --git a/packages/marketplace/src/sagas/__tests__/webhook-edit-modal.ts b/packages/marketplace/src/sagas/__tests__/webhook-edit-modal.ts index 11eabdbc29..2532b8ffb7 100644 --- a/packages/marketplace/src/sagas/__tests__/webhook-edit-modal.ts +++ b/packages/marketplace/src/sagas/__tests__/webhook-edit-modal.ts @@ -9,39 +9,48 @@ import developerWebhookSagas, { requestWebhookSupcriptionDataListen, requestWebhookDataListen, deleteWebhookListen, + deleteWebhook, + editWebhook, + createNewWebhook, + deleteEditWebhook, + putEditWebhook, + postCreateWebhook, } from '../webhook-edit-modal' -import { call, put, all, fork } from '@redux-saga/core/effects' +import { call, put, all, fork, takeLatest } from '@redux-saga/core/effects' import { requestWebhookSubcriptionReceiveData, - webhookEditLoading, requestWebhookReceiveData, - requestWebhookReceiveDataFailure, requestWebhookSubcriptionReceiveFailure, + DeleteWebhookParams, + EditWebhookParams, + CreateWebhookParams, + requestWebhookSubcriptionData, + requestWebhookReceiveDataFailure, + webhookSetOpenModal, } from '@/actions/webhook-edit-modal' import { cloneableGenerator } from '@redux-saga/testing-utils' -import { initAuthorizedRequestHeaders } from '@/constants/api' import { webhookDataStub, webhookItemDataStub } from '../__stubs__/webhook-edit' import { errorThrownServer } from '@/actions/error' import errorMessages from '../../../../elements/src/utils/validators/error-messages' -import { setApplicationId } from '@/actions/webhook-subscriptions' +import { setApplicationId, webhookSubscriptionsReceiveData } from '@/actions/webhook-subscriptions' +import ActionTypes from '@/constants/action-types' +import { Action } from '@/types/core' +import { fetchSubscriptions } from '../webhook-subscriptions' +import { subscriptions } from '../__stubs__/webhooks' +import { initAuthorizedRequestHeaders } from '@/constants/api' +import { fetcher } from '@reapit/elements' jest.mock('@reapit/elements') const applicationId = '1161242a-f650-4d1d-aed7-909853fe7ee1' const params = { data: applicationId } -const mockHeaders = { - Authorization: '123', -} + describe('developer fetch subscription data', () => { const gen = cloneableGenerator(requestSupcriptionData as any)(params) - expect(gen.next().value).toEqual(put(webhookEditLoading(true))) expect(gen.next().value).toEqual(put(setApplicationId(applicationId))) - const header = gen.next().value - expect(header).toEqual(call(initAuthorizedRequestHeaders)) - - expect(gen.next(mockHeaders as any).value).toEqual( + expect(gen.next().value).toEqual( all([ - call(fetchWebhookSubscriptionTopics, { applicationId, headers: mockHeaders }), + call(fetchWebhookSubscriptionTopics, { applicationId }), call(fetchWebhookSubscriptionCustomers, { AppId: applicationId }), ]), ) @@ -75,27 +84,22 @@ describe('developer fetch subscription data', () => { }) describe('developer fetch webhook data', () => { - const webhookId = '1161242a-f650-4d1d-aed7-909853fe7ee1' + const webhookId = '' + const applicationId = '' const gen = cloneableGenerator(requestWebhookData as any)({ data: webhookId }) - expect(gen.next().value).toEqual(put(webhookEditLoading(true))) - const header = gen.next().value - expect(header).toEqual(call(initAuthorizedRequestHeaders)) - expect(gen.next(mockHeaders as any).value).toEqual(call(fetchWebhookData, { webhookId, headers: mockHeaders })) + expect(gen.next().value).toEqual(call(fetchWebhookData, { webhookId })) it('api call success', () => { const clone = gen.clone() expect(clone.next(webhookItemDataStub as any).value).toEqual(put(requestWebhookReceiveData(webhookItemDataStub))) - }) - test('api call fail', () => { - const clone = gen.clone() - expect(clone.next(undefined).value).toEqual(put(requestWebhookReceiveDataFailure())) - expect(clone.next().done).toBe(true) + expect(clone.next(applicationId).value).toEqual(put(requestWebhookSubcriptionData(applicationId))) }) test('api call fail', () => { const clone = gen.clone() // @ts-ignore - expect(clone.throw(new Error('Call API Failed')).value).toEqual( + expect(clone.throw(new Error('Call API Failed')).value).toEqual(put(requestWebhookReceiveDataFailure())) + expect(clone.next().value).toEqual( put( errorThrownServer({ type: 'SERVER', @@ -106,7 +110,6 @@ describe('developer fetch webhook data', () => { expect(clone.next().done).toBe(true) }) }) - describe('developerWebhookSagas', () => { it('should listen request data', () => { const gen = developerWebhookSagas() @@ -123,3 +126,239 @@ describe('developerWebhookSagas', () => { expect(gen.next().done).toBe(true) }) }) +describe('webhook edit thunks', () => { + describe('deleteWebhookListen', () => { + it('should deleteWebhook when called', () => { + const gen = deleteWebhookListen() + expect(gen.next().value).toEqual( + takeLatest>(ActionTypes.WEBHOOK_DELETE, deleteWebhook), + ) + expect(gen.next().done).toBe(true) + }) + }) + describe('requestWebhookDataListen', () => { + it('should requestWebhookData when called', () => { + const gen = requestWebhookDataListen() + expect(gen.next().value).toEqual(takeLatest>(ActionTypes.WEBHOOK_REQUEST_DATA, requestWebhookData)) + expect(gen.next().done).toBe(true) + }) + }) + describe('editWebhookListen', () => { + it('should editWebhook when called', () => { + const gen = editWebhookListen() + expect(gen.next().value).toEqual(takeLatest>(ActionTypes.WEBHOOK_EDIT, editWebhook)) + expect(gen.next().done).toBe(true) + }) + }) + describe('createWebhookListen', () => { + it('should createNewWebhook when called', () => { + const gen = createWebhookListen() + expect(gen.next().value).toEqual( + takeLatest>(ActionTypes.WEBHOOK_CREATE, createNewWebhook), + ) + expect(gen.next().done).toBe(true) + }) + }) + describe('requestWebhookSupcriptionDataListen', () => { + it('should createNewWebhook when called', () => { + const gen = requestWebhookSupcriptionDataListen() + expect(gen.next().value).toEqual( + takeLatest>(ActionTypes.WEBHOOK_EDIT_SUBCRIPTION_REQUEST_DATA, requestSupcriptionData), + ) + expect(gen.next().done).toBe(true) + }) + }) +}) + +describe('deleteWebhook', () => { + const webhookId = 'webhookId' + const applicationId = 'applicationId' + const gen = cloneableGenerator(deleteWebhook as any)({ data: { applicationId, webhookId } }) + expect(gen.next().value).toEqual(call(deleteEditWebhook, { webhookId })) + + it('api call success', () => { + const clone = gen.clone() + expect(clone.next(true).value).toEqual(put(webhookSetOpenModal(''))) + expect(clone.next().value).toEqual(call(fetchSubscriptions, applicationId)) + expect(clone.next(subscriptions).value).toEqual(put(webhookSubscriptionsReceiveData(subscriptions))) + expect(clone.next().done).toBe(true) + }) + it('api call error', () => { + const clone = gen.clone() + // @ts-ignore + expect(clone.throw(new Error('Call API Failed')).value).toEqual( + put( + errorThrownServer({ + type: 'SERVER', + message: errorMessages.DEFAULT_SERVER_ERROR, + }), + ), + ) + expect(clone.next().done).toBe(true) + }) +}) + +describe('editWebhook', () => { + const data = { + applicationId: 'applicationId', + webhookId: 'webhookId', + url: 'url', + topicIds: [], + customerIds: [], + active: true, + } + const gen = cloneableGenerator(editWebhook as any)({ data }) + expect(gen.next().value).toEqual(call(putEditWebhook, data)) + + it('api call success', () => { + const clone = gen.clone() + expect(clone.next(true).value).toEqual(put(webhookSetOpenModal(''))) + expect(clone.next().value).toEqual(call(fetchSubscriptions, data.applicationId)) + expect(clone.next(subscriptions).value).toEqual(put(webhookSubscriptionsReceiveData(subscriptions))) + expect(clone.next().done).toBe(true) + }) + it('api call error', () => { + const clone = gen.clone() + // @ts-ignore + expect(clone.throw(new Error('Call API Failed')).value).toEqual( + put( + errorThrownServer({ + type: 'SERVER', + message: errorMessages.DEFAULT_SERVER_ERROR, + }), + ), + ) + expect(clone.next().done).toBe(true) + }) +}) + +describe('createNewWebhook', () => { + const data = { + applicationId: 'applicationId', + webhookId: 'webhookId', + url: 'url', + topicIds: [], + customerIds: [], + active: true, + } + const gen = cloneableGenerator(createNewWebhook as any)({ data }) + expect(gen.next().value).toEqual(call(postCreateWebhook, data)) + + it('api call success', () => { + const clone = gen.clone() + expect(clone.next(true).value).toEqual(put(webhookSetOpenModal(''))) + expect(clone.next().value).toEqual(call(fetchSubscriptions, data.applicationId)) + expect(clone.next(subscriptions).value).toEqual(put(webhookSubscriptionsReceiveData(subscriptions))) + expect(clone.next().done).toBe(true) + }) + it('api call error', () => { + const clone = gen.clone() + // @ts-ignore + expect(clone.throw(new Error('Call API Failed')).value).toEqual( + put( + errorThrownServer({ + type: 'SERVER', + message: errorMessages.DEFAULT_SERVER_ERROR, + }), + ), + ) + expect(clone.next().done).toBe(true) + }) +}) + +describe('deleteEditWebhook request', () => { + it('should deleteEditWebhook run correctly', () => { + deleteEditWebhook({ webhookId: '' }) + .then(() => { + expect(initAuthorizedRequestHeaders).toHaveBeenCalled() + }) + .then(() => { + expect(fetcher).toHaveBeenCalled() + }) + }) +}) + +describe('putEditWebhook request', () => { + it('should putEditWebhook run correctly', () => { + const data = { + applicationId: 'applicationId', + webhookId: 'webhookId', + url: 'url', + topicIds: [], + customerIds: [], + active: true, + } + putEditWebhook(data) + .then(() => { + expect(initAuthorizedRequestHeaders).toHaveBeenCalled() + }) + .then(() => { + expect(fetcher).toHaveBeenCalled() + }) + }) +}) + +describe('postCreateWebhook request', () => { + it('should postCreateWebhook run correctly', () => { + const data = { + applicationId: 'applicationId', + webhookId: 'webhookId', + url: 'url', + topicIds: [], + customerIds: [], + active: true, + } + postCreateWebhook(data) + .then(() => { + expect(initAuthorizedRequestHeaders).toHaveBeenCalled() + }) + .then(() => { + expect(fetcher).toHaveBeenCalled() + }) + }) +}) + +describe('fetchWebhookData request', () => { + it('should fetchWebhookData run correctly', () => { + const data = { + webhookId: 'webhookId', + } + fetchWebhookData(data) + .then(() => { + expect(initAuthorizedRequestHeaders).toHaveBeenCalled() + }) + .then(() => { + expect(fetcher).toHaveBeenCalled() + }) + }) +}) + +describe('fetchWebhookSubscriptionCustomers request', () => { + it('should fetchWebhookSubscriptionCustomers run correctly', () => { + const data = { + AppId: 'AppId', + } + fetchWebhookSubscriptionCustomers(data) + .then(() => { + expect(initAuthorizedRequestHeaders).toHaveBeenCalled() + }) + .then(() => { + expect(fetcher).toHaveBeenCalled() + }) + }) +}) + +describe('fetchWebhookSubscriptionTopics request', () => { + it('should fetchWebhookSubscriptionTopics run correctly', () => { + const data = { + applicationId: 'webhookId', + } + fetchWebhookSubscriptionTopics(data) + .then(() => { + expect(initAuthorizedRequestHeaders).toHaveBeenCalled() + }) + .then(() => { + expect(fetcher).toHaveBeenCalled() + }) + }) +}) diff --git a/packages/marketplace/src/sagas/__tests__/webhook-subscriptions.ts b/packages/marketplace/src/sagas/__tests__/webhook-subscriptions.ts index b565067fca..47e1d6db35 100644 --- a/packages/marketplace/src/sagas/__tests__/webhook-subscriptions.ts +++ b/packages/marketplace/src/sagas/__tests__/webhook-subscriptions.ts @@ -1,12 +1,13 @@ -import { +import webhookSubscriptionsSagas, { fetchSubscriptions, - fetchWebhookTopic, webhookSubscriptionsFetch, webhookTopicsFetch, + webhookSubscriptionsListen, + webhookTopicsListen, } from '../webhook-subscriptions' import { errorThrownServer } from '@/actions/error' import errorMessages from '@/constants/error-messages' -import { put, call } from '@redux-saga/core/effects' +import { put, call, fork, all, takeLatest } from '@redux-saga/core/effects' import { Action } from '@/types/core' import { cloneableGenerator } from '@redux-saga/testing-utils' import { subscriptions, topics } from '../__stubs__/webhooks' @@ -15,6 +16,8 @@ import { webhookTopicsReceiveData, setApplicationId, } from '@/actions/webhook-subscriptions' +import ActionTypes from '@/constants/action-types' +import { fetchWebhookTopic } from '@/services/topics' jest.mock('@reapit/elements') @@ -49,8 +52,12 @@ describe('webhook sagas', () => { }) describe('webhookTopics fetch data', () => { - const gen = cloneableGenerator(webhookTopicsFetch)() - expect(gen.next().value).toEqual(call(fetchWebhookTopic)) + const applicationIdParam: Action = { + data: 'applicationId', + type: 'WEBHOOK_SUBSCRIPTION_REQUEST_DATA', + } + const gen = cloneableGenerator(webhookTopicsFetch)(applicationIdParam) + expect(gen.next().value).toEqual(call(fetchWebhookTopic, { applicationId: applicationIdParam.data })) test('api call success', () => { const clone = gen.clone() @@ -72,3 +79,32 @@ describe('webhook sagas', () => { }) }) }) +describe('developerWebhookSagas', () => { + it('should listen request data', () => { + const gen = webhookSubscriptionsSagas() + + expect(gen.next().value).toEqual(all([fork(webhookSubscriptionsListen), fork(webhookTopicsListen)])) + expect(gen.next().done).toBe(true) + }) +}) + +describe('developerWebhook thunks', () => { + describe('webhookSubscriptionsListen', () => { + it('should webhookSubscriptionsFetch when called', () => { + const gen = webhookSubscriptionsListen() + expect(gen.next().value).toEqual( + takeLatest>(ActionTypes.WEBHOOK_SUBSCRIPTION_REQUEST_DATA, webhookSubscriptionsFetch), + ) + expect(gen.next().done).toBe(true) + }) + }) + describe('webhookTopicsListen', () => { + it('should webhookTopicsFetch when called', () => { + const gen = webhookTopicsListen() + expect(gen.next().value).toEqual( + takeLatest>(ActionTypes.WEBHOOK_TOPICS_REQUEST_DATA, webhookTopicsFetch), + ) + expect(gen.next().done).toBe(true) + }) + }) +}) diff --git a/packages/marketplace/src/sagas/webhook-edit-modal.ts b/packages/marketplace/src/sagas/webhook-edit-modal.ts index b46fe0c37c..6abd34dcbe 100644 --- a/packages/marketplace/src/sagas/webhook-edit-modal.ts +++ b/packages/marketplace/src/sagas/webhook-edit-modal.ts @@ -3,7 +3,6 @@ import { Action } from '../types/core' import ActionTypes from '../constants/action-types' import { WebhookModal } from '@/reducers/webhook-edit-modal' import { - webhookEditLoading, requestWebhookSubcriptionReceiveFailure, requestWebhookSubcriptionReceiveData, SubscriptionCustomersRequestParams, @@ -30,7 +29,8 @@ import { PagedResultWebhookModel_ } from '@/reducers/webhook-subscriptions' export const fetchWebhookSubscriptionTopics = async (params: SubscriptionTopicsRequestParams) => { try { - const { applicationId, headers } = params + const { applicationId } = params + const headers = await initAuthorizedRequestHeaders() const response = await fetcher({ url: `${URLS.webhook}/topics?${setQueryParams({ applicationId })}`, api: window.reapit.config.platformApiUrl, @@ -62,7 +62,8 @@ export const fetchWebhookSubscriptionCustomers = async (params: SubscriptionCust export const fetchWebhookData = async (params: FetchWebhookRequestParams) => { try { - const { webhookId, headers } = params + const { webhookId } = params + const headers = await initAuthorizedRequestHeaders() const response = await fetcher({ url: `${URLS.webhook}/subscriptions/${webhookId}`, api: window.reapit.config.platformApiUrl, @@ -129,12 +130,10 @@ export const deleteEditWebhook = async (params: DeleteWebhookRequestParams) => { } export const requestSupcriptionData = function*({ data: applicationId }: Action) { - yield put(webhookEditLoading(true)) yield put(setApplicationId(applicationId)) - const headers = yield call(initAuthorizedRequestHeaders) try { const [subcriptionTopics, subcriptionCustomers] = yield all([ - call(fetchWebhookSubscriptionTopics, { applicationId, headers }), + call(fetchWebhookSubscriptionTopics, { applicationId }), call(fetchWebhookSubscriptionCustomers, { AppId: applicationId }), ]) if (subcriptionCustomers && subcriptionTopics) { @@ -207,8 +206,7 @@ export const editWebhook = function*({ data }: Action) { export const deleteWebhook = function*({ data }: Action) { try { const { webhookId, applicationId } = data - const headers = yield call(initAuthorizedRequestHeaders) - const deleteResponse = yield call(deleteEditWebhook, { webhookId, headers }) + const deleteResponse = yield call(deleteEditWebhook, { webhookId }) let newListResponse = false if (deleteResponse) { yield put(webhookSetOpenModal('')) @@ -230,18 +228,13 @@ export const deleteWebhook = function*({ data }: Action) { export const requestWebhookData = function*({ data: webhookId }: Action) { try { - yield put(webhookEditLoading(true)) - const headers = yield call(initAuthorizedRequestHeaders) - const data: WebhookModal = yield call(fetchWebhookData, { webhookId, headers }) - if (data) { - const { applicationId } = data - yield put(requestWebhookReceiveData(data)) - yield put(requestWebhookSubcriptionData(applicationId)) - } else { - yield put(requestWebhookReceiveDataFailure()) - } + const data: WebhookModal = yield call(fetchWebhookData, { webhookId }) + const { applicationId } = data + yield put(requestWebhookReceiveData(data)) + yield put(requestWebhookSubcriptionData(applicationId)) } catch (err) { logger(err) + yield put(requestWebhookReceiveDataFailure()) yield put( errorThrownServer({ type: 'SERVER', diff --git a/packages/marketplace/src/sagas/webhook-subscriptions.ts b/packages/marketplace/src/sagas/webhook-subscriptions.ts index 1bd796fef6..9c4d1918a8 100644 --- a/packages/marketplace/src/sagas/webhook-subscriptions.ts +++ b/packages/marketplace/src/sagas/webhook-subscriptions.ts @@ -10,6 +10,7 @@ import { webhookTopicsReceiveData, setApplicationId, } from '@/actions/webhook-subscriptions' +import { fetchWebhookTopic } from '@/services/topics' export const fetchSubscriptions = async (applicationId: string) => { const headers = await initAuthorizedRequestHeaders() @@ -22,17 +23,6 @@ export const fetchSubscriptions = async (applicationId: string) => { return response } -export const fetchWebhookTopic = async () => { - const headers = await initAuthorizedRequestHeaders() - const response = await fetcher({ - url: `${URLS.webhookTopics}`, - api: window.reapit.config.platformApiUrl, - method: 'GET', - headers: headers, - }) - return response -} - export const webhookSubscriptionsFetch = function*({ data: applicationId }: Action) { try { yield put(setApplicationId(applicationId)) @@ -50,9 +40,9 @@ export const webhookSubscriptionsFetch = function*({ data: applicationId }: Acti } } -export const webhookTopicsFetch = function*() { +export const webhookTopicsFetch = function*({ data: applicationId }: Action) { try { - const response = yield call(fetchWebhookTopic) + const response = yield call(fetchWebhookTopic, { applicationId }) if (response) { yield put(webhookTopicsReceiveData(response)) } @@ -71,7 +61,7 @@ export const webhookSubscriptionsListen = function*() { } export const webhookTopicsListen = function*() { - yield takeLatest>(ActionTypes.WEBHOOK_TOPICS_REQUEST_DATA, webhookTopicsFetch) + yield takeLatest>(ActionTypes.WEBHOOK_TOPICS_REQUEST_DATA, webhookTopicsFetch) } const webhookSubscriptionsSagas = function*() { diff --git a/packages/marketplace/src/services/__tests__/topics.ts b/packages/marketplace/src/services/__tests__/topics.ts new file mode 100644 index 0000000000..215606c523 --- /dev/null +++ b/packages/marketplace/src/services/__tests__/topics.ts @@ -0,0 +1,16 @@ +import { fetchWebhookTopic } from '../topics' +import { initAuthorizedRequestHeaders } from '@/constants/api' +import { fetcher } from '@reapit/elements' + +describe('should fetchWebhookTopic run correctly', () => { + it('initAuthorizedRequestHeaders should be called', () => { + const applicationId = 'applicationId' + fetchWebhookTopic({ applicationId }) + .then(() => { + expect(initAuthorizedRequestHeaders).toBeCalled() + }) + .then(() => { + expect(fetcher).toBeCalledWith() + }) + }) +}) diff --git a/packages/marketplace/src/services/topics.ts b/packages/marketplace/src/services/topics.ts new file mode 100644 index 0000000000..56194bef44 --- /dev/null +++ b/packages/marketplace/src/services/topics.ts @@ -0,0 +1,20 @@ +import { URLS, initAuthorizedRequestHeaders } from '@/constants/api' +import { fetcher, setQueryParams } from '@reapit/elements' + +export interface FetchWebhookTopicParams { + applicationId: string + sortBy?: string + pageSize?: string + pageNumber?: string +} + +export const fetchWebhookTopic = async (params: FetchWebhookTopicParams) => { + const headers = await initAuthorizedRequestHeaders() + const response = await fetcher({ + url: `${URLS.webhookTopics}?${setQueryParams(params)}`, + api: window.reapit.config.platformApiUrl, + method: 'GET', + headers: headers, + }) + return response +} diff --git a/packages/marketplace/src/tests/badges/badge-branches.svg b/packages/marketplace/src/tests/badges/badge-branches.svg index c1f75c4258..39ed6b3ad1 100644 --- a/packages/marketplace/src/tests/badges/badge-branches.svg +++ b/packages/marketplace/src/tests/badges/badge-branches.svg @@ -1 +1 @@ -Coverage:branchesCoverage:branches69.87%69.87% +Coverage:branchesCoverage:branches69.92%69.92% \ No newline at end of file diff --git a/packages/marketplace/src/tests/badges/badge-functions.svg b/packages/marketplace/src/tests/badges/badge-functions.svg index 0b53d4236e..e2f0d126c2 100644 --- a/packages/marketplace/src/tests/badges/badge-functions.svg +++ b/packages/marketplace/src/tests/badges/badge-functions.svg @@ -1 +1 @@ -Coverage:functionsCoverage:functions73.3%73.3% +Coverage:functionsCoverage:functions74.39%74.39% \ No newline at end of file diff --git a/packages/marketplace/src/tests/badges/badge-lines.svg b/packages/marketplace/src/tests/badges/badge-lines.svg index 76addc855d..8183f9991f 100644 --- a/packages/marketplace/src/tests/badges/badge-lines.svg +++ b/packages/marketplace/src/tests/badges/badge-lines.svg @@ -1 +1 @@ -Coverage:linesCoverage:lines89.85%89.85% +Coverage:linesCoverage:lines89.99%89.99% \ No newline at end of file diff --git a/packages/marketplace/src/tests/badges/badge-statements.svg b/packages/marketplace/src/tests/badges/badge-statements.svg index b0d2f731b6..1db8ad2977 100644 --- a/packages/marketplace/src/tests/badges/badge-statements.svg +++ b/packages/marketplace/src/tests/badges/badge-statements.svg @@ -1 +1 @@ -Coverage:statementsCoverage:statements88.96%88.96% +Coverage:statementsCoverage:statements89.08%89.08% \ No newline at end of file diff --git a/packages/marketplace/src/utils/route-dispatcher.ts b/packages/marketplace/src/utils/route-dispatcher.ts index 0d7c63f6d4..e7df7649fb 100644 --- a/packages/marketplace/src/utils/route-dispatcher.ts +++ b/packages/marketplace/src/utils/route-dispatcher.ts @@ -16,7 +16,6 @@ import { requestDeveloperData } from '@/actions/settings' import { getParamsFromPath } from '@/utils/client-url-params' import { adminAppsRequestData } from '@/actions/admin-apps' import { selectClientId } from '@/selector/client' -import { webhookTopicsRequestData } from '@/actions/webhook-subscriptions' import { DeveloperRequestParams } from '@/reducers/developer' const routeDispatcher = async (route: RouteValue, params?: StringMap, search?: string) => { @@ -91,7 +90,6 @@ const routeDispatcher = async (route: RouteValue, params?: StringMap, search?: s break case Routes.DEVELOPER_WEBHOOKS: store.dispatch(developerRequestData({ page: 1, appsPerPage: GET_ALL_PAGE_SIZE } as DeveloperRequestParams)) - store.dispatch(webhookTopicsRequestData()) break case Routes.DEVELOPER_HELP: // Need the fetcher to have retrieved the login session only.