Merge pull request #17860 from edx/yro/EDUCATOR-2333

Delete visual_progress_enabled waffle flag.
This commit is contained in:
Gregory Martin
2018-04-06 15:55:32 -04:00
committed by GitHub
11 changed files with 48 additions and 200 deletions

View File

@@ -720,8 +720,7 @@ class StudentDashboardTests(SharedModuleStoreTestCase, MilestonesTestCaseMixin,
submit_completions_for_testing(self.user, course_key, block_keys)
with patch('completion.utilities.visual_progress_enabled', return_value=True):
response = self.client.get(reverse('dashboard'))
response = self.client.get(reverse('dashboard'))
course_key_string = str(course_key)
resume_block_key_string = str(block_keys[-1])
@@ -808,8 +807,7 @@ class StudentDashboardTests(SharedModuleStoreTestCase, MilestonesTestCaseMixin,
)
)
with patch('completion.utilities.visual_progress_enabled', return_value=True):
response = self.client.get(reverse('dashboard'))
response = self.client.get(reverse('dashboard'))
html_for_view_buttons = [
self._remove_whitespace_from_html_string(button)

View File

@@ -210,8 +210,6 @@ class SequenceModule(SequenceFields, ProctoringFields, XModule):
if dispatch == 'get_completion':
completion_service = self.runtime.service(self, 'completion')
if not completion_service.visual_progress_enabled():
return None
usage_key = data.get('usage_key', None)
item = self.get_child(UsageKey.from_string(usage_key))
@@ -472,8 +470,9 @@ class SequenceModule(SequenceFields, ProctoringFields, XModule):
'path': " > ".join(display_names + [item.display_name_with_default]),
}
if is_user_authenticated and completion_service.visual_progress_enabled():
iteminfo['complete'] = completion_service.vertical_is_complete(item)
if is_user_authenticated:
if item.location.block_type == 'vertical':
iteminfo['complete'] = completion_service.vertical_is_complete(item)
contents.append(iteminfo)

View File

@@ -280,22 +280,6 @@ class SequenceBlockTestCase(XModuleXmlImportTest):
# assert content shown as normal
self._assert_ungated(html, self.sequence_1_2)
def test_handle_ajax_get_completion_disabled(self):
"""
Test when completion service is turned off by waffle, the ajax call returns correct
None value
"""
completion_waffle_mock = Mock()
completion_waffle_mock.return_value.visual_progress_enabled.return_value = False
self.sequence_3_1.xmodule_runtime._services['completion'] = completion_waffle_mock # pylint: disable=protected-access
for child in self.sequence_3_1.get_children():
usage_key = unicode(child.location)
completion_return = self.sequence_3_1.handle_ajax(
'get_completion',
{'usage_key': usage_key}
)
self.assertIs(completion_return, None)
def test_handle_ajax_get_completion_success(self):
"""
Test that the completion data is returned successfully on

View File

@@ -124,16 +124,6 @@ class CourseHomeTest(CourseHomeBaseTest):
bookmarks_page = BookmarksPage(self.browser, self.course_id)
self.assertTrue(bookmarks_page.is_browser_on_page())
# Test "Resume Course" button from header
self.course_home_page.visit()
self.course_home_page.resume_course_from_header()
self.assertTrue(self.courseware_page.nav.is_on_section('Test Section 2', 'Test Subsection 3'))
# Test "Resume Course" button from within outline
self.course_home_page.visit()
self.course_home_page.outline.resume_course_from_outline()
self.assertTrue(self.courseware_page.nav.is_on_section('Test Section 2', 'Test Subsection 3'))
@attr('a11y')
class CourseHomeA11yTest(CourseHomeBaseTest):

View File

@@ -113,9 +113,8 @@ class CompletionUtilsTestCase(SharedModuleStoreTestCase, CompletionWaffleTestMix
)
@override_settings(LMS_ROOT_URL='test_url:9999')
@patch('completion.waffle.get_current_site')
@ddt.data(True, False)
def test_retrieve_last_sitewide_block_completed(self, use_username, get_patched_current_site): # pylint: disable=unused-argument
def test_retrieve_last_sitewide_block_completed(self, use_username):
"""
Test that the method returns a URL for the "last completed" block
when sending a user object

View File

@@ -37,7 +37,7 @@ from openedx.core.djangolib.markup import HTML, Text
id="${ section['id'] }">
<span class="fa fa-chevron-right ${ 'fa-rotate-90' if section_is_auto_opened else '' }" aria-hidden="true"></span>
<h3 class="section-title">${ section['display_name'] }</h3>
% if show_visual_progress and section.get('complete'):
% if section.get('complete'):
<span class="complete-checkmark fa fa-check"></span>
% endif
</button>
@@ -83,7 +83,7 @@ from openedx.core.djangolib.markup import HTML, Text
<span class="subsection-title">
${ subsection['display_name'] }
</span>
% if subsection.get('complete') and show_visual_progress:
% if subsection.get('complete'):
<span class="complete-checkmark fa fa-check"></span>
% endif
% endif
@@ -168,7 +168,7 @@ from openedx.core.djangolib.markup import HTML, Text
${ vertical['display_name'] }
</span>
</div>
% if vertical.get('complete') and show_visual_progress:
% if vertical.get('complete'):
<span class="complete-checkmark fa fa-check"></span>
% endif
</a>

View File

@@ -307,11 +307,6 @@ class TestCourseOutlineResumeCourse(SharedModuleStoreTestCase, CompletionWaffleT
cls.user = UserFactory(password=TEST_PASSWORD)
CourseEnrollment.enroll(cls.user, cls.course.id)
cls.site = Site.objects.get_current()
SiteConfiguration.objects.get_or_create(
site=cls.site,
enabled=True,
values={waffle.ENABLE_SITE_VISUAL_PROGRESS: True}
)
@classmethod
def create_test_course(cls):
@@ -354,6 +349,27 @@ class TestCourseOutlineResumeCourse(SharedModuleStoreTestCase, CompletionWaffleT
)
self.assertEqual(200, self.client.get(last_accessed_url).status_code)
@override_switch(
'{}.{}'.format(
waffle.WAFFLE_NAMESPACE, waffle.ENABLE_COMPLETION_TRACKING
),
active=True
)
def complete_sequential(self, course, sequential):
"""
Completes provided sequential.
"""
course_key = CourseKey.from_string(str(course.id))
# Fake a visit to sequence2/vertical2
block_key = UsageKey.from_string(unicode(sequential.location))
completion = 1.0
BlockCompletion.objects.submit_completion(
user=self.user,
course_key=course_key,
block_key=block_key,
completion=completion
)
def visit_course_home(self, course, start_count=0, resume_count=0):
"""
Helper function to navigates to course home page, test for resume buttons
@@ -384,37 +400,12 @@ class TestCourseOutlineResumeCourse(SharedModuleStoreTestCase, CompletionWaffleT
self.assertTrue(content('.action-resume-course').attr('href').endswith('/course/' + course.url_name))
def test_resume_course(self):
"""
Tests that two resume course buttons appear when the course has been accessed.
"""
course = self.course
# first navigate to a sequential to make it the last accessed
chapter = course.children[0]
sequential = chapter.children[0]
vertical = sequential.children[0]
self.visit_sequential(course, chapter, sequential)
# check resume course buttons
response = self.visit_course_home(course, resume_count=2)
content = pq(response.content)
self.assertTrue(content('.action-resume-course').attr('href').endswith('/vertical/' + vertical.url_name))
@override_switch(
'{}.{}'.format(
waffle.WAFFLE_NAMESPACE, waffle.ENABLE_VISUAL_PROGRESS
),
active=True
)
@override_settings(LMS_BASE='test_url:9999')
@patch('completion.waffle.get_current_site')
def test_resume_course_with_completion_api(self, get_patched_current_site):
def test_resume_course_with_completion_api(self):
"""
Tests completion API resume button functionality
"""
self.override_waffle_switch(True)
get_patched_current_site.return_value = self.site
# Course tree
course = self.course
@@ -422,16 +413,7 @@ class TestCourseOutlineResumeCourse(SharedModuleStoreTestCase, CompletionWaffleT
vertical1 = course.children[0].children[0].children[0]
vertical2 = course.children[0].children[1].children[0]
# Fake a visit to sequence1/vertical1
block_key = UsageKey.from_string(unicode(vertical1.location))
completion = 1.0
BlockCompletion.objects.submit_completion(
user=self.user,
course_key=course_key,
block_key=block_key,
completion=completion
)
self.complete_sequential(self.course, vertical1)
# Test for 'resume' link
response = self.visit_course_home(course, resume_count=2)
@@ -439,15 +421,8 @@ class TestCourseOutlineResumeCourse(SharedModuleStoreTestCase, CompletionWaffleT
content = pq(response.content)
self.assertTrue(content('.action-resume-course').attr('href').endswith('/vertical/' + vertical1.url_name))
# Fake a visit to sequence2/vertical2
block_key = UsageKey.from_string(unicode(vertical2.location))
completion = 1.0
BlockCompletion.objects.submit_completion(
user=self.user,
course_key=course_key,
block_key=block_key,
completion=completion
)
self.complete_sequential(self.course, vertical2)
# Test for 'resume' link
response = self.visit_course_home(course, resume_count=2)
# Test for 'resume' link URL - should be vertical 2
@@ -465,7 +440,7 @@ class TestCourseOutlineResumeCourse(SharedModuleStoreTestCase, CompletionWaffleT
def test_resume_course_deleted_sequential(self):
"""
Tests resume course when the last accessed sequential is deleted and
Tests resume course when the last completed sequential is deleted and
there is another sequential in the vertical.
"""
@@ -476,7 +451,8 @@ class TestCourseOutlineResumeCourse(SharedModuleStoreTestCase, CompletionWaffleT
self.assertGreaterEqual(len(chapter.children), 2)
sequential = chapter.children[0]
sequential2 = chapter.children[1]
self.visit_sequential(course, chapter, sequential)
self.complete_sequential(course, sequential)
self.complete_sequential(course, sequential2)
# remove one of the sequentials from the chapter
with self.store.branch_setting(ModuleStoreEnum.Branch.draft_preferred, course.id):
@@ -490,7 +466,7 @@ class TestCourseOutlineResumeCourse(SharedModuleStoreTestCase, CompletionWaffleT
def test_resume_course_deleted_sequentials(self):
"""
Tests resume course when the last accessed sequential is deleted and
Tests resume course when the last completed sequential is deleted and
there are no sequentials left in the vertical.
"""
@@ -500,7 +476,7 @@ class TestCourseOutlineResumeCourse(SharedModuleStoreTestCase, CompletionWaffleT
chapter = course.children[0]
self.assertEqual(len(chapter.children), 2)
sequential = chapter.children[0]
self.visit_sequential(course, chapter, sequential)
self.complete_sequential(course, sequential)
# remove all sequentials from chapter
with self.store.branch_setting(ModuleStoreEnum.Branch.draft_preferred, course.id):
@@ -508,22 +484,14 @@ class TestCourseOutlineResumeCourse(SharedModuleStoreTestCase, CompletionWaffleT
self.store.delete_item(sequential.location, self.user.id)
# check resume course buttons
self.visit_course_home(course, resume_count=1)
self.visit_course_home(course, start_count=1, resume_count=0)
@override_switch(
'{}.{}'.format(
waffle.WAFFLE_NAMESPACE, waffle.ENABLE_VISUAL_PROGRESS
),
active=True
)
@patch('completion.waffle.get_current_site')
def test_course_home_for_global_staff(self, get_patched_current_site):
def test_course_home_for_global_staff(self):
"""
Tests that staff user can access the course home without being enrolled
in the course.
"""
course = self.course
get_patched_current_site.return_value = self.site
self.user.is_staff = True
self.user.save()

View File

@@ -2,7 +2,6 @@
Common utilities for the course experience, including course outline.
"""
from completion.models import BlockCompletion
from completion.waffle import visual_progress_enabled
from lms.djangoapps.course_api.blocks.api import get_blocks
from lms.djangoapps.course_blocks.utils import get_student_module_as_dict
@@ -154,14 +153,11 @@ def get_course_outline_block_tree(request, course_id):
populate_children(course_outline_root_block, all_blocks['blocks'])
set_last_accessed_default(course_outline_root_block)
if visual_progress_enabled(course_key=course_key):
mark_blocks_completed(
block=course_outline_root_block,
user=request.user,
course_key=course_key
)
else:
mark_last_accessed(request.user, course_key, course_outline_root_block)
mark_blocks_completed(
block=course_outline_root_block,
user=request.user,
course_key=course_key
)
return course_outline_root_block

View File

@@ -43,18 +43,11 @@ class CourseOutlineFragmentView(EdxFragmentView):
if not course_block_tree:
return None
# TODO: EDUCATOR-2283 Remove 'show_visual_progress' from context
# and remove the check for it in the HTML file
show_visual_progress = (
completion_waffle.visual_progress_enabled(course_key) and
self.user_enrolled_after_completion_collection(request.user, course_key)
)
context = {
'csrf': csrf(request)['csrf_token'],
'course': course_overview,
'blocks': course_block_tree,
'show_visual_progress': show_visual_progress,
'due_date_display_format': course.due_date_display_format,
'blocks': course_block_tree
}
# TODO: EDUCATOR-2283 Remove this check when the waffle flag is turned on in production

View File

@@ -1,79 +0,0 @@
"""
Tests waffle mechanics and feature-gating for block completion features.
"""
from __future__ import absolute_import, unicode_literals
from completion import waffle
import ddt
from django.test import TestCase
import mock
from opaque_keys.edx.keys import CourseKey
from openedx.core.djangoapps.site_configuration.tests.factories import SiteFactory, SiteConfigurationFactory
from openedx.core.djangoapps.waffle_utils.testutils import override_waffle_flag
from openedx.core.djangolib.testing.utils import skip_unless_lms
@skip_unless_lms
@ddt.ddt
class FeatureGatingTests(TestCase):
"""
Tests the logic of the completion feature-gating functions in the LMS.
"""
def setUp(self):
self.site = SiteFactory.create()
self.site_patcher = mock.patch('completion.waffle.get_current_site')
mocked_current_site = self.site_patcher.start()
mocked_current_site.return_value = self.site
self.course_key = CourseKey.from_string('course-v1:edX+DemoX+Demo_Course')
def tearDown(self):
self.site_patcher.stop()
def _make_site_config(self, enable_feature):
site_config = SiteConfigurationFactory.create(site=self.site)
site_config.values[waffle.ENABLE_SITE_VISUAL_PROGRESS] = enable_feature
site_config.save()
def test_site_disables_visual_progress_no_config(self):
assert waffle.site_disables_visual_progress() is False
@ddt.data(True, False)
def test_site_disables_visual_progress_with_config(self, config_value):
self._make_site_config(config_value)
assert (not config_value) == waffle.site_disables_visual_progress()
def test_visual_progress_gating_tracking_disabled(self):
with waffle.waffle().override(waffle.ENABLE_COMPLETION_TRACKING, False):
assert waffle.visual_progress_enabled(self.course_key) is False
def test_visual_progress_gating_site_disabled(self):
self._make_site_config(False)
assert waffle.visual_progress_enabled(self.course_key) is False
def test_visual_progress_gating_course_disabled(self):
self._make_site_config(True)
with waffle.waffle().override(waffle.ENABLE_COMPLETION_TRACKING, True):
with waffle.waffle().override(waffle.ENABLE_VISUAL_PROGRESS, False):
with override_waffle_flag(waffle.waffle_flag(), active=False):
assert waffle.visual_progress_enabled(self.course_key) is False
def test_visual_progress_happy_path_no_site_config(self):
with waffle.waffle().override(waffle.ENABLE_COMPLETION_TRACKING, True):
with waffle.waffle().override(waffle.ENABLE_VISUAL_PROGRESS, True):
assert waffle.visual_progress_enabled(self.course_key) is True
def test_visual_progress_happy_path_with_site_config(self):
self._make_site_config(True)
with waffle.waffle().override(waffle.ENABLE_COMPLETION_TRACKING, True):
with waffle.waffle().override(waffle.ENABLE_VISUAL_PROGRESS, True):
assert waffle.visual_progress_enabled(self.course_key) is True
def test_visual_progress_happy_path_visual_switch_disabled(self):
self._make_site_config(True)
with waffle.waffle().override(waffle.ENABLE_COMPLETION_TRACKING, True):
with waffle.waffle().override(waffle.ENABLE_VISUAL_PROGRESS, False):
with override_waffle_flag(waffle.waffle_flag(), active=True):
assert waffle.visual_progress_enabled(self.course_key) is True

View File

@@ -54,7 +54,7 @@ edx-lint==0.5.4
git+https://github.com/cpennington/pylint-django@fix-field-inference-during-monkey-patching#egg=pylint-django==0.0
enum34==1.1.6
edx-completion==0.1.4
edx-completion==0.1.5
edx-django-oauth2-provider==1.2.5
edx-django-sites-extensions==2.3.1
edx-enterprise==0.67.3