Add course overrides of waffle flags.

This commit is contained in:
Robert Raposa
2017-05-19 17:25:16 -04:00
parent 867fac315f
commit eaab2cf444
33 changed files with 812 additions and 211 deletions

View File

@@ -231,18 +231,18 @@ class TestFieldOverrideMongoPerformance(FieldOverridePerformanceTestCase):
# # of sql queries to default,
# # of mongo queries,
# )
('no_overrides', 1, True, False): (24, 1),
('no_overrides', 2, True, False): (24, 1),
('no_overrides', 3, True, False): (24, 1),
('ccx', 1, True, False): (24, 1),
('ccx', 2, True, False): (24, 1),
('ccx', 3, True, False): (24, 1),
('no_overrides', 1, False, False): (24, 1),
('no_overrides', 2, False, False): (24, 1),
('no_overrides', 3, False, False): (24, 1),
('ccx', 1, False, False): (24, 1),
('ccx', 2, False, False): (24, 1),
('ccx', 3, False, False): (24, 1),
('no_overrides', 1, True, False): (25, 1),
('no_overrides', 2, True, False): (25, 1),
('no_overrides', 3, True, False): (25, 1),
('ccx', 1, True, False): (25, 1),
('ccx', 2, True, False): (25, 1),
('ccx', 3, True, False): (25, 1),
('no_overrides', 1, False, False): (25, 1),
('no_overrides', 2, False, False): (25, 1),
('no_overrides', 3, False, False): (25, 1),
('ccx', 1, False, False): (25, 1),
('ccx', 2, False, False): (25, 1),
('ccx', 3, False, False): (25, 1),
}
@@ -254,19 +254,19 @@ class TestFieldOverrideSplitPerformance(FieldOverridePerformanceTestCase):
__test__ = True
TEST_DATA = {
('no_overrides', 1, True, False): (24, 3),
('no_overrides', 2, True, False): (24, 3),
('no_overrides', 3, True, False): (24, 3),
('ccx', 1, True, False): (24, 3),
('ccx', 2, True, False): (24, 3),
('ccx', 3, True, False): (24, 3),
('ccx', 1, True, True): (25, 3),
('ccx', 2, True, True): (25, 3),
('ccx', 3, True, True): (25, 3),
('no_overrides', 1, False, False): (24, 3),
('no_overrides', 2, False, False): (24, 3),
('no_overrides', 3, False, False): (24, 3),
('ccx', 1, False, False): (24, 3),
('ccx', 2, False, False): (24, 3),
('ccx', 3, False, False): (24, 3),
('no_overrides', 1, True, False): (25, 3),
('no_overrides', 2, True, False): (25, 3),
('no_overrides', 3, True, False): (25, 3),
('ccx', 1, True, False): (25, 3),
('ccx', 2, True, False): (25, 3),
('ccx', 3, True, False): (25, 3),
('ccx', 1, True, True): (26, 3),
('ccx', 2, True, True): (26, 3),
('ccx', 3, True, True): (26, 3),
('no_overrides', 1, False, False): (25, 3),
('no_overrides', 2, False, False): (25, 3),
('no_overrides', 3, False, False): (25, 3),
('ccx', 1, False, False): (25, 3),
('ccx', 2, False, False): (25, 3),
('ccx', 3, False, False): (25, 3),
}

View File

