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
9d44417c
Commit
9d44417c
authored
Jul 29, 2014
by
Ben McMorran
Committed by
cahrens
Aug 07, 2014
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add tests for course outline warning messages
Fix failing bokchoy tests
parent
2118453e
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
241 additions
and
9 deletions
+241
-9
cms/templates/js/course-outline.underscore
+3
-1
common/test/acceptance/pages/studio/container.py
+6
-2
common/test/acceptance/pages/studio/overview.py
+26
-6
common/test/acceptance/tests/test_studio_outline.py
+206
-0
No files found.
cms/templates/js/course-outline.underscore
View file @
9d44417c
...
...
@@ -14,8 +14,10 @@ if (visibilityState === 'staff_only') {
statusType = 'warning';
if (published && releasedToStudents) {
statusMessage = gettext('Unpublished changes to live content');
} else {
} else
if (!published)
{
statusMessage = gettext('Unpublished units will not be released');
} else {
statusMessage = gettext('Unpublished changes to content that will release in the future');
}
}
}
...
...
common/test/acceptance/pages/studio/container.py
View file @
9d44417c
...
...
@@ -139,14 +139,18 @@ class ContainerPage(PageObject):
confirm_prompt
(
self
)
self
.
wait_for_ajax
()
@property
def
is_staff_locked
(
self
):
""" Returns True if staff lock is currently enabled, False otherwise """
return
'icon-check'
in
self
.
q
(
css
=
'a.action-staff-lock>i'
)
.
attrs
(
'class'
)
def
toggle_staff_lock
(
self
):
"""
Toggles "hide from students" which enables or disables a staff-only lock.
Returns True if the lock is now enabled, else False.
"""
class_attribute_values
=
self
.
q
(
css
=
'a.action-staff-lock>i'
)
.
attrs
(
'class'
)
was_locked_initially
=
'icon-check'
in
class_attribute_values
was_locked_initially
=
self
.
is_staff_locked
if
not
was_locked_initially
:
self
.
q
(
css
=
'a.action-staff-lock'
)
.
first
.
click
()
else
:
...
...
common/test/acceptance/pages/studio/overview.py
View file @
9d44417c
...
...
@@ -18,6 +18,7 @@ class CourseOutlineItem(object):
NAME_SELECTOR
=
'.xblock-title .xblock-field-value'
NAME_INPUT_SELECTOR
=
'.xblock-field-input'
NAME_FIELD_WRAPPER_SELECTOR
=
'.xblock-title .wrapper-xblock-field'
STATUS_MESSAGE_SELECTOR
=
'> div[class$="status"] .status-message'
def
__repr__
(
self
):
# CourseOutlineItem is also used as a mixin for CourseOutlinePage, which doesn't have a locator
...
...
@@ -29,11 +30,16 @@ class CourseOutlineItem(object):
"""
Returns `selector`, but limited to this particular `CourseOutlineItem` context
"""
return
'{}[data-locator="{}"] {}'
.
format
(
self
.
BODY_SELECTOR
,
self
.
locator
,
selector
)
# If the item doesn't have a body selector or locator, then it can't be bounded
# This happens in the context of the CourseOutlinePage
if
self
.
BODY_SELECTOR
and
hasattr
(
self
,
'locator'
):
return
'{}[data-locator="{}"] {}'
.
format
(
self
.
BODY_SELECTOR
,
self
.
locator
,
selector
)
else
:
return
selector
@property
def
name
(
self
):
...
...
@@ -46,6 +52,20 @@ class CourseOutlineItem(object):
else
:
return
None
@property
def
has_status_message
(
self
):
"""
Returns True if the item has a status message, False otherwise.
"""
return
self
.
q
(
css
=
self
.
_bounded_selector
(
self
.
STATUS_MESSAGE_SELECTOR
))
.
first
.
visible
@property
def
status_message
(
self
):
"""
Returns the status message of this item.
"""
return
self
.
q
(
css
=
self
.
_bounded_selector
(
self
.
STATUS_MESSAGE_SELECTOR
))
.
text
[
0
]
def
edit_name
(
self
):
"""
Puts the item's name into editable form.
...
...
@@ -106,7 +126,7 @@ class CourseOutlineContainer(CourseOutlineItem):
"""
if
not
child_class
:
child_class
=
self
.
CHILD_CLASS
return
self
.
q
(
css
=
child_class
.
BODY_SELECTOR
)
.
map
(
return
self
.
q
(
css
=
self
.
_bounded_selector
(
child_class
.
BODY_SELECTOR
)
)
.
map
(
lambda
el
:
child_class
(
self
.
browser
,
el
.
get_attribute
(
'data-locator'
)))
.
results
def
child_at
(
self
,
index
,
child_class
=
None
):
...
...
common/test/acceptance/tests/test_studio_outline.py
View file @
9d44417c
...
...
@@ -2,9 +2,13 @@
Acceptance tests for studio related to the outline page.
"""
from
datetime
import
datetime
,
timedelta
import
itertools
from
pytz
import
UTC
from
bok_choy.promise
import
EmptyPromise
from
..pages.studio.overview
import
CourseOutlinePage
,
ContainerPage
,
ExpandCollapseLinkState
from
..pages.studio.utils
import
add_discussion
from
..pages.lms.courseware
import
CoursewarePage
from
..fixtures.course
import
XBlockFixtureDesc
...
...
@@ -41,6 +45,208 @@ class CourseOutlineTest(StudioCourseTest):
)
class
WarningMessagesTest
(
CourseOutlineTest
):
"""
Feature: Warning messages on sections, subsections, and units
"""
__test__
=
True
STAFF_ONLY_WARNING
=
'Contains staff only content'
LIVE_UNPUBLISHED_WARNING
=
'Unpublished changes to live content'
FUTURE_UNPUBLISHED_WARNING
=
'Unpublished changes to content that will release in the future'
NEVER_PUBLISHED_WARNING
=
'Unpublished units will not be released'
class
PublishState
:
NEVER_PUBLISHED
=
1
UNPUBLISHED_CHANGES
=
2
PUBLISHED
=
3
VALUES
=
[
NEVER_PUBLISHED
,
UNPUBLISHED_CHANGES
,
PUBLISHED
]
class
UnitState
:
""" Represents the state of a unit """
def
__init__
(
self
,
is_released
,
publish_state
,
is_locked
):
""" Creates a new UnitState with the given properties """
self
.
is_released
=
is_released
self
.
publish_state
=
publish_state
self
.
is_locked
=
is_locked
@property
def
name
(
self
):
""" Returns an appropriate name based on the properties of the unit """
result
=
"Released "
if
self
.
is_released
else
"Unreleased "
if
self
.
publish_state
==
WarningMessagesTest
.
PublishState
.
NEVER_PUBLISHED
:
result
+=
"Never Published "
elif
self
.
publish_state
==
WarningMessagesTest
.
PublishState
.
UNPUBLISHED_CHANGES
:
result
+=
"Unpublished Changes "
else
:
result
+=
"Published "
result
+=
"Locked"
if
self
.
is_locked
else
"Unlocked"
return
result
def
populate_course_fixture
(
self
,
course_fixture
):
""" Install a course with various configurations that could produce warning messages """
# Define the dimensions that map to the UnitState constructor
features
=
[
[
True
,
False
],
# Possible values for is_released
self
.
PublishState
.
VALUES
,
# Possible values for publish_state
[
True
,
False
]
# Possible values for is_locked
]
# Add a fixture for every state in the product of features
course_fixture
.
add_children
(
*
[
self
.
_build_fixture
(
self
.
UnitState
(
*
state
))
for
state
in
itertools
.
product
(
*
features
)
])
def
_build_fixture
(
self
,
unit_state
):
""" Returns an XBlockFixtureDesc with a section, subsection, and possibly unit that has the given state. """
name
=
unit_state
.
name
start
=
(
datetime
(
1984
,
3
,
4
)
if
unit_state
.
is_released
else
datetime
.
now
(
UTC
)
+
timedelta
(
1
))
.
isoformat
()
subsection
=
XBlockFixtureDesc
(
'sequential'
,
name
,
metadata
=
{
'start'
:
start
})
# Children of never published subsections will be added on demand via _ensure_unit_present
return
XBlockFixtureDesc
(
'chapter'
,
name
)
.
add_children
(
subsection
if
unit_state
.
publish_state
==
self
.
PublishState
.
NEVER_PUBLISHED
else
subsection
.
add_children
(
XBlockFixtureDesc
(
'vertical'
,
name
,
metadata
=
{
'visible_to_staff_only'
:
unit_state
.
is_locked
})
)
)
def
test_released_never_published_locked
(
self
):
""" Tests that released never published locked units display staff only warnings """
self
.
_verify_unit_warning
(
self
.
UnitState
(
is_released
=
True
,
publish_state
=
self
.
PublishState
.
NEVER_PUBLISHED
,
is_locked
=
True
),
self
.
STAFF_ONLY_WARNING
)
def
test_released_never_published_unlocked
(
self
):
""" Tests that released never published unlocked units display 'Unpublished units will not be released' """
self
.
_verify_unit_warning
(
self
.
UnitState
(
is_released
=
True
,
publish_state
=
self
.
PublishState
.
NEVER_PUBLISHED
,
is_locked
=
False
),
self
.
NEVER_PUBLISHED_WARNING
)
def
test_released_unpublished_changes_locked
(
self
):
""" Tests that released unpublished changes locked units display staff only warnings """
self
.
_verify_unit_warning
(
self
.
UnitState
(
is_released
=
True
,
publish_state
=
self
.
PublishState
.
UNPUBLISHED_CHANGES
,
is_locked
=
True
),
self
.
STAFF_ONLY_WARNING
)
def
test_released_unpublished_changes_unlocked
(
self
):
""" Tests that released unpublished changes unlocked units display 'Unpublished changes to live content' """
self
.
_verify_unit_warning
(
self
.
UnitState
(
is_released
=
True
,
publish_state
=
self
.
PublishState
.
UNPUBLISHED_CHANGES
,
is_locked
=
False
),
self
.
LIVE_UNPUBLISHED_WARNING
)
def
test_released_published_locked
(
self
):
""" Tests that released published locked units display staff only warnings """
self
.
_verify_unit_warning
(
self
.
UnitState
(
is_released
=
True
,
publish_state
=
self
.
PublishState
.
PUBLISHED
,
is_locked
=
True
),
self
.
STAFF_ONLY_WARNING
)
def
test_released_published_unlocked
(
self
):
""" Tests that released published unlocked units display no warnings """
self
.
_verify_unit_warning
(
self
.
UnitState
(
is_released
=
True
,
publish_state
=
self
.
PublishState
.
PUBLISHED
,
is_locked
=
False
),
None
)
def
test_unreleased_never_published_locked
(
self
):
""" Tests that unreleased never published locked units display staff only warnings """
self
.
_verify_unit_warning
(
self
.
UnitState
(
is_released
=
False
,
publish_state
=
self
.
PublishState
.
NEVER_PUBLISHED
,
is_locked
=
True
),
self
.
STAFF_ONLY_WARNING
)
def
test_unreleased_never_published_unlocked
(
self
):
""" Tests that unreleased never published unlocked units display 'Unpublished units will not be released' """
self
.
_verify_unit_warning
(
self
.
UnitState
(
is_released
=
False
,
publish_state
=
self
.
PublishState
.
NEVER_PUBLISHED
,
is_locked
=
False
),
self
.
NEVER_PUBLISHED_WARNING
)
def
test_unreleased_unpublished_changes_locked
(
self
):
""" Tests that unreleased unpublished changes locked units display staff only warnings """
self
.
_verify_unit_warning
(
self
.
UnitState
(
is_released
=
False
,
publish_state
=
self
.
PublishState
.
UNPUBLISHED_CHANGES
,
is_locked
=
True
),
self
.
STAFF_ONLY_WARNING
)
def
test_unreleased_unpublished_changes_unlocked
(
self
):
"""
Tests that unreleased unpublished changes unlocked units display 'Unpublished changes to content that will
release in the future'
"""
self
.
_verify_unit_warning
(
self
.
UnitState
(
is_released
=
False
,
publish_state
=
self
.
PublishState
.
UNPUBLISHED_CHANGES
,
is_locked
=
False
),
self
.
FUTURE_UNPUBLISHED_WARNING
)
def
test_unreleased_published_locked
(
self
):
""" Tests that unreleased published locked units display staff only warnings """
self
.
_verify_unit_warning
(
self
.
UnitState
(
is_released
=
False
,
publish_state
=
self
.
PublishState
.
PUBLISHED
,
is_locked
=
True
),
self
.
STAFF_ONLY_WARNING
)
def
test_unreleased_published_unlocked
(
self
):
""" Tests that unreleased published unlocked units display no warnings """
self
.
_verify_unit_warning
(
self
.
UnitState
(
is_released
=
False
,
publish_state
=
self
.
PublishState
.
PUBLISHED
,
is_locked
=
False
),
None
)
def
_verify_unit_warning
(
self
,
unit_state
,
expected_status_message
):
"""
Verifies that the given unit's messages match the expected messages.
If expected_status_message is None, then the unit status message is expected to not be present.
"""
self
.
_ensure_unit_present
(
unit_state
)
self
.
course_outline_page
.
visit
()
section
=
self
.
course_outline_page
.
section
(
unit_state
.
name
)
subsection
=
section
.
subsection_at
(
0
)
subsection
.
toggle_expand
()
unit
=
subsection
.
unit_at
(
0
)
if
expected_status_message
==
self
.
STAFF_ONLY_WARNING
:
self
.
assertEqual
(
section
.
status_message
,
self
.
STAFF_ONLY_WARNING
)
self
.
assertEqual
(
subsection
.
status_message
,
self
.
STAFF_ONLY_WARNING
)
self
.
assertEqual
(
unit
.
status_message
,
self
.
STAFF_ONLY_WARNING
)
else
:
self
.
assertFalse
(
section
.
has_status_message
)
self
.
assertFalse
(
subsection
.
has_status_message
)
if
expected_status_message
:
self
.
assertEqual
(
unit
.
status_message
,
expected_status_message
)
else
:
self
.
assertFalse
(
unit
.
has_status_message
)
def
_ensure_unit_present
(
self
,
unit_state
):
""" Ensures that a unit with the given state is present on the course outline """
if
unit_state
.
publish_state
==
self
.
PublishState
.
PUBLISHED
:
return
name
=
unit_state
.
name
self
.
course_outline_page
.
visit
()
subsection
=
self
.
course_outline_page
.
section
(
name
)
.
subsection
(
name
)
subsection
.
toggle_expand
()
if
unit_state
.
publish_state
==
self
.
PublishState
.
UNPUBLISHED_CHANGES
:
unit
=
subsection
.
unit
(
name
)
.
go_to
()
add_discussion
(
unit
)
elif
unit_state
.
publish_state
==
self
.
PublishState
.
NEVER_PUBLISHED
:
subsection
.
add_unit
()
unit
=
ContainerPage
(
self
.
browser
,
None
)
unit
.
wait_for_page
()
if
unit
.
is_staff_locked
!=
unit_state
.
is_locked
:
unit
.
toggle_staff_lock
()
class
EditNamesTest
(
CourseOutlineTest
):
"""
Feature: Click-to-edit section/subsection names
...
...
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