Create flag for Courseware MFE staff rollout.
Create the COURSEWARE_MICROFRONTEND_COURSE_TEAM_PREVIEW CourseWaffleFlag (courseware.microfrontend_course_team_preview) to enable us to roll out the new Courseware MFE as a preview to select course teams without affecting their students. TNL-7117 This commit also fixes an issue where these links are shown in Old Mongo courses (TNL-7116). Old Mongo is marked for deprecation (DEPR-58), and is not intended to ever be supported by the new MFE.
This commit is contained in:
@@ -61,7 +61,10 @@ from lms.djangoapps.certificates.tests.factories import CertificateInvalidationF
|
||||
from lms.djangoapps.commerce.models import CommerceConfiguration
|
||||
from lms.djangoapps.commerce.utils import EcommerceService
|
||||
from lms.djangoapps.courseware.views.index import show_courseware_mfe_link
|
||||
from lms.djangoapps.courseware.toggles import REDIRECT_TO_COURSEWARE_MICROFRONTEND
|
||||
from lms.djangoapps.courseware.toggles import (
|
||||
COURSEWARE_MICROFRONTEND_COURSE_TEAM_PREVIEW,
|
||||
REDIRECT_TO_COURSEWARE_MICROFRONTEND,
|
||||
)
|
||||
from lms.djangoapps.courseware.url_helpers import get_microfrontend_url
|
||||
from lms.djangoapps.grades.config.waffle import ASSUME_ZERO_GRADE_IF_ABSENT
|
||||
from lms.djangoapps.grades.config.waffle import waffle as grades_waffle
|
||||
@@ -3221,36 +3224,109 @@ class DatesTabTestCase(ModuleStoreTestCase):
|
||||
class TestShowCoursewareMFE(TestCase):
|
||||
"""
|
||||
Make sure we're showing the Courseware MFE link when appropriate.
|
||||
|
||||
There are an unfortunate number of state permutations here since we have
|
||||
the product of the following binary states:
|
||||
|
||||
* the ENABLE_COURSEWARE_MICROFRONTEND Django setting
|
||||
* user is global staff member
|
||||
* user is member of the course team
|
||||
* whether the course_key is an old Mongo style of key
|
||||
* the COURSEWARE_MICROFRONTEND_COURSE_TEAM_PREVIEW CourseWaffleFlag
|
||||
* the REDIRECT_TO_COURSEWARE_MICROFRONTEND CourseWaffleFlag
|
||||
|
||||
Giving us theoretically 2^6 = 64 states. >_<
|
||||
"""
|
||||
def test_when_to_show(self):
|
||||
course_key = CourseKey.from_string("course-v1:OpenEdX+MFE+2020")
|
||||
@patch.dict(settings.FEATURES, {'ENABLE_COURSEWARE_MICROFRONTEND': False})
|
||||
def test_disabled_at_platform_level(self):
|
||||
"""Test every permutation where the platform feature is disabled."""
|
||||
old_course_key = CourseKey.from_string("OpenEdX/Old/2020")
|
||||
new_course_key = CourseKey.from_string("course-v1:OpenEdX+New+2020")
|
||||
global_staff_user = UserFactory(username="global_staff", is_staff=True)
|
||||
user = UserFactory(username="normal", is_staff=False)
|
||||
regular_user = UserFactory(username="normal", is_staff=False)
|
||||
|
||||
# We never show when the feature is entirely disabled.
|
||||
with patch.dict(settings.FEATURES, {'ENABLE_COURSEWARE_MICROFRONTEND': False}):
|
||||
self.assertFalse(show_courseware_mfe_link(global_staff_user, True, course_key))
|
||||
self.assertFalse(show_courseware_mfe_link(user, True, course_key))
|
||||
self.assertFalse(show_courseware_mfe_link(user, False, course_key))
|
||||
# We never show when the feature is entirely disabled, no matter what
|
||||
# the waffle flags are set to, who the user is, or what the course_key
|
||||
# type is.
|
||||
combos = itertools.product(
|
||||
[regular_user, global_staff_user], # User (is global staff)
|
||||
[old_course_key, new_course_key], # Course Key (old vs. new)
|
||||
[True, False], # is_course_staff
|
||||
[True, False], # preview_active (COURSEWARE_MICROFRONTEND_COURSE_TEAM_PREVIEW)
|
||||
[True, False], # redirect_active (REDIRECT_TO_COURSEWARE_MICROFRONTEND)
|
||||
)
|
||||
for user, course_key, is_course_staff, preview_active, redirect_active in combos:
|
||||
with override_waffle_flag(COURSEWARE_MICROFRONTEND_COURSE_TEAM_PREVIEW, preview_active):
|
||||
with override_waffle_flag(REDIRECT_TO_COURSEWARE_MICROFRONTEND, redirect_active):
|
||||
assert show_courseware_mfe_link(user, is_course_staff, course_key) is False
|
||||
|
||||
# If it's enabled at the platform level, what we do depends on the
|
||||
# CourseWaffleFlag and type of user...
|
||||
with patch.dict(settings.FEATURES, {'ENABLE_COURSEWARE_MICROFRONTEND': True}):
|
||||
# If the feature is enabled at the platform level, we always display
|
||||
# the MFE link to global staff. But course staff only see it if the
|
||||
# CourseWaffleFlag is also enabled for that course. Regular users
|
||||
# never see the link.
|
||||
with override_waffle_flag(REDIRECT_TO_COURSEWARE_MICROFRONTEND, False):
|
||||
self.assertTrue(show_courseware_mfe_link(global_staff_user, True, course_key))
|
||||
self.assertFalse(show_courseware_mfe_link(user, True, course_key))
|
||||
self.assertFalse(show_courseware_mfe_link(user, False, course_key))
|
||||
@patch.dict(settings.FEATURES, {'ENABLE_COURSEWARE_MICROFRONTEND': True})
|
||||
def test_enabled_at_platform_level(self):
|
||||
"""Test every permutation where the platform feature is enabled."""
|
||||
old_course_key = CourseKey.from_string("OpenEdX/Old/2020")
|
||||
new_course_key = CourseKey.from_string("course-v1:OpenEdX+New+2020")
|
||||
global_staff_user = UserFactory(username="global_staff", is_staff=True)
|
||||
regular_user = UserFactory(username="normal", is_staff=False)
|
||||
|
||||
# If both the feature flag and CourseWaffleFlag are enabled, we should show
|
||||
# to global and course staff, but not normal users.
|
||||
# Old style course keys are never supported and should always return false...
|
||||
old_mongo_combos = itertools.product(
|
||||
[regular_user, global_staff_user], # User (is global staff)
|
||||
[True, False], # is_course_staff
|
||||
[True, False], # preview_active (COURSEWARE_MICROFRONTEND_COURSE_TEAM_PREVIEW)
|
||||
[True, False], # redirect_active (REDIRECT_TO_COURSEWARE_MICROFRONTEND)
|
||||
)
|
||||
for user, is_course_staff, preview_active, redirect_active in old_mongo_combos:
|
||||
with override_waffle_flag(COURSEWARE_MICROFRONTEND_COURSE_TEAM_PREVIEW, preview_active):
|
||||
with override_waffle_flag(REDIRECT_TO_COURSEWARE_MICROFRONTEND, redirect_active):
|
||||
assert show_courseware_mfe_link(user, is_course_staff, old_course_key) is False
|
||||
|
||||
# We've checked all old-style course keys now, so we can test only the
|
||||
# new ones going forward. Now we check combinations of waffle flags and
|
||||
# user permissions...
|
||||
with override_waffle_flag(COURSEWARE_MICROFRONTEND_COURSE_TEAM_PREVIEW, True):
|
||||
with override_waffle_flag(REDIRECT_TO_COURSEWARE_MICROFRONTEND, True):
|
||||
self.assertTrue(show_courseware_mfe_link(global_staff_user, True, course_key))
|
||||
self.assertTrue(show_courseware_mfe_link(user, True, course_key))
|
||||
self.assertFalse(show_courseware_mfe_link(user, False, course_key))
|
||||
# (preview=on, redirect=on)
|
||||
# Global and Course Staff can see the link.
|
||||
self.assertTrue(show_courseware_mfe_link(global_staff_user, True, new_course_key))
|
||||
self.assertTrue(show_courseware_mfe_link(global_staff_user, False, new_course_key))
|
||||
self.assertTrue(show_courseware_mfe_link(regular_user, True, new_course_key))
|
||||
|
||||
# Regular users don't see the link.
|
||||
self.assertFalse(show_courseware_mfe_link(regular_user, False, new_course_key))
|
||||
with override_waffle_flag(REDIRECT_TO_COURSEWARE_MICROFRONTEND, False):
|
||||
# (preview=on, redirect=off)
|
||||
# Global and Course Staff can see the link.
|
||||
self.assertTrue(show_courseware_mfe_link(global_staff_user, True, new_course_key))
|
||||
self.assertTrue(show_courseware_mfe_link(global_staff_user, False, new_course_key))
|
||||
self.assertTrue(show_courseware_mfe_link(regular_user, True, new_course_key))
|
||||
|
||||
# Regular users don't see the link.
|
||||
self.assertFalse(show_courseware_mfe_link(regular_user, False, new_course_key))
|
||||
|
||||
with override_waffle_flag(COURSEWARE_MICROFRONTEND_COURSE_TEAM_PREVIEW, False):
|
||||
with override_waffle_flag(REDIRECT_TO_COURSEWARE_MICROFRONTEND, True):
|
||||
# (preview=off, redirect=on)
|
||||
# Global staff see the link anyway
|
||||
self.assertTrue(show_courseware_mfe_link(global_staff_user, True, new_course_key))
|
||||
self.assertTrue(show_courseware_mfe_link(global_staff_user, False, new_course_key))
|
||||
|
||||
# If redirect is active for their students, course staff see the link even
|
||||
# if preview=off.
|
||||
self.assertTrue(show_courseware_mfe_link(regular_user, True, new_course_key))
|
||||
|
||||
# Regular users don't see the link.
|
||||
self.assertFalse(show_courseware_mfe_link(regular_user, False, new_course_key))
|
||||
with override_waffle_flag(REDIRECT_TO_COURSEWARE_MICROFRONTEND, False):
|
||||
# (preview=off, redirect=off)
|
||||
# Global staff see the link anyway
|
||||
self.assertTrue(show_courseware_mfe_link(global_staff_user, True, new_course_key))
|
||||
self.assertTrue(show_courseware_mfe_link(global_staff_user, False, new_course_key))
|
||||
|
||||
# Course teams can NOT see the link because both rollout waffle flags are false.
|
||||
self.assertFalse(show_courseware_mfe_link(regular_user, True, new_course_key))
|
||||
|
||||
# Regular users don't see the link.
|
||||
self.assertFalse(show_courseware_mfe_link(regular_user, False, new_course_key))
|
||||
|
||||
@override_settings(LEARNING_MICROFRONTEND_URL='https://learningmfe.openedx.org')
|
||||
def test_url_generation(self):
|
||||
|
||||
@@ -12,7 +12,7 @@ WAFFLE_FLAG_NAMESPACE = WaffleFlagNamespace(name='courseware')
|
||||
# .. toggle_name: courseware.redirect_to_microfrontend
|
||||
# .. toggle_implementation: CourseWaffleFlag
|
||||
# .. toggle_default: False
|
||||
# .. toggle_description: Supports staged rollout of a new micro-frontend-based implementation of the courseware page.
|
||||
# .. toggle_description: Supports staged rollout to students for a new micro-frontend-based implementation of the courseware page.
|
||||
# .. toggle_category: micro-frontend
|
||||
# .. toggle_use_cases: incremental_release, open_edx
|
||||
# .. toggle_creation_date: 2020-01-29
|
||||
@@ -22,9 +22,25 @@ WAFFLE_FLAG_NAMESPACE = WaffleFlagNamespace(name='courseware')
|
||||
# .. toggle_status: supported
|
||||
REDIRECT_TO_COURSEWARE_MICROFRONTEND = CourseWaffleFlag(WAFFLE_FLAG_NAMESPACE, 'redirect_to_microfrontend')
|
||||
|
||||
# Waffle flag to display a link for the new learner experience to course teams without redirecting students.
|
||||
#
|
||||
# .. toggle_name: courseware.microfrontend_course_team_preview
|
||||
# .. toggle_implementation: CourseWaffleFlag
|
||||
# .. toggle_default: False
|
||||
# .. toggle_description: Supports staged rollout to course teams of a new micro-frontend-based implementation of the courseware page.
|
||||
# .. toggle_category: micro-frontend
|
||||
# .. toggle_use_cases: incremental_release, open_edx
|
||||
# .. toggle_creation_date: 2020-03-09
|
||||
# .. toggle_expiration_date: 2020-12-31
|
||||
# .. toggle_warnings: Also set settings.LEARNING_MICROFRONTEND_URL and ENABLE_COURSEWARE_MICROFRONTEND.
|
||||
# .. toggle_tickets: TNL-6982
|
||||
# .. toggle_status: supported
|
||||
COURSEWARE_MICROFRONTEND_COURSE_TEAM_PREVIEW = CourseWaffleFlag(WAFFLE_FLAG_NAMESPACE, 'microfrontend_course_team_preview')
|
||||
|
||||
|
||||
def should_redirect_to_courseware_microfrontend(course_key):
|
||||
return (
|
||||
settings.FEATURES.get('ENABLE_COURSEWARE_MICROFRONTEND') and
|
||||
(not course_key.deprecated) and # Old Mongo courses not supported
|
||||
REDIRECT_TO_COURSEWARE_MICROFRONTEND.is_enabled(course_key)
|
||||
)
|
||||
|
||||
@@ -32,7 +32,10 @@ from web_fragments.fragment import Fragment
|
||||
from edxmako.shortcuts import render_to_response, render_to_string
|
||||
from lms.djangoapps.courseware.courses import allow_public_access
|
||||
from lms.djangoapps.courseware.exceptions import CourseAccessRedirect
|
||||
from lms.djangoapps.courseware.toggles import should_redirect_to_courseware_microfrontend
|
||||
from lms.djangoapps.courseware.toggles import (
|
||||
COURSEWARE_MICROFRONTEND_COURSE_TEAM_PREVIEW,
|
||||
should_redirect_to_courseware_microfrontend,
|
||||
)
|
||||
from lms.djangoapps.courseware.url_helpers import get_microfrontend_url
|
||||
from lms.djangoapps.experiments.utils import get_experiment_user_metadata_context
|
||||
from lms.djangoapps.gating.api import get_entrance_exam_score_ratio, get_entrance_exam_usage_key
|
||||
@@ -640,16 +643,22 @@ def show_courseware_mfe_link(user, staff_access, course_key):
|
||||
if not settings.FEATURES.get('ENABLE_COURSEWARE_MICROFRONTEND'):
|
||||
return False
|
||||
|
||||
# Global staff members always get to see the courseware MFE button if
|
||||
# the basic feature is enabled at all, regardless of whether a course
|
||||
# has enabled it via flag.
|
||||
# MFE does not work for Old Mongo courses.
|
||||
if course_key.deprecated:
|
||||
return False
|
||||
|
||||
# Global staff members always get to see the courseware MFE button if the
|
||||
# platform and course are capable, regardless of rollout waffle flags.
|
||||
if user.is_staff:
|
||||
return True
|
||||
|
||||
# If you have course staff access, you see this link only if your
|
||||
# students would be redirected to the new experience (course staff are
|
||||
# never automatically redirected).
|
||||
if staff_access and should_redirect_to_courseware_microfrontend(course_key):
|
||||
# If you have course staff access, you see this link if we've enabled the
|
||||
# course team preview CourseWaffleFlag for this course *or* if we've turned
|
||||
# on the redirect for your students.
|
||||
mfe_enabled_for_course_team = COURSEWARE_MICROFRONTEND_COURSE_TEAM_PREVIEW.is_enabled(course_key)
|
||||
mfe_enabled_for_students = should_redirect_to_courseware_microfrontend(course_key)
|
||||
|
||||
if staff_access and (mfe_enabled_for_course_team or mfe_enabled_for_students):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
Reference in New Issue
Block a user