diff --git a/src/data/services/lms/api.js b/src/data/services/lms/api.js index 65bb4bc..ea51d2b 100644 --- a/src/data/services/lms/api.js +++ b/src/data/services/lms/api.js @@ -4,35 +4,41 @@ import { post, stringifyUrl, } from './utils'; +import { + apiKeys, + unenrollmentAction, + enableEmailsAction, + unknownErrorMessage, +} from './constants'; import urls from './urls'; /********************************************************************************* * GET Actions *********************************************************************************/ const initializeList = ({ user } = {}) => new Promise((resolve, reject) => { - get(stringifyUrl(urls.init, { user })) + get(stringifyUrl(urls.init, { [apiKeys.user]: user })) .then(({ data }) => resolve(data)) - .catch(({ response }) => reject(response ? response.statusText : 'Unknown Error')); + .catch(({ response }) => reject(response ? response.statusText : unknownErrorMessage)); }); const updateEntitlementEnrollment = ({ uuid, courseId }) => post(stringifyUrl( urls.entitlementEnrollment(uuid), - { course_run_id: courseId }, + { [apiKeys.courseRunId]: courseId }, )); const deleteEntitlementEnrollment = ({ uuid }) => client().delete(stringifyUrl( urls.entitlementEnrollment(uuid), - { course_run_id: null }, + { [apiKeys.courseRunId]: null }, )); const updateEmailSettings = ({ courseId, enable }) => post(stringifyUrl( urls.updateEmailSettings, - { course_id: courseId, ...(enable && { receive_emails: 'on' }) }, + { [apiKeys.courseId]: courseId, ...(enable && enableEmailsAction) }, )); const unenrollFromCourse = ({ courseId }) => post(stringifyUrl( - urls.unenrollFromCourse, - { course_id: courseId, enrollment_action: 'unenroll' }, + urls.courseUnenroll, + { [apiKeys.courseId]: courseId, ...unenrollmentAction }, )); export default { diff --git a/src/data/services/lms/api.test.js b/src/data/services/lms/api.test.js new file mode 100644 index 0000000..db94112 --- /dev/null +++ b/src/data/services/lms/api.test.js @@ -0,0 +1,119 @@ +import api from './api'; +import * as utils from './utils'; +import urls from './urls'; +import { + apiKeys, + unenrollmentAction, + enableEmailsAction, + unknownErrorMessage, +} from './constants'; + +jest.mock('./utils', () => { + const deleteFn = (...args) => ({ delete: args }); + return { + client: () => ({ delete: deleteFn }), + delete: deleteFn, + get: jest.fn(), + post: (...args) => ({ post: args }), + stringifyUrl: (...args) => ({ stringifyUrl: args }), + }; +}); + +const testUser = 'test-user'; +const testUuid = 'test-UUID'; +const testCourseId = 'TEST-course-ID'; +const testError = { response: { statusText: 'test-error-status-text' } }; + +const mockData = { some: 'test', data: '!!!' }; + +describe('lms api methods', () => { + describe('initializeList', () => { + it('calls get to init url with user field', async () => { + utils.get.mockReturnValueOnce(Promise.resolve({ data: mockData })); + await api.initializeList({ user: testUser }); + expect(utils.get).toHaveBeenCalledWith(utils.stringifyUrl(urls.init, { user: testUser })); + }); + it('passes empty user if not provided', async () => { + utils.get.mockReturnValueOnce(Promise.resolve({ data: mockData })); + await api.initializeList(); + expect(utils.get).toHaveBeenCalledWith(utils.stringifyUrl(urls.init, {})); + }); + it('resolves data from response on success', () => { + utils.get.mockReturnValueOnce(Promise.resolve({ data: mockData })); + expect(api.initializeList({ user: testUser })).resolves.toBe(mockData); + }); + it('rejects with statusText on failure if available', () => { + utils.get.mockReturnValueOnce(Promise.reject(testError)); + expect(api.initializeList({ user: testUser })).rejects.toMatch( + testError.response.statusText, + ); + }); + it('rejects with "Unknown Error" if response not available', () => { + // eslint-disable-next-line prefer-promise-reject-errors + utils.get.mockReturnValueOnce(Promise.reject({})); + expect(api.initializeList({ user: testUser })).rejects.toMatch(unknownErrorMessage); + }); + }); + describe('updateEntitlementEnrollment', () => { + it('calls post on entitlementEnrollment url with uuid and course run ID', () => { + expect( + api.updateEntitlementEnrollment({ uuid: testUuid, courseId: testCourseId }), + ).toEqual( + utils.post(utils.stringifyUrl( + urls.entitlementEnrollment(testUuid), + { [apiKeys.courseRunId]: testCourseId }, + )), + ); + }); + }); + describe('deleteEntitlementEnrollment', () => { + it('calls delete on entitlementEnrollment url with uuid and null course run ID', () => { + expect( + api.deleteEntitlementEnrollment({ uuid: testUuid }), + ).toEqual( + utils.client().delete(utils.stringifyUrl( + urls.entitlementEnrollment(testUuid), + { [apiKeys.courseRunId]: null }, + )), + ); + }); + }); + describe('updateEmailSettings', () => { + describe('disable', () => { + it('calls post on updateEmailSettings url with course ID', () => { + expect( + api.updateEmailSettings({ courseId: testCourseId, enable: false }), + ).toEqual( + utils.post(utils.stringifyUrl( + urls.updateEmailSettings, + { [apiKeys.courseId]: testCourseId }, + )), + ); + }); + }); + describe('enable', () => { + it('calls post on updateEmailSettings url with course ID and enableEmailsAction', () => { + expect( + api.updateEmailSettings({ courseId: testCourseId, enable: true }), + ).toEqual( + utils.post(utils.stringifyUrl( + urls.updateEmailSettings, + { [apiKeys.courseId]: testCourseId, ...enableEmailsAction }, + )), + ); + }); + }); + }); + describe('unenrollFromCourse', () => { + it('calls post on unenrollFromCourse url with courseId and unenrollment action', () => { + expect( + api.unenrollFromCourse({ courseId: testCourseId }), + ).toEqual( + utils.post(utils.stringifyUrl( + urls.courseUnenroll, + { [apiKeys.courseId]: testCourseId, ...unenrollmentAction }, + )), + ); + }); + }); +}); diff --git a/src/data/services/lms/constants.js b/src/data/services/lms/constants.js new file mode 100644 index 0000000..daf4b4c --- /dev/null +++ b/src/data/services/lms/constants.js @@ -0,0 +1,19 @@ +import { StrictDict } from 'utils'; + +export const apiKeys = StrictDict({ + receiveEmails: 'receive_emails', + enrollmentAction: 'enrollment_action', + courseRunId: 'course_run_id', + courseId: 'course_id', + user: 'user', +}); + +export const apiValues = StrictDict({ + on: 'on', + unenroll: 'unenroll', +}); + +export const unenrollmentAction = { [apiKeys.enrollmentAction]: apiValues.unenroll }; +export const enableEmailsAction = { [apiKeys.receiveEmails]: apiValues.on }; + +export const unknownErrorMessage = 'Unknown Error';