Skip to content

Commit

Permalink
refactor: #1325 Refactor developer set status using react-redux hooks (
Browse files Browse the repository at this point in the history
  • Loading branch information
Vu Nguyen authored Jun 19, 2020
1 parent bc54564 commit 92cc55f
Show file tree
Hide file tree
Showing 6 changed files with 136 additions and 131 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -759,28 +759,18 @@ exports[`AdminDevManagement should match a snapshot when LOADING false 1`] = `
/>
</div>
</Component>
<Connect(Component)
<Component
afterClose={[Function]}
developer={Object {}}
onSuccess={[Function]}
visible={false}
>
<Component
afterClose={[Function]}
developer={Object {}}
developerSetStatusRequest={[Function]}
formState="PENDING"
onSuccess={[Function]}
resetDeveloperSetStatusReducer={[Function]}
renderChildren={true}
visible={false}
>
<Component
afterClose={[Function]}
renderChildren={true}
visible={false}
/>
</Component>
</Connect(Component)>
/>
</Component>
</ErrorBoundary>
</Connect(ErrorBoundary)>
</Component>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,48 +1,33 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`SetDeveloperStatusModal should match snapshot 1`] = `
<Component
afterClose={[Function]}
renderChildren={true}
visible={true}
>
<Component
afterClose={[Function]}
title="Confirm undefined Deactivation"
/>
<Component
body={
<Unknown
isCentered={true}
>
Are you sure you want to
deactivate
’?
</Unknown>
<Provider
store={
Object {
"clearActions": [Function],
"dispatch": [Function],
"getActions": [Function],
"getState": [Function],
"replaceReducer": [Function],
"subscribe": [Function],
}
/>
}
>
<Component
footerItems={
<React.Fragment>
<Unknown
loading={false}
onClick={[Function]}
type="button"
variant="danger"
>
Confirm
</Unknown>
<Unknown
disabled={false}
onClick={[Function]}
type="button"
variant="secondary"
>
Cancel
</Unknown>
</React.Fragment>
developer={
Object {
"id": "",
"isInactive": false,
}
}
/>
</Component>
onSuccess={[Function]}
visible={true}
>
<Component
afterClose={[Function]}
renderChildren={true}
visible={true}
/>
</Component>
</Provider>
`;
Original file line number Diff line number Diff line change
@@ -1,55 +1,73 @@
import React from 'react'
import { shallow } from 'enzyme'
import * as ReactRedux from 'react-redux'
import { mount } from 'enzyme'
import configureStore from 'redux-mock-store'
import appState from '@/reducers/__stubs__/app-state'
import {
SetDeveloperStatusModal,
SetDeveloperStatusProps,
onAfterCloseHandler,
onSuccessHandler,
onConfirmButtonClick,
} from '../developer-set-status'
import { developerSetStatusSetInitFormState, developerSetStatusRequest } from '@/actions/developer-set-status'
import { developerStub } from '@/sagas/__stubs__/developer'

const props: SetDeveloperStatusProps = {
developer: { id: '', isInactive: false },
onSuccess: () => jest.fn(),
visible: true,
}

describe('SetDeveloperStatusModal', () => {
let store
let spyDispatch
beforeEach(() => {
/* mocking store */
const mockStore = configureStore()
store = mockStore(appState)
spyDispatch = jest.spyOn(ReactRedux, 'useDispatch').mockImplementation(() => store.dispatch)
})

it('should match snapshot', () => {
const props = {
developer: { id: '', isInactive: false },
developerName: '',
onSuccess: () => jest.fn(),
formState: 'PENDING',
visible: true,
afterClose: () => jest.fn(),
developerSetStatusRequest: () => jest.fn(),
resetDeveloperSetStatusReducer: () => jest.fn(),
} as SetDeveloperStatusProps

const wrapper = shallow(<SetDeveloperStatusModal {...props} />)
const wrapper = mount(
<ReactRedux.Provider store={store}>
<SetDeveloperStatusModal {...props} />
</ReactRedux.Provider>,
)
expect(wrapper).toMatchSnapshot()
})
})

describe('onAfterCloseHandler', () => {
it('should return a function when executing', () => {
const mockAfterClose = jest.fn()
describe('onAfterCloseHandler', () => {
it('should return a function when executing', () => {
const mockAfterClose = jest.fn()

const onAfterCloseHandlerFn = onAfterCloseHandler({ afterClose: mockAfterClose, isLoading: false })
expect(onAfterCloseHandlerFn).toBeDefined()
const onAfterCloseHandlerFn = onAfterCloseHandler(false, mockAfterClose)
expect(onAfterCloseHandlerFn).toBeDefined()

onAfterCloseHandlerFn()
expect(mockAfterClose).toBeCalled()
onAfterCloseHandlerFn()
expect(mockAfterClose).toBeCalled()
})
})
})

describe('onSuccessHandler', () => {
it('should return a function when executing', () => {
const mockOnSuccess = jest.fn()
const mockResetDeveloperSetStatusReducer = jest.fn()
describe('onSuccessHandler', () => {
it('should return a function when executing', () => {
const mockOnSuccess = jest.fn()
const onSuccessHandlerFn = onSuccessHandler(mockOnSuccess, spyDispatch)
expect(onSuccessHandlerFn).toBeDefined()

const onSuccessHandlerFn = onSuccessHandler({
onSuccess: mockOnSuccess,
resetDeveloperSetStatusReducer: mockResetDeveloperSetStatusReducer,
onSuccessHandlerFn()
expect(mockOnSuccess).toBeCalled()
expect(spyDispatch).toBeCalledWith(developerSetStatusSetInitFormState())
})
expect(onSuccessHandlerFn).toBeDefined()
})

onSuccessHandlerFn()
expect(mockOnSuccess).toBeCalled()
expect(mockResetDeveloperSetStatusReducer).toBeCalled()
describe('onConfirmButtonClick', () => {
it('should run correctly', () => {
const mockIsInactive = false
const fn = onConfirmButtonClick(developerStub, spyDispatch, mockIsInactive)
fn()
expect(spyDispatch).toBeCalledWith(developerSetStatusRequest({ ...developerStub, isInactive: !mockIsInactive }))
})
})
})
73 changes: 30 additions & 43 deletions packages/marketplace/src/components/ui/developer-set-status.tsx
Original file line number Diff line number Diff line change
@@ -1,50 +1,58 @@
import * as React from 'react'
import { Dispatch } from 'redux'
import { connect } from 'react-redux'
import { useSelector, useDispatch } from 'react-redux'
import { Button, Modal, ModalBody, ModalHeader, ModalFooter, SubTitleH6, ModalProps } from '@reapit/elements'
import CallToAction from '@/components/ui/call-to-action'
import { ReduxState, FormState } from '@/types/core'
import { developerSetStatusRequest, developerSetStatusSetInitFormState } from '@/actions/developer-set-status'
import { DeveloperModel } from '@reapit/foundations-ts-definitions'
import { selectDeveloperSetStatusFormState } from '@/selector/developer-set-status'

export interface SetDeveloperStatusModal {
export type SetDeveloperStatusProps = Pick<ModalProps, 'visible' | 'afterClose'> & {
onSuccess: () => void
developer: DeveloperModel
}

export interface SetDeveloperStatusMappedProps {
formState: FormState
export const onAfterCloseHandler = (isLoading: boolean, afterClose?: () => void) => {
return () => {
if (!isLoading && afterClose) {
afterClose()
}
}
}
export interface SetDeveloperStatusMappedActions {
developerSetStatusRequest: (developer: DeveloperModel) => void
resetDeveloperSetStatusReducer: () => void

export const onSuccessHandler = (onSuccess: () => void, dispatch: Dispatch) => {
return () => {
dispatch(developerSetStatusSetInitFormState())
onSuccess()
}
}

export type SetDeveloperStatusProps = Pick<ModalProps, 'visible' | 'afterClose'> &
SetDeveloperStatusMappedProps &
SetDeveloperStatusMappedActions &
SetDeveloperStatusModal
export const onConfirmButtonClick = (developer: DeveloperModel, dispatch: Dispatch, isInactive?: boolean) => {
return () => {
dispatch(developerSetStatusRequest({ ...developer, isInactive: !isInactive }))
}
}

export const SetDeveloperStatusModal = ({
export const SetDeveloperStatusModal: React.FC<SetDeveloperStatusProps> = ({
afterClose,
visible,
onSuccess,
formState,
developer,
developerSetStatusRequest,
resetDeveloperSetStatusReducer,
}: SetDeveloperStatusProps) => {
}) => {
const dispatch = useDispatch()
const formState = useSelector(selectDeveloperSetStatusFormState)
const isLoading = Boolean(formState === 'SUBMITTING')
const isSucceeded = Boolean(formState === 'SUCCESS')
const { isInactive, name } = developer

return (
<Modal visible={visible} afterClose={onAfterCloseHandler({ afterClose, isLoading })} renderChildren>
<Modal visible={visible} afterClose={onAfterCloseHandler(isLoading, afterClose)} renderChildren>
<>
{isSucceeded ? (
<CallToAction
title="Success"
buttonText="Back to List"
onButtonClick={onSuccessHandler({ onSuccess, resetDeveloperSetStatusReducer })}
onButtonClick={onSuccessHandler(onSuccess, dispatch)}
isCenter
>
Developer &lsquo;{name}&rsquo; has been {isInactive ? 'activated' : 'deactivated'} successfully.
Expand All @@ -53,7 +61,7 @@ export const SetDeveloperStatusModal = ({
<>
<ModalHeader
title={`Confirm ${name} ${isInactive ? 'Activation' : 'Deactivation'}`}
afterClose={onAfterCloseHandler({ afterClose, isLoading })}
afterClose={onAfterCloseHandler(isLoading, afterClose)}
/>
<ModalBody
body={
Expand All @@ -69,7 +77,7 @@ export const SetDeveloperStatusModal = ({
loading={isLoading}
type="button"
variant="danger"
onClick={() => developerSetStatusRequest({ ...developer, isInactive: !isInactive })}
onClick={onConfirmButtonClick(developer, dispatch, isInactive)}
>
Confirm
</Button>
Expand All @@ -86,25 +94,4 @@ export const SetDeveloperStatusModal = ({
)
}

export const onAfterCloseHandler = ({ afterClose, isLoading }) => () => {
if (!isLoading && afterClose) {
afterClose()
return
}
}

export const onSuccessHandler = ({ onSuccess, resetDeveloperSetStatusReducer }) => () => {
resetDeveloperSetStatusReducer()
onSuccess()
}

export const mapStateToProps = (state: ReduxState): SetDeveloperStatusMappedProps => ({
formState: state.developerSetStatus.formState,
})

export const mapDispatchToProps = (dispatch: Dispatch): SetDeveloperStatusMappedActions => ({
developerSetStatusRequest: (developer: DeveloperModel) => dispatch(developerSetStatusRequest(developer)),
resetDeveloperSetStatusReducer: () => dispatch(developerSetStatusSetInitFormState()),
})

export default connect(mapStateToProps, mapDispatchToProps)(SetDeveloperStatusModal)
export default SetDeveloperStatusModal
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { ReduxState } from '@/types/core'
import { selectDeveloperSetStatusFormState } from '../developer-set-status'

describe('selectAppDeleteFormState', () => {
it('should run correctly', () => {
const input = {
developerSetStatus: {
formState: 'PENDING',
},
} as ReduxState
const result = selectDeveloperSetStatusFormState(input)
expect(result).toEqual('PENDING')
})

it('should run correctly and return []', () => {
const input = {} as ReduxState
const result = selectDeveloperSetStatusFormState(input)
expect(result).toEqual(undefined)
})
})
5 changes: 5 additions & 0 deletions packages/marketplace/src/selector/developer-set-status.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { ReduxState, FormState } from '@/types/core'

export const selectDeveloperSetStatusFormState = (state: ReduxState): FormState => {
return state.developerSetStatus?.formState
}

0 comments on commit 92cc55f

Please sign in to comment.