feat!: Flip Studio MFE Waffle Flags to be On-By-Default (#36495)
This makes nearly all of Studio React-by-default by replacing the "opt-in-to-React" flags with a set of parallel "opt-out-of-React-and-use-the-legacy-experience" flags. Here is the mapping: * `contentstore.new_studio_mfe.use_new_unit_page` -> `!legacy_studio.unit_editor` * `new_core_editors.use_new_problem_editor` -> `!legacy_studio.problem_editor` * `new_core_editors.use_new_text_editor` -> `!legacy_studio.text_editor` * `new_core_editors.use_new_video_editor` -> `!legacy_studio.video_editor` * `new_studio_mfe.use_new_home_page` -> `!legacy_studio.home` * `contentstore.new_studio_mfe.use_new_custom_pages` -> `!legacy_studio.custom_pages` * `contentstore.new_studio_mfe.use_new_schedule_details_page` -> `!legacy_studio.schedule_details` * `contentstore.new_studio_mfe.use_new_advanced_settings_page` -> `!legacy_studio.advanced_settings` * `contentstore.new_studio_mfe.use_new_grading_page` -> `!legacy_studio.grading` * `contentstore.new_studio_mfe.use_new_updates_page` -> `!legacy_studio.updates` * `contentstore.new_studio_mfe.use_new_import_page` -> `!legacy_studio.import` * `contentstore.new_studio_mfe.use_new_export_page` -> `!legacy_studio.export` * `contentstore.new_studio_mfe.use_new_files_uploads_page` -> `!legacy_studio.files_uploads` * `contentstore.new_studio_mfe.use_new_course_outline_page` -> `!legacy_studio.course_outline` * `contentstore.new_studio_mfe.use_new_course_team_page` -> `!legacy_studio.course_team` * `contentstore.new_studio_mfe.use_new_certificates_page` -> `!legacy_studio.certificates` * `contentstore.new_studio_mfe.use_new_textbooks_page` -> `!legacy_studio.textbooks` * `contentstore.new_studio_mfe.use_new_group_configurations_page` -> `!legacy_studio.configurations` Part of: https://github.com/openedx/edx-platform/issues/36275
This commit is contained in:
@@ -6,14 +6,11 @@ import json
|
||||
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):
|
||||
"""
|
||||
|
||||
@@ -8,15 +8,12 @@ from urllib.parse import urlencode
|
||||
|
||||
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):
|
||||
"""
|
||||
|
||||
@@ -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 @@ class CourseIndexViewTest(CourseTestCase, PermissionAccessMixin):
|
||||
},
|
||||
"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 @@ class CourseIndexViewTest(CourseTestCase, PermissionAccessMixin):
|
||||
},
|
||||
"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 @@ class CourseIndexViewTest(CourseTestCase, PermissionAccessMixin):
|
||||
"""
|
||||
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)
|
||||
|
||||
@@ -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.
|
||||
"""
|
||||
maxDiff = None # Show the whole dictionary in the diff
|
||||
|
||||
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"]
|
||||
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.
|
||||
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:
|
||||
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.
|
||||
|
||||
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,
|
||||
}
|
||||
|
||||
@@ -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.conf import settings
|
||||
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.modulestore.xml_importer import import_course_from_xml, perform_xli
|
||||
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 @@ class MiscCourseTests(ContentStoreTestCase):
|
||||
for expected in expected_types:
|
||||
self.assertContains(resp, expected)
|
||||
|
||||
@override_waffle_flag(toggles.LEGACY_STUDIO_UNIT_EDITOR, True)
|
||||
@ddt.data("<script>alert(1)</script>", "alert('hi')", "</script><script>alert(1)</script>")
|
||||
def test_container_handler_xss_prevent(self, malicious_code):
|
||||
"""
|
||||
@@ -596,6 +602,7 @@ class MiscCourseTests(ContentStoreTestCase):
|
||||
# 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 @@ class MiscCourseTests(ContentStoreTestCase):
|
||||
# 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 @@ class ContentStoreTest(ContentStoreTestCase):
|
||||
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 @@ class ContentStoreTest(ContentStoreTestCase):
|
||||
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 @@ class ContentStoreTest(ContentStoreTestCase):
|
||||
)
|
||||
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 @@ class ContentStoreTest(ContentStoreTestCase):
|
||||
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 @@ class RerunCourseTest(ContentStoreTestCase):
|
||||
"""
|
||||
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,
|
||||
|
||||
@@ -10,8 +10,10 @@ import ddt
|
||||
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 @@ class TestCourseListing(ModuleStoreTestCase):
|
||||
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
|
||||
|
||||
@@ -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.models import MilestoneRelationshipType
|
||||
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 @@ class CourseAdvanceSettingViewTest(CourseTestCase, MilestonesTestCaseMixin):
|
||||
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 @@ class CourseAdvanceSettingViewTest(CourseTestCase, MilestonesTestCaseMixin):
|
||||
(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 @@ class CourseAdvanceSettingViewTest(CourseTestCase, MilestonesTestCaseMixin):
|
||||
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 @@ class CourseDetailsViewTest(CourseTestCase, MilestonesTestCaseMixin):
|
||||
(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 @@ class CourseDetailsViewTest(CourseTestCase, MilestonesTestCaseMixin):
|
||||
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 @@ class CourseDetailsViewTest(CourseTestCase, MilestonesTestCaseMixin):
|
||||
(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 @@ class CourseDetailsViewTest(CourseTestCase, MilestonesTestCaseMixin):
|
||||
b'<h3 id="heading-entrance-exam">' in resp.content
|
||||
)
|
||||
|
||||
@override_waffle_flag(toggles.LEGACY_STUDIO_SCHEDULE_DETAILS, True)
|
||||
def test_marketing_site_fetch(self):
|
||||
settings_details_url = get_url(self.course.id)
|
||||
|
||||
@@ -593,6 +618,7 @@ class CourseDetailsViewTest(CourseTestCase, MilestonesTestCaseMixin):
|
||||
assert milestones_helpers.any_unfulfilled_milestones(self.course.id, self.user.id), \
|
||||
'The entrance exam should be required.'
|
||||
|
||||
@override_waffle_flag(toggles.LEGACY_STUDIO_SCHEDULE_DETAILS, True)
|
||||
def test_editable_short_description_fetch(self):
|
||||
settings_details_url = get_url(self.course.id)
|
||||
|
||||
@@ -631,6 +657,7 @@ class CourseDetailsViewTest(CourseTestCase, MilestonesTestCaseMixin):
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(course_details.overview, '<p> </p>')
|
||||
|
||||
@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 @@ class CourseMetadataEditingTest(CourseTestCase):
|
||||
'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 @@ class CourseMetadataEditingTest(CourseTestCase):
|
||||
'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 @@ id=\"course-enrollment-end-time\" value=\"\" placeholder=\"HH:MM\" autocomplete=
|
||||
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 @@ id=\"course-enrollment-end-time\" value=\"\" placeholder=\"HH:MM\" autocomplete=
|
||||
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 @@ id=\"course-enrollment-end-time\" value=\"\" placeholder=\"HH:MM\" autocomplete=
|
||||
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 @@ id=\"course-enrollment-end-time\" value=\"\" placeholder=\"HH:MM\" autocomplete=
|
||||
|
||||
@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.
|
||||
|
||||
@@ -5,6 +5,8 @@ import gettext
|
||||
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.django_utils import TEST_DATA_SPLIT_MODULESTORE,
|
||||
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 @@ class InternationalizationTest(ModuleStoreTestCase):
|
||||
'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 @@ class InternationalizationTest(ModuleStoreTestCase):
|
||||
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
|
||||
|
||||
@@ -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 @@ class TestCourseAccess(ModuleStoreTestCase):
|
||||
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)
|
||||
|
||||
@@ -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.conf import settings
|
||||
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 @@ class AuthTestCase(ContentStoreTestCase):
|
||||
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 @@ class AuthTestCase(ContentStoreTestCase):
|
||||
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 @@ class CourseKeyVerificationTestCase(CourseTestCase):
|
||||
|
||||
@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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -370,14 +370,14 @@ def get_component_templates(courselike, library=False): # lint-amnesty, pylint:
|
||||
|
||||
#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]
|
||||
|
||||
@@ -12,11 +12,13 @@ from unittest.mock import patch
|
||||
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)
|
||||
|
||||
@@ -12,6 +12,7 @@ from django.http import Http404
|
||||
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.partitions import (
|
||||
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 @@ class TestComponentHandler(TestCase):
|
||||
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.
|
||||
|
||||
@@ -10,8 +10,10 @@ from unittest import mock
|
||||
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 @@ class CertificatesListHandlerTestCase(
|
||||
)
|
||||
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 @@ class CertificatesListHandlerTestCase(
|
||||
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 @@ class CertificatesListHandlerTestCase(
|
||||
)
|
||||
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 @@ class CertificatesListHandlerTestCase(
|
||||
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 @@ class CertificatesListHandlerTestCase(
|
||||
['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.
|
||||
|
||||
@@ -10,10 +10,12 @@ from unittest.mock import Mock, patch
|
||||
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 @@ class ContainerPageTestCase(StudioPageTestCase, LibraryTestCase):
|
||||
),
|
||||
)
|
||||
|
||||
@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 @@ class ContainerPageTestCase(StudioPageTestCase, LibraryTestCase):
|
||||
'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 @@ class ContainerEmbedPageTestCase(ContainerPageTestCase): # lint-amnesty, pylint
|
||||
),
|
||||
)
|
||||
|
||||
@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.
|
||||
|
||||
@@ -14,9 +14,11 @@ from django.conf import settings
|
||||
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 ..course import _deprecated_blocks_info, course_outline_initial_state, rein
|
||||
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 @@ class TestCourseIndex(CourseTestCase):
|
||||
self.assertContains(response, 'display_course_number: ""')
|
||||
|
||||
|
||||
@override_waffle_flag(toggles.LEGACY_STUDIO_HOME, True)
|
||||
@ddt.ddt
|
||||
class TestCourseIndexArchived(CourseTestCase):
|
||||
"""
|
||||
@@ -492,6 +497,7 @@ class TestCourseIndexArchived(CourseTestCase):
|
||||
sql_queries=sql_queries)
|
||||
|
||||
|
||||
@override_waffle_flag(toggles.LEGACY_STUDIO_COURSE_OUTLINE, True)
|
||||
@ddt.ddt
|
||||
class TestCourseOutline(CourseTestCase):
|
||||
"""
|
||||
@@ -709,11 +715,12 @@ class TestCourseOutline(CourseTestCase):
|
||||
"""
|
||||
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.
|
||||
|
||||
@@ -5,7 +5,9 @@ unit tests for course_info views and models.
|
||||
|
||||
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 @@ class CourseUpdateTest(CourseTestCase): # lint-amnesty, pylint: disable=missing
|
||||
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):
|
||||
|
||||
@@ -4,7 +4,9 @@ Unit tests for credit eligibility UI in Studio.
|
||||
|
||||
|
||||
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 @@ class CreditEligibilityTest(CourseTestCase):
|
||||
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 @@ class CreditEligibilityTest(CourseTestCase):
|
||||
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
|
||||
|
||||
@@ -8,24 +8,28 @@ import ddt
|
||||
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 @@ class TestExamSettingsView(CourseTestCase, UrlResetMixin):
|
||||
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 @@ class TestExamSettingsView(CourseTestCase, UrlResetMixin):
|
||||
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 @@ class TestExamSettingsView(CourseTestCase, UrlResetMixin):
|
||||
'DEFAULT': 'test_proctoring_provider',
|
||||
'proctortrack': {}
|
||||
},
|
||||
FEATURES=FEATURES_WITH_EXAM_SETTINGS_ENABLED,
|
||||
)
|
||||
@ddt.data(
|
||||
"advanced_settings_handler",
|
||||
@@ -125,12 +127,12 @@ class TestExamSettingsView(CourseTestCase, UrlResetMixin):
|
||||
'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 @@ class TestExamSettingsView(CourseTestCase, UrlResetMixin):
|
||||
'proctortrack': {},
|
||||
'test_proctoring_provider': {},
|
||||
},
|
||||
FEATURES=FEATURES_WITH_EXAM_SETTINGS_ENABLED,
|
||||
)
|
||||
@ddt.data(
|
||||
"advanced_settings_handler",
|
||||
@@ -212,7 +213,6 @@ class TestExamSettingsView(CourseTestCase, UrlResetMixin):
|
||||
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):
|
||||
|
||||
|
||||
@@ -6,9 +6,11 @@ Group Configuration Tests.
|
||||
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 @@ class GroupConfigurationsListHandlerTestCase(CourseTestCase, GroupConfigurations
|
||||
"""
|
||||
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.
|
||||
|
||||
@@ -5,7 +5,9 @@ from unittest import SkipTest
|
||||
|
||||
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 @@ FEATURES_WITH_EXAM_SETTINGS_DISABLED['ENABLE_EXAM_SETTINGS_HTML_VIEW'] = False
|
||||
|
||||
|
||||
@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 @@ class TestHeaderMenu(CourseTestCase, UrlResetMixin):
|
||||
self.assertContains(resp, '<li class="nav-item nav-course-settings-certificates">')
|
||||
|
||||
@override_settings(FEATURES=FEATURES_WITH_EXAM_SETTINGS_DISABLED)
|
||||
@override_waffle_flag(toggles.LEGACY_STUDIO_EXAM_SETTINGS, True)
|
||||
def test_header_menu_without_exam_settings_enabled(self):
|
||||
"""
|
||||
Tests course header menu should not have `Exam Settings` menu item
|
||||
|
||||
@@ -23,12 +23,14 @@ from django.contrib.auth import get_user_model
|
||||
from django.core.exceptions import SuspiciousOperation
|
||||
from django.core.files.storage import FileSystemStorage
|
||||
from django.test.utils import override_settings
|
||||
from edx_toggles.toggles.testutils import override_waffle_flag
|
||||
from milestones.tests.utils import MilestonesTestCaseMixin
|
||||
from opaque_keys.edx.locator import LibraryLocator
|
||||
from path import Path as path
|
||||
from storages.backends.s3boto3 import S3Boto3Storage
|
||||
from user_tasks.models import UserTaskStatus
|
||||
|
||||
from cms.djangoapps.contentstore import toggles
|
||||
from cms.djangoapps.contentstore import errors as import_error
|
||||
from cms.djangoapps.contentstore.storage import course_import_export_storage
|
||||
from cms.djangoapps.contentstore.tests.test_libraries import LibraryTestCase
|
||||
@@ -746,6 +748,7 @@ class ExportTestCase(CourseTestCase):
|
||||
self.url = reverse_course_url('export_handler', self.course.id)
|
||||
self.status_url = reverse_course_url('export_status_handler', self.course.id)
|
||||
|
||||
@override_waffle_flag(toggles.LEGACY_STUDIO_EXPORT, True)
|
||||
def test_export_html(self):
|
||||
"""
|
||||
Get the HTML for the page.
|
||||
|
||||
@@ -4,7 +4,9 @@
|
||||
import json
|
||||
import random
|
||||
|
||||
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 cms.djangoapps.contentstore.views import tabs
|
||||
@@ -66,6 +68,7 @@ class TabsPageTests(CourseTestCase):
|
||||
data={'invalid_request': None},
|
||||
)
|
||||
|
||||
@override_waffle_flag(toggles.LEGACY_STUDIO_CUSTOM_PAGES, True)
|
||||
def test_view_index(self):
|
||||
"""Basic check that the Pages page responds correctly"""
|
||||
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
import json
|
||||
from unittest import TestCase
|
||||
|
||||
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
|
||||
|
||||
@@ -17,6 +20,7 @@ class TextbookIndexTestCase(CourseTestCase):
|
||||
super().setUp()
|
||||
self.url = reverse_course_url('textbooks_list_handler', self.course.id)
|
||||
|
||||
@override_waffle_flag(toggles.LEGACY_STUDIO_TEXTBOOKS, True)
|
||||
def test_view_index(self):
|
||||
"Basic check that the textbook index page responds correctly"
|
||||
resp = self.client.get(self.url)
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
"""
|
||||
Tests for contentstore/views/user.py.
|
||||
"""
|
||||
|
||||
|
||||
import json
|
||||
|
||||
from django.contrib.auth.models import User # lint-amnesty, pylint: disable=imported-auth-user
|
||||
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.student import auth
|
||||
@@ -42,12 +42,14 @@ class UsersTestCase(CourseTestCase): # lint-amnesty, pylint: disable=missing-cl
|
||||
kwargs={'email': email} if email else {}
|
||||
)
|
||||
|
||||
@override_waffle_flag(toggles.LEGACY_STUDIO_COURSE_TEAM, True)
|
||||
def test_index(self):
|
||||
resp = self.client.get(self.index_url, HTTP_ACCEPT='text/html')
|
||||
# ext_user is not currently a member of the course team, and so should
|
||||
# not show up on the page.
|
||||
self.assertNotContains(resp, self.ext_user.email)
|
||||
|
||||
@override_waffle_flag(toggles.LEGACY_STUDIO_COURSE_TEAM, True)
|
||||
def test_index_member(self):
|
||||
auth.add_users(self.user, CourseStaffRole(self.course.id), self.ext_user)
|
||||
|
||||
|
||||
@@ -416,7 +416,6 @@ FEATURES:
|
||||
ENABLE_DISCUSSION_SERVICE: true
|
||||
ENABLE_EDXNOTES: true
|
||||
ENABLE_ENTERPRISE_INTEGRATION: true
|
||||
ENABLE_EXAM_SETTINGS_HTML_VIEW: true
|
||||
ENABLE_EXPORT_GIT: true
|
||||
ENABLE_FEEDBACK_SUBMISSION: true
|
||||
ENABLE_FINANCIAL_ASSISTANCE_FORM: true
|
||||
|
||||
@@ -115,9 +115,9 @@ from openedx.core.djangolib.markup import HTML, Text
|
||||
<%block name="content">
|
||||
|
||||
<%
|
||||
use_new_editor_text = use_new_text_editor()
|
||||
use_new_editor_video = use_new_video_editor()
|
||||
use_new_editor_problem = use_new_problem_editor()
|
||||
use_new_editor_text = use_new_text_editor(xblock_locator.course_key)
|
||||
use_new_editor_video = use_new_video_editor(xblock_locator.course_key)
|
||||
use_new_editor_problem = use_new_problem_editor(xblock_locator.course_key)
|
||||
use_new_video_gallery_flow = use_video_gallery_flow()
|
||||
%>
|
||||
|
||||
|
||||
@@ -12,9 +12,9 @@ from cms.lib.xblock.upstream_sync import UpstreamLink
|
||||
from openedx.core.djangoapps.content_tagging.toggles import is_tagging_feature_disabled
|
||||
%>
|
||||
<%
|
||||
use_new_editor_text = use_new_text_editor()
|
||||
use_new_editor_video = use_new_video_editor()
|
||||
use_new_editor_problem = use_new_problem_editor()
|
||||
use_new_editor_text = use_new_text_editor(xblock.context_key)
|
||||
use_new_editor_video = use_new_video_editor(xblock.context_key)
|
||||
use_new_editor_problem = use_new_problem_editor(xblock.context_key)
|
||||
use_new_video_gallery_flow = use_video_gallery_flow()
|
||||
use_tagging = not is_tagging_feature_disabled()
|
||||
xblock_url = xblock_studio_url(xblock)
|
||||
|
||||
@@ -27,32 +27,6 @@ class CachedAuthMiddlewareTestCase(TestCase):
|
||||
self.client.response = HttpResponse()
|
||||
self.client.response.cookies = SimpleCookie() # preparing cookies
|
||||
|
||||
def _test_change_session_hash(self, test_url, redirect_url, target_status_code=200):
|
||||
"""
|
||||
Verify that if a user's session auth hash and the request's hash
|
||||
differ, the user is logged out. The URL to test and the
|
||||
expected redirect are passed in, since we want to test this
|
||||
behavior in both LMS and CMS, but the two systems have
|
||||
different URLconfs.
|
||||
"""
|
||||
response = self.client.get(test_url)
|
||||
assert response.status_code == 200
|
||||
|
||||
with patch(
|
||||
"openedx.core.djangoapps.cache_toolbox.middleware.set_custom_attribute"
|
||||
) as mock_set_custom_attribute:
|
||||
with patch.object(User, 'get_session_auth_hash', return_value='abc123', autospec=True):
|
||||
# Django 3.2 has _legacy_get_session_auth_hash, and Django 4 does not
|
||||
# Remove once we reach Django 4
|
||||
if hasattr(User, '_legacy_get_session_auth_hash'):
|
||||
with patch.object(User, '_legacy_get_session_auth_hash', return_value='abc123'):
|
||||
response = self.client.get(test_url)
|
||||
else:
|
||||
response = self.client.get(test_url)
|
||||
|
||||
self.assertRedirects(response, redirect_url, target_status_code=target_status_code)
|
||||
mock_set_custom_attribute.assert_any_call('failed_session_verification', True)
|
||||
|
||||
def _test_custom_attribute_after_changing_hash(self, test_url, mock_set_custom_attribute):
|
||||
"""verify that set_custom_attribute is called with expected values"""
|
||||
password = 'test-password'
|
||||
@@ -102,16 +76,44 @@ class CachedAuthMiddlewareTestCase(TestCase):
|
||||
|
||||
@skip_unless_lms
|
||||
def test_session_change_lms(self):
|
||||
"""Test session verification with LMS-specific URLs."""
|
||||
"""
|
||||
Verify (from the LMS side) that if a user's session auth hash and the request's
|
||||
hash differ, the user is logged out.
|
||||
"""
|
||||
dashboard_url = reverse('dashboard')
|
||||
self._test_change_session_hash(dashboard_url, reverse('signin_user') + '?next=' + dashboard_url)
|
||||
response = self.client.get(dashboard_url)
|
||||
assert response.status_code == 200
|
||||
|
||||
with patch(
|
||||
"openedx.core.djangoapps.cache_toolbox.middleware.set_custom_attribute"
|
||||
) as mock_set_custom_attribute:
|
||||
with patch.object(User, 'get_session_auth_hash', return_value='abc123', autospec=True):
|
||||
response = self.client.get(dashboard_url)
|
||||
|
||||
redirect_url = reverse('signin_user') + '?next=' + dashboard_url
|
||||
self.assertRedirects(response, redirect_url, target_status_code=200)
|
||||
mock_set_custom_attribute.assert_any_call('failed_session_verification', True)
|
||||
|
||||
@skip_unless_cms
|
||||
def test_session_change_cms(self):
|
||||
"""Test session verification with CMS-specific URLs."""
|
||||
"""
|
||||
Verify (from the CMS side) that if a user's session auth hash and the request's
|
||||
hash differ, the user is logged out.
|
||||
"""
|
||||
home_url = reverse('home')
|
||||
# Studio login redirects to LMS login
|
||||
self._test_change_session_hash(home_url, settings.LOGIN_URL + '?next=' + home_url, target_status_code=302)
|
||||
response = self.client.get(home_url)
|
||||
assert response.status_code == 302
|
||||
assert response.url == "http://course-authoring-mfe/home"
|
||||
|
||||
with patch(
|
||||
"openedx.core.djangoapps.cache_toolbox.middleware.set_custom_attribute"
|
||||
) as mock_set_custom_attribute:
|
||||
with patch.object(User, 'get_session_auth_hash', return_value='abc123', autospec=True):
|
||||
response = self.client.get(home_url)
|
||||
|
||||
redirect_url = settings.LOGIN_URL + '?next=' + home_url
|
||||
self.assertRedirects(response, redirect_url, target_status_code=302)
|
||||
mock_set_custom_attribute.assert_any_call('failed_session_verification', True)
|
||||
|
||||
@skip_unless_lms
|
||||
@patch("openedx.core.djangoapps.cache_toolbox.middleware.set_custom_attribute")
|
||||
|
||||
Reference in New Issue
Block a user