diff --git a/openedx/features/course_experience/tests/views/test_course_outline.py b/openedx/features/course_experience/tests/views/test_course_outline.py index 1bbbde067a..e0a5d21248 100644 --- a/openedx/features/course_experience/tests/views/test_course_outline.py +++ b/openedx/features/course_experience/tests/views/test_course_outline.py @@ -13,6 +13,8 @@ from django.core.urlresolvers import reverse from django.test import override_settings from mock import Mock, patch from six import text_type +from waffle.models import Switch +from waffle.testutils import override_switch from courseware.tests.factories import StaffFactory from gating import api as lms_gating_api @@ -21,10 +23,12 @@ from milestones.tests.utils import MilestonesTestCaseMixin from opaque_keys.edx.keys import CourseKey, UsageKey from openedx.core.djangoapps.site_configuration.models import SiteConfiguration from openedx.core.lib.gating import api as gating_api +from openedx.features.course_experience.views.course_outline import ( + CourseOutlineFragmentView, DEFAULT_COMPLETION_TRACKING_START +) from pyquery import PyQuery as pq from student.models import CourseEnrollment from student.tests.factories import UserFactory -from waffle.testutils import override_switch from xmodule.modulestore import ModuleStoreEnum from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory @@ -563,6 +567,31 @@ class TestCourseOutlineResumeCourse(SharedModuleStoreTestCase, CompletionWaffleT self.assertTrue(get_sequential_button(text_type(sequential1.location), False) in stripped_response) self.assertTrue(get_sequential_button(text_type(sequential2.location), True) in stripped_response) + def test_user_enrolled_after_completion_collection(self): + """ + Tests that the _completion_data_collection_start() method returns the created + time of the waffle switch that enables completion data tracking. + """ + view = CourseOutlineFragmentView() + switches = waffle.waffle() + # pylint: disable=protected-access + switch_name = switches._namespaced_name(waffle.ENABLE_COMPLETION_TRACKING) + switch, _ = Switch.objects.get_or_create(name=switch_name) # pylint: disable=unpacking-non-sequence + + self.assertEqual(switch.created, view._completion_data_collection_start()) + + switch.delete() + + def test_user_enrolled_after_completion_collection_default(self): + """ + Tests that the _completion_data_collection_start() method returns a default constant + when no Switch object exists for completion data tracking. + """ + view = CourseOutlineFragmentView() + + # pylint: disable=protected-access + self.assertEqual(DEFAULT_COMPLETION_TRACKING_START, view._completion_data_collection_start()) + class TestCourseOutlinePreview(SharedModuleStoreTestCase): """ diff --git a/openedx/features/course_experience/views/course_outline.py b/openedx/features/course_experience/views/course_outline.py index 841979c902..03d704d2ae 100644 --- a/openedx/features/course_experience/views/course_outline.py +++ b/openedx/features/course_experience/views/course_outline.py @@ -3,22 +3,26 @@ Views to show a course outline. """ import re import datetime -import pytz +from completion import waffle as completion_waffle from django.contrib.auth.models import User from django.template.context_processors import csrf from django.template.loader import render_to_string from opaque_keys.edx.keys import CourseKey +from pytz import UTC +from waffle.models import Switch from web_fragments.fragment import Fragment from courseware.courses import get_course_overview_with_access from openedx.core.djangoapps.plugin_api.views import EdxFragmentView from openedx.features.course_experience import waffle as course_experience_waffle -from completion import waffle as completion_waffle from student.models import CourseEnrollment -from ..utils import get_course_outline_block_tree, get_resume_block from util.milestones_helpers import get_course_content_milestones +from ..utils import get_course_outline_block_tree, get_resume_block + + +DEFAULT_COMPLETION_TRACKING_START = datetime.datetime(2018, 1, 24, tzinfo=UTC) class CourseOutlineFragmentView(EdxFragmentView): @@ -143,7 +147,6 @@ class CourseOutlineFragmentView(EdxFragmentView): before this date, they may see incomplete collection data. This is a temporary check until all active enrollments are created after the date. """ - begin_collection_date = datetime.datetime(2018, 01, 24, tzinfo=pytz.utc) user = User.objects.get(username=user) try: user_enrollment = CourseEnrollment.objects.get( @@ -151,10 +154,21 @@ class CourseOutlineFragmentView(EdxFragmentView): course_id=course_key, is_active=True ) - return user_enrollment.created > begin_collection_date + return user_enrollment.created > self._completion_data_collection_start() except CourseEnrollment.DoesNotExist: return False + def _completion_data_collection_start(self): + """ + Returns the date that the ENABLE_COMPLETION_TRACKING waffle switch was enabled. + """ + # pylint: disable=protected-access + switch_name = completion_waffle.waffle()._namespaced_name(completion_waffle.ENABLE_COMPLETION_TRACKING) + try: + return Switch.objects.get(name=switch_name).created + except Switch.DoesNotExist: + return DEFAULT_COMPLETION_TRACKING_START + def mark_first_unit_to_resume(self, block_node): children = block_node.get('children') if children: