Deprecate WaffleSwitch.override* methods
This allows us to get rid of the custom WaffleSwitch and WaffleSwitchNamespace classes from waffle_utils in favour of edx_toggles.toggles classes.
This commit is contained in:
@@ -35,6 +35,7 @@ from cms.djangoapps.contentstore.tests.utils import CourseTestCase
|
||||
from cms.djangoapps.contentstore.utils import reverse_course_url, reverse_usage_url
|
||||
from cms.djangoapps.contentstore.views import item as item_module
|
||||
from lms_xblock.mixin import NONSENSICAL_ACCESS_RESTRICTION
|
||||
from openedx.core.djangoapps.waffle_utils.testutils import override_waffle_switch
|
||||
from student.tests.factories import UserFactory
|
||||
from xblock_django.models import XBlockConfiguration, XBlockStudioConfiguration, XBlockStudioConfigurationFlag
|
||||
from xblock_django.user_service import DjangoXBlockUserService
|
||||
@@ -2666,7 +2667,7 @@ class TestXBlockInfo(ItemTest):
|
||||
self.course.highlights_enabled_for_messaging = True
|
||||
self.store.update_item(self.course, None)
|
||||
chapter = self.store.get_item(self.chapter.location)
|
||||
with highlights_setting.override():
|
||||
with override_waffle_switch(highlights_setting, active=True):
|
||||
chapter_xblock_info = create_xblock_info(chapter)
|
||||
course_xblock_info = create_xblock_info(self.course)
|
||||
self.assertTrue(chapter_xblock_info['highlights_enabled'])
|
||||
|
||||
@@ -41,7 +41,9 @@ from openedx.core.djangoapps.video_pipeline.config.waffle import (
|
||||
waffle_flags
|
||||
)
|
||||
from openedx.core.djangoapps.video_pipeline.models import VEMPipelineIntegration
|
||||
from openedx.core.djangoapps.waffle_utils import WaffleSwitch
|
||||
from openedx.core.djangoapps.waffle_utils.models import WaffleFlagCourseOverrideModel
|
||||
from openedx.core.djangoapps.waffle_utils.testutils import override_waffle_switch
|
||||
from xmodule.modulestore.tests.factories import CourseFactory
|
||||
|
||||
from ..videos import (
|
||||
@@ -56,23 +58,7 @@ from ..videos import (
|
||||
convert_video_status
|
||||
)
|
||||
|
||||
|
||||
def override_switch(switch, active):
|
||||
"""
|
||||
Overrides the given waffle switch to `active` boolean.
|
||||
|
||||
Arguments:
|
||||
switch(str): switch name
|
||||
active(bool): A boolean representing (to be overridden) value
|
||||
"""
|
||||
def decorate(function):
|
||||
@wraps(function)
|
||||
def inner(*args, **kwargs):
|
||||
with WAFFLE_SWITCHES.override(switch, active=active):
|
||||
function(*args, **kwargs)
|
||||
return inner
|
||||
|
||||
return decorate
|
||||
VIDEO_IMAGE_UPLOAD_ENABLED_SWITCH = WaffleSwitch(WAFFLE_SWITCHES, VIDEO_IMAGE_UPLOAD_ENABLED)
|
||||
|
||||
|
||||
class VideoUploadTestBase(object):
|
||||
@@ -908,7 +894,7 @@ class VideoImageTestCase(VideoUploadTestBase, CourseTestCase):
|
||||
self.assertIn('error', response)
|
||||
self.assertEqual(response['error'], error_message)
|
||||
|
||||
@override_switch(VIDEO_IMAGE_UPLOAD_ENABLED, False)
|
||||
@override_waffle_switch(VIDEO_IMAGE_UPLOAD_ENABLED_SWITCH, False)
|
||||
def test_video_image_upload_disabled(self):
|
||||
"""
|
||||
Tests the video image upload when the feature is disabled.
|
||||
@@ -917,7 +903,7 @@ class VideoImageTestCase(VideoUploadTestBase, CourseTestCase):
|
||||
response = self.client.post(video_image_upload_url, {'file': 'dummy_file'}, format='multipart')
|
||||
self.assertEqual(response.status_code, 404)
|
||||
|
||||
@override_switch(VIDEO_IMAGE_UPLOAD_ENABLED, True)
|
||||
@override_waffle_switch(VIDEO_IMAGE_UPLOAD_ENABLED_SWITCH, True)
|
||||
def test_video_image(self):
|
||||
"""
|
||||
Test video image is saved.
|
||||
@@ -939,7 +925,7 @@ class VideoImageTestCase(VideoUploadTestBase, CourseTestCase):
|
||||
|
||||
self.assertNotEqual(image_url1, image_url2)
|
||||
|
||||
@override_switch(VIDEO_IMAGE_UPLOAD_ENABLED, True)
|
||||
@override_waffle_switch(VIDEO_IMAGE_UPLOAD_ENABLED_SWITCH, True)
|
||||
def test_video_image_no_file(self):
|
||||
"""
|
||||
Test that an error error message is returned if upload request is incorrect.
|
||||
@@ -948,7 +934,7 @@ class VideoImageTestCase(VideoUploadTestBase, CourseTestCase):
|
||||
response = self.client.post(video_image_upload_url, {})
|
||||
self.verify_error_message(response, 'An image file is required.')
|
||||
|
||||
@override_switch(VIDEO_IMAGE_UPLOAD_ENABLED, True)
|
||||
@override_waffle_switch(VIDEO_IMAGE_UPLOAD_ENABLED_SWITCH, True)
|
||||
def test_no_video_image(self):
|
||||
"""
|
||||
Test image url is set to None if no video image.
|
||||
@@ -1130,7 +1116,7 @@ class VideoImageTestCase(VideoUploadTestBase, CourseTestCase):
|
||||
)
|
||||
)
|
||||
@ddt.unpack
|
||||
@override_switch(VIDEO_IMAGE_UPLOAD_ENABLED, True)
|
||||
@override_waffle_switch(VIDEO_IMAGE_UPLOAD_ENABLED_SWITCH, True)
|
||||
def test_video_image_validation_message(self, image_data, error_message):
|
||||
"""
|
||||
Test video image validation gives proper error message.
|
||||
|
||||
@@ -18,13 +18,14 @@ from django.utils.timezone import now
|
||||
from mock import Mock
|
||||
from pytz import UTC
|
||||
|
||||
from student.admin import AllowedAuthUserForm, COURSE_ENROLLMENT_ADMIN_SWITCH, UserAdmin, CourseEnrollmentForm
|
||||
from openedx.core.djangoapps.content.course_overviews.tests.factories import CourseOverviewFactory
|
||||
from openedx.core.djangoapps.site_configuration.tests.mixins import SiteMixin
|
||||
from openedx.core.djangoapps.waffle_utils.testutils import override_waffle_switch
|
||||
from student.admin import COURSE_ENROLLMENT_ADMIN_SWITCH, AllowedAuthUserForm, CourseEnrollmentForm, UserAdmin
|
||||
from student.models import AllowedAuthUser, CourseEnrollment, LoginFailures
|
||||
from student.tests.factories import CourseEnrollmentFactory, UserFactory
|
||||
from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase
|
||||
from xmodule.modulestore.tests.factories import CourseFactory
|
||||
from openedx.core.djangoapps.content.course_overviews.tests.factories import CourseOverviewFactory
|
||||
from openedx.core.djangoapps.site_configuration.tests.mixins import SiteMixin
|
||||
|
||||
|
||||
class AdminCourseRolesPageTest(SharedModuleStoreTestCase):
|
||||
@@ -243,7 +244,7 @@ class CourseEnrollmentAdminTest(SharedModuleStoreTestCase):
|
||||
"""
|
||||
Ensure CourseEnrollmentAdmin views can be enabled with the waffle switch.
|
||||
"""
|
||||
with COURSE_ENROLLMENT_ADMIN_SWITCH.override(active=True):
|
||||
with override_waffle_switch(COURSE_ENROLLMENT_ADMIN_SWITCH, active=True):
|
||||
response = getattr(self.client, method)(url)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
@@ -257,7 +258,7 @@ class CourseEnrollmentAdminTest(SharedModuleStoreTestCase):
|
||||
course_id=self.course.id, # pylint: disable=no-member
|
||||
)
|
||||
search_url = '{}?q={}'.format(reverse('admin:student_courseenrollment_changelist'), self.user.username)
|
||||
with COURSE_ENROLLMENT_ADMIN_SWITCH.override(active=True):
|
||||
with override_waffle_switch(COURSE_ENROLLMENT_ADMIN_SWITCH, active=True):
|
||||
response = self.client.get(search_url)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
@@ -283,7 +284,7 @@ class CourseEnrollmentAdminTest(SharedModuleStoreTestCase):
|
||||
'mode': self.course_enrollment.mode,
|
||||
}
|
||||
|
||||
with COURSE_ENROLLMENT_ADMIN_SWITCH.override(active=True):
|
||||
with override_waffle_switch(COURSE_ENROLLMENT_ADMIN_SWITCH, active=True):
|
||||
response = self.client.post(
|
||||
reverse('admin:student_courseenrollment_change', args=(self.course_enrollment.id, )),
|
||||
data=data,
|
||||
@@ -304,7 +305,7 @@ class CourseEnrollmentAdminTest(SharedModuleStoreTestCase):
|
||||
'mode': self.course_enrollment.mode,
|
||||
}
|
||||
|
||||
with COURSE_ENROLLMENT_ADMIN_SWITCH.override(active=True):
|
||||
with override_waffle_switch(COURSE_ENROLLMENT_ADMIN_SWITCH, active=True):
|
||||
with self.assertRaises(ValidationError):
|
||||
self.client.post(
|
||||
reverse('admin:student_courseenrollment_change', args=(self.course_enrollment.id, )),
|
||||
|
||||
@@ -20,10 +20,14 @@ from lms.djangoapps.grades.course_grade_factory import CourseGradeFactory
|
||||
from lms.djangoapps.grades.tests.utils import mock_passing_grade
|
||||
from lms.djangoapps.verify_student.models import IDVerificationAttempt, SoftwareSecurePhotoVerification
|
||||
from openedx.core.djangoapps.certificates.config import waffle
|
||||
from openedx.core.djangoapps.waffle_utils import WaffleSwitch
|
||||
from openedx.core.djangoapps.waffle_utils.testutils import override_waffle_switch
|
||||
from student.tests.factories import CourseEnrollmentFactory, UserFactory
|
||||
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
|
||||
from xmodule.modulestore.tests.factories import CourseFactory
|
||||
|
||||
AUTO_CERTIFICATE_GENERATION_SWITCH = WaffleSwitch(waffle.waffle(), waffle.AUTO_CERTIFICATE_GENERATION)
|
||||
|
||||
|
||||
class SelfGeneratedCertsSignalTest(ModuleStoreTestCase):
|
||||
"""
|
||||
@@ -84,13 +88,13 @@ class WhitelistGeneratedCertificatesTest(ModuleStoreTestCase):
|
||||
'lms.djangoapps.certificates.signals.generate_certificate.apply_async',
|
||||
return_value=None
|
||||
) as mock_generate_certificate_apply_async:
|
||||
with waffle.waffle().override(waffle.AUTO_CERTIFICATE_GENERATION, active=False):
|
||||
with override_waffle_switch(AUTO_CERTIFICATE_GENERATION_SWITCH, active=False):
|
||||
CertificateWhitelist.objects.create(
|
||||
user=self.user,
|
||||
course_id=self.course.id
|
||||
)
|
||||
mock_generate_certificate_apply_async.assert_not_called()
|
||||
with waffle.waffle().override(waffle.AUTO_CERTIFICATE_GENERATION, active=True):
|
||||
with override_waffle_switch(AUTO_CERTIFICATE_GENERATION_SWITCH, active=True):
|
||||
CertificateWhitelist.objects.create(
|
||||
user=self.user,
|
||||
course_id=self.course.id
|
||||
@@ -112,13 +116,13 @@ class WhitelistGeneratedCertificatesTest(ModuleStoreTestCase):
|
||||
'lms.djangoapps.certificates.signals.generate_certificate.apply_async',
|
||||
return_value=None
|
||||
) as mock_generate_certificate_apply_async:
|
||||
with waffle.waffle().override(waffle.AUTO_CERTIFICATE_GENERATION, active=False):
|
||||
with override_waffle_switch(AUTO_CERTIFICATE_GENERATION_SWITCH, active=False):
|
||||
CertificateWhitelist.objects.create(
|
||||
user=self.user,
|
||||
course_id=self.ip_course.id
|
||||
)
|
||||
mock_generate_certificate_apply_async.assert_not_called()
|
||||
with waffle.waffle().override(waffle.AUTO_CERTIFICATE_GENERATION, active=True):
|
||||
with override_waffle_switch(AUTO_CERTIFICATE_GENERATION_SWITCH, active=True):
|
||||
CertificateWhitelist.objects.create(
|
||||
user=self.user,
|
||||
course_id=self.ip_course.id
|
||||
@@ -167,7 +171,7 @@ class PassingGradeCertsTest(ModuleStoreTestCase):
|
||||
'lms.djangoapps.certificates.signals.generate_certificate.apply_async',
|
||||
return_value=None
|
||||
) as mock_generate_certificate_apply_async:
|
||||
with waffle.waffle().override(waffle.AUTO_CERTIFICATE_GENERATION, active=True):
|
||||
with override_waffle_switch(AUTO_CERTIFICATE_GENERATION_SWITCH, active=True):
|
||||
grade_factory = CourseGradeFactory()
|
||||
# Not passing
|
||||
grade_factory.update(self.user, self.course)
|
||||
@@ -188,7 +192,7 @@ class PassingGradeCertsTest(ModuleStoreTestCase):
|
||||
'lms.djangoapps.certificates.signals.generate_certificate.apply_async',
|
||||
return_value=None
|
||||
) as mock_generate_certificate_apply_async:
|
||||
with waffle.waffle().override(waffle.AUTO_CERTIFICATE_GENERATION, active=True):
|
||||
with override_waffle_switch(AUTO_CERTIFICATE_GENERATION_SWITCH, active=True):
|
||||
grade_factory = CourseGradeFactory()
|
||||
# Not passing
|
||||
grade_factory.update(self.user, self.ip_course)
|
||||
@@ -312,7 +316,7 @@ class LearnerTrackChangeCertsTest(ModuleStoreTestCase):
|
||||
'lms.djangoapps.certificates.signals.generate_certificate.apply_async',
|
||||
return_value=None
|
||||
) as mock_generate_certificate_apply_async:
|
||||
with waffle.waffle().override(waffle.AUTO_CERTIFICATE_GENERATION, active=True):
|
||||
with override_waffle_switch(AUTO_CERTIFICATE_GENERATION_SWITCH, active=True):
|
||||
mock_generate_certificate_apply_async.assert_not_called()
|
||||
attempt = SoftwareSecurePhotoVerification.objects.create(
|
||||
user=self.user_one,
|
||||
@@ -333,7 +337,7 @@ class LearnerTrackChangeCertsTest(ModuleStoreTestCase):
|
||||
'lms.djangoapps.certificates.signals.generate_certificate.apply_async',
|
||||
return_value=None
|
||||
) as mock_generate_certificate_apply_async:
|
||||
with waffle.waffle().override(waffle.AUTO_CERTIFICATE_GENERATION, active=True):
|
||||
with override_waffle_switch(AUTO_CERTIFICATE_GENERATION_SWITCH, active=True):
|
||||
mock_generate_certificate_apply_async.assert_not_called()
|
||||
attempt = SoftwareSecurePhotoVerification.objects.create(
|
||||
user=self.user_two,
|
||||
@@ -386,7 +390,7 @@ class CertificateGenerationTaskTest(ModuleStoreTestCase):
|
||||
'lms.djangoapps.certificates.signals.generate_certificate.apply_async',
|
||||
return_value=None
|
||||
) as mock_generate_certificate_apply_async:
|
||||
with waffle.waffle().override(waffle.AUTO_CERTIFICATE_GENERATION, active=True):
|
||||
with override_waffle_switch(AUTO_CERTIFICATE_GENERATION_SWITCH, active=True):
|
||||
fire_ungenerated_certificate_task(self.user, self.course.id)
|
||||
task_created = mock_generate_certificate_apply_async.called
|
||||
self.assertEqual(task_created, should_create)
|
||||
|
||||
@@ -14,8 +14,10 @@ from django.test.client import Client, RequestFactory
|
||||
from django.test.utils import override_settings
|
||||
from django.urls import reverse
|
||||
from mock import patch
|
||||
from urllib.parse import urlencode
|
||||
|
||||
from course_modes.models import CourseMode
|
||||
from edx_toggles.toggles.testutils import override_waffle_switch
|
||||
from lms.djangoapps.badges.events.course_complete import get_completion_badge
|
||||
from lms.djangoapps.badges.tests.factories import (
|
||||
BadgeAssertionFactory,
|
||||
@@ -44,6 +46,7 @@ from openedx.core.djangoapps.site_configuration.tests.test_util import (
|
||||
with_site_configuration,
|
||||
with_site_configuration_context
|
||||
)
|
||||
from openedx.core.djangoapps.waffle_utils import WaffleSwitch
|
||||
from openedx.core.djangolib.js_utils import js_escaped_string
|
||||
from openedx.core.djangolib.testing.utils import CacheIsolationTestCase
|
||||
from openedx.core.lib.tests.assertions.events import assert_event_matches
|
||||
@@ -55,6 +58,7 @@ from util.date_utils import strftime_localized
|
||||
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
|
||||
from xmodule.modulestore.tests.factories import CourseFactory
|
||||
|
||||
AUTO_CERTIFICATE_GENERATION_SWITCH = WaffleSwitch(waffle.waffle(), waffle.AUTO_CERTIFICATE_GENERATION)
|
||||
FEATURES_WITH_CERTS_ENABLED = settings.FEATURES.copy()
|
||||
FEATURES_WITH_CERTS_ENABLED['CERTIFICATES_HTML_VIEW'] = True
|
||||
FEATURES_WITH_BADGES_ENABLED = FEATURES_WITH_CERTS_ENABLED.copy()
|
||||
@@ -937,7 +941,7 @@ class CertificatesViewsTests(CommonCertificatesTestCase, CacheIsolationTestCase)
|
||||
expected_date = today
|
||||
else:
|
||||
expected_date = self.course.certificate_available_date
|
||||
with waffle.waffle().override(waffle.AUTO_CERTIFICATE_GENERATION, active=True):
|
||||
with override_waffle_switch(AUTO_CERTIFICATE_GENERATION_SWITCH, active=True):
|
||||
response = self.client.get(test_url)
|
||||
date = u'{month} {day}, {year}'.format(
|
||||
month=strftime_localized(expected_date, "%B"),
|
||||
|
||||
@@ -11,7 +11,8 @@ from django.test.client import RequestFactory
|
||||
from mock import patch
|
||||
|
||||
from openedx.core.djangoapps.content.block_structure.api import clear_course_from_cache
|
||||
from openedx.core.djangoapps.content.block_structure.config import STORAGE_BACKING_FOR_CACHE, waffle
|
||||
from openedx.core.djangoapps.content.block_structure.config import STORAGE_BACKING_FOR_CACHE, waffle_switch
|
||||
from openedx.core.djangoapps.waffle_utils.testutils import override_waffle_switch
|
||||
from student.tests.factories import UserFactory
|
||||
from xmodule.modulestore import ModuleStoreEnum
|
||||
from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase
|
||||
@@ -229,7 +230,7 @@ class TestGetBlocksQueryCounts(TestGetBlocksQueryCountsBase):
|
||||
)
|
||||
@ddt.unpack
|
||||
def test_query_counts_cached(self, store_type, with_storage_backing):
|
||||
with waffle().override(STORAGE_BACKING_FOR_CACHE, active=with_storage_backing):
|
||||
with override_waffle_switch(waffle_switch(STORAGE_BACKING_FOR_CACHE), active=with_storage_backing):
|
||||
course = self._create_course(store_type)
|
||||
self._get_blocks(
|
||||
course,
|
||||
@@ -246,7 +247,7 @@ class TestGetBlocksQueryCounts(TestGetBlocksQueryCountsBase):
|
||||
@ddt.unpack
|
||||
def test_query_counts_uncached(self, store_type_tuple, with_storage_backing):
|
||||
store_type, expected_mongo_queries = store_type_tuple
|
||||
with waffle().override(STORAGE_BACKING_FOR_CACHE, active=with_storage_backing):
|
||||
with override_waffle_switch(waffle_switch(STORAGE_BACKING_FOR_CACHE), active=with_storage_backing):
|
||||
course = self._create_course(store_type)
|
||||
clear_course_from_cache(course.id)
|
||||
|
||||
|
||||
@@ -48,21 +48,26 @@ from course_modes.models import CourseMode
|
||||
from lms.djangoapps.courseware import module_render as render
|
||||
from lms.djangoapps.courseware.access_response import AccessResponse
|
||||
from lms.djangoapps.courseware.courses import get_course_info_section, get_course_with_access
|
||||
from lms.djangoapps.courseware.field_overrides import OverrideFieldData
|
||||
from lms.djangoapps.courseware.masquerade import CourseMasquerade
|
||||
from lms.djangoapps.courseware.model_data import FieldDataCache
|
||||
from lms.djangoapps.courseware.models import StudentModule
|
||||
from lms.djangoapps.courseware.module_render import get_module_for_descriptor, hash_resource
|
||||
from lms.djangoapps.courseware.tests.factories import (
|
||||
GlobalStaffFactory, RequestFactoryNoCsrf, StudentModuleFactory, UserFactory,
|
||||
GlobalStaffFactory,
|
||||
RequestFactoryNoCsrf,
|
||||
StudentModuleFactory,
|
||||
UserFactory
|
||||
)
|
||||
from lms.djangoapps.courseware.tests.test_submitting_problems import TestSubmittingProblems
|
||||
from lms.djangoapps.courseware.tests.tests import LoginEnrollmentTestCase
|
||||
from lms.djangoapps.courseware.field_overrides import OverrideFieldData
|
||||
from lms.djangoapps.lms_xblock.field_data import LmsFieldData
|
||||
from openedx.core.djangoapps.credit.api import set_credit_requirement_status, set_credit_requirements
|
||||
from openedx.core.djangoapps.credit.models import CreditCourse
|
||||
from openedx.core.djangoapps.oauth_dispatch.jwt import create_jwt_for_user
|
||||
from openedx.core.djangoapps.oauth_dispatch.tests.factories import ApplicationFactory, AccessTokenFactory
|
||||
from openedx.core.djangoapps.oauth_dispatch.tests.factories import AccessTokenFactory, ApplicationFactory
|
||||
from openedx.core.djangoapps.waffle_utils import WaffleSwitch
|
||||
from openedx.core.djangoapps.waffle_utils.testutils import override_waffle_switch
|
||||
from openedx.core.lib.courses import course_image_url
|
||||
from openedx.core.lib.gating import api as gating_api
|
||||
from openedx.core.lib.url_utils import quote_slashes
|
||||
@@ -86,6 +91,10 @@ from xmodule.x_module import STUDENT_VIEW, CombinedSystem, XModule, XModuleDescr
|
||||
|
||||
TEST_DATA_DIR = settings.COMMON_TEST_DATA_ROOT
|
||||
|
||||
ENABLE_COMPLETION_TRACKING_SWITCH = WaffleSwitch(
|
||||
completion_waffle.waffle(), completion_waffle.ENABLE_COMPLETION_TRACKING, __name__
|
||||
)
|
||||
|
||||
|
||||
@XBlock.needs("field-data")
|
||||
@XBlock.needs("i18n")
|
||||
@@ -760,7 +769,7 @@ class TestHandleXBlockCallback(SharedModuleStoreTestCase, LoginEnrollmentTestCas
|
||||
@ddt.unpack
|
||||
@XBlock.register_temp_plugin(StubCompletableXBlock, identifier='comp')
|
||||
def test_completion_events_with_completion_disabled(self, signal, data):
|
||||
with completion_waffle.waffle().override(completion_waffle.ENABLE_COMPLETION_TRACKING, False):
|
||||
with override_waffle_switch(ENABLE_COMPLETION_TRACKING_SWITCH, False):
|
||||
course = CourseFactory.create()
|
||||
block = ItemFactory.create(category='comp', parent=course)
|
||||
request = self.request_factory.post(
|
||||
@@ -782,7 +791,7 @@ class TestHandleXBlockCallback(SharedModuleStoreTestCase, LoginEnrollmentTestCas
|
||||
|
||||
@XBlock.register_temp_plugin(StubCompletableXBlock, identifier='comp')
|
||||
def test_completion_signal_for_completable_xblock(self):
|
||||
with completion_waffle.waffle().override(completion_waffle.ENABLE_COMPLETION_TRACKING, True):
|
||||
with override_waffle_switch(ENABLE_COMPLETION_TRACKING_SWITCH, True):
|
||||
course = CourseFactory.create()
|
||||
block = ItemFactory.create(category='comp', parent=course)
|
||||
|
||||
@@ -862,7 +871,7 @@ class TestHandleXBlockCallback(SharedModuleStoreTestCase, LoginEnrollmentTestCas
|
||||
|
||||
@XBlock.register_temp_plugin(StubCompletableXBlock, identifier='comp')
|
||||
def test_progress_signal_ignored_for_completable_xblock(self):
|
||||
with completion_waffle.waffle().override(completion_waffle.ENABLE_COMPLETION_TRACKING, True):
|
||||
with override_waffle_switch(ENABLE_COMPLETION_TRACKING_SWITCH, True):
|
||||
course = CourseFactory.create()
|
||||
block = ItemFactory.create(category='comp', parent=course)
|
||||
|
||||
@@ -875,7 +884,7 @@ class TestHandleXBlockCallback(SharedModuleStoreTestCase, LoginEnrollmentTestCas
|
||||
|
||||
@XBlock.register_temp_plugin(XBlockWithoutCompletionAPI, identifier='no_comp')
|
||||
def test_progress_signal_processed_for_xblock_without_completion_api(self):
|
||||
with completion_waffle.waffle().override(completion_waffle.ENABLE_COMPLETION_TRACKING, True):
|
||||
with override_waffle_switch(ENABLE_COMPLETION_TRACKING_SWITCH, True):
|
||||
course = CourseFactory.create()
|
||||
block = ItemFactory.create(category='no_comp', parent=course)
|
||||
|
||||
@@ -889,7 +898,7 @@ class TestHandleXBlockCallback(SharedModuleStoreTestCase, LoginEnrollmentTestCas
|
||||
|
||||
@XBlock.register_temp_plugin(StubCompletableXBlock, identifier='comp')
|
||||
def test_skip_handlers_for_masquerading_staff(self):
|
||||
with completion_waffle.waffle().override(completion_waffle.ENABLE_COMPLETION_TRACKING, True):
|
||||
with override_waffle_switch(ENABLE_COMPLETION_TRACKING_SWITCH, True):
|
||||
course = CourseFactory.create()
|
||||
block = ItemFactory.create(category='comp', parent=course)
|
||||
request = self.request_factory.post(
|
||||
|
||||
@@ -65,7 +65,7 @@ from lms.djangoapps.courseware.user_state_client import DjangoXBlockUserStateCli
|
||||
from lms.djangoapps.courseware.views.index import show_courseware_mfe_link
|
||||
from lms.djangoapps.experiments.testutils import override_experiment_waffle_flag
|
||||
from lms.djangoapps.grades.config.waffle import ASSUME_ZERO_GRADE_IF_ABSENT
|
||||
from lms.djangoapps.grades.config.waffle import waffle as grades_waffle
|
||||
from lms.djangoapps.grades.config.waffle import waffle_switch as grades_waffle_switch
|
||||
from lms.djangoapps.verify_student.models import VerificationDeadline
|
||||
from lms.djangoapps.verify_student.services import IDVerificationService
|
||||
from openedx.core.djangoapps.catalog.tests.factories import CourseFactory as CatalogCourseFactory
|
||||
@@ -74,7 +74,7 @@ from openedx.core.djangoapps.content.course_overviews.models import CourseOvervi
|
||||
from openedx.core.djangoapps.crawlers.models import CrawlersConfig
|
||||
from openedx.core.djangoapps.credit.api import set_credit_requirements
|
||||
from openedx.core.djangoapps.credit.models import CreditCourse, CreditProvider
|
||||
from openedx.core.djangoapps.waffle_utils.testutils import WAFFLE_TABLES
|
||||
from openedx.core.djangoapps.waffle_utils.testutils import WAFFLE_TABLES, override_waffle_switch
|
||||
from openedx.core.djangolib.testing.utils import get_mock_request
|
||||
from openedx.core.lib.gating import api as gating_api
|
||||
from openedx.core.lib.url_utils import quote_slashes
|
||||
@@ -1446,7 +1446,7 @@ class ProgressPageTests(ProgressPageBaseTests):
|
||||
def test_progress_queries(self, enable_waffle, initial, subsequent):
|
||||
ContentTypeGatingConfig.objects.create(enabled=True, enabled_as_of=datetime(2018, 1, 1))
|
||||
self.setup_course()
|
||||
with grades_waffle().override(ASSUME_ZERO_GRADE_IF_ABSENT, active=enable_waffle):
|
||||
with override_waffle_switch(grades_waffle_switch(ASSUME_ZERO_GRADE_IF_ABSENT), active=enable_waffle):
|
||||
with self.assertNumQueries(
|
||||
initial, table_blacklist=QUERY_COUNT_TABLE_BLACKLIST
|
||||
), check_mongo_calls(1):
|
||||
|
||||
@@ -7,6 +7,7 @@ import datetime
|
||||
import logging
|
||||
|
||||
import ddt
|
||||
import six
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.models import AnonymousUser
|
||||
from django.contrib.sites.models import Site
|
||||
@@ -17,16 +18,8 @@ from mock import ANY, Mock, patch
|
||||
from opaque_keys.edx.keys import CourseKey
|
||||
from sailthru.sailthru_error import SailthruClientError
|
||||
from sailthru.sailthru_response import SailthruResponse
|
||||
import six
|
||||
from testfixtures import LogCapture
|
||||
|
||||
from ..models import EmailMarketingConfiguration
|
||||
from ..signals import (
|
||||
add_email_marketing_cookies,
|
||||
email_marketing_register_user,
|
||||
email_marketing_user_field_changed,
|
||||
update_sailthru
|
||||
)
|
||||
from lms.djangoapps.email_marketing.tasks import (
|
||||
_create_user_list,
|
||||
_get_list_from_email_marketing_provider,
|
||||
@@ -41,6 +34,14 @@ from student.models import Registration
|
||||
from student.tests.factories import CourseEnrollmentFactory, UserFactory, UserProfileFactory
|
||||
from util.json_request import JsonResponse
|
||||
|
||||
from ..models import EmailMarketingConfiguration
|
||||
from ..signals import (
|
||||
add_email_marketing_cookies,
|
||||
email_marketing_register_user,
|
||||
email_marketing_user_field_changed,
|
||||
update_sailthru
|
||||
)
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
LOGGER_NAME = "lms.djangoapps.email_marketing.signals"
|
||||
@@ -620,7 +621,7 @@ class SailthruTests(TestCase):
|
||||
@patch('sailthru.sailthru_client.SailthruClient.purchase')
|
||||
@patch('sailthru.sailthru_client.SailthruClient.api_get')
|
||||
@patch('sailthru.sailthru_client.SailthruClient.api_post')
|
||||
@patch('openedx.core.djangoapps.waffle_utils.WaffleSwitchNamespace.is_enabled')
|
||||
@patch('edx_toggles.toggles.WaffleSwitchNamespace.is_enabled')
|
||||
def test_update_course_enrollment_whitelabel(
|
||||
self,
|
||||
switch,
|
||||
@@ -645,7 +646,7 @@ class SailthruTests(TestCase):
|
||||
update_sailthru(None, self.user, 'verified', self.course_id)
|
||||
self.assertFalse(mock_sailthru_purchase.called)
|
||||
|
||||
@patch('openedx.core.djangoapps.waffle_utils.WaffleSwitchNamespace.is_enabled')
|
||||
@patch('edx_toggles.toggles.WaffleSwitchNamespace.is_enabled')
|
||||
@patch('sailthru.sailthru_client.SailthruClient.purchase')
|
||||
def test_purchase_is_not_invoked(self, mock_sailthru_purchase, switch):
|
||||
"""Make sure purchase is not called in the following condition:
|
||||
@@ -655,7 +656,7 @@ class SailthruTests(TestCase):
|
||||
update_sailthru(None, self.user, 'verified', self.course_id)
|
||||
self.assertFalse(mock_sailthru_purchase.called)
|
||||
|
||||
@patch('openedx.core.djangoapps.waffle_utils.WaffleSwitchNamespace.is_enabled')
|
||||
@patch('edx_toggles.toggles.WaffleSwitchNamespace.is_enabled')
|
||||
@patch('sailthru.sailthru_client.SailthruClient.purchase')
|
||||
def test_encoding_is_working_for_email_contains_unicode(self, mock_sailthru_purchase, switch):
|
||||
"""Make sure encoding is working for emails contains unicode characters
|
||||
|
||||
@@ -4,7 +4,12 @@ waffle switches for the Grades app.
|
||||
"""
|
||||
|
||||
|
||||
from openedx.core.djangoapps.waffle_utils import CourseWaffleFlag, WaffleFlagNamespace, WaffleSwitchNamespace
|
||||
from openedx.core.djangoapps.waffle_utils import (
|
||||
CourseWaffleFlag,
|
||||
WaffleFlagNamespace,
|
||||
WaffleSwitch,
|
||||
WaffleSwitchNamespace
|
||||
)
|
||||
|
||||
# Namespace
|
||||
WAFFLE_NAMESPACE = u'grades'
|
||||
@@ -81,6 +86,16 @@ def waffle():
|
||||
return WaffleSwitchNamespace(name=WAFFLE_NAMESPACE, log_prefix=u'Grades: ')
|
||||
|
||||
|
||||
def waffle_switch(name):
|
||||
"""
|
||||
Return the corresponding namespaced waffle switch.
|
||||
|
||||
WARNING: do not replicate this pattern. Instead of declaring waffle switch names as strings, you should create
|
||||
WaffleSwitch objects as top-level constants.
|
||||
"""
|
||||
return WaffleSwitch(waffle(), name, module_name=__name__)
|
||||
|
||||
|
||||
def waffle_flags():
|
||||
"""
|
||||
Returns the namespaced, cached, audited Waffle flags dictionary for Grades.
|
||||
|
||||
@@ -4,13 +4,14 @@ from crum import set_current_request
|
||||
from django.conf import settings
|
||||
from mock import patch
|
||||
|
||||
from edx_toggles.toggles.testutils import override_waffle_switch
|
||||
from openedx.core.djangolib.testing.utils import get_mock_request
|
||||
from student.models import CourseEnrollment
|
||||
from student.tests.factories import UserFactory
|
||||
from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase
|
||||
from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory
|
||||
|
||||
from ..config.waffle import ASSUME_ZERO_GRADE_IF_ABSENT, waffle
|
||||
from ..config.waffle import ASSUME_ZERO_GRADE_IF_ABSENT, waffle_switch
|
||||
from ..course_data import CourseData
|
||||
from ..course_grade import ZeroCourseGrade
|
||||
from ..course_grade_factory import CourseGradeFactory
|
||||
@@ -31,7 +32,7 @@ class ZeroGradeTest(GradeTestBase):
|
||||
"""
|
||||
Creates a ZeroCourseGrade and ensures it's empty.
|
||||
"""
|
||||
with waffle().override(ASSUME_ZERO_GRADE_IF_ABSENT, active=assume_zero_enabled):
|
||||
with override_waffle_switch(waffle_switch(ASSUME_ZERO_GRADE_IF_ABSENT), active=assume_zero_enabled):
|
||||
course_data = CourseData(self.request.user, structure=self.course_structure)
|
||||
chapter_grades = ZeroCourseGrade(self.request.user, course_data).chapter_grades
|
||||
for chapter in chapter_grades:
|
||||
@@ -46,7 +47,7 @@ class ZeroGradeTest(GradeTestBase):
|
||||
"""
|
||||
Creates a zero course grade and ensures that null scores aren't included in the section problem scores.
|
||||
"""
|
||||
with waffle().override(ASSUME_ZERO_GRADE_IF_ABSENT, active=assume_zero_enabled):
|
||||
with override_waffle_switch(waffle_switch(ASSUME_ZERO_GRADE_IF_ABSENT), active=assume_zero_enabled):
|
||||
with patch('lms.djangoapps.grades.subsection_grade.get_score', return_value=None):
|
||||
course_data = CourseData(self.request.user, structure=self.course_structure)
|
||||
chapter_grades = ZeroCourseGrade(self.request.user, course_data).chapter_grades
|
||||
|
||||
@@ -9,7 +9,7 @@ import ddt
|
||||
from django.conf import settings
|
||||
from mock import patch
|
||||
from six import text_type
|
||||
|
||||
from edx_toggles.toggles.testutils import override_waffle_switch
|
||||
from lms.djangoapps.courseware.access import has_access
|
||||
from lms.djangoapps.grades.config.tests.utils import persistent_grades_feature_flags
|
||||
from openedx.core.djangoapps.content.block_structure.factory import BlockStructureFactory
|
||||
@@ -17,7 +17,7 @@ from student.tests.factories import UserFactory
|
||||
from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase
|
||||
from xmodule.modulestore.tests.factories import CourseFactory
|
||||
|
||||
from ..config.waffle import ASSUME_ZERO_GRADE_IF_ABSENT, waffle
|
||||
from ..config.waffle import ASSUME_ZERO_GRADE_IF_ABSENT, waffle_switch
|
||||
from ..course_grade import CourseGrade, ZeroCourseGrade
|
||||
from ..course_grade_factory import CourseGradeFactory
|
||||
from ..subsection_grade import ReadSubsectionGrade, ZeroSubsectionGrade
|
||||
@@ -132,7 +132,7 @@ class TestCourseGradeFactory(GradeTestBase):
|
||||
@ddt.data(*itertools.product((True, False), (True, False)))
|
||||
@ddt.unpack
|
||||
def test_read_zero(self, assume_zero_enabled, create_if_needed):
|
||||
with waffle().override(ASSUME_ZERO_GRADE_IF_ABSENT, active=assume_zero_enabled):
|
||||
with override_waffle_switch(waffle_switch(ASSUME_ZERO_GRADE_IF_ABSENT), active=assume_zero_enabled):
|
||||
grade_factory = CourseGradeFactory()
|
||||
course_grade = grade_factory.read(self.request.user, self.course, create_if_needed=create_if_needed)
|
||||
if create_if_needed or assume_zero_enabled:
|
||||
|
||||
@@ -13,6 +13,8 @@ from course_modes.models import CourseMode
|
||||
from openedx.core.djangoapps.certificates import api
|
||||
from openedx.core.djangoapps.certificates.config import waffle as certs_waffle
|
||||
from openedx.core.djangoapps.content.course_overviews.tests.factories import CourseOverviewFactory
|
||||
from openedx.core.djangoapps.waffle_utils import WaffleSwitch
|
||||
from openedx.core.djangoapps.waffle_utils.testutils import override_waffle_switch
|
||||
from student.tests.factories import CourseEnrollmentFactory, UserFactory
|
||||
|
||||
|
||||
@@ -66,8 +68,8 @@ class MockGeneratedCertificate(object):
|
||||
@contextmanager
|
||||
def configure_waffle_namespace(feature_enabled):
|
||||
namespace = certs_waffle.waffle()
|
||||
|
||||
with namespace.override(certs_waffle.AUTO_CERTIFICATE_GENERATION, active=feature_enabled):
|
||||
auto_certificate_generation_switch = WaffleSwitch(namespace, certs_waffle.AUTO_CERTIFICATE_GENERATION)
|
||||
with override_waffle_switch(auto_certificate_generation_switch, active=feature_enabled):
|
||||
yield
|
||||
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ waffle switches for the Block Structure framework.
|
||||
"""
|
||||
|
||||
|
||||
from openedx.core.djangoapps.waffle_utils import WaffleSwitchNamespace
|
||||
from openedx.core.djangoapps.waffle_utils import WaffleSwitch, WaffleSwitchNamespace
|
||||
from openedx.core.lib.cache_utils import request_cached
|
||||
|
||||
from .models import BlockStructureConfiguration
|
||||
@@ -25,6 +25,16 @@ def waffle():
|
||||
return WaffleSwitchNamespace(name=WAFFLE_NAMESPACE, log_prefix=u'BlockStructure: ')
|
||||
|
||||
|
||||
def waffle_switch(name):
|
||||
"""
|
||||
Return the waffle switch associated to this namespace.
|
||||
|
||||
WARNING: do not replicate this pattern. Instead of declaring waffle switch names as strings, you should create
|
||||
WaffleSwitch objects as top-level constants.
|
||||
"""
|
||||
return WaffleSwitch(waffle(), name, module_name=__name__)
|
||||
|
||||
|
||||
@request_cached()
|
||||
def num_versions_to_keep():
|
||||
"""
|
||||
|
||||
@@ -133,7 +133,7 @@ class Command(BaseCommand):
|
||||
Generates course blocks for the given course_keys per the given options.
|
||||
"""
|
||||
if options.get('with_storage'):
|
||||
waffle().override_for_request(STORAGE_BACKING_FOR_CACHE)
|
||||
waffle().set_request_cache_with_short_name(STORAGE_BACKING_FOR_CACHE, True)
|
||||
|
||||
for course_key in course_keys:
|
||||
try:
|
||||
|
||||
@@ -60,7 +60,7 @@ def _update_course_in_cache(self, **kwargs):
|
||||
Updates the course blocks (mongo -> BlockStructure) for the specified course.
|
||||
"""
|
||||
if kwargs.get('with_storage'):
|
||||
waffle().override_for_request(STORAGE_BACKING_FOR_CACHE)
|
||||
waffle().set_request_cache_with_short_name(STORAGE_BACKING_FOR_CACHE, True)
|
||||
_call_and_retry_if_needed(self, api.update_course_in_cache, **kwargs)
|
||||
|
||||
|
||||
@@ -89,7 +89,7 @@ def _get_course_in_cache(self, **kwargs):
|
||||
Gets the course blocks for the specified course, updating the cache if needed.
|
||||
"""
|
||||
if kwargs.get('with_storage'):
|
||||
waffle().override_for_request(STORAGE_BACKING_FOR_CACHE)
|
||||
waffle().set_request_cache_with_short_name(STORAGE_BACKING_FOR_CACHE, True)
|
||||
_call_and_retry_if_needed(self, api.get_course_in_cache, **kwargs)
|
||||
|
||||
|
||||
|
||||
@@ -7,8 +7,10 @@ import ddt
|
||||
import six
|
||||
from django.test import TestCase
|
||||
|
||||
from openedx.core.djangoapps.waffle_utils.testutils import override_waffle_switch
|
||||
|
||||
from ..block_structure import BlockStructureBlockData
|
||||
from ..config import RAISE_ERROR_WHEN_NOT_FOUND, STORAGE_BACKING_FOR_CACHE, waffle
|
||||
from ..config import RAISE_ERROR_WHEN_NOT_FOUND, STORAGE_BACKING_FOR_CACHE, waffle_switch
|
||||
from ..exceptions import BlockStructureNotFound, UsageKeyNotInBlockStructure
|
||||
from ..manager import BlockStructureManager
|
||||
from ..transformers import BlockStructureTransformers
|
||||
@@ -178,14 +180,14 @@ class TestBlockStructureManager(UsageKeyFactoryMixin, ChildrenMapTestMixin, Test
|
||||
assert TestTransformer1.collect_call_count == 1
|
||||
|
||||
def test_get_collected_error_raised(self):
|
||||
with waffle().override(RAISE_ERROR_WHEN_NOT_FOUND, active=True):
|
||||
with override_waffle_switch(waffle_switch(RAISE_ERROR_WHEN_NOT_FOUND), active=True):
|
||||
with mock_registered_transformers(self.registered_transformers):
|
||||
with self.assertRaises(BlockStructureNotFound):
|
||||
self.bs_manager.get_collected()
|
||||
|
||||
@ddt.data(True, False)
|
||||
def test_update_collected_if_needed(self, with_storage_backing):
|
||||
with waffle().override(STORAGE_BACKING_FOR_CACHE, active=with_storage_backing):
|
||||
with override_waffle_switch(waffle_switch(STORAGE_BACKING_FOR_CACHE), active=with_storage_backing):
|
||||
with mock_registered_transformers(self.registered_transformers):
|
||||
assert TestTransformer1.collect_call_count == 0
|
||||
|
||||
|
||||
@@ -7,12 +7,13 @@ import ddt
|
||||
from mock import patch
|
||||
from opaque_keys.edx.locator import CourseLocator, LibraryLocator
|
||||
|
||||
from openedx.core.djangoapps.waffle_utils.testutils import override_waffle_switch
|
||||
from xmodule.modulestore.exceptions import ItemNotFoundError
|
||||
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
|
||||
from xmodule.modulestore.tests.factories import CourseFactory
|
||||
|
||||
from ..api import get_block_structure_manager
|
||||
from ..config import INVALIDATE_CACHE_ON_PUBLISH, waffle
|
||||
from ..config import INVALIDATE_CACHE_ON_PUBLISH, waffle_switch
|
||||
from ..signals import update_block_structure_on_course_publish
|
||||
from .helpers import is_course_in_block_structure_cache
|
||||
|
||||
@@ -56,7 +57,7 @@ class CourseBlocksSignalTest(ModuleStoreTestCase):
|
||||
def test_cache_invalidation(self, invalidate_cache_enabled, mock_bs_manager_clear):
|
||||
test_display_name = "Jedi 101"
|
||||
|
||||
with waffle().override(INVALIDATE_CACHE_ON_PUBLISH, active=invalidate_cache_enabled):
|
||||
with override_waffle_switch(waffle_switch(INVALIDATE_CACHE_ON_PUBLISH), active=invalidate_cache_enabled):
|
||||
self.course.display_name = test_display_name
|
||||
self.store.update_item(self.course, self.user.id)
|
||||
|
||||
|
||||
@@ -5,9 +5,10 @@ Tests for block_structure/cache.py
|
||||
|
||||
import ddt
|
||||
|
||||
from openedx.core.djangoapps.waffle_utils.testutils import override_waffle_switch
|
||||
from openedx.core.djangolib.testing.utils import CacheIsolationTestCase
|
||||
|
||||
from ..config import STORAGE_BACKING_FOR_CACHE, waffle
|
||||
from ..config import STORAGE_BACKING_FOR_CACHE, waffle_switch
|
||||
from ..config.models import BlockStructureConfiguration
|
||||
from ..exceptions import BlockStructureNotFound
|
||||
from ..store import BlockStructureStore
|
||||
@@ -47,13 +48,13 @@ class TestBlockStructureStore(UsageKeyFactoryMixin, ChildrenMapTestMixin, CacheI
|
||||
|
||||
@ddt.data(True, False)
|
||||
def test_get_none(self, with_storage_backing):
|
||||
with waffle().override(STORAGE_BACKING_FOR_CACHE, active=with_storage_backing):
|
||||
with override_waffle_switch(waffle_switch(STORAGE_BACKING_FOR_CACHE), active=with_storage_backing):
|
||||
with self.assertRaises(BlockStructureNotFound):
|
||||
self.store.get(self.block_structure.root_block_usage_key)
|
||||
|
||||
@ddt.data(True, False)
|
||||
def test_add_and_get(self, with_storage_backing):
|
||||
with waffle().override(STORAGE_BACKING_FOR_CACHE, active=with_storage_backing):
|
||||
with override_waffle_switch(waffle_switch(STORAGE_BACKING_FOR_CACHE), active=with_storage_backing):
|
||||
self.store.add(self.block_structure)
|
||||
stored_value = self.store.get(self.block_structure.root_block_usage_key)
|
||||
self.assertIsNotNone(stored_value)
|
||||
@@ -61,7 +62,7 @@ class TestBlockStructureStore(UsageKeyFactoryMixin, ChildrenMapTestMixin, CacheI
|
||||
|
||||
@ddt.data(True, False)
|
||||
def test_delete(self, with_storage_backing):
|
||||
with waffle().override(STORAGE_BACKING_FOR_CACHE, active=with_storage_backing):
|
||||
with override_waffle_switch(waffle_switch(STORAGE_BACKING_FOR_CACHE), active=with_storage_backing):
|
||||
self.store.add(self.block_structure)
|
||||
self.store.delete(self.block_structure.root_block_usage_key)
|
||||
with self.assertRaises(BlockStructureNotFound):
|
||||
@@ -74,7 +75,7 @@ class TestBlockStructureStore(UsageKeyFactoryMixin, ChildrenMapTestMixin, CacheI
|
||||
self.store.get(self.block_structure.root_block_usage_key)
|
||||
|
||||
def test_uncached_with_storage(self):
|
||||
with waffle().override(STORAGE_BACKING_FOR_CACHE, active=True):
|
||||
with override_waffle_switch(waffle_switch(STORAGE_BACKING_FOR_CACHE), active=True):
|
||||
self.store.add(self.block_structure)
|
||||
self.mock_cache.map.clear()
|
||||
stored_value = self.store.get(self.block_structure.root_block_usage_key)
|
||||
|
||||
@@ -10,30 +10,23 @@ import ddt
|
||||
import mock
|
||||
import six
|
||||
from django.core.management import call_command
|
||||
|
||||
import openedx.core.djangoapps.content.block_structure.config as block_structure_config
|
||||
from openedx.core.djangoapps.content.block_structure.signals import update_block_structure_on_course_publish
|
||||
from openedx.core.djangoapps.coursegraph.management.commands.dump_to_neo4j import ModuleStoreSerializer
|
||||
from openedx.core.djangoapps.coursegraph.management.commands.tests.utils import MockGraph, MockNodeSelector
|
||||
from openedx.core.djangoapps.coursegraph.tasks import (
|
||||
coerce_types,
|
||||
serialize_course,
|
||||
serialize_item,
|
||||
should_dump_course,
|
||||
strip_branch_and_version
|
||||
)
|
||||
from openedx.core.djangoapps.waffle_utils.testutils import override_waffle_switch
|
||||
from openedx.core.djangolib.testing.utils import skip_unless_lms
|
||||
from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase
|
||||
from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory
|
||||
|
||||
from openedx.core.djangolib.testing.utils import skip_unless_lms
|
||||
|
||||
from openedx.core.djangoapps.coursegraph.management.commands.dump_to_neo4j import (
|
||||
ModuleStoreSerializer
|
||||
)
|
||||
from openedx.core.djangoapps.coursegraph.management.commands.tests.utils import (
|
||||
MockGraph,
|
||||
MockNodeSelector,
|
||||
)
|
||||
from openedx.core.djangoapps.coursegraph.tasks import (
|
||||
serialize_item,
|
||||
serialize_course,
|
||||
coerce_types,
|
||||
should_dump_course,
|
||||
strip_branch_and_version,
|
||||
)
|
||||
from openedx.core.djangoapps.content.block_structure.signals import (
|
||||
update_block_structure_on_course_publish
|
||||
)
|
||||
import openedx.core.djangoapps.content.block_structure.config as block_structure_config
|
||||
|
||||
|
||||
class TestDumpToNeo4jCommandBase(SharedModuleStoreTestCase):
|
||||
"""
|
||||
@@ -507,7 +500,9 @@ class TestModuleStoreSerializer(TestDumpToNeo4jCommandBase):
|
||||
self.assertEqual(len(submitted), len(self.course_strings))
|
||||
|
||||
# simulate one of the courses being published
|
||||
with block_structure_config.waffle().override(block_structure_config.STORAGE_BACKING_FOR_CACHE):
|
||||
with override_waffle_switch(
|
||||
block_structure_config.waffle_switch(block_structure_config.STORAGE_BACKING_FOR_CACHE), True
|
||||
):
|
||||
update_block_structure_on_course_publish(None, self.course.id)
|
||||
|
||||
# make sure only the published course was dumped
|
||||
|
||||
@@ -32,6 +32,7 @@ from openedx.core.djangoapps.user_authn.views.login import (
|
||||
AllowedAuthUser,
|
||||
_check_user_auth_flow
|
||||
)
|
||||
from openedx.core.djangoapps.waffle_utils.testutils import override_waffle_switch
|
||||
from openedx.core.djangolib.testing.utils import CacheIsolationTestCase, skip_unless_lms
|
||||
from openedx.core.djangoapps.site_configuration.tests.mixins import SiteMixin
|
||||
from openedx.core.lib.api.test_utils import ApiTestCase
|
||||
@@ -725,7 +726,7 @@ class LoginTest(SiteMixin, CacheIsolationTestCase):
|
||||
'THIRD_PARTY_AUTH_ONLY_HINT': provider_tpa_hint,
|
||||
}
|
||||
|
||||
with ENABLE_LOGIN_USING_THIRDPARTY_AUTH_ONLY.override(switch_enabled):
|
||||
with override_waffle_switch(ENABLE_LOGIN_USING_THIRDPARTY_AUTH_ONLY, switch_enabled):
|
||||
if not is_third_party_authenticated:
|
||||
site = self.set_up_site(allowed_domain, default_site_configuration_values)
|
||||
|
||||
@@ -778,7 +779,7 @@ class LoginTest(SiteMixin, CacheIsolationTestCase):
|
||||
'THIRD_PARTY_AUTH_ONLY_HINT': provider_tpa_hint,
|
||||
}
|
||||
|
||||
with ENABLE_LOGIN_USING_THIRDPARTY_AUTH_ONLY.override(True):
|
||||
with override_waffle_switch(ENABLE_LOGIN_USING_THIRDPARTY_AUTH_ONLY, True):
|
||||
site = self.set_up_site(allowed_domain, default_site_configuration_values)
|
||||
|
||||
with self.assertLogs(level='WARN') as log:
|
||||
|
||||
@@ -3,97 +3,15 @@ Extra utilities for waffle: most classes are defined in edx_toggles.toggles (htt
|
||||
we keep here some extra classes for usage within edx-platform. These classes cover course override use cases.
|
||||
"""
|
||||
import logging
|
||||
from contextlib import contextmanager
|
||||
|
||||
from opaque_keys.edx.keys import CourseKey
|
||||
|
||||
from edx_toggles.toggles import WaffleFlag, WaffleFlagNamespace
|
||||
from edx_toggles.toggles import WaffleSwitch as BaseWaffleSwitch
|
||||
from edx_toggles.toggles import WaffleSwitchNamespace as BaseWaffleSwitchNamespace
|
||||
# pylint: disable=unused-import
|
||||
from edx_toggles.toggles import WaffleFlag, WaffleFlagNamespace, WaffleSwitch, WaffleSwitchNamespace
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class WaffleSwitchNamespace(BaseWaffleSwitchNamespace):
|
||||
"""
|
||||
Waffle switch namespace that implements custom overriding methods. We should eventually get rid of this class.
|
||||
|
||||
To test WaffleSwitchNamespace, use the provided context managers. For example:
|
||||
|
||||
with WAFFLE_SWITCHES.override(waffle.ESTIMATE_FIRST_ATTEMPTED, active=True):
|
||||
...
|
||||
|
||||
Note: this should eventually be deprecated in favour of a dedicated `override_waffle_switch` context manager.
|
||||
"""
|
||||
|
||||
@contextmanager
|
||||
def override(self, switch_name, active=True):
|
||||
"""
|
||||
Overrides the active value for the given switch for the duration of this
|
||||
contextmanager.
|
||||
Note: The value is overridden in the request cache AND in the model.
|
||||
"""
|
||||
previous_active = self.is_enabled(switch_name)
|
||||
try:
|
||||
self.override_for_request(switch_name, active)
|
||||
with self.override_in_model(switch_name, active):
|
||||
yield
|
||||
finally:
|
||||
self.override_for_request(switch_name, previous_active)
|
||||
|
||||
def override_for_request(self, switch_name, active=True):
|
||||
"""
|
||||
Overrides the active value for the given switch for the remainder of
|
||||
this request (as this is not a context manager).
|
||||
Note: The value is overridden in the request cache, not in the model.
|
||||
"""
|
||||
namespaced_switch_name = self._namespaced_name(switch_name)
|
||||
self._cached_switches[namespaced_switch_name] = active
|
||||
log.info(
|
||||
"%sSwitch '%s' set to %s for request.",
|
||||
self.log_prefix,
|
||||
namespaced_switch_name,
|
||||
active,
|
||||
)
|
||||
|
||||
@contextmanager
|
||||
def override_in_model(self, switch_name, active=True):
|
||||
"""
|
||||
Overrides the active value for the given switch for the duration of this
|
||||
contextmanager.
|
||||
Note: The value is overridden in the model, not the request cache.
|
||||
Note: This should probably be moved to a test class.
|
||||
"""
|
||||
# Import is placed here to avoid model import at project startup.
|
||||
# pylint: disable=import-outside-toplevel
|
||||
from waffle.testutils import override_switch as waffle_override_switch
|
||||
|
||||
namespaced_switch_name = self._namespaced_name(switch_name)
|
||||
with waffle_override_switch(namespaced_switch_name, active):
|
||||
log.info(
|
||||
"%sSwitch '%s' set to %s in model.",
|
||||
self.log_prefix,
|
||||
namespaced_switch_name,
|
||||
active,
|
||||
)
|
||||
yield
|
||||
|
||||
|
||||
class WaffleSwitch(BaseWaffleSwitch):
|
||||
"""
|
||||
This class should be removed in favour of edx_toggles.toggles.WaffleSwitch once we get rid of the
|
||||
WaffleSwitchNamespace class.
|
||||
"""
|
||||
|
||||
NAMESPACE_CLASS = WaffleSwitchNamespace
|
||||
|
||||
@contextmanager
|
||||
def override(self, active=True):
|
||||
with self.waffle_namespace.override(self.switch_name, active):
|
||||
yield
|
||||
|
||||
|
||||
|
||||
class CourseWaffleFlag(WaffleFlag):
|
||||
"""
|
||||
Represents a single waffle flag that can be forced on/off for a course. This class should be used instead of
|
||||
|
||||
@@ -7,7 +7,8 @@ import ddt
|
||||
from django.test import TestCase
|
||||
from django.test.client import RequestFactory
|
||||
from django.test.utils import override_settings
|
||||
# Note that we really shouldn't import from edx_toggles' internal API
|
||||
# TODO: we really shouldn't import from edx_toggles' internal API, but that's currently the only way to mock the
|
||||
# monitoring functions.
|
||||
import edx_toggles.toggles.internal.waffle
|
||||
from edx_django_utils.cache import RequestCache
|
||||
from mock import call, patch
|
||||
|
||||
@@ -5,7 +5,7 @@ Test utilities for waffle utilities.
|
||||
# Import from edx-toggles to preserve import paths
|
||||
# TODO: Deprecate and remove
|
||||
# pylint: disable=unused-import
|
||||
from edx_toggles.toggles.testutils import override_waffle_flag
|
||||
from edx_toggles.toggles.testutils import override_waffle_flag, override_waffle_switch
|
||||
|
||||
# Can be used with FilteredQueryCountMixin.assertNumQueries() to blacklist
|
||||
# waffle tables. For example:
|
||||
|
||||
@@ -4,10 +4,12 @@ Tests that verify that the admin view loads.
|
||||
This is not inside a django app because it is a global property of the system.
|
||||
"""
|
||||
|
||||
from django.test import TestCase, Client
|
||||
from django.test import Client, TestCase
|
||||
from django.urls import reverse
|
||||
from student.tests.factories import UserFactory, TEST_PASSWORD
|
||||
|
||||
from openedx.core.djangoapps.user_authn.views.login import ENABLE_LOGIN_USING_THIRDPARTY_AUTH_ONLY
|
||||
from openedx.core.djangoapps.waffle_utils.testutils import override_waffle_switch
|
||||
from student.tests.factories import TEST_PASSWORD, UserFactory
|
||||
|
||||
|
||||
class TestAdminView(TestCase):
|
||||
@@ -37,10 +39,10 @@ class TestAdminView(TestCase):
|
||||
assert response.status_code == 302
|
||||
|
||||
def test_admin_login_redirect(self):
|
||||
with ENABLE_LOGIN_USING_THIRDPARTY_AUTH_ONLY.override(True):
|
||||
with override_waffle_switch(ENABLE_LOGIN_USING_THIRDPARTY_AUTH_ONLY, True):
|
||||
response = self.client.get(reverse('admin:login'))
|
||||
assert response.url == '/login?next=/admin'
|
||||
assert response.status_code == 302
|
||||
with ENABLE_LOGIN_USING_THIRDPARTY_AUTH_ONLY.override(False):
|
||||
with override_waffle_switch(ENABLE_LOGIN_USING_THIRDPARTY_AUTH_ONLY, False):
|
||||
response = self.client.get(reverse('admin:login'))
|
||||
assert response.template_name == ['admin/login.html']
|
||||
|
||||
@@ -5,11 +5,11 @@ Test models, managers, and validators.
|
||||
|
||||
|
||||
import ddt
|
||||
import six
|
||||
from completion import waffle
|
||||
from completion.test_utils import CompletionWaffleTestMixin
|
||||
from django.urls import reverse
|
||||
from rest_framework.test import APIClient
|
||||
import six
|
||||
|
||||
from openedx.core.djangolib.testing.utils import skip_unless_lms
|
||||
from student.tests.factories import CourseEnrollmentFactory, UserFactory
|
||||
|
||||
Reference in New Issue
Block a user