-
Notifications
You must be signed in to change notification settings - Fork 18
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #270 from openedx/aakbar/PROD-2521-cancel-retirement
feat: adds cancel retirement feature
- Loading branch information
Showing
6 changed files
with
300 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
import React, { useState } from 'react'; | ||
import PropTypes from 'prop-types'; | ||
import { FormattedMessage } from '@edx/frontend-platform/i18n'; | ||
import { Modal, Button, Alert } from '@edx/paragon'; | ||
import { postCancelRetirement } from '../data/api'; | ||
|
||
export default function CancelRetirement({ | ||
retirementId, | ||
changeHandler, | ||
}) { | ||
const [cancelRetirementModalIsOpen, setCancelRetirementModalIsOpen] = useState(false); | ||
const [errorMessage, setErrorMessage] = useState(null); | ||
|
||
const cancelRetirement = async () => { | ||
const resp = await postCancelRetirement(retirementId); | ||
if (resp.errors) { | ||
setErrorMessage(resp.errors[0].text || 'Something went wrong. Please try again later!'); | ||
} else { | ||
changeHandler(); | ||
} | ||
}; | ||
|
||
const closeCancelRetirementModal = () => { | ||
setCancelRetirementModalIsOpen(false); | ||
setErrorMessage(null); | ||
}; | ||
|
||
const modalBody = ( | ||
errorMessage ? <Alert variant="danger">{errorMessage}</Alert> | ||
: ( | ||
<div> | ||
<Alert variant="warning"> | ||
<FormattedMessage | ||
id="supportTools.accountActions.cancelRetirement" | ||
tagName="p" | ||
description="Cancel Retirement instructions prompt" | ||
defaultMessage="This will cancel retirement for the requested user. Do you wish to proceed?" | ||
/> | ||
</Alert> | ||
</div> | ||
) | ||
); | ||
|
||
return ( | ||
<div> | ||
<Button | ||
id="cancel-retirement" | ||
variant="btn btn-danger" | ||
onClick={() => setCancelRetirementModalIsOpen(true)} | ||
className="mr-1 mb-2" | ||
>Cancel Retirement | ||
</Button> | ||
|
||
<Modal | ||
open={cancelRetirementModalIsOpen} | ||
id="user-account-cancel-retirement" | ||
buttons={[errorMessage ? (<></>) | ||
: ( | ||
<Button | ||
variant="danger" | ||
onClick={cancelRetirement} | ||
> | ||
Confirm | ||
</Button> | ||
), | ||
]} | ||
onClose={closeCancelRetirementModal} | ||
dialogClassName="modal-lg modal-dialog-centered justify-content-center" | ||
title="Cancel Retirement" | ||
body={modalBody} | ||
/> | ||
</div> | ||
); | ||
} | ||
|
||
CancelRetirement.propTypes = { | ||
retirementId: PropTypes.number.isRequired, | ||
changeHandler: PropTypes.func.isRequired, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
import { mount } from 'enzyme'; | ||
import React from 'react'; | ||
import { IntlProvider } from '@edx/frontend-platform/i18n'; | ||
import * as api from '../data/api'; | ||
import CancelRetirement from './CancelRetirement'; | ||
import { waitForComponentToPaint } from '../../setupTest'; | ||
|
||
const CancelRetirementWrapper = (props) => ( | ||
<IntlProvider locale="en"> | ||
<CancelRetirement {...props} /> | ||
</IntlProvider> | ||
); | ||
|
||
describe('Cancel Retirement Component Tests', () => { | ||
let wrapper; | ||
const changeHandler = jest.fn(() => { }); | ||
|
||
beforeEach(() => { | ||
const data = { | ||
retirement_id: 1, | ||
changeHandler, | ||
}; | ||
wrapper = mount(<CancelRetirementWrapper {...data} />); | ||
}); | ||
|
||
afterEach(() => { | ||
wrapper.unmount(); | ||
}); | ||
|
||
it('Cancel Retirement button for a User', () => { | ||
const cancelRetirementButton = wrapper.find('#cancel-retirement').hostNodes(); | ||
expect(cancelRetirementButton.text()).toEqual('Cancel Retirement'); | ||
}); | ||
|
||
it('Cancel Retirement Modal', async () => { | ||
const mockApiCall = jest.spyOn(api, 'postCancelRetirement').mockImplementationOnce(() => Promise.resolve({})); | ||
const cancelRetirementButton = wrapper.find('#cancel-retirement').hostNodes(); | ||
let cancelRetirementModal = wrapper.find('Modal#user-account-cancel-retirement'); | ||
|
||
expect(cancelRetirementModal.prop('open')).toEqual(false); | ||
expect(cancelRetirementButton.text()).toEqual('Cancel Retirement'); | ||
|
||
cancelRetirementButton.simulate('click'); | ||
cancelRetirementModal = wrapper.find('Modal#user-account-cancel-retirement'); | ||
|
||
expect(cancelRetirementModal.prop('open')).toEqual(true); | ||
expect(cancelRetirementModal.prop('title')).toEqual('Cancel Retirement'); | ||
const confirmAlert = cancelRetirementModal.find('.alert-warning'); | ||
expect(confirmAlert.text()).toEqual('This will cancel retirement for the requested user. Do you wish to proceed?'); | ||
|
||
cancelRetirementModal.find('button.btn-danger').hostNodes().simulate('click'); | ||
await waitForComponentToPaint(wrapper); | ||
expect(changeHandler).toHaveBeenCalled(); | ||
cancelRetirementModal.find('button.btn-link').simulate('click'); | ||
cancelRetirementModal = wrapper.find('Modal#user-account-cancel-retirement'); | ||
expect(cancelRetirementModal.prop('open')).toEqual(false); | ||
|
||
mockApiCall.mockRestore(); | ||
}); | ||
|
||
it('Display Error on Cancel RetirementModal', async () => { | ||
const cancelRetirementErrors = { | ||
errors: [ | ||
{ | ||
code: null, | ||
dismissible: true, | ||
text: 'Retirement does not exist!', | ||
type: 'error', | ||
topic: 'cancelRetirement', | ||
}, | ||
], | ||
}; | ||
const mockApiCall = jest.spyOn(api, 'postCancelRetirement').mockImplementationOnce(() => Promise.resolve(cancelRetirementErrors)); | ||
const cancelRetirementButton = wrapper.find('#cancel-retirement').hostNodes(); | ||
cancelRetirementButton.simulate('click'); | ||
let cancelRetirementModal = wrapper.find('Modal#user-account-cancel-retirement'); | ||
expect(cancelRetirementModal.prop('open')).toEqual(true); | ||
const confirmAlert = cancelRetirementModal.find('.alert-warning'); | ||
expect(confirmAlert.text()).toEqual( | ||
'This will cancel retirement for the requested user. Do you wish to proceed?', | ||
); | ||
|
||
cancelRetirementModal.find('button.btn-danger').hostNodes().simulate('click'); | ||
await waitForComponentToPaint(wrapper); | ||
cancelRetirementModal = wrapper.find('Modal#user-account-cancel-retirement'); | ||
const errorAlert = cancelRetirementModal.find('.alert-danger'); | ||
expect(errorAlert.text()).toEqual('Retirement does not exist!'); | ||
|
||
cancelRetirementModal.find('button.btn-link').simulate('click'); | ||
cancelRetirementModal = wrapper.find('Modal#user-account-cancel-retirement'); | ||
expect(cancelRetirementModal.prop('open')).toEqual(false); | ||
mockApiCall.mockRestore(); | ||
}); | ||
|
||
it('Display Unknown Error on Cancel Retirement Modal', async () => { | ||
const cancelRetirementErrors = { | ||
errors: [ | ||
{ | ||
code: null, | ||
dismissible: true, | ||
text: null, | ||
type: 'error', | ||
topic: 'cancelRetirement', | ||
}, | ||
], | ||
}; | ||
const mockApiCall = jest.spyOn(api, 'postCancelRetirement').mockImplementationOnce(() => Promise.resolve(cancelRetirementErrors)); | ||
const cancelRetirementButton = wrapper.find('#cancel-retirement').hostNodes(); | ||
cancelRetirementButton.simulate('click'); | ||
let cancelRetirementModal = wrapper.find('Modal#user-account-cancel-retirement'); | ||
cancelRetirementModal.find('button.btn-danger').hostNodes().simulate('click'); | ||
await waitForComponentToPaint(wrapper); | ||
cancelRetirementModal = wrapper.find('Modal#user-account-cancel-retirement'); | ||
const errorAlert = cancelRetirementModal.find('.alert-danger'); | ||
expect(errorAlert.text()).toEqual( | ||
'Something went wrong. Please try again later!', | ||
); | ||
mockApiCall.mockRestore(); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters