Skip to content

Commit

Permalink
fix: [AXIMST-510] signature edit cancel issue (#182)
Browse files Browse the repository at this point in the history
Co-authored-by: Kyrylo Hudym-Levkovych <[email protected]>
  • Loading branch information
khudym and Kyrylo Hudym-Levkovych authored Feb 22, 2024
1 parent e7aec39 commit 5697088
Show file tree
Hide file tree
Showing 8 changed files with 148 additions and 16 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import PropTypes from 'prop-types';
import { Card, Stack, Button } from '@edx/paragon';
import { useIntl } from '@edx/frontend-platform/i18n';
import { Formik, Form, FieldArray } from 'formik';

import CertificateDetailsForm from '../certificate-details/CertificateDetailsForm';
Expand All @@ -9,8 +10,9 @@ import messages from '../messages';
import useCertificateCreateForm from './hooks/useCertificateCreateForm';

const CertificateCreateForm = ({ courseId }) => {
const intl = useIntl();
const {
intl, courseTitle, handleCertificateSubmit, handleFormCancel,
courseTitle, handleCertificateSubmit, handleFormCancel,
} = useCertificateCreateForm(courseId);

return (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
import { useSelector, useDispatch } from 'react-redux';
import { useIntl } from '@edx/frontend-platform/i18n';

import { MODE_STATES } from '../../data/constants';
import { getCourseTitle } from '../../data/selectors';
import { setMode } from '../../data/slice';
import { createCourseCertificate } from '../../data/thunks';

const useCertificateCreateForm = (courseId) => {
const intl = useIntl();
const dispatch = useDispatch();
const courseTitle = useSelector(getCourseTitle);

Expand All @@ -21,7 +19,7 @@ const useCertificateCreateForm = (courseId) => {
window.scrollTo({ top: 0, behavior: 'smooth' });
};
return {
intl, courseTitle, handleCertificateSubmit, handleFormCancel,
courseTitle, handleCertificateSubmit, handleFormCancel,
};
};

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import PropTypes from 'prop-types';
import { Card, Stack, Button } from '@edx/paragon';
import { useIntl } from '@edx/frontend-platform/i18n';
import { Formik, Form, FieldArray } from 'formik';

import ModalNotification from '../../generic/modal-notification';
Expand All @@ -10,8 +11,8 @@ import messages from '../certificate-details/messages';
import useCertificateEditForm from './hooks/useCertificateEditForm';

const CertificateEditForm = ({ courseId }) => {
const intl = useIntl();
const {
intl,
confirmOpen,
courseTitle,
certificates,
Expand Down
117 changes: 117 additions & 0 deletions src/certificates/certificate-edit-form/CertificateEditForm.test.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import { Provider } from 'react-redux';
import { render, waitFor, within } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { initializeMockApp } from '@edx/frontend-platform';
import { IntlProvider } from '@edx/frontend-platform/i18n';
import MockAdapter from 'axios-mock-adapter';
import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';

import { executeThunk } from '../../utils';
import initializeStore from '../../store';
import { getCertificatesApiUrl, getUpdateCertificateApiUrl } from '../data/api';
import { fetchCertificates, deleteCourseCertificate, updateCourseCertificate } from '../data/thunks';
import { certificatesDataMock } from '../__mocks__';
import { MODE_STATES } from '../data/constants';
import messagesDetails from '../certificate-details/messages';
import messages from '../messages';
import CertificateEditForm from './CertificateEditForm';

let axiosMock;
let store;
const courseId = 'course-123';

jest.mock('@edx/frontend-platform/i18n', () => ({
...jest.requireActual('@edx/frontend-platform/i18n'),
useIntl: () => ({
formatMessage: (message) => message.defaultMessage,
}),
}));

const renderComponent = () => render(
<Provider store={store}>
<IntlProvider locale="en">
<CertificateEditForm courseId="course-123" />
</IntlProvider>
</Provider>,
);

const initialState = {
certificates: {
certificatesData: {},
componentMode: MODE_STATES.editAll,
},
};

describe('CertificatesList Component', () => {
beforeEach(async () => {
initializeMockApp({
authenticatedUser: {
userId: 3,
username: 'abc123',
administrator: true,
roles: [],
},
});
store = initializeStore(initialState);
axiosMock = new MockAdapter(getAuthenticatedHttpClient());
axiosMock
.onGet(getCertificatesApiUrl(courseId))
.reply(200, certificatesDataMock);
await executeThunk(fetchCertificates(courseId), store.dispatch);
});

it('submits the form with updated certificate details', async () => {
const courseTitleOverrideValue = 'Updated Course Title';
const signatoryNameValue = 'Updated signatory name';
const newCertificateData = {
...certificatesDataMock,
courseTitle: courseTitleOverrideValue,
certificates: [{
...certificatesDataMock.certificates[0],
signatories: [{
...certificatesDataMock.certificates[0].signatories[0],
name: signatoryNameValue,
}],
}],
};

const { getByDisplayValue, getByRole, getByPlaceholderText } = renderComponent();

userEvent.type(
getByPlaceholderText(messagesDetails.detailsCourseTitleOverride.defaultMessage),
courseTitleOverrideValue,
);

userEvent.click(getByRole('button', { name: messages.saveTooltip.defaultMessage }));

axiosMock.onPost(
getUpdateCertificateApiUrl(courseId, certificatesDataMock.certificates[0].id),
).reply(200, newCertificateData);
await executeThunk(updateCourseCertificate(courseId, newCertificateData), store.dispatch);

await waitFor(() => {
expect(getByDisplayValue(
certificatesDataMock.certificates[0].courseTitle + courseTitleOverrideValue,
)).toBeInTheDocument();
});
});

it('deletes a certificate and updates the store', async () => {
axiosMock.onDelete(
getUpdateCertificateApiUrl(courseId, certificatesDataMock.certificates[0].id),
).reply(200);

const { getByRole } = renderComponent();

userEvent.click(getByRole('button', { name: messages.deleteTooltip.defaultMessage }));

const confirmDeleteModal = getByRole('dialog');
userEvent.click(within(confirmDeleteModal).getByRole('button', { name: messages.deleteTooltip.defaultMessage }));

await executeThunk(deleteCourseCertificate(courseId, certificatesDataMock.certificates[0].id), store.dispatch);

await waitFor(() => {
expect(store.getState().certificates.certificatesData.certificates.length).toBe(0);
});
});
});
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { useIntl } from '@edx/frontend-platform/i18n';
import { useSelector, useDispatch } from 'react-redux';
import { useToggle } from '@edx/paragon';

Expand All @@ -9,7 +8,6 @@ import { updateCourseCertificate, deleteCourseCertificate } from '../../data/thu
import { defaultCertificate } from '../../constants';

const useCertificateEditForm = (courseId) => {
const intl = useIntl();
const dispatch = useDispatch();
const [isConfirmOpen, confirmOpen, confirmClose] = useToggle(false);
const courseTitle = useSelector(getCourseTitle);
Expand All @@ -36,7 +34,6 @@ const useCertificateEditForm = (courseId) => {
}));

return {
intl,
confirmOpen,
courseTitle,
certificates,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,15 @@ import useCreateSignatory from './hooks/useCreateSignatory';
import messages from './messages';

const CertificateSignatories = ({
signatories, handleChange, handleBlur, arrayHelpers, setFieldValue, isForm, resetForm, editModes, setEditModes,
isForm,
editModes,
signatories,
arrayHelpers,
initialSignatoriesValues,
setFieldValue,
setEditModes,
handleBlur,
handleChange,
}) => {
const intl = useIntl();

Expand All @@ -19,7 +27,7 @@ const CertificateSignatories = ({
handleDeleteSignatory,
handleCancelUpdateSignatory,
} = useEditSignatory({
arrayHelpers, editModes, setEditModes, resetForm,
arrayHelpers, editModes, setEditModes, setFieldValue, initialSignatoriesValues,
});

const { handleAddSignatory } = useCreateSignatory({ arrayHelpers });
Expand Down Expand Up @@ -90,18 +98,23 @@ CertificateSignatories.defaultProps = {
handleBlur: null,
setFieldValue: null,
arrayHelpers: null,
resetForm: null,
isForm: false,
editModes: {},
setEditModes: null,
initialSignatoriesValues: null,
};

CertificateSignatories.propTypes = {
isForm: PropTypes.bool,
editModes: PropTypes.objectOf(PropTypes.bool),
initialSignatoriesValues: PropTypes.arrayOf(PropTypes.shape({
name: PropTypes.string.isRequired,
organization: PropTypes.string.isRequired,
signatureImagePath: PropTypes.string.isRequired,
title: PropTypes.string.isRequired,
})),
handleChange: PropTypes.func,
handleBlur: PropTypes.func,
resetForm: PropTypes.func,
setFieldValue: PropTypes.func,
setEditModes: PropTypes.func,
arrayHelpers: PropTypes.shape({}),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const useEditSignatory = ({
arrayHelpers, editModes, setEditModes, resetForm,
arrayHelpers, editModes, setEditModes, setFieldValue, initialSignatoriesValues,
}) => {
const handleDeleteSignatory = (id) => {
arrayHelpers.remove(id);
Expand All @@ -19,8 +19,12 @@ const useEditSignatory = ({
};

const handleCancelUpdateSignatory = (id) => {
const signatoryInitialValues = initialSignatoriesValues[id];
Object.keys(signatoryInitialValues).forEach(fieldKey => {
const fieldName = `signatories[${id}].${fieldKey}`;
setFieldValue(fieldName, signatoryInitialValues[fieldKey]);
});
toggleEditSignatory(id);
resetForm();
};

return { toggleEditSignatory, handleDeleteSignatory, handleCancelUpdateSignatory };
Expand Down
4 changes: 2 additions & 2 deletions src/certificates/certificates-list/CertificatesList.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const CertificatesList = ({ courseId }) => {
{certificates.map((certificate, idx) => (
<Formik initialValues={initialValues[idx]} onSubmit={handleSubmit} key={certificate.id}>
{({
values, handleChange, handleBlur, resetForm, setFieldValue,
values, handleChange, handleBlur, setFieldValue,
}) => (
<Form className="certificates-card-form" data-testid="certificates-list">
<Card>
Expand All @@ -43,10 +43,10 @@ const CertificatesList = ({ courseId }) => {
signatories={values.signatories}
arrayHelpers={arrayHelpers}
editModes={editModes}
initialSignatoriesValues={initialValues[idx].signatories}
handleChange={handleChange}
handleBlur={handleBlur}
setFieldValue={setFieldValue}
resetForm={resetForm}
setEditModes={setEditModes}
/>
)}
Expand Down

0 comments on commit 5697088

Please sign in to comment.