Commit 67c39aa3 by Renzo Lucioni Committed by GitHub

Merge pull request #12849 from edx/renzo/include-certificate-urls

Include link to shareable run mode certificate, when available.
parents 65bca48e 3ceba562
...@@ -3,6 +3,7 @@ import copy ...@@ -3,6 +3,7 @@ import copy
import datetime import datetime
import json import json
from unittest import skipUnless from unittest import skipUnless
import uuid
import ddt import ddt
from django.conf import settings from django.conf import settings
...@@ -31,6 +32,7 @@ from xmodule.modulestore.tests.factories import CourseFactory ...@@ -31,6 +32,7 @@ from xmodule.modulestore.tests.factories import CourseFactory
UTILS_MODULE = 'openedx.core.djangoapps.programs.utils' UTILS_MODULE = 'openedx.core.djangoapps.programs.utils'
CERTIFICATES_API_MODULE = 'lms.djangoapps.certificates.api'
@skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') @skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms')
...@@ -263,7 +265,7 @@ class GetCompletedCoursesTestCase(TestCase): ...@@ -263,7 +265,7 @@ class GetCompletedCoursesTestCase(TestCase):
result.update(**kwargs) result.update(**kwargs)
return result return result
@mock.patch(UTILS_MODULE + '.get_certificates_for_user') @mock.patch(UTILS_MODULE + '.certificate_api.get_certificates_for_user')
def test_get_completed_courses(self, mock_get_certs_for_user): def test_get_completed_courses(self, mock_get_certs_for_user):
""" """
Ensure the function correctly calls to and handles results from the Ensure the function correctly calls to and handles results from the
...@@ -697,19 +699,22 @@ class TestSupplementProgramData(ProgramsApiConfigMixin, ModuleStoreTestCase): ...@@ -697,19 +699,22 @@ class TestSupplementProgramData(ProgramsApiConfigMixin, ModuleStoreTestCase):
course_codes=[self.course_code] course_codes=[self.course_code]
) )
def _assert_supplemented(self, actual, is_enrolled=False, is_enrollment_open=True): def _assert_supplemented(self, actual, **kwargs):
"""DRY helper used to verify that program data is extended correctly.""" """DRY helper used to verify that program data is extended correctly."""
course_overview = CourseOverview.get_from_id(self.course.id) # pylint: disable=no-member course_overview = CourseOverview.get_from_id(self.course.id) # pylint: disable=no-member
run_mode = factories.RunMode( run_mode = dict(
course_key=unicode(self.course.id), # pylint: disable=no-member factories.RunMode(
course_url=reverse('course_root', args=[self.course.id]), # pylint: disable=no-member course_key=unicode(self.course.id), # pylint: disable=no-member
course_image_url=course_overview.course_image_url, course_url=reverse('course_root', args=[self.course.id]), # pylint: disable=no-member
start_date=self.course.start.strftime(self.human_friendly_format), course_image_url=course_overview.course_image_url,
end_date=self.course.end.strftime(self.human_friendly_format), start_date=self.course.start.strftime(self.human_friendly_format),
is_enrolled=is_enrolled, end_date=self.course.end.strftime(self.human_friendly_format),
is_enrollment_open=is_enrollment_open, is_enrolled=False,
marketing_url='', is_enrollment_open=True,
marketing_url='',
),
**kwargs
) )
course_code = factories.CourseCode(display_name=self.course_code['display_name'], run_modes=[run_mode]) course_code = factories.CourseCode(display_name=self.course_code['display_name'], run_modes=[run_mode])
expected = copy.deepcopy(self.program) expected = copy.deepcopy(self.program)
...@@ -741,3 +746,20 @@ class TestSupplementProgramData(ProgramsApiConfigMixin, ModuleStoreTestCase): ...@@ -741,3 +746,20 @@ class TestSupplementProgramData(ProgramsApiConfigMixin, ModuleStoreTestCase):
data = utils.supplement_program_data(self.program, self.user) data = utils.supplement_program_data(self.program, self.user)
self._assert_supplemented(data, is_enrollment_open=is_enrollment_open) self._assert_supplemented(data, is_enrollment_open=is_enrollment_open)
@ddt.data(True, False)
@mock.patch(UTILS_MODULE + '.certificate_api.certificate_downloadable_status')
@mock.patch(CERTIFICATES_API_MODULE + '.has_html_certificates_enabled')
def test_certificate_url_retrieval(self, is_uuid_available, mock_html_certs_enabled, mock_get_cert_data):
"""Verify that the student's run mode certificate is included, when available."""
test_uuid = uuid.uuid4().hex
mock_get_cert_data.return_value = {'uuid': test_uuid} if is_uuid_available else {}
mock_html_certs_enabled.return_value = True
data = utils.supplement_program_data(self.program, self.user)
if is_uuid_available:
expected_url = reverse('certificates:render_cert_by_uuid', kwargs={'certificate_uuid': test_uuid})
self._assert_supplemented(data, certificate_url=expected_url)
else:
self._assert_supplemented(data)
...@@ -10,7 +10,7 @@ from django.utils.text import slugify ...@@ -10,7 +10,7 @@ from django.utils.text import slugify
from opaque_keys.edx.keys import CourseKey from opaque_keys.edx.keys import CourseKey
import pytz import pytz
from lms.djangoapps.certificates.api import get_certificates_for_user, is_passing_status from lms.djangoapps.certificates import api as certificate_api
from openedx.core.djangoapps.content.course_overviews.models import CourseOverview from openedx.core.djangoapps.content.course_overviews.models import CourseOverview
from openedx.core.djangoapps.programs.models import ProgramsApiConfig from openedx.core.djangoapps.programs.models import ProgramsApiConfig
from openedx.core.lib.edx_api_utils import get_edx_api_data from openedx.core.lib.edx_api_utils import get_edx_api_data
...@@ -179,11 +179,11 @@ def get_completed_courses(student): ...@@ -179,11 +179,11 @@ def get_completed_courses(student):
iterable of dicts with structure {'course_id': course_key, 'mode': cert_type} iterable of dicts with structure {'course_id': course_key, 'mode': cert_type}
""" """
all_certs = get_certificates_for_user(student.username) all_certs = certificate_api.get_certificates_for_user(student.username)
return [ return [
{'course_id': unicode(cert['course_key']), 'mode': cert['type']} {'course_id': unicode(cert['course_key']), 'mode': cert['type']}
for cert in all_certs for cert in all_certs
if is_passing_status(cert['status']) if certificate_api.is_passing_status(cert['status'])
] ]
...@@ -351,4 +351,12 @@ def supplement_program_data(program_data, user): ...@@ -351,4 +351,12 @@ def supplement_program_data(program_data, user):
# TODO: Currently unavailable on LMS. # TODO: Currently unavailable on LMS.
run_mode['marketing_url'] = '' run_mode['marketing_url'] = ''
certificate_data = certificate_api.certificate_downloadable_status(user, course_key)
certificate_uuid = certificate_data.get('uuid')
if certificate_uuid:
run_mode['certificate_url'] = certificate_api.get_certificate_url(
course_id=course_key,
uuid=certificate_uuid,
)
return program_data return program_data
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment