Skip to content
Snippets Groups Projects
Unverified Commit 2e0ee010 authored by Sofiya Semenova's avatar Sofiya Semenova Committed by GitHub
Browse files

Merge pull request #17555 from edx/sofiya/course-outline

Auto-open first unit in course outline if user has no completion data
parents 14e462e9 774fe73c
No related branches found
No related tags found
No related merge requests found
......@@ -3,6 +3,7 @@ Tests for the Course Outline view and supporting views.
"""
import datetime
import json
import re
from completion import waffle
from completion.models import BlockCompletion
......@@ -60,8 +61,16 @@ class TestCourseOutlinePage(SharedModuleStoreTestCase):
chapter = ItemFactory.create(category='chapter', parent_location=course.location)
sequential = ItemFactory.create(category='sequential', parent_location=chapter.location)
sequential2 = ItemFactory.create(category='sequential', parent_location=chapter.location)
vertical = ItemFactory.create(category='vertical', parent_location=sequential.location)
vertical2 = ItemFactory.create(category='vertical', parent_location=sequential2.location)
vertical = ItemFactory.create(
category='vertical',
parent_location=sequential.location,
display_name="Vertical 1"
)
vertical2 = ItemFactory.create(
category='vertical',
parent_location=sequential2.location,
display_name="Vertical 2"
)
course.children = [chapter]
chapter.children = [sequential, sequential2]
sequential.children = [vertical]
......@@ -518,6 +527,40 @@ class TestCourseOutlineResumeCourse(SharedModuleStoreTestCase, CompletionWaffleT
content = pq(response.content)
self.assertTrue(content('.action-resume-course').attr('href').endswith('/course/' + course.url_name))
@override_switch(
'{}.{}'.format(
waffle.WAFFLE_NAMESPACE, waffle.ENABLE_COMPLETION_TRACKING
),
active=True
)
def test_course_outline_auto_open(self):
"""
Tests that the course outline auto-opens to the first unit
in a course if a user has no completion data, and to the
last-accessed unit if a user does have completion data.
"""
def get_sequential_button(url, is_hidden):
is_hidden_string = "is-hidden" if is_hidden else ""
return "<olclass=\"outline-itemaccordion-panel" + is_hidden_string + "\"" \
"id=\"" + url + "_contents\"" \
"role=\"region\"" \
"aria-labelledby=\"" + url + "\"" \
">"
with patch('openedx.features.course_experience.waffle.new_course_outline_enabled', Mock(return_value=True)):
# Course tree
course = self.course
chapter = course.children[0]
sequential1 = chapter.children[0]
sequential2 = chapter.children[1]
response_content = self.client.get(course_home_url(course)).content
stripped_response = text_type(re.sub("\\s+", "", response_content), "utf-8")
self.assertTrue(get_sequential_button(text_type(sequential1.location), False) in stripped_response)
self.assertTrue(get_sequential_button(text_type(sequential2.location), True) in stripped_response)
class TestCourseOutlinePreview(SharedModuleStoreTestCase):
"""
......
......@@ -162,3 +162,20 @@ def get_course_outline_block_tree(request, course_id):
else:
mark_last_accessed(request.user, course_key, course_outline_root_block)
return course_outline_root_block
def get_resume_block(block):
"""
Gets the deepest block marked as 'resume_block'.
"""
if not block['resume_block']:
return None
if not block.get('children'):
return block
for child in block['children']:
resume_block = get_resume_block(child)
if resume_block:
return resume_block
return block
......@@ -29,7 +29,7 @@ from student.models import CourseEnrollment
from util.views import ensure_valid_course_key
from .. import LATEST_UPDATE_FLAG, SHOW_UPGRADE_MSG_ON_COURSE_HOME, USE_BOOTSTRAP_FLAG
from ..utils import get_course_outline_block_tree
from ..utils import get_course_outline_block_tree, get_resume_block
from .course_dates import CourseDatesFragmentView
from .course_home_messages import CourseHomeMessageFragmentView
from .course_outline import CourseOutlineFragmentView
......@@ -81,23 +81,6 @@ class CourseHomeFragmentView(EdxFragmentView):
otherwise the URL of the course root.
"""
def get_resume_block(block):
"""
Gets the deepest block marked as 'resume_block'.
"""
if not block['resume_block']:
return None
if not block.get('children'):
return block
for child in block['children']:
resume_block = get_resume_block(child)
if resume_block:
return resume_block
return block
course_outline_root_block = get_course_outline_block_tree(request, course_id)
resume_block = get_resume_block(course_outline_root_block) if course_outline_root_block else None
has_visited_course = bool(resume_block)
......
......@@ -17,7 +17,7 @@ from openedx.features.course_experience import waffle as course_experience_waffl
from completion import waffle as completion_waffle
from student.models import CourseEnrollment
from ..utils import get_course_outline_block_tree
from ..utils import get_course_outline_block_tree, get_resume_block
from util.milestones_helpers import get_course_content_milestones
......@@ -52,8 +52,11 @@ class CourseOutlineFragmentView(EdxFragmentView):
# TODO: EDUCATOR-2283 Remove this check when the waffle flag is turned on in production
if course_experience_waffle.new_course_outline_enabled(course_key=course_key):
xblock_display_names = self.create_xblock_id_and_name_dict(course_block_tree)
resume_block = get_resume_block(course_block_tree)
if not resume_block:
self.mark_first_unit_to_resume(course_block_tree)
xblock_display_names = self.create_xblock_id_and_name_dict(course_block_tree)
gated_content = self.get_content_milestones(request, course_key)
context['gated_content'] = gated_content
......@@ -151,3 +154,9 @@ class CourseOutlineFragmentView(EdxFragmentView):
return user_enrollment.created > begin_collection_date
except CourseEnrollment.DoesNotExist:
return False
def mark_first_unit_to_resume(self, block_node):
children = block_node.get('children')
if children:
children[0]['resume_block'] = True
self.mark_first_unit_to_resume(children[0])
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment