Skip to content

Instantly share code, notes, and snippets.

@suzubara
Created March 4, 2020 19:58
Show Gist options
  • Save suzubara/15ccef76e0f9c62848d3a62b3c89c22e to your computer and use it in GitHub Desktop.
Save suzubara/15ccef76e0f9c62848d3a62b3c89c22e to your computer and use it in GitHub Desktop.
Confirmation Generator example
import { useRef, useEffect } from 'react'
export const useGenerator = (
generatorFn: () => Generator<any, any, unknown>
): {
generator: { current?: null | Generator<any, any, unknown> }
startGenerator: () => void
next: (
value?: any
) => IteratorReturnResult<any> | IteratorYieldResult<any> | undefined
} => {
const generator: {
current?: null | Generator<any, any, unknown>
} = useRef(null)
const startGenerator = (): void => {
generator.current = generatorFn()
}
const next = (
value?: any
): IteratorReturnResult<any> | IteratorYieldResult<any> | undefined => {
if (generator && generator.current) {
return generator.current.next(value)
}
return undefined
}
return {
generator,
startGenerator,
next,
}
}
import React from 'react'
import { Button, Modal, useModal } from '@trussworks/react-uswds'
import { useGenerator } from '../../containers/customHooks'
import { confirmationModalFlow } from '../../containers/generators'
const ConfirmCloseInvestigationModal = ({
isOpen,
onClose,
onConfirm,
}: ConfirmInvestigationModalProps): React.ReactElement => isOpen ? (
<Modal
title={<h2>Close case?</h2>}
actions={
<>
<Button type="button" outline onClick={onClose}>
Cancel
</Button>
<Button type="button" onClick={onConfirm}>
Close investigation
</Button>
</>
}>
</Modal>
) : null
const VerificationStatus = (): React.ReactElement => {
const confirmCloseInvestigationModal = useModal()
const closeInvestigationFlow = (): Generator<undefined, void, unknown> =>
confirmationModalFlow(confirmCloseInvestigationModal, (): void => {
// Close investigation API call
})
const closeInvestigationGenerator = useGenerator(closeInvestigationFlow)
const handleCloseInvestigation = (): void => {
closeInvestigationGenerator.startGenerator()
closeInvestigationGenerator.next()
}
return (
<div data-testid="verificationStatus">
<Button type="button" onClick={handleCloseInvestigation}>
Close investigation
</Button>
<ConfirmCloseInvestigationModal
isOpen={confirmCloseInvestigationModal.isOpen}
onClose={(): void => {
closeInvestigationGenerator.next(false)
}}
onConfirm={(): void => {
closeInvestigationGenerator.next(true)
}}
/>
</div>
)
}
export default VerificationStatus
import { confirmationModalFlow } from './generators'
describe('The confirmationModalFlow', () => {
describe('if user confirms', () => {
const mockModal = {
openModal: jest.fn(),
closeModal: jest.fn(),
isOpen: false,
}
const mockOnConfirmed = jest.fn()
const mockOnCanceled = jest.fn()
const generator = confirmationModalFlow(
mockModal,
mockOnConfirmed,
mockOnCanceled
)
it('opens the modal', () => {
generator.next()
expect(mockModal.openModal).toHaveBeenCalled()
})
it('waits for user to confirm, closes the modal, and calls the onConfirmed fn', () => {
generator.next(true)
expect(mockModal.closeModal).toHaveBeenCalled()
expect(mockOnConfirmed).toHaveBeenCalled()
expect(mockOnCanceled).not.toHaveBeenCalled()
})
})
describe('if user cancels', () => {
const mockModal = {
openModal: jest.fn(),
closeModal: jest.fn(),
isOpen: false,
}
const mockOnConfirmed = jest.fn()
const mockOnCanceled = jest.fn()
const generator = confirmationModalFlow(
mockModal,
mockOnConfirmed,
mockOnCanceled
)
it('opens the modal', () => {
generator.next()
expect(mockModal.openModal).toHaveBeenCalled()
})
it('waits for user to confirm, closes the modal, and calls the onCanceled fn', () => {
generator.next(false)
expect(mockModal.closeModal).toHaveBeenCalled()
expect(mockOnCanceled).toHaveBeenCalled()
expect(mockOnConfirmed).not.toHaveBeenCalled()
})
})
})
import { ModalHook } from '@trussworks/react-uswds'
export const confirmationModalFlow = function*(
modal: ModalHook,
onConfirmed: () => void,
onCanceled?: () => void
): Generator<undefined, void, unknown> {
modal.openModal()
const confirmed = yield
modal.closeModal()
if (confirmed) onConfirmed()
else if (onCanceled) onCanceled()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment