diff --git a/cms/djangoapps/contentstore/rest_api/v0/tests/test_advanced_settings.py b/cms/djangoapps/contentstore/rest_api/v0/tests/test_advanced_settings.py index a87421a08c32..765246258bf2 100644 --- a/cms/djangoapps/contentstore/rest_api/v0/tests/test_advanced_settings.py +++ b/cms/djangoapps/contentstore/rest_api/v0/tests/test_advanced_settings.py @@ -6,14 +6,11 @@ import ddt from django.test import override_settings from django.urls import reverse -from edx_toggles.toggles.testutils import override_waffle_flag from milestones.tests.utils import MilestonesTestCaseMixin from cms.djangoapps.contentstore.tests.utils import CourseTestCase -from cms.djangoapps.contentstore.toggles import ENABLE_NEW_STUDIO_ADVANCED_SETTINGS_PAGE -@override_waffle_flag(ENABLE_NEW_STUDIO_ADVANCED_SETTINGS_PAGE, active=True) @ddt.ddt class CourseAdvanceSettingViewTest(CourseTestCase, MilestonesTestCaseMixin): """ diff --git a/cms/djangoapps/contentstore/rest_api/v0/tests/test_tabs.py b/cms/djangoapps/contentstore/rest_api/v0/tests/test_tabs.py index 5da8938935d3..5e83c9313617 100644 --- a/cms/djangoapps/contentstore/rest_api/v0/tests/test_tabs.py +++ b/cms/djangoapps/contentstore/rest_api/v0/tests/test_tabs.py @@ -8,15 +8,12 @@ import ddt from django.urls import reverse -from edx_toggles.toggles.testutils import override_waffle_flag from xmodule.modulestore.tests.factories import BlockFactory from xmodule.tabs import CourseTabList from cms.djangoapps.contentstore.tests.utils import CourseTestCase -from cms.djangoapps.contentstore.toggles import ENABLE_NEW_STUDIO_CUSTOM_PAGES -@override_waffle_flag(ENABLE_NEW_STUDIO_CUSTOM_PAGES, active=True) @ddt.ddt class TabsAPITests(CourseTestCase): """ diff --git a/cms/djangoapps/contentstore/rest_api/v1/views/tests/test_course_index.py b/cms/djangoapps/contentstore/rest_api/v1/views/tests/test_course_index.py index 189f2496a427..0e71eeb91941 100644 --- a/cms/djangoapps/contentstore/rest_api/v1/views/tests/test_course_index.py +++ b/cms/djangoapps/contentstore/rest_api/v1/views/tests/test_course_index.py @@ -22,6 +22,7 @@ class CourseIndexViewTest(CourseTestCase, PermissionAccessMixin): """ Tests for CourseIndexView. """ + maxDiff = None # Show the entire dictionary in the diff def setUp(self): super().setUp() @@ -74,7 +75,10 @@ def test_course_index_response(self): }, "language_code": "en", "lms_link": get_lms_link_for_item(self.course.location), - "mfe_proctored_exam_settings_url": "", + "mfe_proctored_exam_settings_url": ( + f"http://course-authoring-mfe/course/{self.course.id}" + "/pages-and-resources/proctoring/settings" + ), "notification_dismiss_url": None, "proctoring_errors": [], "reindex_link": f"/course/{self.course.id}/search_reindex", @@ -121,7 +125,10 @@ def test_course_index_response_with_show_locators(self): }, "language_code": "en", "lms_link": get_lms_link_for_item(self.course.location), - "mfe_proctored_exam_settings_url": "", + "mfe_proctored_exam_settings_url": ( + f"http://course-authoring-mfe/course/{self.course.id}" + "/pages-and-resources/proctoring/settings" + ), "notification_dismiss_url": None, "proctoring_errors": [], "reindex_link": f"/course/{self.course.id}/search_reindex", @@ -151,6 +158,6 @@ def test_number_of_calls_to_db(self): """ Test to check number of queries made to mysql and mongo """ - with self.assertNumQueries(32, table_ignorelist=WAFFLE_TABLES): + with self.assertNumQueries(33, table_ignorelist=WAFFLE_TABLES): with check_mongo_calls(3): self.client.get(self.url) diff --git a/cms/djangoapps/contentstore/rest_api/v1/views/tests/test_course_waffle_flags.py b/cms/djangoapps/contentstore/rest_api/v1/views/tests/test_course_waffle_flags.py index 6dcbe7f9ad40..1d58f99d386c 100644 --- a/cms/djangoapps/contentstore/rest_api/v1/views/tests/test_course_waffle_flags.py +++ b/cms/djangoapps/contentstore/rest_api/v1/views/tests/test_course_waffle_flags.py @@ -1,134 +1,61 @@ """ Unit tests for the course waffle flags view """ - -from django.contrib.auth import get_user_model from django.urls import reverse -from rest_framework import status +from cms.djangoapps.contentstore import toggles from cms.djangoapps.contentstore.tests.utils import CourseTestCase from openedx.core.djangoapps.waffle_utils.models import WaffleFlagCourseOverrideModel -User = get_user_model() - class CourseWaffleFlagsViewTest(CourseTestCase): """ - Tests for the CourseWaffleFlagsView endpoint, which returns waffle flag states + Basic test for the CourseWaffleFlagsView endpoint, which returns waffle flag states for a specific course or globally if no course ID is provided. """ - - course_waffle_flags = [ - "use_new_custom_pages", - "use_new_schedule_details_page", - "use_new_advanced_settings_page", - "use_new_grading_page", - "use_new_updates_page", - "use_new_import_page", - "use_new_export_page", - "use_new_files_uploads_page", - "use_new_video_uploads_page", - "use_new_course_outline_page", - "use_new_unit_page", - "use_new_course_team_page", - "use_new_certificates_page", - "use_new_textbooks_page", - "use_new_group_configurations_page", - "use_react_markdown_editor" - ] - - other_expected_waffle_flags = ["enable_course_optimizer"] + maxDiff = None # Show the whole dictionary in the diff + + defaults = { + 'enable_course_optimizer': False, + 'use_new_advanced_settings_page': True, + 'use_new_certificates_page': True, + 'use_new_course_outline_page': True, + 'use_new_course_team_page': True, + 'use_new_custom_pages': True, + 'use_new_export_page': True, + 'use_new_files_uploads_page': True, + 'use_new_grading_page': True, + 'use_new_group_configurations_page': True, + 'use_new_home_page': True, + 'use_new_import_page': True, + 'use_new_schedule_details_page': True, + 'use_new_textbooks_page': True, + 'use_new_unit_page': True, + 'use_new_updates_page': True, + 'use_new_video_uploads_page': False, + 'use_react_markdown_editor': False, + } def setUp(self): - """ - Set up test data and state before each test method. - - This method initializes the endpoint URL and creates a set of waffle flags - for the test course, setting each flag's value to `True`. - """ super().setUp() - self.url = reverse("cms.djangoapps.contentstore:v1:course_waffle_flags") - self.create_waffle_flags(self.course_waffle_flags) - self.create_custom_waffle_flags() - - def create_custom_waffle_flags(self, enabled=True): - """ - Helper method to create waffle flags that are not part of `course_waffle_flags` and have - a different format. - """ WaffleFlagCourseOverrideModel.objects.create( - waffle_flag="contentstore.enable_course_optimizer", + waffle_flag=toggles.ENABLE_COURSE_OPTIMIZER.name, course_id=self.course.id, - enabled=enabled, + enabled=True, ) - def create_waffle_flags(self, flags, enabled=True): - """ - Helper method to create waffle flag entries in the database for the test course. - - Args: - flags (list): A list of flag names to set up. - enabled (bool): The value to set for each flag's enabled state. - """ - for flag in flags: - WaffleFlagCourseOverrideModel.objects.create( - waffle_flag=( - f"contentstore.new_studio_mfe.{flag}" - if flag != "use_react_markdown_editor" - else "contentstore.use_react_markdown_editor" - ), - course_id=self.course.id, - enabled=enabled, - ) - - def expected_response(self, enabled=False): - """ - Generate an expected response dictionary based on the enabled flag. + def test_global_defaults(self): + url = reverse("cms.djangoapps.contentstore:v1:course_waffle_flags") + response = self.client.get(url) + assert response.data == self.defaults - Args: - enabled (bool): State to assign to each waffle flag in the response. - - Returns: - dict: A dictionary with each flag set to the value of `enabled`. - """ - res = {flag: enabled for flag in self.course_waffle_flags} - for flag in self.other_expected_waffle_flags: - res[flag] = enabled - return res - - def test_get_course_waffle_flags_with_course_id(self): - """ - Test that waffle flags for a specific course are correctly returned when - a valid course ID is provided. - - Expected Behavior: - - The response should return HTTP 200 status. - - Each flag returned should be `True` as set up in the `setUp` method. - """ - course_url = reverse( + def test_course_override(self): + url = reverse( "cms.djangoapps.contentstore:v1:course_waffle_flags", kwargs={"course_id": self.course.id}, ) - - expected_response = self.expected_response(enabled=True) - expected_response["use_new_home_page"] = False - - response = self.client.get(course_url) - self.assertEqual(response.status_code, status.HTTP_200_OK) - self.assertDictEqual(expected_response, response.data) - - def test_get_course_waffle_flags_without_course_id(self): - """ - Test that the default waffle flag states are returned when no course ID is provided. - - Expected Behavior: - - The response should return HTTP 200 status. - - Each flag returned should default to `False`, representing the global - default state for each flag. - """ - expected_response = self.expected_response(enabled=False) - expected_response["use_new_home_page"] = False - - response = self.client.get(self.url) - self.assertEqual(response.status_code, status.HTTP_200_OK) - self.assertDictEqual(expected_response, response.data) + response = self.client.get(url) + assert response.data == { + **self.defaults, + "enable_course_optimizer": True, + } diff --git a/cms/djangoapps/contentstore/tests/test_contentstore.py b/cms/djangoapps/contentstore/tests/test_contentstore.py index 39e826b3e4f3..99f746700525 100644 --- a/cms/djangoapps/contentstore/tests/test_contentstore.py +++ b/cms/djangoapps/contentstore/tests/test_contentstore.py @@ -1,5 +1,9 @@ # lint-amnesty, pylint: disable=missing-module-docstring +# TODO: Rewrite several of these assertions so that they check the output of the REST or Python +# APIs rather than parsing HTML from the deprecated legacy frontend pages. In particular, any +# test case using override_waffle_flag(toggles.LEGACY_STUDIO_*, True) will need to be fixed. +# Part of https://github.com/openedx/edx-platform/issues/36275. import copy import re @@ -17,7 +21,7 @@ from django.contrib.auth.models import User # lint-amnesty, pylint: disable=imported-auth-user from django.test import TestCase from django.test.utils import override_settings -from edx_toggles.toggles.testutils import override_waffle_switch +from edx_toggles.toggles.testutils import override_waffle_switch, override_waffle_flag from edxval.api import create_video, get_videos_for_course from fs.osfs import OSFS from lxml import etree @@ -43,6 +47,7 @@ from xmodule.seq_block import SequenceBlock from xmodule.video_block import VideoBlock +from cms.djangoapps.contentstore import toggles from cms.djangoapps.contentstore.config import waffle from cms.djangoapps.contentstore.tests.utils import AjaxEnabledTestClient, CourseTestCase, get_url, parse_json from cms.djangoapps.contentstore.utils import ( @@ -587,6 +592,7 @@ def check_components_on_page(self, component_types, expected_types): for expected in expected_types: self.assertContains(resp, expected) + @override_waffle_flag(toggles.LEGACY_STUDIO_UNIT_EDITOR, True) @ddt.data("", "alert('hi')", "") def test_container_handler_xss_prevent(self, malicious_code): """ @@ -596,6 +602,7 @@ def test_container_handler_xss_prevent(self, malicious_code): # Test that malicious code does not appear in html self.assertNotContains(resp, malicious_code) + @override_waffle_flag(toggles.LEGACY_STUDIO_UNIT_EDITOR, True) def test_advanced_components_in_edit_unit(self): # This could be made better, but for now let's just assert that we see the advanced modules mentioned in the # page response HTML @@ -697,9 +704,11 @@ def test_assets_overwrite(self): # Remove tempdir shutil.rmtree(root_dir) + @override_waffle_flag(toggles.LEGACY_STUDIO_UNIT_EDITOR, True) def test_advanced_components_require_two_clicks(self): self.check_components_on_page(['word_cloud'], ['Word cloud']) + @override_waffle_flag(toggles.LEGACY_STUDIO_UNIT_EDITOR, True) def test_edit_unit(self): """Verifies rendering the editor in all the verticals in the given test course""" self._check_verticals([self.vert_loc]) @@ -1379,6 +1388,7 @@ def assert_course_permission_denied(self): resp = self.client.ajax_post('/course/', self.course_data) self.assertEqual(resp.status_code, 403) + @override_waffle_flag(toggles.LEGACY_STUDIO_HOME, True) def test_course_index_view_with_no_courses(self): """Test viewing the index page with no courses""" resp = self.client.get_html('/home/') @@ -1400,6 +1410,7 @@ def test_item_factory(self): item = BlockFactory.create(parent_location=course.location) self.assertIsInstance(item, SequenceBlock) + @override_waffle_flag(toggles.LEGACY_STUDIO_COURSE_OUTLINE, True) def test_course_overview_view_with_course(self): """Test viewing the course overview page with an existing course""" course = CourseFactory.create() @@ -1499,7 +1510,8 @@ def test_get_html(handler): ) course_key = course_items[0].id - resp = self._show_course_overview(course_key) + with override_waffle_flag(toggles.LEGACY_STUDIO_COURSE_OUTLINE, True): + resp = self._show_course_overview(course_key) # course_handler raise 404 for old mongo course if course_key.deprecated: @@ -1510,20 +1522,31 @@ def test_get_html(handler): self.assertContains(resp, 'Chapter 2') # go to various pages - test_get_html('import_handler') - test_get_html('export_handler') - test_get_html('course_team_handler') - test_get_html('course_info_handler') - test_get_html('assets_handler') - test_get_html('tabs_handler') - test_get_html('settings_handler') - test_get_html('grading_handler') - test_get_html('advanced_settings_handler') - test_get_html('textbooks_list_handler') + with override_waffle_flag(toggles.LEGACY_STUDIO_IMPORT, True): + test_get_html('import_handler') + with override_waffle_flag(toggles.LEGACY_STUDIO_EXPORT, True): + test_get_html('export_handler') + with override_waffle_flag(toggles.LEGACY_STUDIO_COURSE_TEAM, True): + test_get_html('course_team_handler') + with override_waffle_flag(toggles.LEGACY_STUDIO_UPDATES, True): + test_get_html('course_info_handler') + with override_waffle_flag(toggles.LEGACY_STUDIO_FILES_UPLOADS, True): + test_get_html('assets_handler') + with override_waffle_flag(toggles.LEGACY_STUDIO_CUSTOM_PAGES, True): + test_get_html('tabs_handler') + with override_waffle_flag(toggles.LEGACY_STUDIO_SCHEDULE_DETAILS, True): + test_get_html('settings_handler') + with override_waffle_flag(toggles.LEGACY_STUDIO_GRADING, True): + test_get_html('grading_handler') + with override_waffle_flag(toggles.LEGACY_STUDIO_ADVANCED_SETTINGS, True): + test_get_html('advanced_settings_handler') + with override_waffle_flag(toggles.LEGACY_STUDIO_TEXTBOOKS, True): + test_get_html('textbooks_list_handler') # go look at the Edit page unit_key = course_key.make_usage_key('vertical', 'test_vertical') - resp = self.client.get_html(get_url('container_handler', unit_key)) + with override_waffle_flag(toggles.LEGACY_STUDIO_UNIT_EDITOR, True): + resp = self.client.get_html(get_url('container_handler', unit_key)) self.assertEqual(resp.status_code, 200) def delete_item(category, name): @@ -1856,20 +1879,23 @@ def assertInCourseListing(self, course_key): """ Asserts that the given course key is NOT in the unsucceeded course action section of the html. """ - course_listing = lxml.html.fromstring(self.client.get_html('/home/').content) + with override_waffle_flag(toggles.LEGACY_STUDIO_HOME, True): + course_listing = lxml.html.fromstring(self.client.get_html('/home/').content) self.assertEqual(len(self.get_unsucceeded_course_action_elements(course_listing, course_key)), 0) def assertInUnsucceededCourseActions(self, course_key): """ Asserts that the given course key is in the unsucceeded course action section of the html. """ - course_listing = lxml.html.fromstring(self.client.get_html('/home/').content) + with override_waffle_flag(toggles.LEGACY_STUDIO_HOME, True): + course_listing = lxml.html.fromstring(self.client.get_html('/home/').content) self.assertEqual(len(self.get_unsucceeded_course_action_elements(course_listing, course_key)), 1) def verify_rerun_course(self, source_course_key, destination_course_key, destination_display_name): """ Verify the contents of the course rerun action """ + rerun_state = CourseRerunState.objects.find_first(course_key=destination_course_key) expected_states = { 'state': CourseRerunUIStateManager.State.SUCCEEDED, diff --git a/cms/djangoapps/contentstore/tests/test_course_listing.py b/cms/djangoapps/contentstore/tests/test_course_listing.py index 7db6d078eaa8..e46b493b7b39 100644 --- a/cms/djangoapps/contentstore/tests/test_course_listing.py +++ b/cms/djangoapps/contentstore/tests/test_course_listing.py @@ -10,8 +10,10 @@ from ccx_keys.locator import CCXLocator from django.conf import settings from django.test import RequestFactory +from edx_toggles.toggles.testutils import override_waffle_flag from opaque_keys.edx.locations import CourseLocator +from cms.djangoapps.contentstore import toggles from cms.djangoapps.contentstore.tests.utils import AjaxEnabledTestClient from cms.djangoapps.contentstore.utils import delete_course from cms.djangoapps.contentstore.views.course import ( @@ -87,6 +89,7 @@ def tearDown(self): self.client.logout() ModuleStoreTestCase.tearDown(self) # pylint: disable=non-parent-method-called + @override_waffle_flag(toggles.LEGACY_STUDIO_HOME, True) def test_empty_course_listing(self): """ Test on empty course listing, studio name is properly displayed diff --git a/cms/djangoapps/contentstore/tests/test_course_settings.py b/cms/djangoapps/contentstore/tests/test_course_settings.py index 77baf73d90bd..a72d14e931f7 100644 --- a/cms/djangoapps/contentstore/tests/test_course_settings.py +++ b/cms/djangoapps/contentstore/tests/test_course_settings.py @@ -1,7 +1,15 @@ """ Tests for Studio Course Settings. -""" +# TODO: Remove each `override_waffle_flag(toggles.LEGACY_STUDIO_*)` by Ulmo. For each occurance: +# * If the test case is just testing the legacy frontend, and we've got the underlying +# functionality tested elsewhere, then just delete the whole test case. +# * Otherwise (i.e., the test is using the legacy UI test a unique backend behavior), then +# rewrite the test to make assertions about the output of the Python API (preferred) or +# REST API (if necessary) so that we can delete the legacy UI without sacrificing the test +# coverage. +# Part of https://github.com/openedx/edx-platform/issues/36275. +""" import copy import datetime @@ -20,6 +28,7 @@ from milestones.tests.utils import MilestonesTestCaseMixin from pytz import UTC +from cms.djangoapps.contentstore import toggles from cms.djangoapps.contentstore.utils import reverse_course_url, reverse_usage_url from cms.djangoapps.models.settings.course_grading import ( GRADING_POLICY_CHANGED_EVENT_TYPE, @@ -115,6 +124,7 @@ def setUp(self): CourseStaffRole(self.course.id).add_users(self.nonstaff) @override_settings(FEATURES={'DISABLE_MOBILE_COURSE_AVAILABLE': True}) + @override_waffle_flag(toggles.LEGACY_STUDIO_ADVANCED_SETTINGS, True) def test_mobile_field_available(self): """ @@ -137,6 +147,7 @@ def test_mobile_field_available(self): (False, True, True) ) @ddt.unpack + @override_waffle_flag(toggles.LEGACY_STUDIO_ADVANCED_SETTINGS, True) def test_discussion_fields_available(self, is_pages_and_resources_enabled, is_legacy_discussion_setting_enabled, fields_visible): """ @@ -152,6 +163,16 @@ def test_discussion_fields_available(self, is_pages_and_resources_enabled, self.assertEqual('discussion_topics' in response, fields_visible) @ddt.data(False, True) + @override_waffle_flag(toggles.LEGACY_STUDIO_ADVANCED_SETTINGS, True) + @override_waffle_flag(toggles.LEGACY_STUDIO_IMPORT, True) + @override_waffle_flag(toggles.LEGACY_STUDIO_EXPORT, True) + @override_waffle_flag(toggles.LEGACY_STUDIO_COURSE_TEAM, True) + @override_waffle_flag(toggles.LEGACY_STUDIO_UPDATES, True) + @override_waffle_flag(toggles.LEGACY_STUDIO_FILES_UPLOADS, True) + @override_waffle_flag(toggles.LEGACY_STUDIO_CUSTOM_PAGES, True) + @override_waffle_flag(toggles.LEGACY_STUDIO_SCHEDULE_DETAILS, True) + @override_waffle_flag(toggles.LEGACY_STUDIO_GRADING, True) + @override_waffle_flag(toggles.LEGACY_STUDIO_TEXTBOOKS, True) def test_disable_advanced_settings_feature(self, disable_advanced_settings): """ If this feature is enabled, only Django Staff/Superuser should be able to access the "Advanced Settings" page. @@ -292,6 +313,7 @@ def compare_date_fields(self, details, encoded, context, field): (True, True), ) @ddt.unpack + @override_waffle_flag(toggles.LEGACY_STUDIO_SCHEDULE_DETAILS, True) def test_upgrade_deadline(self, has_verified_mode, has_expiration_date): if has_verified_mode: deadline = None @@ -310,6 +332,7 @@ def test_upgrade_deadline(self, has_verified_mode, has_expiration_date): self.assertEqual(b"Upgrade Deadline Date" in response.content, has_expiration_date and has_verified_mode) @mock.patch.dict("django.conf.settings.FEATURES", {'ENABLE_PREREQUISITE_COURSES': True}) + @override_waffle_flag(toggles.LEGACY_STUDIO_SCHEDULE_DETAILS, True) def test_pre_requisite_course_list_present(self): settings_details_url = get_url(self.course.id) response = self.client.get_html(settings_details_url) @@ -370,6 +393,7 @@ def test_invalid_pre_requisite_course(self): (False, True, False), (True, True, True), ) + @override_waffle_flag(toggles.LEGACY_STUDIO_SCHEDULE_DETAILS, True) def test_visibility_of_entrance_exam_section(self, feature_flags): """ Tests entrance exam section is available if ENTRANCE_EXAMS feature is enabled no matter any other @@ -386,6 +410,7 @@ def test_visibility_of_entrance_exam_section(self, feature_flags): b'
') + @override_waffle_flag(toggles.LEGACY_STUDIO_SCHEDULE_DETAILS, True) def test_regular_site_fetch(self): settings_details_url = get_url(self.course.id) @@ -1504,7 +1531,6 @@ def test_validate_update_does_not_allow_proctoring_provider_changes_after_course 'test_proctoring_provider': {}, 'proctortrack': {} }, - FEATURES={'ENABLE_EXAM_SETTINGS_HTML_VIEW': True}, ) def test_validate_update_requires_escalation_email_for_proctortrack(self, include_blank_email): json_data = { @@ -1552,7 +1578,6 @@ def test_validate_update_does_not_require_escalation_email_by_default(self): 'DEFAULT': 'proctortrack', 'proctortrack': {} }, - FEATURES={'ENABLE_EXAM_SETTINGS_HTML_VIEW': True}, ) def test_validate_update_cannot_unset_escalation_email_when_proctortrack_is_provider(self): course = CourseFactory.create() @@ -1982,6 +2007,7 @@ def _verify_not_editable(self, response): self.assertNotContains(response, element) @mock.patch.dict("django.conf.settings.FEATURES", {'ENABLE_PUBLISHER': False}) + @override_waffle_flag(toggles.LEGACY_STUDIO_SCHEDULE_DETAILS, True) def test_course_details_with_disabled_setting_global_staff(self): """ Test that user enrollment end date is editable in response. @@ -1992,6 +2018,7 @@ def test_course_details_with_disabled_setting_global_staff(self): self._verify_editable(self._get_course_details_response(True)) @mock.patch.dict("django.conf.settings.FEATURES", {'ENABLE_PUBLISHER': False}) + @override_waffle_flag(toggles.LEGACY_STUDIO_SCHEDULE_DETAILS, True) def test_course_details_with_disabled_setting_non_global_staff(self): """ Test that user enrollment end date is editable in response. @@ -2002,6 +2029,7 @@ def test_course_details_with_disabled_setting_non_global_staff(self): self._verify_editable(self._get_course_details_response(False)) @mock.patch.dict("django.conf.settings.FEATURES", {'ENABLE_PUBLISHER': True}) + @override_waffle_flag(toggles.LEGACY_STUDIO_SCHEDULE_DETAILS, True) def test_course_details_with_enabled_setting_global_staff(self): """ Test that user enrollment end date is editable in response. @@ -2013,6 +2041,7 @@ def test_course_details_with_enabled_setting_global_staff(self): @mock.patch.dict("django.conf.settings.FEATURES", {'ENABLE_PUBLISHER': True}) @override_settings(PLATFORM_NAME='edX') + @override_waffle_flag(toggles.LEGACY_STUDIO_SCHEDULE_DETAILS, True) def test_course_details_with_enabled_setting_non_global_staff(self): """ Test that user enrollment end date is not editable in response. diff --git a/cms/djangoapps/contentstore/tests/test_i18n.py b/cms/djangoapps/contentstore/tests/test_i18n.py index fdab4aef83f1..6201253babf4 100644 --- a/cms/djangoapps/contentstore/tests/test_i18n.py +++ b/cms/djangoapps/contentstore/tests/test_i18n.py @@ -5,6 +5,8 @@ from unittest import mock, skip from django.utils import translation +from edx_toggles.toggles.testutils import override_waffle_flag + from django.utils.translation import get_language from xblock.core import XBlock from xmodule.modulestore.django import XBlockI18nService @@ -12,6 +14,7 @@ from xmodule.modulestore.tests.factories import CourseFactory, BlockFactory from xmodule.tests.test_export import PureXBlock +from cms.djangoapps.contentstore import toggles from cms.djangoapps.contentstore.tests.utils import AjaxEnabledTestClient from cms.djangoapps.contentstore.views.preview import _prepare_runtime_for_preview from common.djangoapps.student.tests.factories import UserFactory @@ -202,6 +205,7 @@ def setUp(self): 'display_name': 'Robot Super Course', } + @override_waffle_flag(toggles.LEGACY_STUDIO_HOME, True) def test_course_plain_english(self): """Test viewing the index page with no courses""" self.client = AjaxEnabledTestClient() # lint-amnesty, pylint: disable=attribute-defined-outside-init @@ -213,6 +217,7 @@ def test_course_plain_english(self): status_code=200, html=True) + @override_waffle_flag(toggles.LEGACY_STUDIO_HOME, True) def test_course_explicit_english(self): """Test viewing the index page with no courses""" self.client = AjaxEnabledTestClient() # lint-amnesty, pylint: disable=attribute-defined-outside-init diff --git a/cms/djangoapps/contentstore/tests/test_permissions.py b/cms/djangoapps/contentstore/tests/test_permissions.py index 7f0a7079dd1e..d8fad571658d 100644 --- a/cms/djangoapps/contentstore/tests/test_permissions.py +++ b/cms/djangoapps/contentstore/tests/test_permissions.py @@ -2,9 +2,11 @@ Test CRUD for authorization. """ - import copy +from edx_toggles.toggles.testutils import override_waffle_flag + +from cms.djangoapps.contentstore import toggles from cms.djangoapps.contentstore.tests.utils import AjaxEnabledTestClient from cms.djangoapps.contentstore.utils import reverse_course_url, reverse_url from common.djangoapps.student import auth @@ -64,10 +66,15 @@ def tearDown(self): self.client.logout() ModuleStoreTestCase.tearDown(self) # pylint: disable=non-parent-method-called + @override_waffle_flag(toggles.LEGACY_STUDIO_COURSE_TEAM, True) def test_get_all_users(self): """ Test getting all authors for a course where their permissions run the gamut of allowed group types. + + TODO: Replace the call to the legacy course_team_handler with a call to the course team REST API. + The legacy page will be removed, but we still want to the test these behaviors. + Part of https://github.com/openedx/edx-platform/issues/36275. """ # first check the course creator.has explicit access (don't use has_access as is_staff # will trump the actual test) diff --git a/cms/djangoapps/contentstore/tests/tests.py b/cms/djangoapps/contentstore/tests/tests.py index bd2c3dbfd3c8..c6410764675e 100644 --- a/cms/djangoapps/contentstore/tests/tests.py +++ b/cms/djangoapps/contentstore/tests/tests.py @@ -1,5 +1,10 @@ """ This test file will test registration, login, activation, and session activity timeouts + +TODO: Rewrite several of these assertions so that they check the output of the REST or Python +APIs rather than parsing HTML from the deprecated legacy frontend pages. In particular, any +test case using override_waffle_flag(toggles.LEGACY_STUDIO_*, True) will need to be fixed. +Part of https://github.com/openedx/edx-platform/issues/36275. """ @@ -13,8 +18,10 @@ from django.core.cache import cache from django.test.utils import override_settings from django.urls import reverse +from edx_toggles.toggles.testutils import override_waffle_flag from pytz import UTC +from cms.djangoapps.contentstore import toggles from cms.djangoapps.contentstore.tests.test_course_settings import CourseTestCase from cms.djangoapps.contentstore.tests.utils import AjaxEnabledTestClient, parse_json, registration, user from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase # lint-amnesty, pylint: disable=wrong-import-order @@ -106,6 +113,7 @@ def check_page_get(self, url, expected): self.assertEqual(resp.status_code, expected) return resp + @override_waffle_flag(toggles.LEGACY_STUDIO_HOME, True) def test_private_pages_auth(self): """Make sure pages that do require login work.""" auth_pages = ( @@ -140,6 +148,7 @@ def test_private_pages_auth(self): self.check_page_get(page, expected=200) @override_settings(SESSION_INACTIVITY_TIMEOUT_IN_SECONDS=1) + @override_waffle_flag(toggles.LEGACY_STUDIO_HOME, True) def test_inactive_session_timeout(self): """ Verify that an inactive session times out and redirects to the @@ -249,6 +258,7 @@ def setUp(self): @data(('edX/test_course_key/Test_Course', 200), ('garbage:edX+test_course_key+Test_Course', 404)) @unpack + @override_waffle_flag(toggles.LEGACY_STUDIO_IMPORT, True) def test_course_key_decorator(self, course_key, status_code): """ Tests for the ensure_valid_course_key decorator. diff --git a/cms/djangoapps/contentstore/toggles.py b/cms/djangoapps/contentstore/toggles.py index 5bc1615057c5..efc6127af80a 100644 --- a/cms/djangoapps/contentstore/toggles.py +++ b/cms/djangoapps/contentstore/toggles.py @@ -67,61 +67,61 @@ def bypass_olx_failure_enabled(): return BYPASS_OLX_FAILURE.is_enabled() -# .. toggle_name: FEATURES['ENABLE_EXAM_SETTINGS_HTML_VIEW'] -# .. toggle_use_cases: open_edx -# .. toggle_implementation: SettingDictToggle +# .. toggle_name: legacy_studio.exam_settings +# .. toggle_implementation: WaffleFlag # .. toggle_default: False -# .. toggle_description: When enabled, users can access the new course authoring view for proctoring exams -# .. toggle_warning: None -# .. toggle_creation_date: 2020-07-23 -ENABLE_EXAM_SETTINGS_HTML_VIEW = SettingDictToggle( - "FEATURES", "ENABLE_EXAM_SETTINGS_HTML_VIEW", default=False, module_name=__name__ -) +# .. toggle_description: Temporarily fall back to the old proctored exam settings view. +# .. toggle_use_cases: temporary +# .. toggle_creation_date: 2025-03-14 +# .. toggle_target_removal_date: 2025-09-14 +# .. toggle_tickets: https://github.com/openedx/edx-platform/issues/36275 +# .. toggle_warning: In Ulmo, this toggle will be removed. Only the new (React-based) experience will be available. +LEGACY_STUDIO_EXAM_SETTINGS = CourseWaffleFlag("legacy_studio.exam_settings", __name__) -def exam_setting_view_enabled(): +def exam_setting_view_enabled(course_key): """ Returns a boolean if proctoring exam setting mfe view is enabled. """ - return ENABLE_EXAM_SETTINGS_HTML_VIEW.is_enabled() + return not LEGACY_STUDIO_EXAM_SETTINGS.is_enabled(course_key) -# .. toggle_name: new_core_editors.use_new_text_editor +# .. toggle_name: legacy_studio.text_editor # .. toggle_implementation: WaffleFlag # .. toggle_default: False -# .. toggle_description: This flag enables the use of the new core text xblock editor +# .. toggle_description: Temporarily fall back to the old Text component (a.k.a. html block) editor. # .. toggle_use_cases: temporary -# .. toggle_creation_date: 2021-12-1 -# .. toggle_target_removal_date: 2022-1-30 -# .. toggle_tickets: TNL-9306 -# .. toggle_warning: -ENABLE_NEW_TEXT_EDITOR_FLAG = WaffleFlag('new_core_editors.use_new_text_editor', __name__) +# .. toggle_creation_date: 2025-03-14 +# .. toggle_target_removal_date: 2025-09-14 +# .. toggle_tickets: https://github.com/openedx/edx-platform/issues/36275 +# .. toggle_warning: In Ulmo, this toggle will be removed. Only the new (React-based) experience will be available. +LEGACY_STUDIO_TEXT_EDITOR = CourseWaffleFlag("legacy_studio.text_editor", __name__) -def use_new_text_editor(): +def use_new_text_editor(course_key): """ Returns a boolean = true if new text editor is enabled """ - return ENABLE_NEW_TEXT_EDITOR_FLAG.is_enabled() + return not LEGACY_STUDIO_TEXT_EDITOR.is_enabled(course_key) -# .. toggle_name: new_core_editors.use_new_video_editor +# .. toggle_name: legacy_studio.video_editor # .. toggle_implementation: WaffleFlag # .. toggle_default: False -# .. toggle_description: This flag enables the use of the new core video xblock editor +# .. toggle_description: Temporarily fall back to the old Video component (a.k.a. video block) editor. # .. toggle_use_cases: temporary -# .. toggle_creation_date: 2021-12-1 -# .. toggle_target_removal_date: 2022-1-30 -# .. toggle_tickets: TNL-9306 -# .. toggle_warning: -ENABLE_NEW_VIDEO_EDITOR_FLAG = WaffleFlag('new_core_editors.use_new_video_editor', __name__) +# .. toggle_creation_date: 2025-03-14 +# .. toggle_target_removal_date: 2025-09-14 +# .. toggle_tickets: https://github.com/openedx/edx-platform/issues/36275 +# .. toggle_warning: In Ulmo, this toggle will be removed. Only the new (React-based) experience will be available. +LEGACY_STUDIO_VIDEO_EDITOR = CourseWaffleFlag('legacy_studio.video_editor', __name__) -def use_new_video_editor(): +def use_new_video_editor(course_key): """ Returns a boolean = true if new video editor is enabled """ - return ENABLE_NEW_VIDEO_EDITOR_FLAG.is_enabled() + return not LEGACY_STUDIO_VIDEO_EDITOR.is_enabled(course_key) # .. toggle_name: new_core_editors.use_video_gallery_flow @@ -142,23 +142,23 @@ def use_video_gallery_flow(): return ENABLE_VIDEO_GALLERY_FLOW_FLAG.is_enabled() -# .. toggle_name: new_core_editors.use_new_problem_editor +# .. toggle_name: legacy_studio.problem_editor # .. toggle_implementation: WaffleFlag # .. toggle_default: False -# .. toggle_description: This flag enables the use of the new core problem xblock editor +# .. toggle_description: Temporarily fall back to the old Problem component (a.k.a. CAPA/problem block) editor. # .. toggle_use_cases: temporary -# .. toggle_creation_date: 2021-12-1 -# .. toggle_target_removal_date: 2022-1-30 -# .. toggle_tickets: TNL-9306 -# .. toggle_warning: -ENABLE_NEW_PROBLEM_EDITOR_FLAG = WaffleFlag('new_core_editors.use_new_problem_editor', __name__) +# .. toggle_creation_date: 2025-03-14 +# .. toggle_target_removal_date: 2025-09-14 +# .. toggle_tickets: https://github.com/openedx/edx-platform/issues/36275 +# .. toggle_warning: In Ulmo, this toggle will be removed. Only the new (React-based) experience will be available. +LEGACY_STUDIO_PROBLEM_EDITOR = CourseWaffleFlag('legacy_studio.problem_editor', __name__) -def use_new_problem_editor(): +def use_new_problem_editor(course_key): """ Returns a boolean if new problem editor is enabled """ - return ENABLE_NEW_PROBLEM_EDITOR_FLAG.is_enabled() + return not LEGACY_STUDIO_PROBLEM_EDITOR.is_enabled(course_key) # .. toggle_name: contentstore.individualize_anonymous_user_id @@ -181,43 +181,43 @@ def individualize_anonymous_user_id(course_id): return INDIVIDUALIZE_ANONYMOUS_USER_ID.is_enabled(course_id) -# .. toggle_name: new_studio_mfe.use_new_home_page +# .. toggle_name: legacy_studio.home # .. toggle_implementation: WaffleFlag # .. toggle_default: False -# .. toggle_description: This flag enables the use of the new studio home page mfe +# .. toggle_description: Temporarily fall back to the old Studio logged-in landing page. # .. toggle_use_cases: temporary -# .. toggle_creation_date: 2023-5-15 -# .. toggle_target_removal_date: 2023-8-31 -# .. toggle_tickets: TNL-9306 -# .. toggle_warning: -ENABLE_NEW_STUDIO_HOME_PAGE = WaffleFlag('new_studio_mfe.use_new_home_page', __name__) +# .. toggle_creation_date: 2025-03-14 +# .. toggle_target_removal_date: 2025-09-14 +# .. toggle_tickets: https://github.com/openedx/edx-platform/issues/36275 +# .. toggle_warning: In Ulmo, this toggle will be removed. Only the new (React-based) experience will be available. +LEGACY_STUDIO_HOME = WaffleFlag('legacy_studio.home', __name__) def use_new_home_page(): """ Returns a boolean if new studio home page mfe is enabled """ - return ENABLE_NEW_STUDIO_HOME_PAGE.is_enabled() + return not LEGACY_STUDIO_HOME.is_enabled() -# .. toggle_name: contentstore.new_studio_mfe.use_new_custom_pages -# .. toggle_implementation: CourseWaffleFlag +# .. toggle_name: legacy_studio.custom_pages +# .. toggle_implementation: WaffleFlag # .. toggle_default: False -# .. toggle_description: This flag enables the use of the new studio custom pages mfe +# .. toggle_description: Temporarily fall back to the old Studio custom pages tab. # .. toggle_use_cases: temporary -# .. toggle_creation_date: 2023-5-15 -# .. toggle_target_removal_date: 2023-8-31 -# .. toggle_tickets: TNL-10619 -# .. toggle_warning: -ENABLE_NEW_STUDIO_CUSTOM_PAGES = CourseWaffleFlag( - f'{CONTENTSTORE_NAMESPACE}.new_studio_mfe.use_new_custom_pages', __name__) +# .. toggle_creation_date: 2025-03-14 +# .. toggle_target_removal_date: 2025-09-14 +# .. toggle_tickets: https://github.com/openedx/edx-platform/issues/36275 +# .. toggle_warning: In Ulmo, this toggle will be removed. Only the new (React-based) experience will be available. +LEGACY_STUDIO_CUSTOM_PAGES = CourseWaffleFlag("legacy_studio.custom_pages", __name__) def use_new_custom_pages(course_key): """ Returns a boolean if new studio custom pages mfe is enabled """ - return ENABLE_NEW_STUDIO_CUSTOM_PAGES.is_enabled(course_key) + return not LEGACY_STUDIO_CUSTOM_PAGES.is_enabled(course_key) + # .. toggle_name: contentstore.use_react_markdown_editor # .. toggle_implementation: CourseWaffleFlag @@ -236,150 +236,144 @@ def use_react_markdown_editor(course_key): """ return ENABLE_REACT_MARKDOWN_EDITOR.is_enabled(course_key) -# .. toggle_name: contentstore.new_studio_mfe.use_new_schedule_details_page -# .. toggle_implementation: CourseWaffleFlag + +# .. toggle_name: legacy_studio.schedule_details +# .. toggle_implementation: WaffleFlag # .. toggle_default: False -# .. toggle_description: This flag enables the use of the new studio schedule and details mfe +# .. toggle_description: Temporarily fall back to the old Studio Schedule & Details page. # .. toggle_use_cases: temporary -# .. toggle_creation_date: 2023-5-15 -# .. toggle_target_removal_date: 2023-8-31 -# .. toggle_tickets: TNL-10619 -# .. toggle_warning: -ENABLE_NEW_STUDIO_SCHEDULE_DETAILS_PAGE = CourseWaffleFlag( - f'{CONTENTSTORE_NAMESPACE}.new_studio_mfe.use_new_schedule_details_page', __name__) +# .. toggle_creation_date: 2025-03-14 +# .. toggle_target_removal_date: 2025-09-14 +# .. toggle_tickets: https://github.com/openedx/edx-platform/issues/36275 +# .. toggle_warning: In Ulmo, this toggle will be removed. Only the new (React-based) experience will be available. +LEGACY_STUDIO_SCHEDULE_DETAILS = CourseWaffleFlag('legacy_studio.schedule_details', __name__) def use_new_schedule_details_page(course_key): """ Returns a boolean if new studio schedule and details mfe is enabled """ - return ENABLE_NEW_STUDIO_SCHEDULE_DETAILS_PAGE.is_enabled(course_key) + return not LEGACY_STUDIO_SCHEDULE_DETAILS.is_enabled(course_key) -# .. toggle_name: contentstore.new_studio_mfe.use_new_advanced_settings_page -# .. toggle_implementation: CourseWaffleFlag +# .. toggle_name: legacy_studio.advanced_settings +# .. toggle_implementation: WaffleFlag # .. toggle_default: False -# .. toggle_description: This flag enables the use of the new studio advanced settings page mfe +# .. toggle_description: Temporarily fall back to the old Studio Advanced Settings page. # .. toggle_use_cases: temporary -# .. toggle_creation_date: 2023-5-15 -# .. toggle_target_removal_date: 2023-8-31 -# .. toggle_tickets: TNL-10619 -# .. toggle_warning: -ENABLE_NEW_STUDIO_ADVANCED_SETTINGS_PAGE = CourseWaffleFlag( - f'{CONTENTSTORE_NAMESPACE}.new_studio_mfe.use_new_advanced_settings_page', __name__) +# .. toggle_creation_date: 2025-03-14 +# .. toggle_target_removal_date: 2025-09-14 +# .. toggle_tickets: https://github.com/openedx/edx-platform/issues/36275 +# .. toggle_warning: In Ulmo, this toggle will be removed. Only the new (React-based) experience will be available. +LEGACY_STUDIO_ADVANCED_SETTINGS = CourseWaffleFlag('legacy_studio.advanced_settings', __name__) def use_new_advanced_settings_page(course_key): """ Returns a boolean if new studio advanced settings pafe mfe is enabled """ - return ENABLE_NEW_STUDIO_ADVANCED_SETTINGS_PAGE.is_enabled(course_key) + return not LEGACY_STUDIO_ADVANCED_SETTINGS.is_enabled(course_key) -# .. toggle_name: contentstore.new_studio_mfe.use_new_grading_page -# .. toggle_implementation: CourseWaffleFlag +# .. toggle_name: legacy_studio.grading +# .. toggle_implementation: WaffleFlag # .. toggle_default: False -# .. toggle_description: This flag enables the use of the new studio grading page mfe +# .. toggle_description: Temporarily fall back to the old Studio Course Grading page. # .. toggle_use_cases: temporary -# .. toggle_creation_date: 2023-5-15 -# .. toggle_target_removal_date: 2023-8-31 -# .. toggle_tickets: TNL-10619 -# .. toggle_warning: -ENABLE_NEW_STUDIO_GRADING_PAGE = CourseWaffleFlag( - f'{CONTENTSTORE_NAMESPACE}.new_studio_mfe.use_new_grading_page', __name__) +# .. toggle_creation_date: 2025-03-14 +# .. toggle_target_removal_date: 2025-09-14 +# .. toggle_tickets: https://github.com/openedx/edx-platform/issues/36275 +# .. toggle_warning: In Ulmo, this toggle will be removed. Only the new (React-based) experience will be available. +LEGACY_STUDIO_GRADING = CourseWaffleFlag('legacy_studio.grading', __name__) def use_new_grading_page(course_key): """ Returns a boolean if new studio grading mfe is enabled """ - return ENABLE_NEW_STUDIO_GRADING_PAGE.is_enabled(course_key) + return not LEGACY_STUDIO_GRADING.is_enabled(course_key) -# .. toggle_name: contentstore.new_studio_mfe.use_new_updates_page -# .. toggle_implementation: CourseWaffleFlag +# .. toggle_name: legacy_studio.updates +# .. toggle_implementation: WaffleFlag # .. toggle_default: False -# .. toggle_description: This flag enables the use of the new studio updates page mfe +# .. toggle_description: Temporarily fall back to the old Studio Course Updates page. # .. toggle_use_cases: temporary -# .. toggle_creation_date: 2023-5-15 -# .. toggle_target_removal_date: 2023-8-31 -# .. toggle_tickets: TNL-10619 -# .. toggle_warning: -ENABLE_NEW_STUDIO_UPDATES_PAGE = CourseWaffleFlag( - f'{CONTENTSTORE_NAMESPACE}.new_studio_mfe.use_new_updates_page', __name__) +# .. toggle_creation_date: 2025-03-14 +# .. toggle_target_removal_date: 2025-09-14 +# .. toggle_tickets: https://github.com/openedx/edx-platform/issues/36275 +# .. toggle_warning: In Ulmo, this toggle will be removed. Only the new (React-based) experience will be available. +LEGACY_STUDIO_UPDATES = CourseWaffleFlag('legacy_studio.updates', __name__) def use_new_updates_page(course_key): """ Returns a boolean if new studio updates mfe is enabled """ - return ENABLE_NEW_STUDIO_UPDATES_PAGE.is_enabled(course_key) + return not LEGACY_STUDIO_UPDATES.is_enabled(course_key) -# .. toggle_name: contentstore.new_studio_mfe.use_new_import_page -# .. toggle_implementation: CourseWaffleFlag +# .. toggle_name: legacy_studio.import +# .. toggle_implementation: WaffleFlag # .. toggle_default: False -# .. toggle_description: This flag enables the use of the new studio import page mfe +# .. toggle_description: Temporarily fall back to the old Course Import page. # .. toggle_use_cases: temporary -# .. toggle_creation_date: 2023-5-15 -# .. toggle_target_removal_date: 2023-8-31 -# .. toggle_tickets: TNL-10619 -# .. toggle_warning: -ENABLE_NEW_STUDIO_IMPORT_PAGE = CourseWaffleFlag( - f'{CONTENTSTORE_NAMESPACE}.new_studio_mfe.use_new_import_page', __name__) +# .. toggle_creation_date: 2025-03-14 +# .. toggle_target_removal_date: 2025-09-14 +# .. toggle_tickets: https://github.com/openedx/edx-platform/issues/36275 +# .. toggle_warning: In Ulmo, this toggle will be removed. Only the new (React-based) experience will be available. +LEGACY_STUDIO_IMPORT = CourseWaffleFlag('legacy_studio.import', __name__) def use_new_import_page(course_key): """ Returns a boolean if new studio import mfe is enabled """ - return ENABLE_NEW_STUDIO_IMPORT_PAGE.is_enabled(course_key) + return not LEGACY_STUDIO_IMPORT.is_enabled(course_key) -# .. toggle_name: contentstore.new_studio_mfe.use_new_export_page -# .. toggle_implementation: CourseWaffleFlag +# .. toggle_name: legacy_studio.export +# .. toggle_implementation: WaffleFlag # .. toggle_default: False -# .. toggle_description: This flag enables the use of the new studio export page mfe +# .. toggle_description: Temporarily fall back to the old Course Export page. # .. toggle_use_cases: temporary -# .. toggle_creation_date: 2023-5-15 -# .. toggle_target_removal_date: 2023-8-31 -# .. toggle_tickets: TNL-10619 -# .. toggle_warning: -ENABLE_NEW_STUDIO_EXPORT_PAGE = CourseWaffleFlag( - f'{CONTENTSTORE_NAMESPACE}.new_studio_mfe.use_new_export_page', __name__) +# .. toggle_creation_date: 2025-03-14 +# .. toggle_target_removal_date: 2025-09-14 +# .. toggle_tickets: https://github.com/openedx/edx-platform/issues/36275 +# .. toggle_warning: In Ulmo, this toggle will be removed. Only the new (React-based) experience will be available. +LEGACY_STUDIO_EXPORT = CourseWaffleFlag('legacy_studio.export', __name__) def use_new_export_page(course_key): """ Returns a boolean if new studio export mfe is enabled """ - return ENABLE_NEW_STUDIO_EXPORT_PAGE.is_enabled(course_key) + return not LEGACY_STUDIO_EXPORT.is_enabled(course_key) -# .. toggle_name: contentstore.new_studio_mfe.use_new_files_uploads_page -# .. toggle_implementation: CourseWaffleFlag +# .. toggle_name: legacy_studio.files_uploads +# .. toggle_implementation: WaffleFlag # .. toggle_default: False -# .. toggle_description: This flag enables the use of the new studio files and uploads page mfe +# .. toggle_description: Temporarily fall back to the old Studio Files & Uploads page. # .. toggle_use_cases: temporary -# .. toggle_creation_date: 2023-5-15 -# .. toggle_target_removal_date: 2023-8-31 -# .. toggle_tickets: TNL-10619 -# .. toggle_warning: -ENABLE_NEW_STUDIO_FILES_UPLOADS_PAGE = CourseWaffleFlag( - f'{CONTENTSTORE_NAMESPACE}.new_studio_mfe.use_new_files_uploads_page', __name__) +# .. toggle_creation_date: 2025-03-14 +# .. toggle_target_removal_date: 2025-09-14 +# .. toggle_tickets: https://github.com/openedx/edx-platform/issues/36275 +# .. toggle_warning: In Ulmo, this toggle will be removed. Only the new (React-based) experience will be available. +LEGACY_STUDIO_FILES_UPLOADS = CourseWaffleFlag('legacy_studio.files_uploads', __name__) def use_new_files_uploads_page(course_key): """ Returns a boolean if new studio files and uploads mfe is enabled """ - return ENABLE_NEW_STUDIO_FILES_UPLOADS_PAGE.is_enabled(course_key) + return not LEGACY_STUDIO_FILES_UPLOADS.is_enabled(course_key) -# .. toggle_name: contentstore.new_studio_mfe.use_new_video_uploads_page +# .. toggle_name: contentstore.new_studio_mfe.use_new_files_uploads_page # .. toggle_implementation: CourseWaffleFlag # .. toggle_default: False -# .. toggle_description: This flag enables the use of the new video uploads page mfe +# .. toggle_description: This flag enables the use of the new studio files and uploads page mfe # .. toggle_use_cases: temporary # .. toggle_creation_date: 2023-5-15 # .. toggle_target_removal_date: 2023-8-31 @@ -396,124 +390,118 @@ def use_new_video_uploads_page(course_key): return ENABLE_NEW_STUDIO_VIDEO_UPLOADS_PAGE.is_enabled(course_key) -# .. toggle_name: contentstore.new_studio_mfe.use_new_course_outline_page -# .. toggle_implementation: CourseWaffleFlag +# .. toggle_name: legacy_studio.course_outline +# .. toggle_implementation: WaffleFlag # .. toggle_default: False -# .. toggle_description: This flag enables the use of the new studio course outline page mfe +# .. toggle_description: Temporarily fall back to the old Studio Course Outline editor. # .. toggle_use_cases: temporary -# .. toggle_creation_date: 2023-5-15 -# .. toggle_target_removal_date: 2023-8-31 -# .. toggle_tickets: TNL-10619 -# .. toggle_warning: -ENABLE_NEW_STUDIO_COURSE_OUTLINE_PAGE = CourseWaffleFlag( - f'{CONTENTSTORE_NAMESPACE}.new_studio_mfe.use_new_course_outline_page', __name__) +# .. toggle_creation_date: 2025-03-14 +# .. toggle_target_removal_date: 2025-09-14 +# .. toggle_tickets: https://github.com/openedx/edx-platform/issues/36275 +# .. toggle_warning: In Ulmo, this toggle will be removed. Only the new (React-based) experience will be available. +LEGACY_STUDIO_COURSE_OUTLINE = CourseWaffleFlag('legacy_studio.course_outline', __name__) def use_new_course_outline_page(course_key): """ Returns a boolean if new studio course outline mfe is enabled """ - return ENABLE_NEW_STUDIO_COURSE_OUTLINE_PAGE.is_enabled(course_key) + return not LEGACY_STUDIO_COURSE_OUTLINE.is_enabled(course_key) -# .. toggle_name: contentstore.new_studio_mfe.use_new_unit_page -# .. toggle_implementation: CourseWaffleFlag +# .. toggle_name: legacy_studio.unit_editor +# .. toggle_implementation: WaffleFlag # .. toggle_default: False -# .. toggle_description: This flag enables the use of the new studio course outline page mfe +# .. toggle_description: Temporarily fall back to the old Studio unit editing page. # .. toggle_use_cases: temporary -# .. toggle_creation_date: 2023-5-15 -# .. toggle_target_removal_date: 2023-8-31 -# .. toggle_tickets: TNL-10619 -# .. toggle_warning: -ENABLE_NEW_STUDIO_UNIT_PAGE = CourseWaffleFlag( - f'{CONTENTSTORE_NAMESPACE}.new_studio_mfe.use_new_unit_page', __name__) +# .. toggle_creation_date: 2025-03-14 +# .. toggle_target_removal_date: 2025-09-14 +# .. toggle_tickets: https://github.com/openedx/edx-platform/issues/36275 +# .. toggle_warning: In Ulmo, this toggle will be removed. Only the new (React-based) experience will be available. +LEGACY_STUDIO_UNIT_EDITOR = CourseWaffleFlag('legacy_studio.unit_editor', __name__) def use_new_unit_page(course_key): """ Returns a boolean if new studio course outline mfe is enabled """ - return ENABLE_NEW_STUDIO_UNIT_PAGE.is_enabled(course_key) + return not LEGACY_STUDIO_UNIT_EDITOR.is_enabled(course_key) -# .. toggle_name: contentstore.new_studio_mfe.use_new_course_team_page -# .. toggle_implementation: CourseWaffleFlag +# .. toggle_name: legacy_studio.course_team +# .. toggle_implementation: WaffleFlag # .. toggle_default: False -# .. toggle_description: This flag enables the use of the new studio course team page mfe +# .. toggle_description: Temporarily fall back to the old Studio Course Team page. # .. toggle_use_cases: temporary -# .. toggle_creation_date: 2023-5-15 -# .. toggle_target_removal_date: 2023-8-31 -# .. toggle_tickets: TNL-10619 -# .. toggle_warning: -ENABLE_NEW_STUDIO_COURSE_TEAM_PAGE = CourseWaffleFlag( - f'{CONTENTSTORE_NAMESPACE}.new_studio_mfe.use_new_course_team_page', __name__) +# .. toggle_creation_date: 2025-03-14 +# .. toggle_target_removal_date: 2025-09-14 +# .. toggle_tickets: https://github.com/openedx/edx-platform/issues/36275 +# .. toggle_warning: In Ulmo, this toggle will be removed. Only the new (React-based) experience will be available. +LEGACY_STUDIO_COURSE_TEAM = CourseWaffleFlag('legacy_studio.course_team', __name__) def use_new_course_team_page(course_key): """ Returns a boolean if new studio course team mfe is enabled """ - return ENABLE_NEW_STUDIO_COURSE_TEAM_PAGE.is_enabled(course_key) + return not LEGACY_STUDIO_COURSE_TEAM.is_enabled(course_key) -# .. toggle_name: contentstore.new_studio_mfe.use_new_certificates_page -# .. toggle_implementation: CourseWaffleFlag +# .. toggle_name: legacy_studio.certificates +# .. toggle_implementation: WaffleFlag # .. toggle_default: False -# .. toggle_description: This flag enables the use of the new studio course certificates page mfe +# .. toggle_description: Temporarily fall back to the old Studio Course Certificates page. # .. toggle_use_cases: temporary -# .. toggle_creation_date: 2024-1-18 -# .. toggle_target_removal_date: 2023-4-31 -# .. toggle_tickets: https://github.com/openedx/platform-roadmap/issues/317 -# .. toggle_warning: -ENABLE_NEW_STUDIO_CERTIFICATES_PAGE = CourseWaffleFlag( - f'{CONTENTSTORE_NAMESPACE}.new_studio_mfe.use_new_certificates_page', __name__) +# .. toggle_creation_date: 2025-03-14 +# .. toggle_target_removal_date: 2025-09-14 +# .. toggle_tickets: https://github.com/openedx/edx-platform/issues/36275 +# .. toggle_warning: In Ulmo, this toggle will be removed. Only the new (React-based) experience will be available. +LEGACY_STUDIO_CERTIFICATES = CourseWaffleFlag('legacy_studio.certificates', __name__) def use_new_certificates_page(course_key): """ Returns a boolean if new studio certificates mfe is enabled """ - return ENABLE_NEW_STUDIO_CERTIFICATES_PAGE.is_enabled(course_key) + return not LEGACY_STUDIO_CERTIFICATES.is_enabled(course_key) -# .. toggle_name: contentstore.new_studio_mfe.use_new_textbooks_page -# .. toggle_implementation: CourseWaffleFlag +# .. toggle_name: legacy_studio.textbooks +# .. toggle_implementation: WaffleFlag # .. toggle_default: False -# .. toggle_description: This flag enables the use of the new studio course textbooks page mfe +# .. toggle_description: Temporarily fall back to the old Studio Textbooks page. # .. toggle_use_cases: temporary -# .. toggle_creation_date: 2024-1-18 -# .. toggle_target_removal_date: 2023-4-31 -# .. toggle_tickets: https://github.com/openedx/platform-roadmap/issues/319 -# .. toggle_warning: -ENABLE_NEW_STUDIO_TEXTBOOKS_PAGE = CourseWaffleFlag( - f'{CONTENTSTORE_NAMESPACE}.new_studio_mfe.use_new_textbooks_page', __name__) +# .. toggle_creation_date: 2025-03-14 +# .. toggle_target_removal_date: 2025-09-14 +# .. toggle_tickets: https://github.com/openedx/edx-platform/issues/36275 +# .. toggle_warning: In Ulmo, this toggle will be removed. Only the new (React-based) experience will be available. +LEGACY_STUDIO_TEXTBOOKS = CourseWaffleFlag('legacy_studio.textbooks', __name__) def use_new_textbooks_page(course_key): """ Returns a boolean if new studio textbooks mfe is enabled """ - return ENABLE_NEW_STUDIO_TEXTBOOKS_PAGE.is_enabled(course_key) + return not LEGACY_STUDIO_TEXTBOOKS.is_enabled(course_key) -# .. toggle_name: contentstore.new_studio_mfe.use_new_group_configurations_page -# .. toggle_implementation: CourseWaffleFlag +# .. toggle_name: legacy_studio.configurations +# .. toggle_implementation: WaffleFlag # .. toggle_default: False -# .. toggle_description: This flag enables the use of the new studio course group configurations page mfe +# .. toggle_description: Temporarily fall back to the old Studio Configurations page. # .. toggle_use_cases: temporary -# .. toggle_creation_date: 2024-1-18 -# .. toggle_target_removal_date: 2023-4-31 -# .. toggle_tickets: https://github.com/openedx/platform-roadmap/issues/318 -# .. toggle_warning: -ENABLE_NEW_STUDIO_GROUP_CONFIGURATIONS_PAGE = CourseWaffleFlag( - f'{CONTENTSTORE_NAMESPACE}.new_studio_mfe.use_new_group_configurations_page', __name__) +# .. toggle_creation_date: 2025-03-14 +# .. toggle_target_removal_date: 2025-09-14 +# .. toggle_tickets: https://github.com/openedx/edx-platform/issues/36275 +# .. toggle_warning: In Ulmo, this toggle will be removed. Only the new (React-based) experience will be available. +LEGACY_STUDIO_CONFIGURATIONS = CourseWaffleFlag('legacy_studio.configurations', __name__) def use_new_group_configurations_page(course_key): """ Returns a boolean if new studio group configurations mfe is enabled """ - return ENABLE_NEW_STUDIO_GROUP_CONFIGURATIONS_PAGE.is_enabled(course_key) + return not LEGACY_STUDIO_CONFIGURATIONS.is_enabled(course_key) # .. toggle_name: contentstore.mock_video_uploads diff --git a/cms/djangoapps/contentstore/utils.py b/cms/djangoapps/contentstore/utils.py index 1ff309aa6e50..b989f69434e4 100644 --- a/cms/djangoapps/contentstore/utils.py +++ b/cms/djangoapps/contentstore/utils.py @@ -270,7 +270,7 @@ def get_proctored_exam_settings_url(course_locator) -> str: Gets course authoring microfrontend URL for links to proctored exam settings page """ proctored_exam_settings_url = '' - if exam_setting_view_enabled(): + if exam_setting_view_enabled(course_locator): mfe_base_url = get_course_authoring_url(course_locator) course_mfe_url = f'{mfe_base_url}/course/{course_locator}' if mfe_base_url: @@ -283,7 +283,7 @@ def get_editor_page_base_url(course_locator) -> str: Gets course authoring microfrontend URL for links to the new base editors """ editor_url = None - if use_new_text_editor() or use_new_video_editor(): + if use_new_text_editor(course_locator) or use_new_video_editor(course_locator): mfe_base_url = get_course_authoring_url(course_locator) course_mfe_url = f'{mfe_base_url}/course/{course_locator}/editor' if mfe_base_url: diff --git a/cms/djangoapps/contentstore/views/component.py b/cms/djangoapps/contentstore/views/component.py index ded3b9d2f462..f08f733c6292 100644 --- a/cms/djangoapps/contentstore/views/component.py +++ b/cms/djangoapps/contentstore/views/component.py @@ -370,14 +370,14 @@ def create_support_legend_dict(): #If using new problem editor, we select problem type inside the editor # because of this, we only show one problem. - if category == 'problem' and use_new_problem_editor(): + if category == 'problem' and use_new_problem_editor(courselike.context_key): templates_for_category = [ template for template in templates_for_category if template['boilerplate_name'] == 'blank_common.yaml' ] # Add any advanced problem types. Note that these are different xblocks being stored as Advanced Problems, # currently not supported in libraries . - if category == 'problem' and not library and not use_new_problem_editor(): + if category == 'problem' and not library and not use_new_problem_editor(courselike.context_key): disabled_block_names = [block.name for block in disabled_xblocks()] advanced_problem_types = [advanced_problem_type for advanced_problem_type in ADVANCED_PROBLEM_TYPES if advanced_problem_type['component'] not in disabled_block_names] diff --git a/cms/djangoapps/contentstore/views/tests/test_assets.py b/cms/djangoapps/contentstore/views/tests/test_assets.py index a6dafab55c00..2b13338c0dc7 100644 --- a/cms/djangoapps/contentstore/views/tests/test_assets.py +++ b/cms/djangoapps/contentstore/views/tests/test_assets.py @@ -12,11 +12,13 @@ from ddt import data, ddt from django.conf import settings from django.test.utils import override_settings +from edx_toggles.toggles.testutils import override_waffle_flag from opaque_keys.edx.keys import AssetKey from opaque_keys.edx.locator import CourseLocator from PIL import Image from pytz import UTC +from cms.djangoapps.contentstore import toggles from cms.djangoapps.contentstore.tests.utils import CourseTestCase from cms.djangoapps.contentstore.utils import reverse_course_url from cms.djangoapps.contentstore.views import assets @@ -84,6 +86,8 @@ class BasicAssetsTestCase(AssetsTestCase): """ Test getting assets via html w/o additional args """ + + @override_waffle_flag(toggles.LEGACY_STUDIO_FILES_UPLOADS, True) def test_basic(self): resp = self.client.get(self.url, HTTP_ACCEPT='text/html') self.assertEqual(resp.status_code, 200) diff --git a/cms/djangoapps/contentstore/views/tests/test_block.py b/cms/djangoapps/contentstore/views/tests/test_block.py index 019220246a14..f03e21342f97 100644 --- a/cms/djangoapps/contentstore/views/tests/test_block.py +++ b/cms/djangoapps/contentstore/views/tests/test_block.py @@ -12,6 +12,7 @@ from django.test import TestCase from django.test.client import RequestFactory from django.urls import reverse +from edx_toggles.toggles.testutils import override_waffle_flag from openedx.core.djangoapps.video_config.toggles import PUBLIC_VIDEO_SHARE from openedx_events.content_authoring.data import DuplicatedXBlockData from openedx_events.content_authoring.signals import XBLOCK_DUPLICATED @@ -56,6 +57,7 @@ from xmodule.partitions.tests.test_partitions import MockPartitionService from xmodule.x_module import STUDENT_VIEW, STUDIO_VIEW +from cms.djangoapps.contentstore import toggles from cms.djangoapps.contentstore.tests.utils import CourseTestCase from cms.djangoapps.contentstore.utils import ( reverse_course_url, @@ -2852,6 +2854,7 @@ def get_usage_key(): assert mocked_get_aside_from_xblock.called is is_get_aside_called +@override_waffle_flag(toggles.LEGACY_STUDIO_PROBLEM_EDITOR, True) class TestComponentTemplates(CourseTestCase): """ Unit tests for the generation of the component templates for a course. diff --git a/cms/djangoapps/contentstore/views/tests/test_certificates.py b/cms/djangoapps/contentstore/views/tests/test_certificates.py index 7af7a448de10..f50c3d3f1bef 100644 --- a/cms/djangoapps/contentstore/views/tests/test_certificates.py +++ b/cms/djangoapps/contentstore/views/tests/test_certificates.py @@ -10,8 +10,10 @@ import ddt from django.conf import settings from django.test.utils import override_settings +from edx_toggles.toggles.testutils import override_waffle_flag from opaque_keys.edx.keys import AssetKey +from cms.djangoapps.contentstore import toggles from cms.djangoapps.contentstore.tests.utils import CourseTestCase from cms.djangoapps.contentstore.utils import get_lms_link_for_certificate_web_view, reverse_course_url from common.djangoapps.course_modes.tests.factories import CourseModeFactory @@ -275,6 +277,7 @@ def test_lms_link_for_certificate_web_view(self): ) self.assertEqual(link, test_url) + @override_waffle_flag(toggles.LEGACY_STUDIO_CERTIFICATES, True) @mock.patch.dict('django.conf.settings.FEATURES', {'CERTIFICATES_HTML_VIEW': True}) def test_certificate_info_in_response(self): """ @@ -302,6 +305,7 @@ def test_certificate_info_in_response(self): self.assertEqual(data[0]['version'], CERTIFICATE_SCHEMA_VERSION) @mock.patch.dict('django.conf.settings.FEATURES', {'CERTIFICATES_HTML_VIEW': True}) + @override_waffle_flag(toggles.LEGACY_STUDIO_CERTIFICATES, True) def test_certificate_info_not_in_response(self): """ Test that certificate has not been rendered audit only course mode. @@ -346,6 +350,7 @@ def test_not_permitted(self): ) self.assertContains(response, "error", status_code=403) + @override_waffle_flag(toggles.LEGACY_STUDIO_CERTIFICATES, True) def test_audit_course_mode_is_skipped(self): """ Tests audit course mode is skipped when rendering certificates page. @@ -359,6 +364,7 @@ def test_audit_course_mode_is_skipped(self): self.assertContains(response, 'verified') self.assertNotContains(response, 'audit') + @override_waffle_flag(toggles.LEGACY_STUDIO_CERTIFICATES, True) def test_audit_only_disables_cert(self): """ Tests audit course mode is skipped when rendering certificates page. @@ -379,6 +385,7 @@ def test_audit_only_disables_cert(self): ['verified', 'credit'], ['professional'] ) + @override_waffle_flag(toggles.LEGACY_STUDIO_CERTIFICATES, True) def test_non_audit_enables_cert(self, slugs): """ Tests audit course mode is skipped when rendering certificates page. diff --git a/cms/djangoapps/contentstore/views/tests/test_container_page.py b/cms/djangoapps/contentstore/views/tests/test_container_page.py index 426477e23408..e6b58257b69d 100644 --- a/cms/djangoapps/contentstore/views/tests/test_container_page.py +++ b/cms/djangoapps/contentstore/views/tests/test_container_page.py @@ -10,10 +10,12 @@ from django.http import Http404 from django.test.client import RequestFactory from django.urls import reverse +from edx_toggles.toggles.testutils import override_waffle_flag from pytz import UTC from urllib.parse import quote import cms.djangoapps.contentstore.views.component as views +from cms.djangoapps.contentstore import toggles from cms.djangoapps.contentstore.tests.test_libraries import LibraryTestCase from xmodule.modulestore import ModuleStoreEnum # lint-amnesty, pylint: disable=wrong-import-order from xmodule.modulestore.django import modulestore # lint-amnesty, pylint: disable=wrong-import-order @@ -83,6 +85,7 @@ def test_container_html(self): ), ) + @override_waffle_flag(toggles.LEGACY_STUDIO_UNIT_EDITOR, True) def test_container_on_container_html(self): """ Create the scenario of an xblock with children (non-vertical) on the container page. @@ -221,6 +224,7 @@ def test_draft_child_container_preview_html(self): 'cms.djangoapps.contentstore.views.component.render_to_response', Mock(return_value=Mock(status_code=200, content='')) ) + @override_waffle_flag(toggles.LEGACY_STUDIO_UNIT_EDITOR, True) def test_container_page_with_valid_and_invalid_usage_key_string(self): """ Check that invalid 'usage_key_string' raises Http404. @@ -263,6 +267,7 @@ def test_container_html(self): ), ) + @override_waffle_flag(toggles.LEGACY_STUDIO_UNIT_EDITOR, True) def test_container_on_container_html(self): """ Create the scenario of an xblock with children (non-vertical) on the container page. diff --git a/cms/djangoapps/contentstore/views/tests/test_course_index.py b/cms/djangoapps/contentstore/views/tests/test_course_index.py index b121a490cd2b..4db00a63fdcb 100644 --- a/cms/djangoapps/contentstore/views/tests/test_course_index.py +++ b/cms/djangoapps/contentstore/views/tests/test_course_index.py @@ -14,9 +14,11 @@ from django.core.exceptions import PermissionDenied from django.test.utils import override_settings from django.utils.translation import gettext as _ +from edx_toggles.toggles.testutils import override_waffle_flag from opaque_keys.edx.locator import CourseLocator from search.api import perform_search +from cms.djangoapps.contentstore import toggles from cms.djangoapps.contentstore.courseware_index import CoursewareSearchIndexer, SearchIndexingError from cms.djangoapps.contentstore.tests.utils import CourseTestCase from cms.djangoapps.contentstore.utils import ( @@ -41,6 +43,8 @@ from cms.djangoapps.contentstore.xblock_storage_handlers.view_handlers import VisibilityState, create_xblock_info +@override_waffle_flag(toggles.LEGACY_STUDIO_HOME, True) +@override_waffle_flag(toggles.LEGACY_STUDIO_COURSE_OUTLINE, True) class TestCourseIndex(CourseTestCase): """ Unit tests for getting the list of courses and the course outline. @@ -335,6 +339,7 @@ def test_course_outline_with_display_course_number_as_none(self): self.assertContains(response, 'display_course_number: ""') +@override_waffle_flag(toggles.LEGACY_STUDIO_HOME, True) @ddt.ddt class TestCourseIndexArchived(CourseTestCase): """ @@ -492,6 +497,7 @@ def test_separate_archived_courses_with_home_page_course_v2_api( sql_queries=sql_queries) +@override_waffle_flag(toggles.LEGACY_STUDIO_COURSE_OUTLINE, True) @ddt.ddt class TestCourseOutline(CourseTestCase): """ @@ -709,11 +715,12 @@ def test_number_of_calls_to_db(self): """ Test to check number of queries made to mysql and mongo """ - with self.assertNumQueries(29, table_ignorelist=WAFFLE_TABLES): + with self.assertNumQueries(38, table_ignorelist=WAFFLE_TABLES): with check_mongo_calls(3): self.client.get_html(reverse_course_url('course_handler', self.course.id)) +@override_waffle_flag(toggles.LEGACY_STUDIO_COURSE_OUTLINE, True) class TestCourseReIndex(CourseTestCase): """ Unit tests for the course outline. diff --git a/cms/djangoapps/contentstore/views/tests/test_course_updates.py b/cms/djangoapps/contentstore/views/tests/test_course_updates.py index be8e8cac82af..7b3c31abe190 100644 --- a/cms/djangoapps/contentstore/views/tests/test_course_updates.py +++ b/cms/djangoapps/contentstore/views/tests/test_course_updates.py @@ -5,7 +5,9 @@ import json from opaque_keys.edx.keys import UsageKey +from edx_toggles.toggles.testutils import override_waffle_flag +from cms.djangoapps.contentstore import toggles from cms.djangoapps.contentstore.tests.test_course_settings import CourseTestCase from cms.djangoapps.contentstore.utils import reverse_course_url, reverse_usage_url from openedx.core.lib.xblock_utils import get_course_update_items @@ -21,6 +23,7 @@ def create_update_url(self, provided_id=None, course_key=None): return reverse_course_url('course_info_update_handler', course_key, kwargs=kwargs) # The do all and end all of unit test cases. + @override_waffle_flag(toggles.LEGACY_STUDIO_UPDATES, True) def test_course_update(self): """Go through each interface and ensure it works.""" def get_response(content, date): diff --git a/cms/djangoapps/contentstore/views/tests/test_credit_eligibility.py b/cms/djangoapps/contentstore/views/tests/test_credit_eligibility.py index 5cfa2ded2b80..66e42598bee6 100644 --- a/cms/djangoapps/contentstore/views/tests/test_credit_eligibility.py +++ b/cms/djangoapps/contentstore/views/tests/test_credit_eligibility.py @@ -4,7 +4,9 @@ from unittest import mock +from edx_toggles.toggles.testutils import override_waffle_flag +from cms.djangoapps.contentstore import toggles from cms.djangoapps.contentstore.tests.utils import CourseTestCase from cms.djangoapps.contentstore.utils import reverse_course_url from openedx.core.djangoapps.credit.api import get_credit_requirements @@ -24,6 +26,7 @@ def setUp(self): self.course_details_url = reverse_course_url('settings_handler', str(self.course.id)) @mock.patch.dict("django.conf.settings.FEATURES", {'ENABLE_CREDIT_ELIGIBILITY': False}) + @override_waffle_flag(toggles.LEGACY_STUDIO_SCHEDULE_DETAILS, True) def test_course_details_with_disabled_setting(self): """ Test that user don't see credit eligibility requirements in response @@ -35,6 +38,7 @@ def test_course_details_with_disabled_setting(self): self.assertNotContains(response, "Steps required to earn course credit") @mock.patch.dict("django.conf.settings.FEATURES", {'ENABLE_CREDIT_ELIGIBILITY': True}) + @override_waffle_flag(toggles.LEGACY_STUDIO_SCHEDULE_DETAILS, True) def test_course_details_with_enabled_setting(self): """ Test that credit eligibility requirements are present in diff --git a/cms/djangoapps/contentstore/views/tests/test_exam_settings_view.py b/cms/djangoapps/contentstore/views/tests/test_exam_settings_view.py index 0f38722e1208..9bad2c77fc1a 100644 --- a/cms/djangoapps/contentstore/views/tests/test_exam_settings_view.py +++ b/cms/djangoapps/contentstore/views/tests/test_exam_settings_view.py @@ -8,24 +8,28 @@ import lxml from django.conf import settings from django.test.utils import override_settings +from edx_toggles.toggles.testutils import override_waffle_flag +from cms.djangoapps.contentstore import toggles from cms.djangoapps.contentstore.tests.utils import CourseTestCase from cms.djangoapps.contentstore.utils import get_proctored_exam_settings_url, reverse_course_url from common.djangoapps.util.testing import UrlResetMixin -FEATURES_WITH_CERTS_ENABLED = settings.FEATURES.copy() -FEATURES_WITH_CERTS_ENABLED['CERTIFICATES_HTML_VIEW'] = True - -FEATURES_WITH_EXAM_SETTINGS_ENABLED = FEATURES_WITH_CERTS_ENABLED.copy() -FEATURES_WITH_EXAM_SETTINGS_ENABLED['ENABLE_EXAM_SETTINGS_HTML_VIEW'] = True -FEATURES_WITH_EXAM_SETTINGS_ENABLED['ENABLE_PROCTORED_EXAMS'] = True - -FEATURES_WITH_EXAM_SETTINGS_DISABLED = FEATURES_WITH_CERTS_ENABLED.copy() -FEATURES_WITH_EXAM_SETTINGS_DISABLED['ENABLE_EXAM_SETTINGS_HTML_VIEW'] = False -FEATURES_WITH_EXAM_SETTINGS_DISABLED['ENABLE_PROCTORED_EXAMS'] = True - @ddt.ddt +@override_settings( + FEATURES={ + **settings.FEATURES, + "CERTIFICATES_HTML_VIEW": True, + "ENABLE_PROCTORED_EXAMS": True, + }, +) +@override_waffle_flag(toggles.LEGACY_STUDIO_COURSE_OUTLINE, True) +@override_waffle_flag(toggles.LEGACY_STUDIO_CERTIFICATES, True) +@override_waffle_flag(toggles.LEGACY_STUDIO_SCHEDULE_DETAILS, True) +@override_waffle_flag(toggles.LEGACY_STUDIO_CONFIGURATIONS, True) +@override_waffle_flag(toggles.LEGACY_STUDIO_GRADING, True) +@override_waffle_flag(toggles.LEGACY_STUDIO_ADVANCED_SETTINGS, True) class TestExamSettingsView(CourseTestCase, UrlResetMixin): """ Unit tests for the exam settings view. @@ -46,7 +50,7 @@ def _get_exam_settings_alert_text(raw_html_content): alert_node = alert_nodes[0] return alert_node.text_content() - @override_settings(FEATURES=FEATURES_WITH_EXAM_SETTINGS_DISABLED) + @override_waffle_flag(toggles.LEGACY_STUDIO_EXAM_SETTINGS, True) @ddt.data( "certificates_list_handler", "settings_handler", @@ -64,7 +68,6 @@ def test_view_without_exam_settings_enabled(self, handler): self.assertEqual(resp.status_code, 200) self.assertNotContains(resp, 'Proctored Exam Settings') - @override_settings(FEATURES=FEATURES_WITH_EXAM_SETTINGS_ENABLED) @ddt.data( "certificates_list_handler", "settings_handler", @@ -87,7 +90,6 @@ def test_view_with_exam_settings_enabled(self, handler): 'DEFAULT': 'test_proctoring_provider', 'proctortrack': {} }, - FEATURES=FEATURES_WITH_EXAM_SETTINGS_ENABLED, ) @ddt.data( "advanced_settings_handler", @@ -125,12 +127,12 @@ def test_exam_settings_alert_with_exam_settings_enabled(self, page_handler): 'DEFAULT': 'test_proctoring_provider', 'proctortrack': {} }, - FEATURES=FEATURES_WITH_EXAM_SETTINGS_DISABLED, ) @ddt.data( "advanced_settings_handler", "course_handler", ) + @override_waffle_flag(toggles.LEGACY_STUDIO_EXAM_SETTINGS, True) def test_exam_settings_alert_with_exam_settings_disabled(self, page_handler): """ An alert should appear if current exam settings are invalid. @@ -168,7 +170,6 @@ def test_exam_settings_alert_with_exam_settings_disabled(self, page_handler): 'proctortrack': {}, 'test_proctoring_provider': {}, }, - FEATURES=FEATURES_WITH_EXAM_SETTINGS_ENABLED, ) @ddt.data( "advanced_settings_handler", @@ -212,7 +213,6 @@ def test_exam_settings_alert_not_shown(self, page_handler): alert_nodes = parsed_html.find_class('exam-settings-alert') assert len(alert_nodes) == 0 - @override_settings(FEATURES={'ENABLE_EXAM_SETTINGS_HTML_VIEW': True}) @patch('cms.djangoapps.models.settings.course_metadata.CourseMetadata.validate_proctoring_settings') def test_proctoring_link_is_visible(self, mock_validate_proctoring_settings): diff --git a/cms/djangoapps/contentstore/views/tests/test_group_configurations.py b/cms/djangoapps/contentstore/views/tests/test_group_configurations.py index 0c3c7dc6aa30..6e9192aff526 100644 --- a/cms/djangoapps/contentstore/views/tests/test_group_configurations.py +++ b/cms/djangoapps/contentstore/views/tests/test_group_configurations.py @@ -6,9 +6,11 @@ import json from operator import itemgetter from unittest.mock import patch +from edx_toggles.toggles.testutils import override_waffle_flag import ddt +from cms.djangoapps.contentstore import toggles from cms.djangoapps.contentstore.course_group_config import ( CONTENT_GROUP_CONFIGURATION_NAME, ENROLLMENT_SCHEME, @@ -256,6 +258,7 @@ def _url(self): """ return reverse_course_url('group_configurations_list_handler', self.course.id) + @override_waffle_flag(toggles.LEGACY_STUDIO_CONFIGURATIONS, True) def test_view_index_ok(self): """ Basic check that the groups configuration page responds correctly. diff --git a/cms/djangoapps/contentstore/views/tests/test_header_menu.py b/cms/djangoapps/contentstore/views/tests/test_header_menu.py index 454fd7e257e2..fb961cc4fa89 100644 --- a/cms/djangoapps/contentstore/views/tests/test_header_menu.py +++ b/cms/djangoapps/contentstore/views/tests/test_header_menu.py @@ -5,7 +5,9 @@ from django.conf import settings from django.test.utils import override_settings +from edx_toggles.toggles.testutils import override_waffle_flag +from cms.djangoapps.contentstore import toggles from cms.djangoapps.contentstore.tests.utils import CourseTestCase from cms.djangoapps.contentstore.utils import reverse_course_url from common.djangoapps.util.testing import UrlResetMixin @@ -21,6 +23,7 @@ @override_settings(FEATURES=FEATURES_WITH_CERTS_ENABLED) +@override_waffle_flag(toggles.LEGACY_STUDIO_COURSE_OUTLINE, True) class TestHeaderMenu(CourseTestCase, UrlResetMixin): """ Unit tests for the course header menu. @@ -61,6 +64,7 @@ def test_header_menu_with_web_certs_enabled(self): self.assertContains(resp, '