Skip to content

Commit

Permalink
Merge pull request #139 from edx/aakbar/PROD-2419
Browse files Browse the repository at this point in the history
feat: add error handling in enrollment and onboardingStatus component
  • Loading branch information
Ali-D-Akbar authored Jul 9, 2021
2 parents af1b687 + 4c02384 commit eb596ff
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 6 deletions.
29 changes: 25 additions & 4 deletions src/users/data/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,24 @@ export async function getEntitlements(username, page = 1) {
}

export async function getEnrollments(username) {
const { data } = await getAuthenticatedHttpClient().get(
AppUrls.getEnrollmentsUrl(username),
);
return data;
try {
const { data } = await getAuthenticatedHttpClient().get(
AppUrls.getEnrollmentsUrl(username),
);
return data;
} catch (error) {
return {
errors: [
{
code: null,
dismissible: true,
text: JSON.parse(error.customAttributes.httpErrorResponseData),
type: 'danger',
topic: 'enrollments',
},
],
};
}
}

export async function getSsoRecords(username) {
Expand Down Expand Up @@ -218,6 +232,13 @@ export async function getOnboardingStatus(enrollments, username) {
reviewRequirementsUrl: null,
};

if (enrollments.errors) {
return {
...defaultResponse,
onboardingStatus: 'Error while fetching data',
};
}

// get most recent paid active enrollment
const paidEnrollments = enrollments.filter((enrollment) => enrollment.is_active && (enrollment.mode === 'verified' || enrollment.mode === 'professional'));

Expand Down
24 changes: 24 additions & 0 deletions src/users/data/api.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,18 @@ describe('API', () => {
mockAdapter.reset();
});

const enrollmentErrors = {
errors: [
{
code: null,
dismissible: true,
text: 'An unexpected error occurred. Please try refreshing the page.',
type: 'danger',
topic: 'enrollments',
},
],
};

describe('Onboarding Status Fetch', () => {
const expectedSuccessResponse = {
onboardingStatus: 'verified',
Expand Down Expand Up @@ -83,6 +95,11 @@ describe('API', () => {
const response = await api.getOnboardingStatus(data, testUsername);
expect(response).toEqual({ ...expectedSuccessResponse, onboardingStatus: 'Error while fetching data' });
});

it('Unexpected error fetching enrollments', async () => {
const response = await api.getOnboardingStatus(enrollmentErrors, testUsername);
expect(response).toEqual({ ...expectedSuccessResponse, onboardingStatus: 'Error while fetching data' });
});
});

describe('SSO Records Fetch', () => {
Expand Down Expand Up @@ -579,6 +596,13 @@ describe('API', () => {
const response = await api.getEnrollments(testUsername);
expect(response[0]).toEqual(expectedData);
});

it('Enrollments Errors', async () => {
mockAdapter.onGet(enrollmentsApiUrl).reply(() => throwError(500, 'An unexpected error occurred. Please try refreshing the page.'));

const response = await api.getEnrollments(testUsername);
expect(response).toEqual(enrollmentErrors);
});
});

describe('Post Enrollment', () => {
Expand Down
13 changes: 12 additions & 1 deletion src/users/enrollments/Enrollments.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import React, {
useRef,
useLayoutEffect,
useEffect,
useContext,
} from 'react';

import { Button, TransitionReplace, Collapsible } from '@edx/paragon';
Expand All @@ -15,13 +16,16 @@ import EnrollmentForm from './EnrollmentForm';
import EnrollmentExtra from './EnrollmentExtra';
import { CREATE, CHANGE } from './constants';
import PageLoading from '../../components/common/PageLoading';
import UserMessagesContext from '../../userMessages/UserMessagesContext';
import Table from '../../Table';
import { formatDate, sort } from '../../utils';
import { getEnrollments } from '../data/api';
import AlertList from '../../userMessages/AlertList';

export default function Enrollments({
changeHandler, user, expanded,
}) {
const { add, clear } = useContext(UserMessagesContext);
const [sortColumn, setSortColumn] = useState('created');
const [sortDirection, setSortDirection] = useState('desc');
const [formType, setFormType] = useState(null);
Expand All @@ -44,9 +48,15 @@ export default function Enrollments({
}

useEffect(() => {
clear('enrollments');
getEnrollments(user).then((result) => {
const camelCaseResult = camelCaseObject(result);
setEnrollmentData(camelCaseResult);
if (camelCaseResult.errors) {
camelCaseResult.errors.forEach(error => add(error));
setEnrollmentData([]);
} else {
setEnrollmentData(camelCaseResult);
}
});
}, [user]);

Expand Down Expand Up @@ -200,6 +210,7 @@ export default function Enrollments({
</Button>
)}
</div>
<AlertList topic="enrollments" className="mb-3" />
<TransitionReplace>
{formType != null ? (
<EnrollmentForm
Expand Down
26 changes: 25 additions & 1 deletion src/users/enrollments/Enrollments.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,19 +26,43 @@ describe('Course Enrollments Listing', () => {
await waitForComponentToPaint(wrapper);
});

afterEach(() => {
wrapper.unmount();
});

it('default collapsible with enrollment data', () => {
const collapsible = wrapper.find('CollapsibleAdvanced').find('.collapsible-trigger').hostNodes();
expect(collapsible.text()).toEqual('Enrollments (2)');
});

it('No Enrollment Data', async () => {
jest.spyOn(api, 'getEnrollments').mockImplementationOnce(() => Promise.resolve([]));
wrapper = mount(<Enrollments {...props} />);
wrapper = mount(<EnrollmentPageWrapper {...props} />);
await waitForComponentToPaint(wrapper);
const collapsible = wrapper.find('CollapsibleAdvanced').find('.collapsible-trigger').hostNodes();
expect(collapsible.text()).toEqual('Enrollments (0)');
});

it('Error fetching enrollments', async () => {
const enrollmentErrors = {
errors: [
{
code: null,
dismissible: true,
text: 'An unexpected error occurred. Please try refreshing the page.',
type: 'danger',
topic: 'enrollments',
},
],
};
jest.spyOn(api, 'getEnrollments').mockImplementationOnce(() => Promise.resolve(enrollmentErrors));
wrapper = mount(<EnrollmentPageWrapper {...props} />);
await waitForComponentToPaint(wrapper);

const alert = wrapper.find('div.alert');
expect(alert.text()).toEqual(enrollmentErrors.errors[0].text);
});

it('Enrollment create form is rendered', () => {
const createEnrollmentButton = wrapper.find('button#create-enrollment-button');
createEnrollmentButton.simulate('click');
Expand Down

0 comments on commit eb596ff

Please sign in to comment.