Skip to content

Commit

Permalink
feat: add view certificate button (#121)
Browse files Browse the repository at this point in the history
* feat: add view certificate button
  • Loading branch information
DawoudSheraz authored Jun 28, 2021
1 parent dbb9cfb commit 6630c19
Show file tree
Hide file tree
Showing 8 changed files with 663 additions and 2 deletions.
71 changes: 71 additions & 0 deletions src/users/data/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -443,3 +443,74 @@ export async function postResetPassword(email) {
);
return data;
}

export async function getCertificate(username, courseKey) {
try {
const { data } = await getAuthenticatedHttpClient().get(
AppUrls.getCertificateUrl(username, courseKey),
);
return Array.isArray(data) && data.length > 0 ? data[0] : data;
} catch (error) {
return {
errors: [
{
code: null,
dismissible: true,
text: error.message,
type: 'danger',
topic: 'certificates',
},
],
};
}
}

export async function generateCertificate(username, courseKey) {
const formData = new FormData();
formData.append('username', username);
formData.append('course_key', courseKey);
try {
const { data } = await getAuthenticatedHttpClient().post(
AppUrls.generateCertificateUrl(),
formData,
);
return data;
} catch (error) {
return {
errors: [
{
code: null,
dismissible: true,
text: error.message,
type: 'danger',
topic: 'certificates',
},
],
};
}
}

export async function regenerateCertificate(username, courseKey) {
const formData = new FormData();
formData.append('username', username);
formData.append('course_key', courseKey);
try {
const { data } = await getAuthenticatedHttpClient().post(
AppUrls.regenerateCertificateUrl(),
formData,
);
return data;
} catch (error) {
return {
errors: [
{
code: null,
dismissible: true,
text: error.message,
type: 'danger',
topic: 'certificates',
},
],
};
}
}
76 changes: 75 additions & 1 deletion src/users/data/api.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,14 @@ import { getConfig } from '@edx/frontend-platform';
import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';

import { enrollmentsData } from './test/enrollments';
import { downloadableCertificate } from './test/certificates';
import * as api from './api';
import * as urls from './urls';

