From c9197d3cfc545f622d8d6984a67d983fb2b11759 Mon Sep 17 00:00:00 2001 From: Dillon Dumesnil Date: Tue, 6 Apr 2021 14:29:32 -0400 Subject: [PATCH] refactor: AA-677: Switch relative dates to CourseWaffleFlag We have been bucketing all users into the relative dates experiment since May 18, 2020. We no longer need to keep this as an ExperimentWaffleFlag and can convert to a CourseWaffleFlag (so it continues to support exemptions). --- .../course_api/blocks/tests/test_api.py | 6 +++--- .../courseware/tests/test_date_summary.py | 10 +++++----- lms/djangoapps/courseware/tests/test_views.py | 5 ++--- lms/djangoapps/grades/tests/test_tasks.py | 20 +++++++++---------- lms/djangoapps/instructor/tests/test_api.py | 8 ++++---- .../schedules/tests/test_resolvers.py | 2 +- .../calendar_sync/tests/test_plugins.py | 3 +-- .../features/course_experience/__init__.py | 7 +++---- .../course-outline-fragment.html | 2 +- .../tests/views/test_course_outline.py | 11 +++++----- .../tests/test_show_answer_override.py | 7 ++++--- 11 files changed, 39 insertions(+), 42 deletions(-) diff --git a/lms/djangoapps/course_api/blocks/tests/test_api.py b/lms/djangoapps/course_api/blocks/tests/test_api.py index a1e04fb714..7265c7693c 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 @@ class TestGetBlocksQueryCounts(TestGetBlocksQueryCountsBase): 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 @@ class TestGetBlocksQueryCounts(TestGetBlocksQueryCountsBase): 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/courseware/tests/test_date_summary.py b/lms/djangoapps/courseware/tests/test_date_summary.py index c31ff41750..5e0fe316e5 100644 --- a/lms/djangoapps/courseware/tests/test_date_summary.py +++ b/lms/djangoapps/courseware/tests/test_date_summary.py @@ -150,7 +150,7 @@ class CourseDateSummaryTest(SharedModuleStoreTestCase): 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 @@ -309,7 +309,7 @@ class CourseDateSummaryTest(SharedModuleStoreTestCase): 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 +375,7 @@ class CourseDateSummaryTest(SharedModuleStoreTestCase): 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 +544,7 @@ class CourseDateSummaryTest(SharedModuleStoreTestCase): {'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 @@ -727,7 +727,7 @@ class CourseDateSummaryTest(SharedModuleStoreTestCase): ) @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_views.py b/lms/djangoapps/courseware/tests/test_views.py index 77f8f3059f..6bb65a2ea2 100644 --- a/lms/djangoapps/courseware/tests/test_views.py +++ b/lms/djangoapps/courseware/tests/test_views.py @@ -59,7 +59,6 @@ from lms.djangoapps.courseware.toggles import ( ) from lms.djangoapps.courseware.user_state_client import DjangoXBlockUserStateClient from lms.djangoapps.courseware.views.index import show_courseware_mfe_link -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 @@ -3152,7 +3151,7 @@ class DatesTabTestCase(ModuleStoreTestCase): 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) @@ -3213,7 +3212,7 @@ class DatesTabTestCase(ModuleStoreTestCase): # 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 6f8a4973ec..0deefa06e1 100644 --- a/lms/djangoapps/grades/tests/test_tasks.py +++ b/lms/djangoapps/grades/tests/test_tasks.py @@ -162,10 +162,10 @@ class RecalculateSubsectionGradeTest(HasCourseWithProblemsMixin, ModuleStoreTest 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 @@ class RecalculateSubsectionGradeTest(HasCourseWithProblemsMixin, ModuleStoreTest 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 @@ class RecalculateSubsectionGradeTest(HasCourseWithProblemsMixin, ModuleStoreTest ) @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 @@ class RecalculateSubsectionGradeTest(HasCourseWithProblemsMixin, ModuleStoreTest 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 9f4499a42e..8707bbc0c8 100644 --- a/lms/djangoapps/instructor/tests/test_api.py +++ b/lms/djangoapps/instructor/tests/test_api.py @@ -23,6 +23,7 @@ from django.test import RequestFactory, TestCase from django.urls import reverse as django_reverse from django.utils.translation import ugettext as _ from edx_when.api import get_dates_for_course, get_overrides_for_user, set_date_for_block +from edx_toggles.toggles.testutils import override_waffle_flag from opaque_keys.edx.keys import CourseKey from opaque_keys.edx.locator import UsageKey from pytz import UTC @@ -66,7 +67,6 @@ from lms.djangoapps.courseware.tests.factories import ( 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 @@ class TestDueDateExtensions(SharedModuleStoreTestCase, LoginEnrollmentTestCase): 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 @@ class TestDueDateExtensions(SharedModuleStoreTestCase, LoginEnrollmentTestCase): 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 @@ class TestDueDateExtensionsDeletedDate(ModuleStoreTestCase, LoginEnrollmentTestC 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/openedx/core/djangoapps/schedules/tests/test_resolvers.py b/openedx/core/djangoapps/schedules/tests/test_resolvers.py index 957f779369..5f1dcc5025 100644 --- a/openedx/core/djangoapps/schedules/tests/test_resolvers.py +++ b/openedx/core/djangoapps/schedules/tests/test_resolvers.py @@ -248,7 +248,7 @@ class TestCourseNextSectionUpdateResolver(SchedulesResolverTestMixin, ModuleStor 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 37313e4fa9..7705d2c4d1 100644 --- a/openedx/features/calendar_sync/tests/test_plugins.py +++ b/openedx/features/calendar_sync/tests/test_plugins.py @@ -8,7 +8,6 @@ import ddt 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 @@ class TestCalendarSyncToggleTool(SharedModuleStoreTestCase): ) @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 fe11b3d28e..f3a4a39e0b 100644 --- a/openedx/features/course_experience/__init__.py +++ b/openedx/features/course_experience/__init__.py @@ -7,7 +7,6 @@ from edx_django_utils.monitoring import set_custom_attribute from waffle import flag_is_active from edx_toggles.toggles import LegacyWaffleFlag, LegacyWaffleFlagNamespace -from lms.djangoapps.experiments.flags import ExperimentWaffleFlag from openedx.core.djangoapps.util.user_messages import UserMessageCollection from openedx.core.djangoapps.waffle_utils import CourseWaffleFlag @@ -73,16 +72,16 @@ COURSE_ENABLE_UNENROLLED_ACCESS_FLAG = CourseWaffleFlag( ) # .. toggle_name: course_experience.relative_dates -# .. toggle_implementation: ExperimentWaffleFlag +# .. toggle_implementation: CourseWaffleFlag # .. toggle_default: False # .. toggle_description: Waffle flag to enable relative dates for course content. A 'Dates' tab will be visible in the -# course view showing key course dates. +# course view showing key course dates. Was previously an ExperimentWaffleFlag with experiment_id=17. # .. toggle_use_cases: opt_in # .. toggle_creation_date: 2020-02-10 # .. 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', __name__) # .. 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 6b7e30d76b..7d2ce5b158 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 @@ from openedx.features.course_experience import RELATIVE_DATES_FLAG <% 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/tests/views/test_course_outline.py b/openedx/features/course_experience/tests/views/test_course_outline.py index 2368d20f9b..1b8e080e86 100644 --- a/openedx/features/course_experience/tests/views/test_course_outline.py +++ b/openedx/features/course_experience/tests/views/test_course_outline.py @@ -15,7 +15,7 @@ from django.contrib.sites.models import Site from django.test import RequestFactory, override_settings from django.urls import reverse from django.utils import timezone -from edx_toggles.toggles.testutils import override_waffle_switch +from edx_toggles.toggles.testutils import override_waffle_flag, override_waffle_switch from milestones.tests.utils import MilestonesTestCaseMixin from mock import Mock, patch from opaque_keys.edx.keys import CourseKey, UsageKey @@ -30,7 +30,6 @@ from lms.djangoapps.course_api.blocks.transformers.milestones import MilestonesA from lms.djangoapps.gating import api as lms_gating_api from lms.djangoapps.courseware.tests.factories import StaffFactory 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 +137,7 @@ class TestCourseOutlinePage(SharedModuleStoreTestCase, MasqueradeMixin): 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 +192,7 @@ class TestCourseOutlinePage(SharedModuleStoreTestCase, MasqueradeMixin): 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 +231,7 @@ class TestCourseOutlinePage(SharedModuleStoreTestCase, MasqueradeMixin): else: self.assertNotContains(response, '