@@ -2,15 +2,14 @@
This module is essentially a broker to xmodule/tabs.py -- it was originally introduced to
perform some LMS-specific tab display gymnastics for the Entrance Exams feature
"""
import waffle
from django.conf import settings
from django.utils.translation import ugettext as _, ugettext_noop
from courseware.access import has_access
from courseware.entrance_exams import user_can_skip_entrance_exam
from openedx.core.lib.course_tabs import CourseTabPluginManager
from openedx.features.course_experience import default_course_url_name, UNIFIED_COURSE_EXPERIENCE_FLAG
from openedx.features.course_experience import default_course_url_name
from openedx.features.course_experience import UNIFIED_COURSE_TAB_FLAG
from request_cache.middleware import RequestCache
from student.models import CourseEnrollment
from xmodule.tabs import CourseTab, CourseTabList, key_checker, link_reverse_func
@@ -66,8 +65,7 @@ class CourseInfoTab(CourseTab):
"""
The "Home" tab is not shown for the new unified course experience.
"""
request = RequestCache.get_current_request()
return not waffle.flag_is_active(request, UNIFIED_COURSE_EXPERIENCE_FLAG)
return not UNIFIED_COURSE_TAB_FLAG.is_enabled(course.id)
class SyllabusTab(EnrolledTab):

View File

@@ -7,8 +7,6 @@ from django.core.urlresolvers import reverse
from freezegun import freeze_time
from nose.plugins.attrib import attr
from pytz import utc
from waffle.testutils import override_flag
from openedx.features.course_experience import UNIFIED_COURSE_EXPERIENCE_FLAG
from commerce.models import CommerceConfiguration
from course_modes.tests.factories import CourseModeFactory
@@ -24,6 +22,8 @@ from courseware.date_summary import (
)
from openedx.core.djangoapps.self_paced.models import SelfPacedConfiguration
from openedx.core.djangoapps.user_api.preferences.api import set_user_preference
from openedx.core.djangoapps.waffle_utils.testutils import override_waffle_flag
from openedx.features.course_experience import UNIFIED_COURSE_TAB_FLAG
from student.tests.factories import CourseEnrollmentFactory, UserFactory
from lms.djangoapps.verify_student.models import VerificationDeadline
from lms.djangoapps.verify_student.tests.factories import SoftwareSecurePhotoVerificationFactory
@@ -194,7 +194,7 @@ class CourseDateSummaryTest(SharedModuleStoreTestCase):
'info',
'openedx.course_experience.course_home',
)
@override_flag(UNIFIED_COURSE_EXPERIENCE_FLAG, active=True)
@override_waffle_flag(UNIFIED_COURSE_TAB_FLAG, active=True)
def test_todays_date_no_timezone(self, url_name):
with freeze_time('2015-01-02'):
self.setup_course_and_user()
@@ -218,7 +218,7 @@ class CourseDateSummaryTest(SharedModuleStoreTestCase):
'info',
'openedx.course_experience.course_home',
)
@override_flag(UNIFIED_COURSE_EXPERIENCE_FLAG, active=True)
@override_waffle_flag(UNIFIED_COURSE_TAB_FLAG, active=True)
def test_todays_date_timezone(self, url_name):
with freeze_time('2015-01-02'):
self.setup_course_and_user()
@@ -249,7 +249,7 @@ class CourseDateSummaryTest(SharedModuleStoreTestCase):
'info',
'openedx.course_experience.course_home',
)
@override_flag(UNIFIED_COURSE_EXPERIENCE_FLAG, active=True)
@override_waffle_flag(UNIFIED_COURSE_TAB_FLAG, active=True)
def test_start_date_render(self, url_name):
with freeze_time('2015-01-02'):
self.setup_course_and_user()
@@ -267,7 +267,7 @@ class CourseDateSummaryTest(SharedModuleStoreTestCase):
'info',
'openedx.course_experience.course_home',
)
@override_flag(UNIFIED_COURSE_EXPERIENCE_FLAG, active=True)
@override_waffle_flag(UNIFIED_COURSE_TAB_FLAG, active=True)
def test_start_date_render_time_zone(self, url_name):
with freeze_time('2015-01-02'):
self.setup_course_and_user()

View File

@@ -2,8 +2,6 @@
Test cases for tabs.
"""
from waffle.testutils import override_flag
from django.core.urlresolvers import reverse
from django.http import Http404
from mock import MagicMock, Mock, patch
@@ -18,7 +16,8 @@ from courseware.tests.helpers import LoginEnrollmentTestCase
from courseware.tests.factories import InstructorFactory, StaffFactory
from courseware.views.views import get_static_tab_fragment, StaticCourseTabView
from openedx.core.djangolib.testing.utils import get_mock_request
from openedx.features.course_experience import UNIFIED_COURSE_EXPERIENCE_FLAG
from openedx.core.djangoapps.waffle_utils.testutils import override_waffle_flag
from openedx.features.course_experience import UNIFIED_COURSE_TAB_FLAG
from student.models import CourseEnrollment
from student.tests.factories import UserFactory
from util.milestones_helpers import (
@@ -776,12 +775,13 @@ class CourseInfoTabTestCase(TabTestCase):
self.user = self.create_mock_user()
self.request = get_mock_request(self.user)
@override_waffle_flag(UNIFIED_COURSE_TAB_FLAG, active=False)
def test_default_tab(self):
# Verify that the course info tab is the first tab
tabs = get_course_tab_list(self.request, self.course)
self.assertEqual(tabs[0].type, 'course_info')
@override_flag(UNIFIED_COURSE_EXPERIENCE_FLAG, active=True)
@override_waffle_flag(UNIFIED_COURSE_TAB_FLAG, active=True)
def test_default_tab_for_new_course_experience(self):
# Verify that the unified course experience hides the course info tab
tabs = get_course_tab_list(self.request, self.course)

View File

@@ -210,8 +210,8 @@ class IndexQueryTestCase(ModuleStoreTestCase):
NUM_PROBLEMS = 20
@ddt.data(
(ModuleStoreEnum.Type.mongo, 10, 142),
(ModuleStoreEnum.Type.split, 4, 142),
(ModuleStoreEnum.Type.mongo, 10, 143),
(ModuleStoreEnum.Type.split, 4, 143),
)
@ddt.unpack
def test_index_query_counts(self, store_type, expected_mongo_query_count, expected_mysql_query_count):
@@ -1420,12 +1420,12 @@ class ProgressPageTests(ProgressPageBaseTests):
"""Test that query counts remain the same for self-paced and instructor-paced courses."""
SelfPacedConfiguration(enabled=self_paced_enabled).save()
self.setup_course(self_paced=self_paced)
with self.assertNumQueries(40), check_mongo_calls(1):
with self.assertNumQueries(41), check_mongo_calls(1):
self._get_progress_page()
@ddt.data(
(False, 40, 26),
(True, 33, 22)
(False, 41, 27),
(True, 34, 23)
)
@ddt.unpack
def test_progress_queries(self, enable_waffle, initial, subsequent):

View File

@@ -86,9 +86,9 @@ from openedx.core.djangoapps.programs.utils import ProgramMarketingDataExtender
from openedx.core.djangoapps.self_paced.models import SelfPacedConfiguration
from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers
from openedx.features.course_experience import (
UNIFIED_COURSE_EXPERIENCE_FLAG,
UNIFIED_COURSE_TAB_FLAG,
UNIFIED_COURSE_VIEW_FLAG,
course_home_url_name
course_home_url_name,
)
from openedx.features.course_experience.views.course_dates import CourseDatesFragmentView
from openedx.features.enterprise_support.api import data_sharing_consent_required
@@ -263,11 +263,12 @@ def course_info(request, course_id):
return url
return None
# If the unified course experience is enabled, redirect to the "Course" tab
if waffle.flag_is_active(request, UNIFIED_COURSE_EXPERIENCE_FLAG):
return redirect(reverse(course_home_url_name(request), args=[course_id]))
course_key = CourseKey.from_string(course_id)
# If the unified course experience is enabled, redirect to the "Course" tab
if UNIFIED_COURSE_TAB_FLAG.is_enabled(course_key):
return redirect(reverse(course_home_url_name(course_key), args=[course_id]))
with modulestore().bulk_operations(course_key):
course = get_course_by_id(course_key, depth=2)
access_response = has_access(request.user, 'load', course, course_key)
@@ -669,7 +670,7 @@ def course_about(request, course_id):
modes = CourseMode.modes_for_course_dict(course_key)
if configuration_helpers.get_value('ENABLE_MKTG_SITE', settings.FEATURES.get('ENABLE_MKTG_SITE', False)):
return redirect(reverse(course_home_url_name(request), args=[unicode(course.id)]))
return redirect(reverse(course_home_url_name(course.id), args=[unicode(course.id)]))
registered = registered_for_course(course, request.user)
@@ -677,7 +678,7 @@ def course_about(request, course_id):
studio_url = get_studio_url(course, 'settings/details')
if has_access(request.user, 'load', course):
course_target = reverse(course_home_url_name(request), args=[course.id.to_deprecated_string()])
course_target = reverse(course_home_url_name(course.id), args=[course.id.to_deprecated_string()])
else:
course_target = reverse('about_course', args=[course.id.to_deprecated_string()])
@@ -1241,7 +1242,7 @@ def course_survey(request, course_id):
course_key = CourseKey.from_string(course_id)
course = get_course_with_access(request.user, 'load', course_key)
redirect_url = reverse(course_home_url_name(request), args=[course_id])
redirect_url = reverse(course_home_url_name(course.id), args=[course_id])
# if there is no Survey associated with this course,
# then redirect to the course instead

View File

@@ -2,7 +2,7 @@
This module contains various configuration settings via
waffle switches for the Grades app.
"""
from openedx.core.djangolib.waffle_utils import WaffleSwitchPlus
from openedx.core.djangoapps.waffle_utils import WaffleSwitchNamespace
# Namespace
@@ -18,4 +18,4 @@ def waffle():
"""
Returns the namespaced, cached, audited Waffle class for Grades.
"""
return WaffleSwitchPlus(namespace=WAFFLE_NAMESPACE, log_prefix=u'Grades: ')
return WaffleSwitchNamespace(name=WAFFLE_NAMESPACE, log_prefix=u'Grades: ')

View File

@@ -2211,6 +2211,9 @@ INSTALLED_APPS = (
# Unusual migrations
'database_fixups',
# Waffle related utilities
'openedx.core.djangoapps.waffle_utils',
# Features
'openedx.features.course_bookmarks',
'openedx.features.course_experience',

View File

@@ -56,7 +56,7 @@ from util.course import get_link_for_about_page, get_encoded_course_sharing_utm_
% endif
<div class="course-container">
<article class="course${mode_class}">
<% course_target = reverse(course_home_url_name(), args=[unicode(course_overview.id)]) %>
<% course_target = reverse(course_home_url_name(course_overview.id), args=[unicode(course_overview.id)]) %>
<section class="details" aria-labelledby="details-heading-${course_overview.number}">
<h2 class="hd hd-2 sr" id="details-heading-${course_overview.number}">${_('Course details')}</h2>
<div class="wrapper-course-image" aria-hidden="true">

View File

@@ -75,7 +75,7 @@ from openedx.features.course_experience import course_home_url_name
</div>
% if not reg_code_already_redeemed:
%if redemption_success:
<% course_url = reverse(course_home_url_name(), args=[course.id.to_deprecated_string()]) %>
<% course_url = reverse(course_home_url_name(course.id), args=[course.id.to_deprecated_string()]) %>
<a href="${course_url}" class="link-button course-link-bg-color">${_("View Course")} <span class="icon fa fa-caret-right" aria-hidden="true"></span></a>
%elif not registered_for_course:
<form method="post">

View File

@@ -55,6 +55,6 @@ class HelpModalTests(ModuleStoreTestCase):
Simple test to make sure that you don't get a 500 error when the modal
is enabled.
"""
url = reverse(course_home_url_name(), args=[self.course.id.to_deprecated_string()])
url = reverse(course_home_url_name(self.course.id), args=[self.course.id.to_deprecated_string()])
resp = self.client.get(url)
self.assertEqual(resp.status_code, 200)