describe('API', () => {
const testUsername = 'username';
const testEmail = '[email protected]';
const testCourseId = 'course-v1:testX+test123+2030';
const userAccountApiBaseUrl = `${getConfig().LMS_BASE_URL}/api/user/v1/accounts`;
const ssoRecordsApiUrl = `${getConfig().LMS_BASE_URL}/support/sso_records/${testUsername}`;
const enrollmentsApiUrl = `${getConfig().LMS_BASE_URL}/support/enrollment/${testUsername}`;
Expand All @@ -17,6 +20,9 @@ describe('API', () => {
const verificationStatusApiUrl = `${getConfig().LMS_BASE_URL}/api/user/v1/accounts/${testUsername}/verification_status/`;
const licensesApiUrl = `${getConfig().LICENSE_MANAGER_URL}/api/v1/staff_lookup_licenses/`;
const onboardingStatusApiUrl = `${getConfig().LMS_BASE_URL}/api/edx_proctoring/v1/user_onboarding/status`;
const certificatesUrl = urls.getCertificateUrl(testUsername, testCourseId);
const generateCertificateUrl = urls.generateCertificateUrl();
const regenerateCertificateUrl = urls.regenerateCertificateUrl();

let mockAdapter;

Expand All @@ -30,7 +36,7 @@ describe('API', () => {
};

beforeEach(() => {
mockAdapter = new MockAdapter(getAuthenticatedHttpClient());
mockAdapter = new MockAdapter(getAuthenticatedHttpClient(), { onNoMatch: 'throwException' });
});

afterEach(() => {
Expand Down Expand Up @@ -682,4 +688,72 @@ describe('API', () => {
});
});
});

describe('Certificate Operations', () => {
const successDictResponse = downloadableCertificate;
const successListResponse = [successDictResponse];
const expectedError = {
code: null,
dismissible: true,
text: '',
type: 'danger',
topic: 'certificates',
};

test.each([successDictResponse, successListResponse])('Successful Certificate Fetch', async (successResponse) => {
mockAdapter.onGet(certificatesUrl).reply(200, successResponse);
const response = await api.getCertificate(testUsername, testCourseId);
expect(response).toEqual(Array.isArray(successResponse) ? successResponse[0] : successResponse);
});

it('Unsuccessful Certificates fetch', async () => {
mockAdapter.onGet(certificatesUrl).reply(() => throwError(400, ''));
const response = await api.getCertificate(testUsername, testCourseId);
expect(...response.errors).toEqual(expectedError);
});

it('Successful generate Certificate', async () => {
/**
* No data is added in the post request check because axios-mock-adapter fails
* with formData in post request.
* See: https://github.com/ctimmerm/axios-mock-adapter/issues/253
*/
mockAdapter.onPost(generateCertificateUrl).reply(200, successDictResponse);
const response = await api.generateCertificate(testUsername, testCourseId);
expect(response).toEqual(successDictResponse);
});

it('Unsuccessful generate Certificate', async () => {
/**
* No data is added in the post request check because axios-mock-adapter fails
* with formData in post request.
* See: https://github.com/ctimmerm/axios-mock-adapter/issues/253
*/
mockAdapter.onPost(generateCertificateUrl).reply(() => throwError(400, ''));
const response = await api.generateCertificate(testUsername, testCourseId);
expect(...response.errors).toEqual(expectedError);
});

it('Successful regenerate Certificate', async () => {
/**
* No data is added in the post request check because axios-mock-adapter fails
* with formData in post request.
* See: https://github.com/ctimmerm/axios-mock-adapter/issues/253
*/
mockAdapter.onPost(regenerateCertificateUrl).reply(200, successDictResponse);
const response = await api.regenerateCertificate(testUsername, testCourseId);
expect(response).toEqual(successDictResponse);
});

it('Unsuccessful regenerate Certificate', async () => {
/**
* No data is added in the post request check because axios-mock-adapter fails
* with formData in post request.
* See: https://github.com/ctimmerm/axios-mock-adapter/issues/253
*/
mockAdapter.onPost(regenerateCertificateUrl).reply(() => throwError(400, ''));
const response = await api.regenerateCertificate(testUsername, testCourseId);
expect(...response.errors).toEqual(expectedError);
});
});
});
19 changes: 19 additions & 0 deletions src/users/data/test/certificates.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
export const downloadableCertificate = {
courseKey: 'course-v1:testX+test123+2030',
type: 'verified',
status: 'passing',
grade: '60',
modified: new Date('2020/01/01').toLocaleString(),
downloadUrl: '/certificates/1234-abcd',
regenerate: false,
};

export const regeneratableCertificate = {
courseKey: 'course-v1:testX+test123+2030',
type: 'verified',
status: 'passing',
grade: '60',
modified: new Date('2020/01/01').toLocaleString(),
downloadUrl: null,
regenerate: true,
};
12 changes: 12 additions & 0 deletions src/users/data/urls.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,3 +69,15 @@ export const getAccountActivationUrl = (activationKey) => `${
export const getOnboardingStatusUrl = (courseId, username) => `${
LMS_BASE_URL
}/api/edx_proctoring/v1/user_onboarding/status?course_id=${encodeURIComponent(courseId)}&username=${encodeURIComponent(username)}`;

export const getCertificateUrl = (username, courseKey) => `${
LMS_BASE_URL
}/certificates/search?user=${username}&course_id=${courseKey}`;

export const generateCertificateUrl = () => `${
LMS_BASE_URL
}/certificates/generate`;

export const regenerateCertificateUrl = () => `${
LMS_BASE_URL
}/certificates/regenerate`;
Loading

0 comments on commit 6630c19

Please sign in to comment.