From 3e426ccecc5f1b6d9a5bdb1c950bddee4f9d79fc Mon Sep 17 00:00:00 2001 From: Zainab Amir <40633976+zainab-amir@users.noreply.github.com> Date: Thu, 12 Dec 2019 17:22:58 +0500 Subject: [PATCH] Suppress grade on dashboard (#22471) Learners should not be able to view final grade before course end date.Suppress the grade achieved so far till course end date on dashboard. PROD-701 --- common/djangoapps/student/tests/test_views.py | 53 ++++++++++++++----- common/djangoapps/util/course.py | 7 +++ .../_dashboard_certificate_information.html | 9 ++-- 3 files changed, 53 insertions(+), 16 deletions(-) diff --git a/common/djangoapps/student/tests/test_views.py b/common/djangoapps/student/tests/test_views.py index 3f956d2a7c6..dec14876041 100644 --- a/common/djangoapps/student/tests/test_views.py +++ b/common/djangoapps/student/tests/test_views.py @@ -12,39 +12,39 @@ from datetime import datetime, timedelta import ddt import six from completion.test_utils import CompletionWaffleTestMixin, submit_completions_for_testing +from course_modes.models import CourseMode from django.conf import settings -from django.test import RequestFactory, TestCase +from django.test import TestCase from django.test.utils import override_settings from django.urls import reverse from django.utils.timezone import now +from entitlements.tests.factories import CourseEntitlementFactory from milestones.tests.utils import MilestonesTestCaseMixin from mock import patch from opaque_keys import InvalidKeyError from opaque_keys.edx.keys import CourseKey from pyquery import PyQuery as pq from six.moves import range +from student.helpers import DISABLE_UNENROLL_CERT_STATES +from student.models import CourseEnrollment, UserProfile +from student.signals import REFUND_ORDER +from student.tests.factories import CourseEnrollmentFactory, UserFactory +from util.milestones_helpers import get_course_milestones, remove_prerequisite_course, set_prerequisite_courses +from util.testing import UrlResetMixin +from xmodule.modulestore import ModuleStoreEnum +from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase +from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory -from course_modes.models import CourseMode -from entitlements.tests.factories import CourseEntitlementFactory +from lms.djangoapps.certificates.tests.factories import GeneratedCertificateFactory from openedx.core.djangoapps.catalog.tests.factories import ProgramFactory from openedx.core.djangoapps.content.course_overviews.models import CourseOverview from openedx.core.djangoapps.content.course_overviews.tests.factories import CourseOverviewFactory from openedx.core.djangoapps.schedules.config import COURSE_UPDATE_WAFFLE_FLAG from openedx.core.djangoapps.schedules.tests.factories import ScheduleFactory from openedx.core.djangoapps.site_configuration.tests.test_util import with_site_configuration_context -from openedx.core.djangoapps.user_authn.cookies import _get_user_info_cookie_data from openedx.core.djangoapps.waffle_utils.testutils import override_waffle_flag from openedx.features.course_duration_limits.models import CourseDurationLimitConfig from openedx.features.course_experience.tests.views.helpers import add_course_mode -from student.helpers import DISABLE_UNENROLL_CERT_STATES -from student.models import CourseEnrollment, UserProfile -from student.signals import REFUND_ORDER -from student.tests.factories import CourseEnrollmentFactory, UserFactory -from util.milestones_helpers import get_course_milestones, remove_prerequisite_course, set_prerequisite_courses -from util.testing import UrlResetMixin -from xmodule.modulestore import ModuleStoreEnum -from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase -from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory PASSWORD = 'test' @@ -222,6 +222,33 @@ class StudentDashboardTests(SharedModuleStoreTestCase, MilestonesTestCaseMixin, response = self.client.get(self.path) self.assertRedirects(response, reverse('account_settings')) + def test_grade_doesnt_appears_before_course_end_date(self): + """ + Verify that learners are not able to see their final grade before the end + of course in the learner dashboard + """ + self.course = CourseFactory.create(end=self.TOMORROW, emit_signals=True) + self.course_enrollment = CourseEnrollmentFactory(course_id=self.course.id, user=self.user) + GeneratedCertificateFactory(status='notpassing', course_id=self.course.id, user=self.user, grade=0.45) + + response = self.client.get(reverse('dashboard')) + # The final grade does not appear before the course has ended + self.assertNotContains(response, 'Your final grade:') + self.assertNotContains(response, '<span class="grade-value">45%</span>') + + def test_grade_appears_after_course_has_ended(self): + """ + Verify that learners are able to see their final grade of the course in + the learner dashboard after the course had ended + """ + self.course = CourseFactory.create(end=self.THREE_YEARS_AGO, emit_signals=True) + self.course_enrollment = CourseEnrollmentFactory(course_id=self.course.id, user=self.user) + GeneratedCertificateFactory(status='notpassing', course_id=self.course.id, user=self.user, grade=0.45) + + response = self.client.get(reverse('dashboard')) + self.assertContains(response, 'Your final grade:') + self.assertContains(response, '<span class="grade-value">45%</span>') + @patch.multiple('django.conf.settings', **MOCK_SETTINGS) @ddt.data( *itertools.product( diff --git a/common/djangoapps/util/course.py b/common/djangoapps/util/course.py index 1ef703d4243..1c738746fb3 100644 --- a/common/djangoapps/util/course.py +++ b/common/djangoapps/util/course.py @@ -10,6 +10,7 @@ import six.moves.urllib.error import six.moves.urllib.parse import six.moves.urllib.request from django.conf import settings +from django.utils.timezone import now from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers @@ -73,3 +74,9 @@ def has_certificates_enabled(course): if not settings.FEATURES.get('CERTIFICATES_HTML_VIEW', False): return False return course.cert_html_view_enabled + + +def should_display_grade(end_date): + if end_date and end_date < now().replace(hour=0, minute=0, second=0, microsecond=0): + return True + return False diff --git a/lms/templates/dashboard/_dashboard_certificate_information.html b/lms/templates/dashboard/_dashboard_certificate_information.html index 651f80cd9ee..1d8d29cc881 100644 --- a/lms/templates/dashboard/_dashboard_certificate_information.html +++ b/lms/templates/dashboard/_dashboard_certificate_information.html @@ -4,6 +4,7 @@ from django.utils.translation import ugettext as _ from openedx.core.djangolib.markup import HTML, Text from course_modes.models import CourseMode +from util.course import should_display_grade %> <%namespace name='static' file='../static_content.html'/> @@ -44,9 +45,11 @@ else: </div> % else: <div class="message message-status ${status_css_class} is-shown"> - <p class="message-copy">${_("Your final grade:")} - <span class="grade-value">${"{0:.0f}%".format(float(cert_status['grade'])*100)}</span>. - + <p class="message-copy"> + % if should_display_grade(course_overview.end): + ${_("Your final grade:")} + <span class="grade-value">${"{0:.0f}%".format(float(cert_status['grade'])*100)}</span>. + % endif % if cert_status['status'] == 'notpassing': % if enrollment.mode != 'audit': ${_("Grade required for a {cert_name_short}:").format(cert_name_short=cert_name_short)} -- GitLab