Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-platform
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
edx-platform
Commits
0899ac56
Commit
0899ac56
authored
Apr 12, 2017
by
Robert Raposa
Committed by
Diana Huang
Apr 13, 2017
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fix review comments.
parent
69ba8eb0
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
61 additions
and
65 deletions
+61
-65
common/test/acceptance/tests/lms/test_lms_course_home.py
+3
-24
lms/djangoapps/course_api/blocks/transformers/milestones.py
+57
-41
openedx/features/course_experience/templates/course_experience/course-outline-fragment.html
+1
-0
No files found.
common/test/acceptance/tests/lms/test_lms_course_home.py
View file @
0899ac56
...
...
@@ -7,11 +7,9 @@ from nose.plugins.attrib import attr
from
..helpers
import
auto_auth
,
load_data_str
,
UniqueCourseTest
from
...fixtures.course
import
CourseFixture
,
XBlockFixtureDesc
from
...pages.common.logout
import
LogoutPage
from
...pages.lms.bookmarks
import
BookmarksPage
from
...pages.lms.course_home
import
CourseHomePage
from
...pages.lms.courseware
import
CoursewarePage
from
...pages.studio.overview
import
CourseOutlinePage
as
StudioCourseOutlinePage
class
CourseHomeBaseTest
(
UniqueCourseTest
):
...
...
@@ -132,29 +130,10 @@ class CourseHomeA11yTest(CourseHomeBaseTest):
def
setUp
(
self
):
super
(
CourseHomeA11yTest
,
self
)
.
setUp
()
self
.
logout_page
=
LogoutPage
(
self
.
browser
)
def
test_course_home_a11y
(
self
):
"""
Test the accessibility of the course home page with course outline.
"""
with
self
.
_logged_in_session
():
course_home_page
=
CourseHomePage
(
self
.
browser
,
self
.
course_id
)
course_home_page
.
visit
()
course_home_page
.
a11y_audit
.
check_for_accessibility_errors
()
@contextmanager
def
_logged_in_session
(
self
,
staff
=
False
):
"""
Ensure that the user is logged in and out appropriately at the beginning
and end of the current test.
"""
self
.
logout_page
.
visit
()
try
:
if
staff
:
auto_auth
(
self
.
browser
,
"STAFF_TESTER"
,
"staff101@example.com"
,
True
,
self
.
course_id
)
else
:
auto_auth
(
self
.
browser
,
self
.
USERNAME
,
self
.
EMAIL
,
False
,
self
.
course_id
)
yield
finally
:
self
.
logout_page
.
visit
()
course_home_page
=
CourseHomePage
(
self
.
browser
,
self
.
course_id
)
course_home_page
.
visit
()
course_home_page
.
a11y_audit
.
check_for_accessibility_errors
()
lms/djangoapps/course_api/blocks/transformers/milestones.py
View file @
0899ac56
...
...
@@ -19,9 +19,14 @@ log = logging.getLogger(__name__)
class
MilestonesTransformer
(
BlockStructureTransformer
):
"""
Adds special exams (timed, proctored, practice proctored) to the student view.
May exclude special exams.
Excludes all blocks with unfulfilled milestones from the student view.
A transformer that handles both milestones and special (timed) exams.
It excludes all blocks with unfulfilled milestones from the student view. An entrance exam is considered a
milestone, and is not considered a "special exam".
It also includes or excludes all special (timed) exams (timed, proctored, practice proctored) in/from the
student view, based on the value of `include_special_exams`.
"""
WRITE_VERSION
=
1
READ_VERSION
=
1
...
...
@@ -51,21 +56,19 @@ class MilestonesTransformer(BlockStructureTransformer):
"""
Modify block structure according to the behavior of milestones and special exams.
"""
course_key
=
block_structure
.
root_block_usage_key
.
course_key
user_can_skip
=
EntranceExamConfiguration
.
user_can_skip_entrance_exam
(
usage_info
.
user
,
course_key
)
required_content
=
milestones_helpers
.
get_required_content
(
course_key
,
usage_info
.
user
)
required_content
=
self
.
get_required_content
(
usage_info
,
block_structure
)
def
user_gated_from_block
(
block_key
):
"""
Checks whether the user is gated from accessing this block, first via special exams,
then via a general milestones check.
"""
if
usage_info
.
has_staff_access
:
return
False
elif
self
.
has_pending_milestones_for_user
(
block_key
,
usage_info
):
return
True
elif
self
.
gated_by_required_content
(
block_key
,
block_structure
,
user_can_skip
,
required_content
):
elif
self
.
gated_by_required_content
(
block_key
,
block_structure
,
required_content
):
return
True
elif
(
settings
.
FEATURES
.
get
(
'ENABLE_SPECIAL_EXAMS'
,
False
)
and
(
self
.
is_special_exam
(
block_key
,
block_structure
)
and
...
...
@@ -76,14 +79,13 @@ class MilestonesTransformer(BlockStructureTransformer):
for
block_key
in
block_structure
.
topological_traversal
():
if
user_gated_from_block
(
block_key
):
block_structure
.
remove_block
(
block_key
,
False
)
el
se
:
el
if
self
.
is_special_exam
(
block_key
,
block_structure
)
:
self
.
add_special_exam_info
(
block_key
,
block_structure
,
usage_info
)
@staticmethod
def
is_special_exam
(
block_key
,
block_structure
):
"""
Test whether the block is a special exam. These exams are always excluded
from the student view.
Test whether the block is a special exam.
"""
return
(
block_structure
.
get_xblock_field
(
block_key
,
'is_proctored_enabled'
)
or
...
...
@@ -106,45 +108,59 @@ class MilestonesTransformer(BlockStructureTransformer):
def
add_special_exam_info
(
self
,
block_key
,
block_structure
,
usage_info
):
"""
Adds special exam information to course blocks.
For special exams, add the special exam information to the course blocks.
"""
special_exam_attempt_context
=
None
try
:
# Calls into edx_proctoring subsystem to get relevant special exam information.
# This will return None, if (user, course_id, content_id) is not applicable.
special_exam_attempt_context
=
get_attempt_status_summary
(
usage_info
.
user
.
id
,
unicode
(
block_key
.
course_key
),
unicode
(
block_key
)
)
except
ProctoredExamNotFoundException
as
ex
:
log
.
exception
(
ex
)
if
special_exam_attempt_context
:
# This user has special exam context for this block so add it.
block_structure
.
set_transformer_block_field
(
block_key
,
self
,
'special_exam_info'
,
special_exam_attempt_context
,
)
@staticmethod
def
get_required_content
(
usage_info
,
block_structure
):
"""
if
self
.
is_special_exam
(
block_key
,
block_structure
):
# call into edx_proctoring subsystem to get relevant special exam information
#
# This will return None, if (user, course_id, content_id) is not applicable
special_exam_attempt_context
=
None
try
:
special_exam_attempt_context
=
get_attempt_status_summary
(
usage_info
.
user
.
id
,
unicode
(
block_key
.
course_key
),
unicode
(
block_key
)
)
except
ProctoredExamNotFoundException
as
ex
:
log
.
exception
(
ex
)
if
special_exam_attempt_context
:
# yes, user has proctoring context about
# this level of the courseware
# so add to the accordion data context
block_structure
.
set_transformer_block_field
(
block_key
,
self
,
'special_exam_info'
,
special_exam_attempt_context
,
)
Get the required content for the course.
This takes into account if the user can skip the entrance exam.
"""
course_key
=
block_structure
.
root_block_usage_key
.
course_key
user_can_skip_entrance_exam
=
EntranceExamConfiguration
.
user_can_skip_entrance_exam
(
usage_info
.
user
,
course_key
)
required_content
=
milestones_helpers
.
get_required_content
(
course_key
,
usage_info
.
user
)
if
not
required_content
:
return
required_content
if
user_can_skip_entrance_exam
:
# remove the entrance exam from required content
entrance_exam_id
=
block_structure
.
get_xblock_field
(
block_structure
.
root_block_usage_key
,
'entrance_exam_id'
)
required_content
=
[
content
for
content
in
required_content
if
not
content
==
entrance_exam_id
]
return
required_content
@staticmethod
def
gated_by_required_content
(
block_key
,
block_structure
,
user_can_skip
,
required_content
):
def
gated_by_required_content
(
block_key
,
block_structure
,
required_content
):
"""
Returns True if the current block associated with the block_key should be gated by the given required_content.
Returns False otherwise.
"""
if
not
required_content
:
return
False
exam_id
=
block_structure
.
get_xblock_field
(
block_structure
.
root_block_usage_key
,
'entrance_exam_id'
)
if
user_can_skip
:
required_content
=
[
content
for
content
in
required_content
if
not
content
==
exam_id
]
if
block_key
.
block_type
==
'chapter'
and
unicode
(
block_key
)
not
in
required_content
:
return
True
...
...
openedx/features/course_experience/templates/course_experience/course-outline-fragment.html
View file @
0899ac56
...
...
@@ -49,6 +49,7 @@ from django.utils.translation import ugettext as _
## Exam subsections expose exam status message field as well as a status icon
<
%
if
subsection
.
get
('
due
')
is
None:
#
examples:
Homework
,
Lab
,
etc
.
data_string =
subsection.get('format')
else:
if
'
special_exam_info
'
in
subsection:
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment