diff --git a/lms/djangoapps/course_api/blocks/tests/test_api.py b/lms/djangoapps/course_api/blocks/tests/test_api.py index a1e04fb714b..7265c7693cd 100644 --- a/lms/djangoapps/course_api/blocks/tests/test_api.py +++ b/lms/djangoapps/course_api/blocks/tests/test_api.py @@ -234,7 +234,7 @@ def test_query_counts_cached(self, store_type, with_storage_backing): self._get_blocks( course, expected_mongo_queries=0, - expected_sql_queries=11 if with_storage_backing else 10, + expected_sql_queries=13 if with_storage_backing else 12, ) @ddt.data( @@ -251,9 +251,9 @@ def test_query_counts_uncached(self, store_type_tuple, with_storage_backing): clear_course_from_cache(course.id) if with_storage_backing: - num_sql_queries = 21 + num_sql_queries = 23 else: - num_sql_queries = 11 + num_sql_queries = 13 self._get_blocks( course, diff --git a/lms/djangoapps/course_home_api/course_metadata/v1/tests/test_views.py b/lms/djangoapps/course_home_api/course_metadata/v1/tests/test_views.py index 0afa1d5ba91..36b4f7548ba 100644 --- a/lms/djangoapps/course_home_api/course_metadata/v1/tests/test_views.py +++ b/lms/djangoapps/course_home_api/course_metadata/v1/tests/test_views.py @@ -41,7 +41,7 @@ def test_get_authenticated_user(self): assert response.status_code == 200 assert not response.data.get('is_staff') # 'Course', 'Wiki', 'Progress' tabs - assert len(response.data.get('tabs', [])) == 4 + assert len(response.data.get('tabs', [])) == 3 def test_get_authenticated_staff_user(self): self.client.logout() @@ -51,7 +51,7 @@ def test_get_authenticated_staff_user(self): assert response.data['is_staff'] # This differs for a staff user because they also receive the Instructor tab # 'Course', 'Wiki', 'Progress', and 'Instructor' tabs - assert len(response.data.get('tabs', [])) == 5 + assert len(response.data.get('tabs', [])) == 4 def test_get_masqueraded_user(self): CourseEnrollment.enroll(self.user, self.course.id, CourseMode.VERIFIED) diff --git a/lms/djangoapps/course_home_api/progress/v1/tests/test_views.py b/lms/djangoapps/course_home_api/progress/v1/tests/test_views.py index edebe868794..f094b1173e4 100644 --- a/lms/djangoapps/course_home_api/progress/v1/tests/test_views.py +++ b/lms/djangoapps/course_home_api/progress/v1/tests/test_views.py @@ -18,7 +18,7 @@ CREDIT_SUPPORT_URL = 'https://support.edx.org/hc/en-us/sections/115004154688-Purchasing-Academic-Credit' -@override_waffle_flag(COURSE_HOME_MICROFRONTEND, active=True) +@override_experiment_waffle_flag(COURSE_HOME_MICROFRONTEND, active=True) @ddt.ddt class ProgressTabTestViews(BaseCourseHomeTests): """ diff --git a/lms/djangoapps/courseware/courses.py b/lms/djangoapps/courseware/courses.py index 9f9bfefbdc3..bc1d693373d 100644 --- a/lms/djangoapps/courseware/courses.py +++ b/lms/djangoapps/courseware/courses.py @@ -18,6 +18,7 @@ from fs.errors import ResourceNotFound from opaque_keys.edx.keys import UsageKey from path import Path as path +from lms.djangoapps.certificates import api as certs_api from openedx.core.lib.cache_utils import request_cached @@ -459,13 +460,6 @@ def get_course_date_blocks(course, user, request=None, include_access=False, Return the list of blocks to display on the course info page, sorted by date. """ - blocks = [] - if RELATIVE_DATES_FLAG.is_enabled(course.id): - blocks.extend(get_course_assignment_date_blocks( - course, user, request, num_return=num_assignments, - include_access=include_access, include_past_dates=include_past_dates, - )) - # Adding these in after the assignment blocks so in the case multiple blocks have the same date, # these blocks will be sorted to come after the assignments. See https://openedx.atlassian.net/browse/AA-158 default_block_classes = [ @@ -477,7 +471,16 @@ def get_course_date_blocks(course, user, request=None, include_access=False, VerificationDeadlineDate, VerifiedUpgradeDeadlineDate, ] - blocks.extend([cls(course, user) for cls in default_block_classes]) + if not course.self_paced and certs_api.get_active_web_certificate(course): + default_block_classes.insert(0, CertificateAvailableDate) + + blocks = [cls(course, user) for cls in default_block_classes] + if RELATIVE_DATES_FLAG.is_enabled(course.id) and user and user.is_authenticated: + blocks.append(CourseExpiredDate(course, user)) + blocks.extend(get_course_assignment_date_blocks( + course, user, request, num_return=num_assignments, + include_access=include_access, include_past_dates=include_past_dates, + )) blocks = filter(lambda b: b.is_allowed and b.date and (include_past_dates or b.is_enabled), blocks) return sorted(blocks, key=date_block_key_fn) diff --git a/lms/djangoapps/courseware/tabs.py b/lms/djangoapps/courseware/tabs.py index 0a8cc2da5c2..44b27faf7d9 100644 --- a/lms/djangoapps/courseware/tabs.py +++ b/lms/djangoapps/courseware/tabs.py @@ -14,6 +14,7 @@ from openedx.core.lib.course_tabs import CourseTabPluginManager from openedx.features.course_experience import DISABLE_UNIFIED_COURSE_TAB_FLAG, default_course_url_name from openedx.features.course_experience.url_helpers import get_learning_mfe_home_url +from openedx.features.course_experience import RELATIVE_DATES_FLAG from common.djangoapps.student.models import CourseEnrollment from xmodule.tabs import CourseTab, CourseTabList, course_reverse_func_from_name_func, key_checker @@ -342,6 +343,11 @@ def link_func(course, reverse_func): tab_dict['link_func'] = link_func super().__init__(tab_dict) + @classmethod + def is_enabled(cls, course, user=None): + """Returns true if this tab is enabled.""" + return RELATIVE_DATES_FLAG.is_enabled(course.id) and super(DatesTab, cls).is_enabled(course, user=user) + def get_course_tab_list(user, course): """ diff --git a/lms/djangoapps/courseware/tests/test_date_summary.py b/lms/djangoapps/courseware/tests/test_date_summary.py index 9537b15c06d..4f9fa9503c0 100644 --- a/lms/djangoapps/courseware/tests/test_date_summary.py +++ b/lms/djangoapps/courseware/tests/test_date_summary.py @@ -35,10 +35,10 @@ DynamicUpgradeDeadlineConfiguration, OrgDynamicUpgradeDeadlineConfiguration ) -from lms.djangoapps.experiments.testutils import override_experiment_waffle_flag from lms.djangoapps.verify_student.models import VerificationDeadline from lms.djangoapps.verify_student.services import IDVerificationService from lms.djangoapps.verify_student.tests.factories import SoftwareSecurePhotoVerificationFactory +from lms.djangoapps.experiments.testutils import override_experiment_waffle_flag from openedx.core.djangoapps.content.course_overviews.models import CourseOverview from openedx.core.djangoapps.self_paced.models import SelfPacedConfiguration from openedx.core.djangoapps.site_configuration.tests.factories import SiteFactory # pylint: disable=unused-import @@ -150,7 +150,7 @@ def test_enabled_block_types(self, course_kwargs, user_kwargs, expected_blocks): CourseEnrollmentFactory(course_id=course.id, user=user, mode=CourseMode.VERIFIED) self.assert_block_types(course, user, expected_blocks) - @override_experiment_waffle_flag(RELATIVE_DATES_FLAG, active=True) + @override_waffle_flag(RELATIVE_DATES_FLAG, active=True) def test_enabled_block_types_with_assignments(self): # pylint: disable=too-many-statements """ Creates a course with multiple subsections to test all of the different @@ -172,7 +172,6 @@ def test_enabled_block_types_with_assignments(self): # pylint: disable=too-many start=now - timedelta(days=1), due=now + timedelta(days=6), graded=True, - format='Homework', ) ItemFactory.create( category='sequential', @@ -181,7 +180,6 @@ def test_enabled_block_types_with_assignments(self): # pylint: disable=too-many start=now + timedelta(days=1), due=now + timedelta(days=7), graded=True, - format='Homework', ) ItemFactory.create( category='sequential', @@ -190,7 +188,6 @@ def test_enabled_block_types_with_assignments(self): # pylint: disable=too-many start=now + timedelta(days=1), due=now + timedelta(days=8), graded=True, - format='Exam', ) ItemFactory.create( category='sequential', @@ -199,7 +196,6 @@ def test_enabled_block_types_with_assignments(self): # pylint: disable=too-many start=now - timedelta(days=14), due=now - timedelta(days=7), graded=True, - format='Exam', ) ItemFactory.create( category='sequential', @@ -216,7 +212,6 @@ def test_enabled_block_types_with_assignments(self): # pylint: disable=too-many start=None, due=now + timedelta(days=9), graded=True, - format='Speech', ) ItemFactory.create( category='sequential', @@ -226,7 +221,6 @@ def test_enabled_block_types_with_assignments(self): # pylint: disable=too-many start=now - timedelta(days=14), due=now + timedelta(days=10), graded=True, - format=None, ) dummy_subsection = ItemFactory.create(category='sequential', graded=True, due=now + timedelta(days=11)) @@ -275,41 +269,34 @@ def test_enabled_block_types_with_assignments(self): # pylint: disable=too-many assignment_title = str(assignment.title_html) or str(assignment.title) assert assignment_title != 'Not returned since we do not get non-graded subsections' - assignment_type = str(assignment.assignment_type) # checking if it is _in_ the title instead of being the title since released assignments # are actually links. Unreleased assignments are just the string of the title. # also checking that the assignment type is returned for graded subsections if 'Released' in assignment_title: - assert assignment_type == 'Homework' for html_tag in assignment_title_html: assert html_tag in assignment_title elif assignment_title == 'Not released': - assert assignment_type == 'Homework' for html_tag in assignment_title_html: assert html_tag not in assignment_title elif assignment_title == 'Third nearest assignment': - assert assignment_type == 'Exam' # It's still not released for html_tag in assignment_title_html: assert html_tag not in assignment_title elif 'Past due date' in assignment_title: assert now > assignment.date - assert assignment_type == 'Exam' for html_tag in assignment_title_html: assert html_tag in assignment_title elif 'No start date' == assignment_title: - assert assignment_type == 'Speech' # Can't determine if it is released so it does not get a link for html_tag in assignment_title_html: assert html_tag not in assignment_title # This is the item with no display name where we set one ourselves. elif 'Assignment' in assignment_title: - assert assignment_type is None # Can't determine if it is released so it does not get a link for html_tag in assignment_title_html: assert html_tag in assignment_title - @override_experiment_waffle_flag(RELATIVE_DATES_FLAG, active=True) + @override_waffle_flag(RELATIVE_DATES_FLAG, active=True) @ddt.data( ([], 3), ([{ @@ -375,7 +362,7 @@ def test_dates_with_openassessments(self, rubric_assessments, date_block_count): blocks = get_course_date_blocks(course, user, request, include_past_dates=True) assert len(blocks) == date_block_count - @override_experiment_waffle_flag(RELATIVE_DATES_FLAG, active=True) + @override_waffle_flag(RELATIVE_DATES_FLAG, active=True) def test_enabled_block_types_with_expired_course(self): course = create_course_run(days_till_start=-100) user = create_user() @@ -544,7 +531,7 @@ def test_course_end_date_after_course(self): {'weeks_to_complete': 7}, # Weeks to complete > time til end (end date shown) {'weeks_to_complete': 4}, # Weeks to complete < time til end (end date not shown) ) - @override_experiment_waffle_flag(RELATIVE_DATES_FLAG, active=True) + @override_waffle_flag(RELATIVE_DATES_FLAG, active=True) def test_course_end_date_self_paced(self, cr_details): """ In self-paced courses, the end date will now only show up if the learner @@ -636,10 +623,7 @@ def test_certificate_available_date_defined(self): CourseEnrollmentFactory(course_id=course.id, user=verified_user, mode=CourseMode.VERIFIED) course.certificate_available_date = datetime.now(utc) + timedelta(days=7) enable_course_certificates(course) - expected_blocks = [ - CourseEndDate, CourseStartDate, TodaysDate, VerificationDeadlineDate, CertificateAvailableDate - ] - self.assert_block_types(course, verified_user, expected_blocks) + CertificateAvailableDate(course, audit_user) for block in (CertificateAvailableDate(course, audit_user), CertificateAvailableDate(course, verified_user)): assert course.certificate_available_date is not None assert block.date == course.certificate_available_date @@ -727,7 +711,7 @@ def test_render_date_string_past(self, delta, expected_date_string): ) @ddt.unpack @override_waffle_flag(DISABLE_UNIFIED_COURSE_TAB_FLAG, active=False) - @override_experiment_waffle_flag(RELATIVE_DATES_FLAG, active=True) + @override_waffle_flag(RELATIVE_DATES_FLAG, active=True) def test_dates_tab_link_render(self, url_name, mfe_active): """ The dates tab link should only show for enrolled or staff users """ course = create_course_run() diff --git a/lms/djangoapps/courseware/tests/test_tabs.py b/lms/djangoapps/courseware/tests/test_tabs.py index 9857a36e341..058c284f0d1 100644 --- a/lms/djangoapps/courseware/tests/test_tabs.py +++ b/lms/djangoapps/courseware/tests/test_tabs.py @@ -400,7 +400,7 @@ def test_get_course_tabs_list_entrance_exam_enabled(self): milestone ) course_tab_list = get_course_tab_list(self.user, self.course) - assert len(course_tab_list) == 2 + assert len(course_tab_list) == 1 assert course_tab_list[0]['tab_id'] == 'courseware' assert course_tab_list[0]['name'] == 'Entrance Exam' @@ -425,7 +425,7 @@ def test_get_course_tabs_list_skipped_entrance_exam(self): self.client.logout() self.login(self.email, self.password) course_tab_list = get_course_tab_list(self.user, self.course) - assert len(course_tab_list) == 5 + assert len(course_tab_list) == 4 def test_course_tabs_list_for_staff_members(self): """ @@ -437,7 +437,7 @@ def test_course_tabs_list_for_staff_members(self): staff_user = StaffFactory(course_key=self.course.id) self.client.login(username=staff_user.username, password='test') course_tab_list = get_course_tab_list(staff_user, self.course) - assert len(course_tab_list) == 5 + assert len(course_tab_list) == 4 class TextBookCourseViewsTestCase(LoginEnrollmentTestCase, SharedModuleStoreTestCase): diff --git a/lms/djangoapps/courseware/tests/test_views.py b/lms/djangoapps/courseware/tests/test_views.py index 7caac724f08..d3adfbfd647 100644 --- a/lms/djangoapps/courseware/tests/test_views.py +++ b/lms/djangoapps/courseware/tests/test_views.py @@ -57,7 +57,6 @@ courseware_mfe_is_advertised, ) from lms.djangoapps.courseware.user_state_client import DjangoXBlockUserStateClient -from lms.djangoapps.experiments.testutils import override_experiment_waffle_flag from lms.djangoapps.grades.config.waffle import ASSUME_ZERO_GRADE_IF_ABSENT from lms.djangoapps.grades.config.waffle import waffle_switch as grades_waffle_switch from lms.djangoapps.verify_student.models import VerificationDeadline @@ -3261,7 +3260,7 @@ def test_tab_redirects_if_not_enrolled_and_not_staff(self): response = self._get_response(self.course) assert response.status_code == 200 - @override_experiment_waffle_flag(RELATIVE_DATES_FLAG, active=True) + @override_waffle_flag(RELATIVE_DATES_FLAG, active=True) @patch('edx_django_utils.monitoring.set_custom_attribute') def test_defaults(self, mock_set_custom_attribute): enrollment = CourseEnrollmentFactory(course_id=self.course.id, user=self.user, mode=CourseMode.VERIFIED) @@ -3322,7 +3321,7 @@ def test_defaults(self, mock_set_custom_attribute): # Make sure the assignment type is rendered self.assertContains(response, 'Homework:') - @override_experiment_waffle_flag(RELATIVE_DATES_FLAG, active=True) + @override_waffle_flag(RELATIVE_DATES_FLAG, active=True) def test_reset_deadlines_banner_displays(self): CourseEnrollmentFactory(course_id=self.course.id, user=self.user, mode=CourseMode.VERIFIED) now = datetime.now(utc) diff --git a/lms/djangoapps/grades/tests/test_tasks.py b/lms/djangoapps/grades/tests/test_tasks.py index 6f8a4973ecf..0deefa06e16 100644 --- a/lms/djangoapps/grades/tests/test_tasks.py +++ b/lms/djangoapps/grades/tests/test_tasks.py @@ -162,10 +162,10 @@ def test_block_structure_created_only_once(self): assert mock_block_structure_create.call_count == 1 @ddt.data( - (ModuleStoreEnum.Type.mongo, 1, 38, True), - (ModuleStoreEnum.Type.mongo, 1, 38, False), - (ModuleStoreEnum.Type.split, 3, 38, True), - (ModuleStoreEnum.Type.split, 3, 38, False), + (ModuleStoreEnum.Type.mongo, 1, 40, True), + (ModuleStoreEnum.Type.mongo, 1, 40, False), + (ModuleStoreEnum.Type.split, 3, 40, True), + (ModuleStoreEnum.Type.split, 3, 40, False), ) @ddt.unpack def test_query_counts(self, default_store, num_mongo_calls, num_sql_calls, create_multiple_subsections): @@ -177,8 +177,8 @@ def test_query_counts(self, default_store, num_mongo_calls, num_sql_calls, creat self._apply_recalculate_subsection_grade() @ddt.data( - (ModuleStoreEnum.Type.mongo, 1, 38), - (ModuleStoreEnum.Type.split, 3, 38), + (ModuleStoreEnum.Type.mongo, 1, 40), + (ModuleStoreEnum.Type.split, 3, 40), ) @ddt.unpack def test_query_counts_dont_change_with_more_content(self, default_store, num_mongo_calls, num_sql_calls): @@ -223,8 +223,8 @@ def test_other_inaccessible_subsection(self, mock_subsection_signal): ) @ddt.data( - (ModuleStoreEnum.Type.mongo, 1, 21), - (ModuleStoreEnum.Type.split, 3, 21), + (ModuleStoreEnum.Type.mongo, 1, 23), + (ModuleStoreEnum.Type.split, 3, 23), ) @ddt.unpack def test_persistent_grades_not_enabled_on_course(self, default_store, num_mongo_queries, num_sql_queries): @@ -238,8 +238,8 @@ def test_persistent_grades_not_enabled_on_course(self, default_store, num_mongo_ assert len(PersistentSubsectionGrade.bulk_read_grades(self.user.id, self.course.id)) == 0 @ddt.data( - (ModuleStoreEnum.Type.mongo, 1, 39), - (ModuleStoreEnum.Type.split, 3, 39), + (ModuleStoreEnum.Type.mongo, 1, 41), + (ModuleStoreEnum.Type.split, 3, 41), ) @ddt.unpack def test_persistent_grades_enabled_on_course(self, default_store, num_mongo_queries, num_sql_queries): diff --git a/lms/djangoapps/instructor/tests/test_api.py b/lms/djangoapps/instructor/tests/test_api.py index 9f4499a42e5..8bc2e7bc6b0 100644 --- a/lms/djangoapps/instructor/tests/test_api.py +++ b/lms/djangoapps/instructor/tests/test_api.py @@ -27,6 +27,7 @@ from opaque_keys.edx.locator import UsageKey from pytz import UTC from testfixtures import LogCapture +from edx_toggles.toggles.testutils import override_waffle_flag from common.djangoapps.course_modes.models import CourseMode from common.djangoapps.course_modes.tests.factories import CourseModeFactory @@ -66,7 +67,6 @@ StaffFactory, ) from lms.djangoapps.courseware.tests.helpers import LoginEnrollmentTestCase -from lms.djangoapps.experiments.testutils import override_experiment_waffle_flag from lms.djangoapps.instructor.tests.utils import FakeContentTask, FakeEmail, FakeEmailInfo from lms.djangoapps.instructor.views.api import ( _get_certificate_for_user, @@ -3930,7 +3930,7 @@ def test_change_nonexistent_due_date(self): assert response.status_code == 400, response.content assert get_extended_due(self.course, self.week3, self.user1) is None - @override_experiment_waffle_flag(RELATIVE_DATES_FLAG, active=True) + @override_waffle_flag(RELATIVE_DATES_FLAG, active=True) def test_reset_date(self): self.test_change_due_date() url = reverse('reset_due_date', kwargs={'course_id': str(self.course.id)}) @@ -3941,7 +3941,7 @@ def test_reset_date(self): assert response.status_code == 200, response.content assert self.due == get_extended_due(self.course, self.week1, self.user1) - @override_experiment_waffle_flag(RELATIVE_DATES_FLAG, active=True) + @override_waffle_flag(RELATIVE_DATES_FLAG, active=True) def test_reset_date_only_in_edx_when(self): # Start with a unit that only has a date in edx-when assert get_date_for_block(self.course, self.week3, self.user1) is None @@ -4070,7 +4070,7 @@ def setUp(self): self.client.login(username=self.instructor.username, password='test') extract_dates(None, self.course.id) - @override_experiment_waffle_flag(RELATIVE_DATES_FLAG, active=True) + @override_waffle_flag(RELATIVE_DATES_FLAG, active=True) def test_reset_extension_to_deleted_date(self): """ Test that we can delete a due date extension after deleting the normal diff --git a/lms/djangoapps/instructor/tests/test_proctoring.py b/lms/djangoapps/instructor/tests/test_proctoring.py index 1791df83611..a58a9a82fbf 100644 --- a/lms/djangoapps/instructor/tests/test_proctoring.py +++ b/lms/djangoapps/instructor/tests/test_proctoring.py @@ -10,7 +10,6 @@ from django.urls import reverse from edx_proctoring.api import create_exam from edx_proctoring.backends.tests.test_backend import TestBackendProvider -from edx_toggles.toggles.testutils import override_waffle_flag from common.djangoapps.student.roles import CourseInstructorRole, CourseStaffRole from common.djangoapps.student.tests.factories import AdminFactory diff --git a/openedx/core/djangoapps/courseware_api/tests/test_views.py b/openedx/core/djangoapps/courseware_api/tests/test_views.py index 0a96cd7bd3e..86c9dd4c162 100644 --- a/openedx/core/djangoapps/courseware_api/tests/test_views.py +++ b/openedx/core/djangoapps/courseware_api/tests/test_views.py @@ -36,7 +36,6 @@ from xmodule.modulestore.tests.django_utils import TEST_DATA_SPLIT_MODULESTORE, SharedModuleStoreTestCase from xmodule.modulestore.tests.factories import ItemFactory, ToyCourseFactory - User = get_user_model() @@ -138,7 +137,7 @@ def test_course_metadata(self, logged_in, enrollment_mode, enable_anonymous, is_ enrollment = response.data['enrollment'] assert enrollment_mode == enrollment['mode'] assert enrollment['is_active'] - assert len(response.data['tabs']) == 6 + assert len(response.data['tabs']) == 5 found = False for tab in response.data['tabs']: if tab['type'] == 'external_link': diff --git a/openedx/core/djangoapps/schedules/tests/test_resolvers.py b/openedx/core/djangoapps/schedules/tests/test_resolvers.py index b8cf1274cff..858315a3a0d 100644 --- a/openedx/core/djangoapps/schedules/tests/test_resolvers.py +++ b/openedx/core/djangoapps/schedules/tests/test_resolvers.py @@ -251,7 +251,7 @@ def create_resolver(self, user_start_date_offset=8): def test_schedule_context(self): resolver = self.create_resolver() # using this to make sure the select_related stays intact - with self.assertNumQueries(15): + with self.assertNumQueries(26): sc = resolver.get_schedules() schedules = list(sc) diff --git a/openedx/features/calendar_sync/tests/test_plugins.py b/openedx/features/calendar_sync/tests/test_plugins.py index 37313e4fa9f..7705d2c4d15 100644 --- a/openedx/features/calendar_sync/tests/test_plugins.py +++ b/openedx/features/calendar_sync/tests/test_plugins.py @@ -8,7 +8,6 @@ from django.test import RequestFactory from edx_toggles.toggles.testutils import override_waffle_flag -from lms.djangoapps.experiments.testutils import override_experiment_waffle_flag from openedx.features.calendar_sync.plugins import CalendarSyncToggleTool from openedx.features.course_experience import CALENDAR_SYNC_FLAG, RELATIVE_DATES_FLAG from xmodule.modulestore.tests.django_utils import CourseUserType, SharedModuleStoreTestCase @@ -35,7 +34,7 @@ def setUpClass(cls): ) @ddt.unpack @override_waffle_flag(CALENDAR_SYNC_FLAG, active=True) - @override_experiment_waffle_flag(RELATIVE_DATES_FLAG, active=True) + @override_waffle_flag(RELATIVE_DATES_FLAG, active=True) def test_calendar_sync_toggle_tool_is_enabled(self, user_type, should_be_enabled): request = RequestFactory().request() request.user = self.create_user_for_course(self.course, user_type) diff --git a/openedx/features/course_experience/__init__.py b/openedx/features/course_experience/__init__.py index 1bbca546aa2..d12d32dc6a9 100644 --- a/openedx/features/course_experience/__init__.py +++ b/openedx/features/course_experience/__init__.py @@ -78,7 +78,7 @@ # .. toggle_warnings: To set a relative due date for self-paced courses, the weeks_to_complete field for a course run # needs to be set. Currently it can be set through the publisher app. # .. toggle_tickets: https://openedx.atlassian.net/browse/AA-27 -RELATIVE_DATES_FLAG = ExperimentWaffleFlag(WAFFLE_FLAG_NAMESPACE, 'relative_dates', __name__, experiment_id=17) +RELATIVE_DATES_FLAG = CourseWaffleFlag(WAFFLE_FLAG_NAMESPACE, 'relative_dates') # .. toggle_name: course_experience.calendar_sync # .. toggle_implementation: CourseWaffleFlag diff --git a/openedx/features/course_experience/templates/course_experience/course-outline-fragment.html b/openedx/features/course_experience/templates/course_experience/course-outline-fragment.html index 6b7e30d76b2..7d2ce5b1581 100644 --- a/openedx/features/course_experience/templates/course_experience/course-outline-fragment.html +++ b/openedx/features/course_experience/templates/course_experience/course-outline-fragment.html @@ -21,7 +21,7 @@ <% course_sections = blocks.get('children') self_paced = context.get('self_paced', False) -relative_dates_flag_is_enabled = RELATIVE_DATES_FLAG.is_enabled(str(course_key)) +relative_dates_flag_is_enabled = RELATIVE_DATES_FLAG.is_enabled(course_key) is_course_staff = bool(user and course and has_access(user, 'staff', course, course.id)) dates_banner_displayed = False %> diff --git a/openedx/features/course_experience/templates/course_experience/next-up-banner-fragment.html b/openedx/features/course_experience/templates/course_experience/next-up-banner-fragment.html new file mode 100644 index 00000000000..63762d52330 --- /dev/null +++ b/openedx/features/course_experience/templates/course_experience/next-up-banner-fragment.html @@ -0,0 +1,13 @@ +## mako + +<%page expression_filter="h"/> + +<%! +from django.utils.translation import ugettext as _ +%> + +
+ ${_("Get started on what's next: ")} + ${assignment_title} + (${assignment_duration}) +
\ No newline at end of file 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 2368d20f9bf..13eff69ab3b 100644 --- a/openedx/features/course_experience/tests/views/test_course_outline.py +++ b/openedx/features/course_experience/tests/views/test_course_outline.py @@ -29,8 +29,8 @@ from lms.djangoapps.course_api.blocks.transformers.milestones import MilestonesAndSpecialExamsTransformer from lms.djangoapps.gating import api as lms_gating_api from lms.djangoapps.courseware.tests.factories import StaffFactory +from edx_toggles.toggles.testutils import override_waffle_flag from lms.djangoapps.courseware.tests.helpers import MasqueradeMixin -from lms.djangoapps.experiments.testutils import override_experiment_waffle_flag from lms.urls import RESET_COURSE_DEADLINES_NAME from openedx.core.djangoapps.course_date_signals.models import SelfPacedRelativeDatesConfig from openedx.core.djangoapps.schedules.models import Schedule @@ -138,7 +138,7 @@ def setUp(self): super(TestCourseOutlinePage, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments self.client.login(username=self.user.username, password=TEST_PASSWORD) - @override_experiment_waffle_flag(RELATIVE_DATES_FLAG, active=True) + @override_waffle_flag(RELATIVE_DATES_FLAG, active=True) def test_outline_details(self): for course in self.courses: @@ -193,7 +193,7 @@ def test_num_graded_problems(self): self.assertRegex(content, sequential2.display_name + r'\s*\(1 Question\)\s*') self.assertRegex(content, sequential3.display_name + r'\s*\(2 Questions\)\s*') - @override_experiment_waffle_flag(RELATIVE_DATES_FLAG, active=True) + @override_waffle_flag(RELATIVE_DATES_FLAG, active=True) @ddt.data( ([CourseMode.AUDIT, CourseMode.VERIFIED], CourseMode.AUDIT, False, True), ([CourseMode.AUDIT, CourseMode.VERIFIED], CourseMode.VERIFIED, False, True), @@ -232,7 +232,7 @@ def test_reset_course_deadlines_banner_shows_for_self_paced_course( else: self.assertNotContains(response, '