From 15df1506f7fca4167582ef2b543b75c3b2c70abf Mon Sep 17 00:00:00 2001 From: Vu Nguyen Date: Thu, 28 May 2020 14:40:55 +0700 Subject: [PATCH] feat: #1325 Update webhook edit + create modal tests --- .../developer-webhooks/developer-webhooks.tsx | 4 +- .../__snapshots__/webhook-edit-modal.tsx.snap | 45 --- .../webhook-edit-modal.test.tsx.snap | 31 ++ .../webhook-test-modal.test.tsx.snap} | 0 .../__test__/webhook-edit-modal.test.tsx} | 112 +++---- .../__test__/webhook-test-modal.test.tsx} | 0 .../developer-webhooks/webhook-edit-modal.tsx | 252 +++++++++++++++ .../webhook-test-modal.tsx | 0 .../src/components/ui/webhook-edit-modal.tsx | 300 ------------------ 9 files changed, 332 insertions(+), 412 deletions(-) delete mode 100644 packages/marketplace/src/components/ui/__tests__/__snapshots__/webhook-edit-modal.tsx.snap create mode 100644 packages/marketplace/src/components/ui/developer-webhooks/__test__/__snapshots__/webhook-edit-modal.test.tsx.snap rename packages/marketplace/src/components/ui/{__tests__/__snapshots__/webhook-test-modal.tsx.snap => developer-webhooks/__test__/__snapshots__/webhook-test-modal.test.tsx.snap} (100%) rename packages/marketplace/src/components/ui/{__tests__/webhook-edit-modal.tsx => developer-webhooks/__test__/webhook-edit-modal.test.tsx} (56%) rename packages/marketplace/src/components/ui/{__tests__/webhook-test-modal.tsx => developer-webhooks/__test__/webhook-test-modal.test.tsx} (100%) create mode 100644 packages/marketplace/src/components/ui/developer-webhooks/webhook-edit-modal.tsx rename packages/marketplace/src/components/ui/{ => developer-webhooks}/webhook-test-modal.tsx (100%) delete mode 100644 packages/marketplace/src/components/ui/webhook-edit-modal.tsx diff --git a/packages/marketplace/src/components/pages/developer-webhooks/developer-webhooks.tsx b/packages/marketplace/src/components/pages/developer-webhooks/developer-webhooks.tsx index a68cfca252..2e8ba3ca7d 100644 --- a/packages/marketplace/src/components/pages/developer-webhooks/developer-webhooks.tsx +++ b/packages/marketplace/src/components/pages/developer-webhooks/developer-webhooks.tsx @@ -27,9 +27,9 @@ import { selectWebhookEditModalType, } from '@/selector/wehooks' import FormikAutoSave from '@/components/hocs/formik-auto-save' -import WebhookEditModal from '@/components/ui/webhook-edit-modal' +import WebhookEditModal from '@/components/ui/developer-webhooks/webhook-edit-modal' import { selectDeveloper } from '@/selector/developer' -import WebhookTestModal from '@/components/ui/webhook-test-modal' +import WebhookTestModal from '@/components/ui/developer-webhooks/webhook-test-modal' import styles from '@/styles/elements/link.scss?mod' import linkStyles from '@/styles/elements/link.scss?mod' import Routes from '@/constants/routes' 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 deleted file mode 100644 index 1bf34b8dc0..0000000000 --- a/packages/marketplace/src/components/ui/__tests__/__snapshots__/webhook-edit-modal.tsx.snap +++ /dev/null @@ -1,45 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`WebhookEditModal should match a snapshot 1`] = ` - - - -`; - -exports[`WebhookEditModal should match a snapshot 2`] = ` - - - -`; - -exports[`WebhookEditModal should match a snapshot 3`] = `""`; - -exports[`WebhookEditModal should match a snapshot 4`] = `""`; - -exports[`WebhookEditModal should match a snapshot 5`] = ` - - - -`; diff --git a/packages/marketplace/src/components/ui/developer-webhooks/__test__/__snapshots__/webhook-edit-modal.test.tsx.snap b/packages/marketplace/src/components/ui/developer-webhooks/__test__/__snapshots__/webhook-edit-modal.test.tsx.snap new file mode 100644 index 0000000000..a4a49894cf --- /dev/null +++ b/packages/marketplace/src/components/ui/developer-webhooks/__test__/__snapshots__/webhook-edit-modal.test.tsx.snap @@ -0,0 +1,31 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`WebhookEditModal should match a snapshot 1`] = ` + + + + + +`; diff --git a/packages/marketplace/src/components/ui/__tests__/__snapshots__/webhook-test-modal.tsx.snap b/packages/marketplace/src/components/ui/developer-webhooks/__test__/__snapshots__/webhook-test-modal.test.tsx.snap similarity index 100% rename from packages/marketplace/src/components/ui/__tests__/__snapshots__/webhook-test-modal.tsx.snap rename to packages/marketplace/src/components/ui/developer-webhooks/__test__/__snapshots__/webhook-test-modal.test.tsx.snap diff --git a/packages/marketplace/src/components/ui/__tests__/webhook-edit-modal.tsx b/packages/marketplace/src/components/ui/developer-webhooks/__test__/webhook-edit-modal.test.tsx similarity index 56% rename from packages/marketplace/src/components/ui/__tests__/webhook-edit-modal.tsx rename to packages/marketplace/src/components/ui/developer-webhooks/__test__/webhook-edit-modal.test.tsx index 381372c5b6..699e5624fa 100644 --- a/packages/marketplace/src/components/ui/__tests__/webhook-edit-modal.tsx +++ b/packages/marketplace/src/components/ui/developer-webhooks/__test__/webhook-edit-modal.test.tsx @@ -1,60 +1,52 @@ import * as React from 'react' -import { shallow } from 'enzyme' +import * as ReactRedux from 'react-redux' +import configureStore from 'redux-mock-store' +import { mount } from 'enzyme' +import appState from '@/reducers/__stubs__/app-state' import WebhookCreateModal, { - WebhookModalInner, WebhookEditProps, onEdit, onCreate, - WebhookModalInnerProps, - mapDispatchToProps, generateCustomerOptions, generateTopicOptions, FormValuesType, validateURL, } from '../webhook-edit-modal' -import { webhookItemDataStub } from '@/sagas/__stubs__/webhook-edit' import { TopicItem, CustomerItem } from '@/reducers/webhook-edit-modal' +import { editWebhook, createWebhook } from '@/actions/webhook-edit-modal' -const createProps: WebhookEditProps = { +const mockProps: WebhookEditProps = { appId: '', visible: true, -} -const editProps: WebhookEditProps = { - appId: '', - visible: true, - isUpdate: true, -} - -const innerModalProps: WebhookModalInnerProps = { - appId: '', - topics: [], - customers: [], - loading: false, isUpdate: true, + afterClose: jest.fn(), closeModal: jest.fn(), - requestWebhookSubcriptionData: jest.fn(), - requestWebhookData: jest.fn(), - createWebhook: jest.fn(), - editWebhook: jest.fn(), - deleteWebhook: jest.fn(), - webhookDataClear: jest.fn(), - webhookData: webhookItemDataStub, + webhookId: 'testWebhookId', } describe('WebhookEditModal', () => { + let store + let spyDispatch + beforeEach(() => { + /* mocking store */ + const mockStore = configureStore() + store = mockStore(appState) + spyDispatch = jest.spyOn(ReactRedux, 'useDispatch').mockImplementation(() => store.dispatch) + }) it('should match a snapshot', () => { - expect(shallow()).toMatchSnapshot() - expect(shallow()).toMatchSnapshot() - expect(shallow()).toMatchSnapshot() - expect(shallow()).toMatchSnapshot() - expect(shallow()).toMatchSnapshot() + expect( + mount( + + + , + ), + ).toMatchSnapshot() }) it('should call editWebhook', () => { - const editWebhook = jest.fn() const webhookId = '' const appId = '' - const fn = onEdit(editWebhook, webhookId, appId) + const fn = onEdit(spyDispatch, webhookId, appId) const values: FormValuesType = { url: '', topicIds: [], @@ -62,12 +54,21 @@ describe('WebhookEditModal', () => { active: false, } fn(values) - expect(editWebhook).toBeCalled() + expect(spyDispatch).toBeCalledWith( + editWebhook({ + applicationId: appId, + webhookId, + url: values.url, + description: '', + topicIds: values.topicIds, + customerIds: values.customerIds, + active: values.active, + }), + ) }) it('should call createWebhook', () => { - const createWebhook = jest.fn() - const webhookId = '' - const fn = onCreate(createWebhook, webhookId) + const appId = '' + const fn = onCreate(spyDispatch, appId) const values = { url: '', topicIds: [], @@ -75,37 +76,18 @@ describe('WebhookEditModal', () => { active: false, } fn(values) - expect(createWebhook).toBeCalled() - }) - describe('mapDispatchToProps', () => { - it('should run correctly', () => { - const mockDispatch = jest.fn() - const { - requestWebhookSubcriptionData, - createWebhook, - editWebhook, - requestWebhookData, - webhookDataClear, - deleteWebhook, - } = mapDispatchToProps(mockDispatch) - requestWebhookSubcriptionData('1') - requestWebhookData('1') - const values = { - applicationId: '', - url: '', + expect(spyDispatch).toBeCalledWith( + createWebhook({ + applicationId: appId, + url: values.url, description: '', - topicIds: [], - customerIds: [], - active: false, - webhookId: '', - } - createWebhook(values) - editWebhook(values) - webhookDataClear() - deleteWebhook(values) - expect(mockDispatch).toBeCalled() - }) + topicIds: values.topicIds, + customerIds: values.customerIds, + active: values.active, + }), + ) }) + it('should return TopicItem Options', () => { const data: TopicItem[] = [ { diff --git a/packages/marketplace/src/components/ui/__tests__/webhook-test-modal.tsx b/packages/marketplace/src/components/ui/developer-webhooks/__test__/webhook-test-modal.test.tsx similarity index 100% rename from packages/marketplace/src/components/ui/__tests__/webhook-test-modal.tsx rename to packages/marketplace/src/components/ui/developer-webhooks/__test__/webhook-test-modal.test.tsx diff --git a/packages/marketplace/src/components/ui/developer-webhooks/webhook-edit-modal.tsx b/packages/marketplace/src/components/ui/developer-webhooks/webhook-edit-modal.tsx new file mode 100644 index 0000000000..509927cddd --- /dev/null +++ b/packages/marketplace/src/components/ui/developer-webhooks/webhook-edit-modal.tsx @@ -0,0 +1,252 @@ +import React, { useEffect } from 'react' +import { useSelector, useDispatch } from 'react-redux' +import { Dispatch } from 'redux' +import styles from '@/styles/blocks/developer-app-modal.scss?mod' +import { + Modal, + Button, + DropdownSelect, + Input, + Formik, + Form, + Content, + Checkbox, + SelectOption, + ModalFooter, + ModalBody, + ModalHeader, + Loader, + Level, + LevelLeft, + LevelRight, +} from '@reapit/elements' +import { + requestWebhookSubcriptionData, + CreateWebhookParams, + EditWebhookParams, + createWebhook, + editWebhook, + requestWebhookData, + webhookDataClear, + deleteWebhook, +} from '@/actions/webhook-edit-modal' +import { CustomerItem, TopicItem } from '@/reducers/webhook-edit-modal' +import { selectTopics, selectWebhookData, selectLoading, selectCustomers } from '@/selector/webhook-edit' +import { isValidHttpsUrl } from '@/utils/validate' + +const CREATE_MODAL = { + title: 'Add New Webhook', + submit: 'Create', +} + +const EDIT_MODAL = { + title: 'Edit', + submit: 'Update', +} + +export type WebhookEditProps = { + isUpdate?: boolean + appId: string + webhookId?: string + visible: boolean + closeModal?: () => void + afterClose?: () => void +} + +export const generateTopicOptions = (topics: TopicItem[]) => { + return topics.map( + topic => + ({ + value: topic.id, + label: topic.name, + description: topic.description, + } as SelectOption), + ) +} + +export const generateCustomerOptions = (customers: CustomerItem[]) => { + const customerOptions: SelectOption[] = [ + { + value: 'SBOX', + label: 'SBOX', + description: 'SBOX', + } as SelectOption, + ] + customers.forEach((customer: CustomerItem) => { + if (customer.status === 'Active') { + customerOptions.push({ + value: customer.client, + label: customer.client, + description: customer.client, + } as SelectOption) + } + }) + return customerOptions +} + +export const onCreate = (dispatch: Dispatch, appId: string) => (values: FormValuesType) => { + const params: CreateWebhookParams = { + applicationId: appId, + url: values.url, + description: '', + topicIds: values.topicIds, + customerIds: values.customerIds, + active: values.active, + } + dispatch(createWebhook(params)) +} + +export const onEdit = (dispatch: Dispatch, webhookId: string, appId: string) => (values: FormValuesType) => { + const params: EditWebhookParams = { + applicationId: appId, + webhookId, + url: values.url, + description: '', + topicIds: values.topicIds, + customerIds: values.customerIds, + active: values.active, + } + dispatch(editWebhook(params)) +} + +export const validateURL = (value: string): string | null => { + return isValidHttpsUrl(value) ? null : 'The value must be a valid and secure URI' +} + +export const WebhookEditModal: React.FunctionComponent = ({ + isUpdate = false, + appId, + visible, + webhookId = '', + closeModal, + afterClose, +}) => { + const dispatch = useDispatch() + const topics = useSelector(selectTopics) + const customers = useSelector(selectCustomers) + const loading = useSelector(selectLoading) + const webhookData = useSelector(selectWebhookData) + + const modalConfig = isUpdate ? EDIT_MODAL : CREATE_MODAL + + const initFormValues: FormValuesType = { + url: webhookData?.url, + topicIds: webhookData?.topicIds, + customerIds: webhookData?.customerIds, + active: webhookData?.active, + } + + const topicOptions: SelectOption[] = generateTopicOptions(topics) + const customerOptions: SelectOption[] = generateCustomerOptions(customers) + + useEffect(() => { + if (isUpdate) { + dispatch(requestWebhookData(webhookId)) + } else { + dispatch(requestWebhookSubcriptionData(appId)) + } + return () => { + dispatch(webhookDataClear()) + } + }, []) + + const onSubmit = isUpdate ? onEdit(dispatch, webhookId, appId) : onCreate(dispatch, appId) + const onDelete = () => dispatch(deleteWebhook({ webhookId, applicationId: appId })) + + if (!visible) { + return null + } + + return ( + + {loading ? ( + + ) : ( + + {({ handleSubmit }) => { + return ( + <> + + + +

+ Webhooks are configured here to allow your application to receive real-time notifications + about the topics you choose to subscribe it to. A single webhook subscription can receive + notifications for multiple topics so long as your application has been granted the required + permissions. +

+

+ Webhooks subscriptions can be set up for any customer who has installed your application. + Additionally, you can choose ‘SBOX’ to listen for sandbox environment notifications. +

+
+ + + + + + } + /> + + + {isUpdate && ( + + )} + + + + + + + } + /> + + ) + }} +
+ )} +
+ ) +} + +export type FormValuesType = { + url: string + topicIds: string[] + customerIds: string[] + active: boolean +} + +export default React.memo(WebhookEditModal) diff --git a/packages/marketplace/src/components/ui/webhook-test-modal.tsx b/packages/marketplace/src/components/ui/developer-webhooks/webhook-test-modal.tsx similarity index 100% rename from packages/marketplace/src/components/ui/webhook-test-modal.tsx rename to packages/marketplace/src/components/ui/developer-webhooks/webhook-test-modal.tsx diff --git a/packages/marketplace/src/components/ui/webhook-edit-modal.tsx b/packages/marketplace/src/components/ui/webhook-edit-modal.tsx deleted file mode 100644 index c0a8c555f1..0000000000 --- a/packages/marketplace/src/components/ui/webhook-edit-modal.tsx +++ /dev/null @@ -1,300 +0,0 @@ -import React, { useEffect } from 'react' -import { connect } from 'react-redux' -import { Dispatch } from 'redux' -import styles from '@/styles/blocks/developer-app-modal.scss?mod' -import { - Modal, - Button, - DropdownSelect, - Input, - Formik, - Form, - Content, - Checkbox, - SelectOption, - ModalFooter, - ModalBody, - ModalHeader, - Loader, - Level, - LevelLeft, - LevelRight, -} from '@reapit/elements' -import { ReduxState } from '@/types/core' -import { - requestWebhookSubcriptionData, - CreateWebhookParams, - EditWebhookParams, - createWebhook, - editWebhook, - requestWebhookData, - webhookDataClear, - deleteWebhook, - DeleteWebhookParams, -} from '@/actions/webhook-edit-modal' -import { WebhookModal, CustomerItem, TopicItem } from '@/reducers/webhook-edit-modal' -import { selectTopics, selectWebhookData, selectLoading, selectCustomers } from '@/selector/webhook-edit' -import { isValidHttpsUrl } from '@/utils/validate' - -const CREATE_MODAL = { - title: 'Add New Webhook', - submit: 'Create', -} - -const EDIT_MODAL = { - title: 'Edit', - submit: 'Update', -} - -export type WebhookEditProps = { - isUpdate?: boolean - appId: string - webhookId?: string - visible: boolean - closeModal?: () => void - afterClose?: () => void -} -export interface WebhookModalInnerMappedAction { - requestWebhookSubcriptionData: (appId: string) => void - requestWebhookData: (webhookId: string) => void - createWebhook: (data: CreateWebhookParams) => void - editWebhook: (data: EditWebhookParams) => void - webhookDataClear: () => void - deleteWebhook: (data: DeleteWebhookParams) => void -} - -export const WebhookEditModal: React.FunctionComponent = ({ - isUpdate = false, - appId, - visible, - webhookId, - closeModal, - afterClose, -}) => { - if (!visible) return null - return ( - - - - ) -} - -export const generateTopicOptions = (topics: TopicItem[]) => { - return topics.map( - topic => - ({ - value: topic.id, - label: topic.name, - description: topic.description, - } as SelectOption), - ) -} - -export const generateCustomerOptions = (customers: CustomerItem[]) => { - const customerOptions: SelectOption[] = [ - { - value: 'SBOX', - label: 'SBOX', - description: 'SBOX', - } as SelectOption, - ] - customers.forEach((customer: CustomerItem) => { - if (customer.status === 'Active') { - customerOptions.push({ - value: customer.client, - label: customer.client, - description: customer.client, - } as SelectOption) - } - }) - return customerOptions -} - -export const onCreate = (createWebhook: (data: CreateWebhookParams) => void, appId: string) => ( - values: FormValuesType, -) => { - const params: CreateWebhookParams = { - applicationId: appId, - url: values.url, - description: '', - topicIds: values.topicIds, - customerIds: values.customerIds, - active: values.active, - } - createWebhook(params) -} - -export const onEdit = (editWebhook: (data: EditWebhookParams) => void, webhookId: string, appId: string) => ( - values: FormValuesType, -) => { - const params: EditWebhookParams = { - applicationId: appId, - webhookId, - url: values.url, - description: '', - topicIds: values.topicIds, - customerIds: values.customerIds, - active: values.active, - } - editWebhook(params) -} - -export const validateURL = (value: string): string | null => { - return isValidHttpsUrl(value) ? null : 'The value must be a valid and secure URI' -} - -export type WebhookModalInnerProps = WebhookModalInnerMappedAction & - StateProps & { - isUpdate?: boolean - webhookId?: string - appId: string - closeModal?: () => void - } - -export type FormValuesType = { - url: string - topicIds: string[] - customerIds: string[] - active: boolean -} - -export const WebhookModalInner: React.FunctionComponent = ({ - isUpdate = false, - closeModal, - topics, - customers, - loading, - webhookData, - webhookId = '', - appId = '', - ...props -}) => { - const modalConfig = isUpdate ? EDIT_MODAL : CREATE_MODAL - - const initFormValues: FormValuesType = { - url: webhookData?.url, - topicIds: webhookData?.topicIds, - customerIds: webhookData?.customerIds, - active: webhookData?.active, - } - - const topicOptions: SelectOption[] = generateTopicOptions(topics) - const customerOptions: SelectOption[] = generateCustomerOptions(customers) - - useEffect(() => { - if (isUpdate) { - props.requestWebhookData(webhookId) - } else { - props.requestWebhookSubcriptionData(appId) - } - return props.webhookDataClear - }, []) - - const onSubmit = isUpdate ? onEdit(props.editWebhook, webhookId, appId) : onCreate(props.createWebhook, appId) - const onDelete = () => props.deleteWebhook({ webhookId, applicationId: appId }) - if (loading) return - return ( - - {({ handleSubmit }) => { - return ( - <> - - - -

- Webhooks are configured here to allow your application to receive real-time notifications about - the topics you choose to subscribe it to. A single webhook subscription can receive notifications - for multiple topics so long as your application has been granted the required permissions. -

-

- Webhooks subscriptions can be set up for any customer who has installed your application. - Additionally, you can choose ‘SBOX’ to listen for sandbox environment notifications. -

-
- - - - - - } - /> - - - {isUpdate && ( - - )} - - - - - - - } - /> - - ) - }} -
- ) -} - -export type StateProps = { - topics: TopicItem[] - customers: CustomerItem[] - loading: boolean - webhookData: WebhookModal -} - -export const mapStateToProps = (state: ReduxState): StateProps => ({ - topics: selectTopics(state), - customers: selectCustomers(state), - loading: selectLoading(state), - webhookData: selectWebhookData(state), -}) - -export const mapDispatchToProps = (dispatch: Dispatch): WebhookModalInnerMappedAction => { - return { - requestWebhookSubcriptionData: (appId: string) => dispatch(requestWebhookSubcriptionData(appId)), - createWebhook: (data: CreateWebhookParams) => dispatch(createWebhook(data)), - editWebhook: (data: EditWebhookParams) => dispatch(editWebhook(data)), - deleteWebhook: (data: DeleteWebhookParams) => dispatch(deleteWebhook(data)), - requestWebhookData: (webhookId: string) => dispatch(requestWebhookData(webhookId)), - webhookDataClear: () => dispatch(webhookDataClear()), - } -} - -export const WebhookModalInnerWithConnect = connect(mapStateToProps, mapDispatchToProps)(WebhookModalInner) -export default React.memo(WebhookEditModal)