diff --git a/lms/djangoapps/certificates/api.py b/lms/djangoapps/certificates/api.py index 8d0f1dc69f..745e6f8420 100644 --- a/lms/djangoapps/certificates/api.py +++ b/lms/djangoapps/certificates/api.py @@ -234,8 +234,9 @@ def certificate_downloadable_status(student, course_key): 'download_url': None, 'uuid': None, } + may_view_certificate = CourseOverview.get_from_id(course_key).may_certify() - if current_status['status'] == CertificateStatuses.downloadable: + if current_status['status'] == CertificateStatuses.downloadable and may_view_certificate: response_data['is_downloadable'] = True response_data['download_url'] = current_status['download_url'] or get_certificate_url(student.id, course_key) response_data['uuid'] = current_status['uuid'] diff --git a/lms/djangoapps/certificates/tests/test_api.py b/lms/djangoapps/certificates/tests/test_api.py index 4a12529528..e583fe105f 100644 --- a/lms/djangoapps/certificates/tests/test_api.py +++ b/lms/djangoapps/certificates/tests/test_api.py @@ -5,6 +5,7 @@ from functools import wraps import ddt from datetime import datetime +from datetime import timedelta from config_models.models import cache from django.conf import settings from django.core.urlresolvers import reverse @@ -15,6 +16,7 @@ from freezegun import freeze_time from mock import patch from nose.plugins.attrib import attr from opaque_keys.edx.locator import CourseLocator +import pytz from certificates import api as certs_api from certificates.models import ( @@ -81,6 +83,7 @@ class WebCertificateTestMixin(object): @attr(shard=1) +@ddt.ddt class CertificateDownloadableStatusTests(WebCertificateTestMixin, ModuleStoreTestCase): """Tests for the `certificate_downloadable_status` helper function. """ ENABLED_SIGNALS = ['course_published'] @@ -94,7 +97,9 @@ class CertificateDownloadableStatusTests(WebCertificateTestMixin, ModuleStoreTes org='edx', number='verified', display_name='Verified Course', - end=datetime.now() + end=datetime.now(pytz.UTC), + self_paced=False, + certificate_available_date=datetime.now(pytz.UTC) - timedelta(days=2) ) self.request_factory = RequestFactory() @@ -201,6 +206,31 @@ class CertificateDownloadableStatusTests(WebCertificateTestMixin, ModuleStoreTes } ) + @ddt.data( + (False, datetime.now(pytz.UTC) + timedelta(days=2), False), + (False, datetime.now(pytz.UTC) - timedelta(days=2), True), + (True, datetime.now(pytz.UTC) + timedelta(days=2), True) + ) + @ddt.unpack + @patch.dict(settings.FEATURES, {'CERTIFICATES_HTML_VIEW': True}) + def test_cert_api_return(self, self_paced, cert_avail_date, cert_downloadable_status): + """ + Test 'downloadable status' + """ + self.course.self_paced = self_paced + self.course.certificate_available_date = cert_avail_date + self.course.save() + + CourseEnrollment.enroll(self.student, self.course.id, mode='honor') + self._setup_course_certificate() + with mock_passing_grade(): + certs_api.generate_user_certificates(self.student, self.course.id) + + self.assertEqual( + certs_api.certificate_downloadable_status(self.student, self.course.id)['is_downloadable'], + cert_downloadable_status + ) + @attr(shard=1) @ddt.ddt diff --git a/lms/djangoapps/courseware/tests/test_views.py b/lms/djangoapps/courseware/tests/test_views.py index 6203de8e9e..650e79a711 100644 --- a/lms/djangoapps/courseware/tests/test_views.py +++ b/lms/djangoapps/courseware/tests/test_views.py @@ -2075,7 +2075,8 @@ class GenerateUserCertTests(ModuleStoreTestCase): number='verified', end=datetime.now(), display_name='Verified Course', - grade_cutoffs={'cutoff': 0.75, 'Pass': 0.5} + grade_cutoffs={'cutoff': 0.75, 'Pass': 0.5}, + self_paced=True ) self.enrollment = CourseEnrollment.enroll(self.student, self.course.id, mode='honor') self.assertTrue(self.client.login(username=self.student, password='123456')) diff --git a/lms/djangoapps/mobile_api/testutils.py b/lms/djangoapps/mobile_api/testutils.py index 85533ef816..3739e5c0d1 100644 --- a/lms/djangoapps/mobile_api/testutils.py +++ b/lms/djangoapps/mobile_api/testutils.py @@ -10,7 +10,6 @@ Test utilities for mobile API tests: MobileCourseAccessTestMixin - tests for APIs with mobile_course_access. """ # pylint: disable=no-member -from datetime import timedelta import ddt import datetime @@ -19,6 +18,7 @@ from django.core.urlresolvers import reverse from django.utils import timezone from mock import patch from opaque_keys.edx.keys import CourseKey +import pytz from rest_framework.test import APITestCase from courseware.access_response import MobileAvailabilityError, StartDateError, VisibilityError @@ -43,7 +43,9 @@ class MobileAPITestCase(ModuleStoreTestCase, APITestCase): self.course = CourseFactory.create( mobile_available=True, static_asset_path="needed_for_split", - end=datetime.datetime.now()) + end=datetime.datetime.now(pytz.UTC), + certificate_available_date=datetime.datetime.now(pytz.UTC) + ) self.user = UserFactory.create() self.password = 'test' self.username = self.user.username @@ -176,7 +178,7 @@ class MobileCourseAccessTestMixin(MobileAPIMilestonesMixin): # pylint: disable=attribute-defined-outside-init self.course = CourseFactory.create(mobile_available=True, static_asset_path="needed_for_split") # pylint: disable=attribute-defined-outside-init - self.course.start = timezone.now() + timedelta(days=365) + self.course.start = timezone.now() + datetime.timedelta(days=365) self.init_course_access() self._verify_response(self.ALLOW_ACCESS_TO_UNRELEASED_COURSE, StartDateError(self.course.start))