diff --git a/common/djangoapps/student/tests/test_views.py b/common/djangoapps/student/tests/test_views.py index 36fb34af55..df2913ed03 100644 --- a/common/djangoapps/student/tests/test_views.py +++ b/common/djangoapps/student/tests/test_views.py @@ -235,13 +235,14 @@ class StudentDashboardTests(SharedModuleStoreTestCase, MilestonesTestCaseMixin, response = self.client.get(self.path) self.assertRedirects(response, reverse('account_settings')) - def test_redirect_to_learner_home(self): + @patch('common.djangoapps.student.views.dashboard.should_redirect_to_learner_home_mfe') + def test_redirect_to_learner_home(self, mock_should_redirect_to_learner_home_mfe): """ if learner home mfe is enabled, redirect to learner home mfe """ - with patch('lms.djangoapps.learner_home.waffle.ENABLE_LEARNER_HOME_MFE.is_enabled', return_value=True): - response = self.client.get(self.path) - self.assertRedirects(response, settings.LEARNER_HOME_MICROFRONTEND_URL, fetch_redirect_response=False) + mock_should_redirect_to_learner_home_mfe.return_value = True + response = self.client.get(self.path) + self.assertRedirects(response, settings.LEARNER_HOME_MICROFRONTEND_URL, fetch_redirect_response=False) def test_course_cert_available_message_after_course_end(self): course_key = CourseKey.from_string('course-v1:edX+DemoX+Demo_Course') diff --git a/common/djangoapps/student/views/dashboard.py b/common/djangoapps/student/views/dashboard.py index 84d4f0edc4..0e73c3c257 100644 --- a/common/djangoapps/student/views/dashboard.py +++ b/common/djangoapps/student/views/dashboard.py @@ -521,7 +521,7 @@ def student_dashboard(request): # lint-amnesty, pylint: disable=too-many-statem if not UserProfile.objects.filter(user=user).exists(): return redirect(reverse('account_settings')) - if should_redirect_to_learner_home_mfe(): + if should_redirect_to_learner_home_mfe(user): return redirect(settings.LEARNER_HOME_MICROFRONTEND_URL) platform_name = configuration_helpers.get_value("platform_name", settings.PLATFORM_NAME) diff --git a/lms/djangoapps/learner_home/test_waffle.py b/lms/djangoapps/learner_home/test_waffle.py new file mode 100644 index 0000000000..c9b4ee281d --- /dev/null +++ b/lms/djangoapps/learner_home/test_waffle.py @@ -0,0 +1,54 @@ +""" +Tests for toggles, where there is logic beyond enable/disable. +""" + +from unittest.mock import patch +import ddt + +from django.test import override_settings + +from common.djangoapps.student.tests.factories import UserFactory +from lms.djangoapps.learner_home.waffle import should_redirect_to_learner_home_mfe +from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase + + +@ddt.ddt +class TestLearnerHomeRedirect(SharedModuleStoreTestCase): + """ + Tests for should_redirect_to_learner_home, used for experimental rollout. + """ + + def setUp(self): + super().setUp() + + # Set up a user for testing + self.user = UserFactory + + @patch("lms.djangoapps.learner_home.waffle.ENABLE_LEARNER_HOME_MFE") + def test_should_redirect_to_learner_home_disabled(self, mock_enable_learner_home): + # Given Learner Home MFE feature is not enabled + mock_enable_learner_home.is_enabled.return_value = False + + # When I check if I should redirect + redirect_choice = should_redirect_to_learner_home_mfe(self.user) + + # Then I never redirect + self.assertFalse(redirect_choice) + + @ddt.data((0, True), (50, False), (100, True)) + @ddt.unpack + @patch("lms.djangoapps.learner_home.waffle.ENABLE_LEARNER_HOME_MFE") + @override_settings(LEARNER_HOME_MFE_REDIRECT_PERCENTAGE=50) + def test_should_redirect_to_learner_home_enabled( + self, user_id, expect_redirect, mock_enable_learner_home + ): + # Given Learner Home MFE feature is enabled + mock_enable_learner_home.is_enabled.return_value = True + self.user.id = user_id + + # When I check if I should redirect + redirect_choice = should_redirect_to_learner_home_mfe(self.user) + + # Then I redirect based on configuration + # (currently user ID % 100 < redirect percentage) + self.assertEqual(expect_redirect, redirect_choice) diff --git a/lms/djangoapps/learner_home/waffle.py b/lms/djangoapps/learner_home/waffle.py index 2af62757a4..5f09e3a9c0 100644 --- a/lms/djangoapps/learner_home/waffle.py +++ b/lms/djangoapps/learner_home/waffle.py @@ -1,6 +1,7 @@ """ Configuration for features of Learner Home """ +from django.conf import settings from edx_toggles.toggles import WaffleFlag @@ -22,7 +23,25 @@ ENABLE_LEARNER_HOME_MFE = WaffleFlag( ) -def should_redirect_to_learner_home_mfe(): - return configuration_helpers.get_value( +def should_redirect_to_learner_home_mfe(user): + """ + Redirect a percentage of learners to Learner Home for experimentation. + + Percentage is based on the LEARNER_HOME_MFE_REDIRECT_PERCENTAGE setting. + """ + + is_learning_mfe_enabled = configuration_helpers.get_value( "ENABLE_LEARNER_HOME_MFE", ENABLE_LEARNER_HOME_MFE.is_enabled() ) + + learning_mfe_redirect_percent = configuration_helpers.get_value( + "LEARNER_HOME_MFE_REDIRECT_PERCENTAGE", + settings.LEARNER_HOME_MFE_REDIRECT_PERCENTAGE, + ) + + # Redirect when 1) Learner Home MFE is enabled and 2) a user falls into the + # target range for experimental rollout. + if is_learning_mfe_enabled and user.id % 100 < learning_mfe_redirect_percent: + return True + + return False diff --git a/lms/envs/common.py b/lms/envs/common.py index 8c74c9dc8e..b9571f93ff 100644 --- a/lms/envs/common.py +++ b/lms/envs/common.py @@ -4976,6 +4976,8 @@ HIBP_LOGIN_BLOCK_PASSWORD_FREQUENCY_THRESHOLD = 5 # .. toggle_tickets: https://openedx.atlassian.net/browse/VAN-838 ENABLE_DYNAMIC_REGISTRATION_FIELDS = False +LEARNER_HOME_MFE_REDIRECT_PERCENTAGE = 0 + ############### Settings for the ace_common plugin ################# # Note that all settings are actually defined by the plugin # pylint: disable=wrong-import-position