Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: error message on reach limit seats in enrollment feature #103

Merged
merged 1 commit into from
Jul 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions src/features/Classes/EnrollStudent/__test__/index.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import '@testing-library/jest-dom/extend-expect';

import EnrollStudent from 'features/Classes/EnrollStudent';

import * as api from 'features/Students/data/api';

jest.mock('react-router-dom', () => ({
useParams: jest.fn(() => ({ courseName: 'Demo course', className: 'demo class' })),
useLocation: jest.fn().mockReturnValue({ search: '?classId=demo class' }),
Expand Down Expand Up @@ -39,6 +41,14 @@ describe('EnrollStudent', () => {
{ preloadedState: {} },
);

const handleEnrollmentsMock = jest.spyOn(api, 'handleEnrollments').mockResolvedValue({
data: {
results: [{
tags: 'success',
}],
},
});

const emailInput = getByPlaceholderText('Enter email of the student to enroll');
fireEvent.change(emailInput, { target: { value: '[email protected]' } });

Expand All @@ -48,5 +58,37 @@ describe('EnrollStudent', () => {
await waitFor(() => {
expect(getByText('Email invite has been sent successfully')).toBeInTheDocument();
});

expect(handleEnrollmentsMock).toHaveBeenCalledTimes(1);
handleEnrollmentsMock.mockRestore();
});

test('Should handle form submission and show error toast', async () => {
const onCloseMock = jest.fn();

const handleEnrollmentsMock = jest.spyOn(api, 'handleEnrollments').mockResolvedValue({
data: {
results: [{ tags: 'error', message: 'Enrollment limit reached' }],
},
});

const { getByPlaceholderText, getByText } = renderWithProviders(
<EnrollStudent isOpen onClose={onCloseMock} />,
{ preloadedState: {} },
);

const emailInput = getByPlaceholderText('Enter email of the student to enroll');
fireEvent.change(emailInput, { target: { value: '[email protected]' } });

const submitButton = getByText('Send invite');
fireEvent.click(submitButton);

await waitFor(() => {
expect(getByText('Enrollment limit reached')).toBeInTheDocument();
});

expect(handleEnrollmentsMock).toHaveBeenCalledTimes(1);

handleEnrollmentsMock.mockRestore();
});
});
26 changes: 20 additions & 6 deletions src/features/Classes/EnrollStudent/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,13 @@ import { initialPage } from 'features/constants';

import 'features/Classes/EnrollStudent/index.scss';

const successToastMessage = 'Email invite has been sent successfully';

const EnrollStudent = ({ isOpen, onClose, queryClassId }) => {
const dispatch = useDispatch();

const { courseName, className } = useParams();
const [showToast, setShowToast] = useState(false);
const [isLoading, setLoading] = useState(false);
const [toastMessage, setToastMessage] = useState('');
const institution = useSelector((state) => state.main.selectedInstitution);
const courseNameDecoded = decodeURIComponent(courseName);
const classNameDecoded = decodeURIComponent(className);
Expand All @@ -47,7 +46,21 @@ const EnrollStudent = ({ isOpen, onClose, queryClassId }) => {

try {
setLoading(true);
await handleEnrollments(formData, queryClassId);
const response = await handleEnrollments(formData, queryClassId);

/**
* This is because the service that checks the enrollment status is a different
* endpoint, and that endpoint always returns a status 200, so the error cannot be
* caught with a .catch.
*/
if (response?.data?.results[0]?.tags === 'error') {
setToastMessage(response?.data?.results[0]?.message);
setShowToast(true);

return onClose();
}

setToastMessage('Email invite has been sent successfully');

const params = {
course_name: courseNameDecoded,
Expand All @@ -59,10 +72,11 @@ const EnrollStudent = ({ isOpen, onClose, queryClassId }) => {

// Get the classes info updated with the new number of students enrolled.
dispatch(fetchAllClassesData(institution.id, courseNameDecoded));

setShowToast(true);
onClose();
return onClose();
} catch (error) {
logError(error);
return logError(error);
} finally {
setLoading(false);
}
Expand All @@ -71,7 +85,7 @@ const EnrollStudent = ({ isOpen, onClose, queryClassId }) => {
return (
<>
<Toast onClose={() => setShowToast(false)} show={showToast}>
{successToastMessage}
{toastMessage}
</Toast>
<ModalDialog
title="Invite student to enroll"
Expand Down
3 changes: 2 additions & 1 deletion src/features/Students/data/_test_/api.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ describe('getStudentbyInstitutionAdmin', () => {
describe('handleEnrollments', () => {
test('should call getAuthenticatedHttpClient with the correct parameters', () => {
const httpClientMock = {
post: jest.fn(),
post: jest.fn().mockResolvedValue({}),
get: jest.fn().mockResolvedValue({}),
};
const courseId = 'course123';
const data = new FormData();
Expand Down
4 changes: 3 additions & 1 deletion src/features/Students/data/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ function handleEnrollments(data, courseId) {
return getAuthenticatedHttpClient().post(
`${INSTRUCTOR_API_URL.replace(courseIdSearchPattern, courseId)}/students_update_enrollment`,
data,
);
).then(() => getAuthenticatedHttpClient().get(
`${getConfig().LMS_BASE_URL}/pearson_course_operation/api/messages/get-messages/`,
));
}

function getStudentsMetrics(institutionId, days) {
Expand Down
Loading