write tests for when verified mode expires

This commit is contained in:
Matthew Piatetsky
2018-12-20 23:49:54 -05:00
parent 0eaa0f8752
commit e0b5e5cb97
5 changed files with 145 additions and 43 deletions

View File

@@ -364,26 +364,35 @@ def get_expiration_banner_text(user, course):
upgrade_link = verified_upgrade_deadline_link(user=user, course=course)
enrollment = CourseEnrollment.get_enrollment(user, course.id)
upgrade_deadline = enrollment.upgrade_deadline
if upgrade_deadline is None:
return
if now() < upgrade_deadline:
if upgrade_deadline is None or now() < upgrade_deadline:
upgrade_deadline = enrollment.course_upgrade_deadline
language = get_language()
if language and language.split('-')[0].lower() == 'es':
language_is_es = language and language.split('-')[0].lower() == 'es'
if language_is_es:
formatted_expiration_date = strftime_localized(expiration_date, '%-d de %b. de %Y').lower()
formatted_upgrade_deadline = strftime_localized(upgrade_deadline, '%-d de %b. de %Y').lower()
else:
formatted_expiration_date = strftime_localized(expiration_date, '%b. %-d, %Y')
formatted_upgrade_deadline = strftime_localized(upgrade_deadline, '%b. %-d, %Y')
bannerText = '<strong>Audit Access Expires {expiration_date}</strong><br>\
You lose all access to this course, including your progress, on {expiration_date}.<br>\
Upgrade by {upgrade_deadline} to get unlimited access to the course as long as it exists on the site.\
<a href="{upgrade_link}">Upgrade now<span class="sr-only"> to retain access past {expiration_date}\
</span></a>'.format(
expiration_date=formatted_expiration_date,
upgrade_link=upgrade_link,
upgrade_deadline=formatted_upgrade_deadline
)
if upgrade_deadline:
if language_is_es:
formatted_upgrade_deadline = strftime_localized(upgrade_deadline, '%-d de %b. de %Y').lower()
else:
formatted_upgrade_deadline = strftime_localized(upgrade_deadline, '%b. %-d, %Y')
bannerText = '<strong>Audit Access Expires {expiration_date}</strong><br>\
You lose all access to this course, including your progress, on {expiration_date}.\
<br>Upgrade by {upgrade_deadline} to get unlimited access to the course as long as it exists\
on the site. <a href="{upgrade_link}">Upgrade now<span class="sr-only"> to retain access past\
{expiration_date}</span></a>'.format(
expiration_date=formatted_expiration_date,
upgrade_link=upgrade_link,
upgrade_deadline=formatted_upgrade_deadline
)
else:
bannerText = '<strong>Audit Access Expires {expiration_date}</strong><br>\
You lose all access to this course, including your progress, on {expiration_date}.\
'.format(
expiration_date=formatted_expiration_date
)
return bannerText

View File

@@ -35,7 +35,11 @@ from lms.djangoapps.courseware.tests.factories import (
from openedx.core.djangoapps.user_api.tests.factories import UserCourseTagFactory
from openedx.core.djangoapps.util.testing import TestConditionalContent
from openedx.core.lib.url_utils import quote_slashes
from openedx.features.content_type_gating.partitions import CONTENT_GATING_PARTITION_ID, CONTENT_TYPE_GATE_GROUP_IDS
from openedx.features.content_type_gating.partitions import (
CONTENT_GATING_PARTITION_ID,
CONTENT_TYPE_GATE_GROUP_IDS,
ContentTypeGatingPartition
)
from openedx.features.content_type_gating.models import ContentTypeGatingConfig
from openedx.features.course_duration_limits.config import (
EXPERIMENT_ID,
@@ -89,7 +93,7 @@ def _get_fragment_from_block(block, user_id, course, request_factory, mock_get_c
return frag
def _assert_block_is_gated(block, is_gated, user_id, course, request_factory):
def _assert_block_is_gated(block, is_gated, user_id, course, request_factory, has_upgrade_link=True):
"""
Asserts that a block in a specific course is gated for a specific user
Arguments:
@@ -98,9 +102,15 @@ def _assert_block_is_gated(block, is_gated, user_id, course, request_factory):
user_id (int): id of user
course_id (CourseLocator): id of course
"""
frag = _get_fragment_from_block(block, user_id, course, request_factory)
checkout_link = '#' if has_upgrade_link else None
with patch.object(ContentTypeGatingPartition, '_get_checkout_link', return_value=checkout_link):
frag = _get_fragment_from_block(block, user_id, course, request_factory)
if is_gated:
assert 'content-paywall' in frag.content
if has_upgrade_link:
assert 'certA_1' in frag.content
else:
assert 'certA_1' not in frag.content
else:
assert 'content-paywall' not in frag.content
@@ -236,6 +246,18 @@ class TestProblemTypeAccess(SharedModuleStoreTestCase):
component_types=['problem', 'html']
)
cls.courses['expired_upgrade_deadline'] = cls._create_course(
run='expired_upgrade_deadline_run_1',
display_name='Expired Upgrade Deadline Course Title',
modes=['audit'],
component_types=['problem', 'html']
)
CourseModeFactory.create(
course_id=cls.courses['expired_upgrade_deadline']['course'].scope_ids.usage_id.course_key,
mode_slug='verified',
expiration_datetime=datetime(2018, 1, 1)
)
def setUp(self):
super(TestProblemTypeAccess, self).setUp()
@@ -266,6 +288,12 @@ class TestProblemTypeAccess(SharedModuleStoreTestCase):
course_id=self.courses['audit_only']['course'].id,
mode='audit'
)
# enroll audit user into the upgrade expired course
CourseEnrollmentFactory.create(
user=self.audit_user,
course_id=self.courses['expired_upgrade_deadline']['course'].id,
mode='audit'
)
ContentTypeGatingConfig.objects.create(enabled=True, enabled_as_of=datetime(2018, 1, 1))
@classmethod
@@ -406,6 +434,20 @@ class TestProblemTypeAccess(SharedModuleStoreTestCase):
request_factory=self.factory,
)
def test_access_expired_upgrade_deadline(self):
"""
If a user is enrolled as an audit user and the upgrade deadline has passed
the user will continue to see gated content, but the upgrade messaging will be removed.
"""
_assert_block_is_gated(
block=self.courses['default']['blocks']['problem'],
user_id=self.users['audit'].id,
course=self.courses['default']['course'],
is_gated=True,
request_factory=self.factory,
has_upgrade_link=False
)
@ddt.data(
('problem', 'graded_problem', 'audit', 404),
('problem', 'graded_problem', 'verified', 200),

View File

@@ -66,7 +66,7 @@ def get_user_course_expiration_date(user, course):
access_duration = MIN_DURATION
if not CourseMode.verified_mode_for_course(course.id):
if not CourseMode.verified_mode_for_course(course.id, include_expired=True):
return None
enrollment = CourseEnrollment.get_enrollment(user, course.id)
@@ -138,11 +138,9 @@ def register_course_expired_message(request, course):
return
upgrade_deadline = enrollment.upgrade_deadline
if upgrade_deadline is None:
return
now = timezone.now()
course_upgrade_deadline = enrollment.course_upgrade_deadline
if now > upgrade_deadline:
if upgrade_deadline and now > upgrade_deadline:
upgrade_deadline = course_upgrade_deadline
expiration_message = _('{strong_open}Audit Access Expires {expiration_date}{strong_close}'
@@ -152,31 +150,47 @@ def register_course_expired_message(request, course):
'as long as it exists on the site. {a_open}Upgrade now{sronly_span_open} to '
'retain access past {expiration_date}{span_close}{a_close}')
full_message = expiration_message
if now < course_upgrade_deadline:
if course_upgrade_deadline and now < course_upgrade_deadline:
full_message += upgrade_deadline_message
language = get_language()
if language and language.split('-')[0].lower() == 'es':
language_is_es = language and language.split('-')[0].lower() == 'es'
if language_is_es:
formatted_expiration_date = strftime_localized(expiration_date, '%-d de %b. de %Y').lower()
formatted_upgrade_deadline = strftime_localized(upgrade_deadline, '%-d de %b. de %Y').lower()
else:
formatted_expiration_date = strftime_localized(expiration_date, '%b. %-d, %Y')
formatted_upgrade_deadline = strftime_localized(upgrade_deadline, '%b. %-d, %Y')
PageLevelMessages.register_info_message(
request,
Text(full_message).format(
a_open=HTML('<a href="{upgrade_link}">').format(
upgrade_link=verified_upgrade_deadline_link(user=request.user, course=course)
),
sronly_span_open=HTML('<span class="sr-only">'),
sighted_only_span_open=HTML('<span aria-hidden="true">'),
span_close=HTML('</span>'),
a_close=HTML('</a>'),
expiration_date=formatted_expiration_date,
strong_open=HTML('<strong>'),
strong_close=HTML('</strong>'),
line_break=HTML('<br>'),
upgrade_deadline=formatted_upgrade_deadline
if upgrade_deadline:
if language_is_es:
formatted_upgrade_deadline = strftime_localized(upgrade_deadline, '%-d de %b. de %Y').lower()
else:
formatted_upgrade_deadline = strftime_localized(upgrade_deadline, '%b. %-d, %Y')
if upgrade_deadline:
PageLevelMessages.register_info_message(
request,
Text(full_message).format(
a_open=HTML('<a href="{upgrade_link}">').format(
upgrade_link=verified_upgrade_deadline_link(user=request.user, course=course)
),
sronly_span_open=HTML('<span class="sr-only">'),
span_close=HTML('</span>'),
a_close=HTML('</a>'),
expiration_date=formatted_expiration_date,
strong_open=HTML('<strong>'),
strong_close=HTML('</strong>'),
line_break=HTML('<br>'),
upgrade_deadline=formatted_upgrade_deadline
)
)
else:
PageLevelMessages.register_info_message(
request,
Text(full_message).format(
span_close=HTML('</span>'),
expiration_date=formatted_expiration_date,
strong_open=HTML('<strong>'),
strong_close=HTML('</strong>'),
line_break=HTML('<br>'),
)
)
)

View File

@@ -129,6 +129,22 @@ class CourseExpirationTestCase(ModuleStoreTestCase):
content_availability_date = start_date
self.assertEqual(result, content_availability_date + access_duration)
@mock.patch("openedx.features.course_duration_limits.access.get_course_run_details")
def test_expired_upgrade_deadline(self, mock_get_course_run_details):
"""
The expiration date still exists if the upgrade deadline has passed
"""
access_duration = timedelta(weeks=7)
mock_get_course_run_details.return_value = {'weeks_to_complete': 7}
start_date = now() - timedelta(weeks=10)
course = CourseFactory(start=start_date)
enrollment = CourseEnrollment.enroll(self.user, course.id, CourseMode.AUDIT)
add_course_mode(course, upgrade_deadline_expired=True)
result = get_user_course_expiration_date(self.user, course)
content_availability_date = enrollment.created
self.assertEqual(result, content_availability_date + access_duration)
@mock.patch("openedx.features.course_duration_limits.access.get_course_run_details")
@ddt.data(
({'user_partition_id': CONTENT_GATING_PARTITION_ID,

View File

@@ -204,7 +204,7 @@ class TestCourseHomePage(CourseHomePageTestCase):
# Fetch the view and verify the query counts
# TODO: decrease query count as part of REVO-28
with self.assertNumQueries(86, table_blacklist=QUERY_COUNT_TABLE_BLACKLIST):
with self.assertNumQueries(87, table_blacklist=QUERY_COUNT_TABLE_BLACKLIST):
with check_mongo_calls(4):
url = course_home_url(self.course)
self.client.get(url)
@@ -538,6 +538,27 @@ class TestCourseHomePageAccess(CourseHomePageTestCase):
)
self.assertRedirects(response, expected_url)
@mock.patch.dict(settings.FEATURES, {'DISABLE_START_DATES': False})
def test_expiration_banner_with_expired_upgrade_deadline(self):
"""
Ensure that a user accessing a course with an expired upgrade deadline
will still see the course expiration banner without the upgrade related text.
"""
past = datetime(2010, 1, 1)
CourseDurationLimitConfig.objects.create(enabled=True, enabled_as_of=past)
course = CourseFactory.create(start=now() - timedelta(days=10))
CourseModeFactory.create(course_id=course.id, mode_slug=CourseMode.AUDIT)
CourseModeFactory.create(course_id=course.id, mode_slug=CourseMode.VERIFIED, expiration_datetime=past)
user = UserFactory(password=self.TEST_PASSWORD)
self.client.login(username=user.username, password=self.TEST_PASSWORD)
CourseEnrollment.enroll(user, course.id, mode=CourseMode.AUDIT)
url = course_home_url(course)
response = self.client.get(url)
bannerText = get_expiration_banner_text(user, course)
self.assertContains(response, bannerText, html=True)
self.assertContains(response, TEST_BANNER_CLASS)
def test_audit_only_not_expired(self):
"""
Verify that enrolled users are NOT shown the course expiration banner and can