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
f31475a2
Commit
f31475a2
authored
Jul 21, 2014
by
Ben McMorran
Committed by
cahrens
Aug 07, 2014
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add bokchoy tests for outline page
parent
327a97f7
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
813 additions
and
130 deletions
+813
-130
cms/static/js/views/course_outline.js
+1
-0
cms/static/js/views/pages/container.js
+1
-1
cms/static/js/views/xblock_outline.js
+1
-1
common/test/acceptance/pages/studio/container.py
+12
-12
common/test/acceptance/pages/studio/overview.py
+173
-25
common/test/acceptance/pages/studio/utils.py
+11
-0
common/test/acceptance/tests/test_studio_container.py
+22
-24
common/test/acceptance/tests/test_studio_general.py
+0
-51
common/test/acceptance/tests/test_studio_outline.py
+574
-0
common/test/acceptance/tests/test_studio_split_test.py
+18
-16
No files found.
cms/static/js/views/course_outline.js
View file @
f31475a2
...
@@ -125,6 +125,7 @@ define(["jquery", "underscore", "js/views/xblock_outline", "js/views/utils/view_
...
@@ -125,6 +125,7 @@ define(["jquery", "underscore", "js/views/xblock_outline", "js/views/utils/view_
// as it cannot visually effect the other sections.
// as it cannot visually effect the other sections.
if
(
childCategory
===
'chapter'
&&
children
&&
children
.
length
>
1
)
{
if
(
childCategory
===
'chapter'
&&
children
&&
children
.
length
>
1
)
{
childView
.
$el
.
remove
();
childView
.
$el
.
remove
();
children
.
splice
(
children
.
indexOf
(
childView
.
model
),
1
);
}
else
{
}
else
{
this
.
refresh
();
this
.
refresh
();
}
}
...
...
cms/static/js/views/pages/container.js
View file @
f31475a2
...
@@ -22,7 +22,7 @@ define(["jquery", "underscore", "gettext", "js/views/pages/base_page", "js/views
...
@@ -22,7 +22,7 @@ define(["jquery", "underscore", "gettext", "js/views/pages/base_page", "js/views
});
});
this
.
nameEditor
.
render
();
this
.
nameEditor
.
render
();
if
(
this
.
options
.
action
===
'new'
)
{
if
(
this
.
options
.
action
===
'new'
)
{
this
.
nameEditor
.
$
(
'.xblock-field-value'
).
click
();
this
.
nameEditor
.
$
(
'.xblock-field-value
-edit
'
).
click
();
}
}
this
.
xblockView
=
new
ContainerView
({
this
.
xblockView
=
new
ContainerView
({
el
:
this
.
$
(
'.wrapper-xblock'
),
el
:
this
.
$
(
'.wrapper-xblock'
),
...
...
cms/static/js/views/xblock_outline.js
View file @
f31475a2
...
@@ -194,7 +194,7 @@ define(["jquery", "underscore", "gettext", "js/views/baseview", "js/views/utils/
...
@@ -194,7 +194,7 @@ define(["jquery", "underscore", "gettext", "js/views/baseview", "js/views/utils/
}
}
ViewUtils
.
setScrollOffset
(
locatorElement
,
scrollOffset
);
ViewUtils
.
setScrollOffset
(
locatorElement
,
scrollOffset
);
if
(
editDisplayName
)
{
if
(
editDisplayName
)
{
locatorElement
.
find
(
'> .wrapper-xblock-header .xblock-field-value'
).
click
();
locatorElement
.
find
(
'> .wrapper-xblock-header .xblock-field-value
-edit
'
).
click
();
}
}
}
}
this
.
initialState
=
null
;
this
.
initialState
=
null
;
...
...
common/test/acceptance/pages/studio/container.py
View file @
f31475a2
...
@@ -8,7 +8,7 @@ from . import BASE_URL
...
@@ -8,7 +8,7 @@ from . import BASE_URL
from
selenium.webdriver.common.action_chains
import
ActionChains
from
selenium.webdriver.common.action_chains
import
ActionChains
from
utils
import
click_css
,
wait_for_notification
from
utils
import
click_css
,
wait_for_notification
,
confirm_prompt
class
ContainerPage
(
PageObject
):
class
ContainerPage
(
PageObject
):
...
@@ -16,6 +16,8 @@ class ContainerPage(PageObject):
...
@@ -16,6 +16,8 @@ class ContainerPage(PageObject):
Container page in Studio
Container page in Studio
"""
"""
NAME_SELECTOR
=
'.page-header-title'
NAME_SELECTOR
=
'.page-header-title'
NAME_INPUT_SELECTOR
=
'.page-header .xblock-field-input'
NAME_FIELD_WRAPPER_SELECTOR
=
'.page-header .wrapper-xblock-field'
def
__init__
(
self
,
browser
,
locator
):
def
__init__
(
self
,
browser
,
locator
):
super
(
ContainerPage
,
self
)
.
__init__
(
browser
)
super
(
ContainerPage
,
self
)
.
__init__
(
browser
)
...
@@ -134,7 +136,7 @@ class ContainerPage(PageObject):
...
@@ -134,7 +136,7 @@ class ContainerPage(PageObject):
Discards draft changes (which will then re-render the page).
Discards draft changes (which will then re-render the page).
"""
"""
click_css
(
self
,
'a.action-discard'
,
0
,
require_notification
=
False
)
click_css
(
self
,
'a.action-discard'
,
0
,
require_notification
=
False
)
self
.
q
(
css
=
'a.button.action-primary'
)
.
first
.
click
(
)
confirm_prompt
(
self
)
self
.
wait_for_ajax
()
self
.
wait_for_ajax
()
def
toggle_staff_lock
(
self
):
def
toggle_staff_lock
(
self
):
...
@@ -149,7 +151,7 @@ class ContainerPage(PageObject):
...
@@ -149,7 +151,7 @@ class ContainerPage(PageObject):
self
.
q
(
css
=
'a.action-staff-lock'
)
.
first
.
click
()
self
.
q
(
css
=
'a.action-staff-lock'
)
.
first
.
click
()
else
:
else
:
click_css
(
self
,
'a.action-staff-lock'
,
0
,
require_notification
=
False
)
click_css
(
self
,
'a.action-staff-lock'
,
0
,
require_notification
=
False
)
self
.
q
(
css
=
'a.button.action-primary'
)
.
first
.
click
(
)
confirm_prompt
(
self
)
self
.
wait_for_ajax
()
self
.
wait_for_ajax
()
return
not
was_locked_initially
return
not
was_locked_initially
...
@@ -218,16 +220,8 @@ class ContainerPage(PageObject):
...
@@ -218,16 +220,8 @@ class ContainerPage(PageObject):
"""
"""
# Click the delete button
# Click the delete button
click_css
(
self
,
'a.delete-button'
,
source_index
,
require_notification
=
False
)
click_css
(
self
,
'a.delete-button'
,
source_index
,
require_notification
=
False
)
# Wait for the warning prompt to appear
self
.
wait_for_element_visibility
(
'#prompt-warning'
,
'Deletion warning prompt is visible'
)
# Make sure the delete button is there
confirmation_button_css
=
'#prompt-warning a.button.action-primary'
self
.
wait_for_element_visibility
(
confirmation_button_css
,
'Confirmation dialog button is visible'
)
# Click the confirmation dialog button
# Click the confirmation dialog button
c
lick_css
(
self
,
confirmation_button_css
,
0
)
c
onfirm_prompt
(
self
)
def
edit
(
self
):
def
edit
(
self
):
"""
"""
...
@@ -255,6 +249,12 @@ class ContainerPage(PageObject):
...
@@ -255,6 +249,12 @@ class ContainerPage(PageObject):
"""
"""
return
self
.
q
(
css
=
".xblock-message.information"
)
.
first
.
text
[
0
]
return
self
.
q
(
css
=
".xblock-message.information"
)
.
first
.
text
[
0
]
def
is_inline_editing_display_name
(
self
):
"""
Return whether this container's display name is in its editable form.
"""
return
"is-editing"
in
self
.
q
(
css
=
self
.
NAME_FIELD_WRAPPER_SELECTOR
)
.
first
.
attrs
(
"class"
)[
0
]
class
XBlockWrapper
(
PageObject
):
class
XBlockWrapper
(
PageObject
):
"""
"""
...
...
common/test/acceptance/pages/studio/overview.py
View file @
f31475a2
...
@@ -6,7 +6,7 @@ from bok_choy.promise import EmptyPromise
...
@@ -6,7 +6,7 @@ from bok_choy.promise import EmptyPromise
from
.course_page
import
CoursePage
from
.course_page
import
CoursePage
from
.container
import
ContainerPage
from
.container
import
ContainerPage
from
.utils
import
set_input_value_and_save
from
.utils
import
set_input_value_and_save
,
click_css
,
confirm_prompt
class
CourseOutlineItem
(
object
):
class
CourseOutlineItem
(
object
):
...
@@ -17,9 +17,13 @@ class CourseOutlineItem(object):
...
@@ -17,9 +17,13 @@ class CourseOutlineItem(object):
EDIT_BUTTON_SELECTOR
=
'.xblock-title .xblock-field-value-edit'
EDIT_BUTTON_SELECTOR
=
'.xblock-title .xblock-field-value-edit'
NAME_SELECTOR
=
'.xblock-title .xblock-field-value'
NAME_SELECTOR
=
'.xblock-title .xblock-field-value'
NAME_INPUT_SELECTOR
=
'.xblock-title .xblock-field-input'
NAME_INPUT_SELECTOR
=
'.xblock-title .xblock-field-input'
NAME_FIELD_WRAPPER_SELECTOR
=
'.xblock-title .wrapper-xblock-field'
def
__repr__
(
self
):
def
__repr__
(
self
):
return
"{}(<browser>, {!r})"
.
format
(
self
.
__class__
.
__name__
,
self
.
locator
)
# CourseOutlineItem is also used as a mixin for CourseOutlinePage, which doesn't have a locator
# Check for the existence of a locator so that errors when navigating to the course outline page don't show up
# as errors in the repr method instead.
return
"{}(<browser>, {!r})"
.
format
(
self
.
__class__
.
__name__
,
self
.
locator
if
hasattr
(
self
,
'locator'
)
else
None
)
def
_bounded_selector
(
self
,
selector
):
def
_bounded_selector
(
self
,
selector
):
"""
"""
...
@@ -50,6 +54,14 @@ class CourseOutlineItem(object):
...
@@ -50,6 +54,14 @@ class CourseOutlineItem(object):
set_input_value_and_save
(
self
,
self
.
_bounded_selector
(
self
.
NAME_INPUT_SELECTOR
),
new_name
)
set_input_value_and_save
(
self
,
self
.
_bounded_selector
(
self
.
NAME_INPUT_SELECTOR
),
new_name
)
self
.
wait_for_ajax
()
self
.
wait_for_ajax
()
def
in_editable_form
(
self
):
"""
Return whether this outline item's display name is in its editable form.
"""
return
"is-editing"
in
self
.
q
(
css
=
self
.
_bounded_selector
(
self
.
NAME_FIELD_WRAPPER_SELECTOR
)
)[
0
]
.
get_attribute
(
"class"
)
class
CourseOutlineContainer
(
CourseOutlineItem
):
class
CourseOutlineContainer
(
CourseOutlineItem
):
"""
"""
...
@@ -76,6 +88,15 @@ class CourseOutlineContainer(CourseOutlineItem):
...
@@ -76,6 +88,15 @@ class CourseOutlineContainer(CourseOutlineItem):
)
.
attrs
(
'data-locator'
)[
0
]
)
.
attrs
(
'data-locator'
)[
0
]
)
)
def
children
(
self
,
child_class
=
None
):
"""
Returns all the children page objects of class child_class.
"""
if
not
child_class
:
child_class
=
self
.
CHILD_CLASS
return
self
.
q
(
css
=
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
):
def
child_at
(
self
,
index
,
child_class
=
None
):
"""
"""
Returns the child at the specified index.
Returns the child at the specified index.
...
@@ -84,11 +105,47 @@ class CourseOutlineContainer(CourseOutlineItem):
...
@@ -84,11 +105,47 @@ class CourseOutlineContainer(CourseOutlineItem):
if
not
child_class
:
if
not
child_class
:
child_class
=
self
.
CHILD_CLASS
child_class
=
self
.
CHILD_CLASS
return
child_class
(
return
self
.
children
(
child_class
)[
index
]
self
.
browser
,
self
.
q
(
css
=
child_class
.
BODY_SELECTOR
)
.
attrs
(
'data-locator'
)[
index
]
def
add_child
(
self
,
require_notification
=
True
):
"""
Adds a child to this xblock, waiting for notifications.
"""
click_css
(
self
,
self
.
_bounded_selector
(
".add-xblock-component a.add-button"
),
require_notification
=
require_notification
,
)
)
def
toggle_expand
(
self
):
"""
Toggle the expansion of this subsection.
"""
self
.
browser
.
execute_script
(
"jQuery.fx.off = true;"
)
def
subsection_expanded
():
add_button
=
self
.
q
(
css
=
self
.
_bounded_selector
(
'> .add-xblock-component a.add-button'
))
.
first
.
results
return
add_button
and
add_button
[
0
]
.
is_displayed
()
currently_expanded
=
subsection_expanded
()
self
.
q
(
css
=
self
.
_bounded_selector
(
'.ui-toggle-expansion'
))
.
first
.
click
()
EmptyPromise
(
lambda
:
subsection_expanded
()
!=
currently_expanded
,
"Check that the container {} has been toggled"
.
format
(
self
.
locator
)
)
.
fulfill
()
return
self
@property
def
is_collapsed
(
self
):
"""
Return whether this outline item is currently collapsed.
"""
return
"collapsed"
in
self
.
q
(
css
=
self
.
_bounded_selector
(
''
))
.
first
.
attrs
(
"class"
)[
0
]
class
CourseOutlineChild
(
PageObject
,
CourseOutlineItem
):
class
CourseOutlineChild
(
PageObject
,
CourseOutlineItem
):
"""
"""
...
@@ -101,10 +158,17 @@ class CourseOutlineChild(PageObject, CourseOutlineItem):
...
@@ -101,10 +158,17 @@ class CourseOutlineChild(PageObject, CourseOutlineItem):
def
is_browser_on_page
(
self
):
def
is_browser_on_page
(
self
):
return
self
.
q
(
css
=
'{}[data-locator="{}"]'
.
format
(
self
.
BODY_SELECTOR
,
self
.
locator
))
.
present
return
self
.
q
(
css
=
'{}[data-locator="{}"]'
.
format
(
self
.
BODY_SELECTOR
,
self
.
locator
))
.
present
def
delete
(
self
,
cancel
=
False
):
"""
Clicks the delete button, then cancels at the confirmation prompt if cancel is True.
"""
click_css
(
self
,
self
.
_bounded_selector
(
'.delete-button'
),
require_notification
=
False
)
confirm_prompt
(
self
,
cancel
)
class
CourseOutlineUnit
(
CourseOutlineChild
):
class
CourseOutlineUnit
(
CourseOutlineChild
):
"""
"""
PageObject that wraps a unit link on the Studio Course O
verview
page.
PageObject that wraps a unit link on the Studio Course O
utline
page.
"""
"""
url
=
None
url
=
None
BODY_SELECTOR
=
'.outline-item-unit'
BODY_SELECTOR
=
'.outline-item-unit'
...
@@ -123,7 +187,7 @@ class CourseOutlineUnit(CourseOutlineChild):
...
@@ -123,7 +187,7 @@ class CourseOutlineUnit(CourseOutlineChild):
class
CourseOutlineSubsection
(
CourseOutlineChild
,
CourseOutlineContainer
):
class
CourseOutlineSubsection
(
CourseOutlineChild
,
CourseOutlineContainer
):
"""
"""
:class`.PageObject` that wraps a subsection block on the Studio Course O
verview
page.
:class`.PageObject` that wraps a subsection block on the Studio Course O
utline
page.
"""
"""
url
=
None
url
=
None
...
@@ -136,31 +200,28 @@ class CourseOutlineSubsection(CourseOutlineChild, CourseOutlineContainer):
...
@@ -136,31 +200,28 @@ class CourseOutlineSubsection(CourseOutlineChild, CourseOutlineContainer):
"""
"""
return
self
.
child
(
title
)
return
self
.
child
(
title
)
def
toggle_expand
(
self
):
def
units
(
self
):
"""
"""
Toggle the expansion of
this subsection.
Returns the units in
this subsection.
"""
"""
self
.
browser
.
execute_script
(
"jQuery.fx.off = true;"
)
return
self
.
children
()
def
subsection_expanded
():
add_button
=
self
.
q
(
css
=
self
.
_bounded_selector
(
'.add-button'
))
.
first
.
results
return
add_button
and
add_button
[
0
]
.
is_displayed
()
currently_expanded
=
subsection_expanded
()
self
.
q
(
css
=
self
.
_bounded_selector
(
'.ui-toggle-expansion'
))
.
first
.
click
()
def
unit_at
(
self
,
index
):
"""
EmptyPromise
(
Returns the CourseOutlineUnit at the specified index.
lambda
:
subsection_expanded
()
!=
currently_expanded
,
"""
"Check that the subsection {} has been toggled"
.
format
(
self
.
locator
)
return
self
.
child_at
(
index
)
)
.
fulfill
()
return
self
def
add_unit
(
self
):
"""
Adds a unit to this subsection
"""
self
.
add_child
(
require_notification
=
False
)
class
CourseOutlineSection
(
CourseOutlineChild
,
CourseOutlineContainer
):
class
CourseOutlineSection
(
CourseOutlineChild
,
CourseOutlineContainer
):
"""
"""
:class`.PageObject` that wraps a section block on the Studio Course O
verview
page.
:class`.PageObject` that wraps a section block on the Studio Course O
utline
page.
"""
"""
url
=
None
url
=
None
BODY_SELECTOR
=
'.outline-item-section'
BODY_SELECTOR
=
'.outline-item-section'
...
@@ -172,6 +233,33 @@ class CourseOutlineSection(CourseOutlineChild, CourseOutlineContainer):
...
@@ -172,6 +233,33 @@ class CourseOutlineSection(CourseOutlineChild, CourseOutlineContainer):
"""
"""
return
self
.
child
(
title
)
return
self
.
child
(
title
)
def
subsections
(
self
):
"""
Returns a list of the CourseOutlineSubsections of this section
"""
return
self
.
children
()
def
subsection_at
(
self
,
index
):
"""
Returns the CourseOutlineSubsection at the specified index.
"""
return
self
.
child_at
(
index
)
def
add_subsection
(
self
):
"""
Adds a subsection to this section
"""
self
.
add_child
()
class
ExpandCollapseLinkState
:
"""
Represents the three states that the expand/collapse link can be in
"""
MISSING
=
0
COLLAPSE
=
1
EXPAND
=
2
class
CourseOutlinePage
(
CoursePage
,
CourseOutlineContainer
):
class
CourseOutlinePage
(
CoursePage
,
CourseOutlineContainer
):
"""
"""
...
@@ -179,10 +267,19 @@ class CourseOutlinePage(CoursePage, CourseOutlineContainer):
...
@@ -179,10 +267,19 @@ class CourseOutlinePage(CoursePage, CourseOutlineContainer):
"""
"""
url_path
=
"course"
url_path
=
"course"
CHILD_CLASS
=
CourseOutlineSection
CHILD_CLASS
=
CourseOutlineSection
EXPAND_COLLAPSE_CSS
=
'.toggle-button-expand-collapse'
BOTTOM_ADD_SECTION_BUTTON
=
'.course-outline > .add-xblock-component .add-button'
def
is_browser_on_page
(
self
):
def
is_browser_on_page
(
self
):
return
self
.
q
(
css
=
'body.view-outline'
)
.
present
return
self
.
q
(
css
=
'body.view-outline'
)
.
present
def
view_live
(
self
):
"""
Clicks the "View Live" link and switches to the new tab
"""
click_css
(
self
,
'.view-live-button'
,
require_notification
=
False
)
self
.
browser
.
switch_to_window
(
self
.
browser
.
window_handles
[
-
1
])
def
section
(
self
,
title
):
def
section
(
self
,
title
):
"""
"""
Return the :class:`.CourseOutlineSection` with the title `title`.
Return the :class:`.CourseOutlineSection` with the title `title`.
...
@@ -194,7 +291,7 @@ class CourseOutlinePage(CoursePage, CourseOutlineContainer):
...
@@ -194,7 +291,7 @@ class CourseOutlinePage(CoursePage, CourseOutlineContainer):
Returns the :class:`.CourseOutlineSection` at the specified index.
Returns the :class:`.CourseOutlineSection` at the specified index.
"""
"""
return
self
.
child_at
(
index
)
return
self
.
child_at
(
index
)
def
click_section_name
(
self
,
parent_css
=
''
):
def
click_section_name
(
self
,
parent_css
=
''
):
"""
"""
Find and click on first section name in course outline
Find and click on first section name in course outline
...
@@ -229,3 +326,54 @@ class CourseOutlinePage(CoursePage, CourseOutlineContainer):
...
@@ -229,3 +326,54 @@ class CourseOutlinePage(CoursePage, CourseOutlineContainer):
Open release date edit modal of first section in course outline
Open release date edit modal of first section in course outline
"""
"""
self
.
q
(
css
=
'div.section-published-date a.edit-release-date'
)
.
first
.
click
()
self
.
q
(
css
=
'div.section-published-date a.edit-release-date'
)
.
first
.
click
()
def
sections
(
self
):
"""
Returns the sections of this course outline page.
"""
return
self
.
children
()
def
add_section_from_top_button
(
self
):
"""
Clicks the button for adding a section which resides at the top of the screen.
"""
click_css
(
self
,
'.wrapper-mast nav.nav-actions .add-button'
)
def
add_section_from_bottom_button
(
self
):
"""
Clicks the button for adding a section which resides at the bottom of the screen.
"""
click_css
(
self
,
self
.
BOTTOM_ADD_SECTION_BUTTON
)
def
toggle_expand_collapse
(
self
):
"""
Toggles whether all sections are expanded or collapsed
"""
self
.
q
(
css
=
self
.
EXPAND_COLLAPSE_CSS
)
.
click
()
@property
def
bottom_add_section_button
(
self
):
"""
Returns the query representing the bottom add section button.
"""
return
self
.
q
(
css
=
self
.
BOTTOM_ADD_SECTION_BUTTON
)
.
first
@property
def
has_no_content_message
(
self
):
"""
Returns true if a message informing the user that the course has no content is visible
"""
return
self
.
q
(
css
=
'.course-outline .no-content'
)
.
is_present
()
@property
def
expand_collapse_link_state
(
self
):
"""
Returns the current state of the expand/collapse link
"""
link
=
self
.
q
(
css
=
self
.
EXPAND_COLLAPSE_CSS
)[
0
]
if
not
link
.
is_displayed
():
return
ExpandCollapseLinkState
.
MISSING
elif
"collapse-all"
in
link
.
get_attribute
(
"class"
):
return
ExpandCollapseLinkState
.
COLLAPSE
else
:
return
ExpandCollapseLinkState
.
EXPAND
common/test/acceptance/pages/studio/utils.py
View file @
f31475a2
...
@@ -139,3 +139,14 @@ def set_input_value_and_save(page, css, value):
...
@@ -139,3 +139,14 @@ def set_input_value_and_save(page, css, value):
action
=
action
.
send_keys
(
Keys
.
BACKSPACE
)
action
=
action
.
send_keys
(
Keys
.
BACKSPACE
)
# Send the new text, then hit the enter key so that the change event is triggered).
# Send the new text, then hit the enter key so that the change event is triggered).
action
.
send_keys
(
value
)
.
send_keys
(
Keys
.
ENTER
)
.
perform
()
action
.
send_keys
(
value
)
.
send_keys
(
Keys
.
ENTER
)
.
perform
()
def
confirm_prompt
(
page
,
cancel
=
False
):
"""
Ensures that a modal prompt and confirmation button are visible, then clicks the button. The prompt is canceled iff
cancel is True.
"""
page
.
wait_for_element_visibility
(
'.prompt'
,
'Prompt is visible'
)
confirmation_button_css
=
'.prompt .action-'
+
(
'secondary'
if
cancel
else
'primary'
)
page
.
wait_for_element_visibility
(
confirmation_button_css
,
'Confirmation button is visible'
)
click_css
(
page
,
confirmation_button_css
,
require_notification
=
(
not
cancel
))
common/test/acceptance/tests/test_studio_container.py
View file @
f31475a2
...
@@ -6,18 +6,17 @@ displaying containers within units.
...
@@ -6,18 +6,17 @@ displaying containers within units.
from
nose.plugins.attrib
import
attr
from
nose.plugins.attrib
import
attr
from
..pages.studio.overview
import
CourseOutlinePage
from
..pages.studio.overview
import
CourseOutlinePage
from
..fixtures.course
import
XBlockFixtureDesc
from
..fixtures.course
import
XBlockFixtureDesc
from
..pages.studio.component_editor
import
ComponentEditorView
from
..pages.studio.component_editor
import
ComponentEditorView
from
..pages.studio.html_component_editor
import
HtmlComponentEditorView
from
..pages.studio.html_component_editor
import
HtmlComponentEditorView
from
..pages.studio.utils
import
add_discussion
from
..pages.studio.utils
import
add_discussion
from
..pages.lms.courseware
import
CoursewarePage
from
..pages.lms.courseware
import
CoursewarePage
from
..pages.lms.staff_view
import
StaffPage
from
..pages.lms.staff_view
import
StaffPage
from
unittest
import
skip
from
acceptance.tests.base_studio_test
import
StudioCourseTest
import
datetime
import
datetime
from
bok_choy.promise
import
Promise
,
EmptyPromise
from
bok_choy.promise
import
Promise
,
EmptyPromise
from
acceptance.tests.base_studio_test
import
StudioCourseTest
@attr
(
'shard_1'
)
@attr
(
'shard_1'
)
...
@@ -388,23 +387,17 @@ class UnitPublishingTest(ContainerBase):
...
@@ -388,23 +387,17 @@ class UnitPublishingTest(ContainerBase):
LAST_PUBLISHED
=
'Last published'
LAST_PUBLISHED
=
'Last published'
LAST_SAVED
=
'Draft saved on'
LAST_SAVED
=
'Draft saved on'
def
setup_fixtures
(
self
):
def
populate_course_fixture
(
self
,
course_fixture
):
"""
"""
Sets up a course structure with a unit and a single HTML child.
Sets up a course structure with a unit and a single HTML child.
"""
"""
self
.
html_content
=
'<p><strong>Body of HTML Unit.</strong></p>'
self
.
html_content
=
'<p><strong>Body of HTML Unit.</strong></p>'
self
.
courseware
=
CoursewarePage
(
self
.
browser
,
self
.
course_id
)
self
.
courseware
=
CoursewarePage
(
self
.
browser
,
self
.
course_id
)
course_fix
=
CourseFixture
(
self
.
course_info
[
'org'
],
self
.
course_info
[
'number'
],
self
.
course_info
[
'run'
],
self
.
course_info
[
'display_name'
]
)
past_start_date
=
datetime
.
datetime
(
1974
,
6
,
22
)
past_start_date
=
datetime
.
datetime
(
1974
,
6
,
22
)
self
.
past_start_date_text
=
"Jun 22, 1974 at 00:00 UTC"
self
.
past_start_date_text
=
"Jun 22, 1974 at 00:00 UTC"
course_fix
.
add_children
(
course_fix
ture
.
add_children
(
XBlockFixtureDesc
(
'chapter'
,
'Test Section'
)
.
add_children
(
XBlockFixtureDesc
(
'chapter'
,
'Test Section'
)
.
add_children
(
XBlockFixtureDesc
(
'sequential'
,
'Test Subsection'
)
.
add_children
(
XBlockFixtureDesc
(
'sequential'
,
'Test Subsection'
)
.
add_children
(
XBlockFixtureDesc
(
'vertical'
,
'Test Unit'
)
.
add_children
(
XBlockFixtureDesc
(
'vertical'
,
'Test Unit'
)
.
add_children
(
...
@@ -426,9 +419,7 @@ class UnitPublishingTest(ContainerBase):
...
@@ -426,9 +419,7 @@ class UnitPublishingTest(ContainerBase):
)
)
)
)
)
)
)
.
install
()
)
self
.
user
=
course_fix
.
user
def
test_publishing
(
self
):
def
test_publishing
(
self
):
"""
"""
...
@@ -495,7 +486,7 @@ class UnitPublishingTest(ContainerBase):
...
@@ -495,7 +486,7 @@ class UnitPublishingTest(ContainerBase):
Then I see the published content in LMS
Then I see the published content in LMS
"""
"""
unit
=
self
.
go_to_unit_page
()
unit
=
self
.
go_to_unit_page
()
unit
.
view_published_version
(
)
self
.
_view_published_version
(
unit
)
self
.
_verify_components_visible
([
'html'
])
self
.
_verify_components_visible
([
'html'
])
def
test_view_live_changes
(
self
):
def
test_view_live_changes
(
self
):
...
@@ -510,7 +501,7 @@ class UnitPublishingTest(ContainerBase):
...
@@ -510,7 +501,7 @@ class UnitPublishingTest(ContainerBase):
"""
"""
unit
=
self
.
go_to_unit_page
()
unit
=
self
.
go_to_unit_page
()
add_discussion
(
unit
)
add_discussion
(
unit
)
unit
.
view_published_version
(
)
self
.
_view_published_version
(
unit
)
self
.
_verify_components_visible
([
'html'
])
self
.
_verify_components_visible
([
'html'
])
self
.
assertEqual
(
self
.
html_content
,
self
.
courseware
.
xblock_component_html_content
(
0
))
self
.
assertEqual
(
self
.
html_content
,
self
.
courseware
.
xblock_component_html_content
(
0
))
...
@@ -527,7 +518,7 @@ class UnitPublishingTest(ContainerBase):
...
@@ -527,7 +518,7 @@ class UnitPublishingTest(ContainerBase):
unit
=
self
.
go_to_unit_page
()
unit
=
self
.
go_to_unit_page
()
add_discussion
(
unit
)
add_discussion
(
unit
)
unit
.
publish_action
.
click
()
unit
.
publish_action
.
click
()
unit
.
view_published_version
(
)
self
.
_view_published_version
(
unit
)
self
.
_verify_components_visible
([
'html'
,
'discussion'
])
self
.
_verify_components_visible
([
'html'
,
'discussion'
])
def
test_initially_unlocked_visible_to_students
(
self
):
def
test_initially_unlocked_visible_to_students
(
self
):
...
@@ -547,7 +538,7 @@ class UnitPublishingTest(ContainerBase):
...
@@ -547,7 +538,7 @@ class UnitPublishingTest(ContainerBase):
self
.
_verify_release_date_info
(
self
.
_verify_release_date_info
(
unit
,
self
.
RELEASE_TITLE_RELEASED
,
self
.
past_start_date_text
+
' with Section "Unlocked Section"'
unit
,
self
.
RELEASE_TITLE_RELEASED
,
self
.
past_start_date_text
+
' with Section "Unlocked Section"'
)
)
unit
.
view_published_version
(
)
self
.
_view_published_version
(
unit
)
self
.
_verify_student_view_visible
([
'problem'
])
self
.
_verify_student_view_visible
([
'problem'
])
def
test_locked_visible_to_staff_only
(
self
):
def
test_locked_visible_to_staff_only
(
self
):
...
@@ -567,7 +558,7 @@ class UnitPublishingTest(ContainerBase):
...
@@ -567,7 +558,7 @@ class UnitPublishingTest(ContainerBase):
self
.
assertTrue
(
checked
)
self
.
assertTrue
(
checked
)
self
.
assertFalse
(
unit
.
currently_visible_to_students
)
self
.
assertFalse
(
unit
.
currently_visible_to_students
)
self
.
_verify_publish_title
(
unit
,
self
.
LOCKED_STATUS
)
self
.
_verify_publish_title
(
unit
,
self
.
LOCKED_STATUS
)
unit
.
view_published_version
(
)
self
.
_view_published_version
(
unit
)
# Will initially be in staff view, locked component should be visible.
# Will initially be in staff view, locked component should be visible.
self
.
_verify_components_visible
([
'problem'
])
self
.
_verify_components_visible
([
'problem'
])
# Switch to student view and verify not visible
# Switch to student view and verify not visible
...
@@ -591,7 +582,7 @@ class UnitPublishingTest(ContainerBase):
...
@@ -591,7 +582,7 @@ class UnitPublishingTest(ContainerBase):
unit
,
self
.
RELEASE_TITLE_RELEASED
,
unit
,
self
.
RELEASE_TITLE_RELEASED
,
self
.
past_start_date_text
+
' with Subsection "Subsection With Locked Unit"'
self
.
past_start_date_text
+
' with Subsection "Subsection With Locked Unit"'
)
)
unit
.
view_published_version
(
)
self
.
_view_published_version
(
unit
)
self
.
_verify_student_view_locked
()
self
.
_verify_student_view_locked
()
def
test_unlocked_visible_to_all
(
self
):
def
test_unlocked_visible_to_all
(
self
):
...
@@ -611,7 +602,7 @@ class UnitPublishingTest(ContainerBase):
...
@@ -611,7 +602,7 @@ class UnitPublishingTest(ContainerBase):
self
.
assertFalse
(
checked
)
self
.
assertFalse
(
checked
)
self
.
_verify_publish_title
(
unit
,
self
.
PUBLISHED_STATUS
)
self
.
_verify_publish_title
(
unit
,
self
.
PUBLISHED_STATUS
)
self
.
assertTrue
(
unit
.
currently_visible_to_students
)
self
.
assertTrue
(
unit
.
currently_visible_to_students
)
unit
.
view_published_version
(
)
self
.
_view_published_version
(
unit
)
# Will initially be in staff view, components always visible.
# Will initially be in staff view, components always visible.
self
.
_verify_components_visible
([
'discussion'
])
self
.
_verify_components_visible
([
'discussion'
])
# Switch to student view and verify visible.
# Switch to student view and verify visible.
...
@@ -641,7 +632,7 @@ class UnitPublishingTest(ContainerBase):
...
@@ -641,7 +632,7 @@ class UnitPublishingTest(ContainerBase):
unit
.
publish_action
.
click
()
unit
.
publish_action
.
click
()
unit
.
wait_for_ajax
()
unit
.
wait_for_ajax
()
self
.
_verify_publish_title
(
unit
,
self
.
PUBLISHED_STATUS
)
self
.
_verify_publish_title
(
unit
,
self
.
PUBLISHED_STATUS
)
unit
.
view_published_version
(
)
self
.
_view_published_version
(
unit
)
self
.
assertTrue
(
modified_content
in
self
.
courseware
.
xblock_component_html_content
(
0
))
self
.
assertTrue
(
modified_content
in
self
.
courseware
.
xblock_component_html_content
(
0
))
def
test_delete_child_in_published_unit
(
self
):
def
test_delete_child_in_published_unit
(
self
):
...
@@ -662,9 +653,16 @@ class UnitPublishingTest(ContainerBase):
...
@@ -662,9 +653,16 @@ class UnitPublishingTest(ContainerBase):
unit
.
publish_action
.
click
()
unit
.
publish_action
.
click
()
unit
.
wait_for_ajax
()
unit
.
wait_for_ajax
()
self
.
_verify_publish_title
(
unit
,
self
.
PUBLISHED_STATUS
)
self
.
_verify_publish_title
(
unit
,
self
.
PUBLISHED_STATUS
)
unit
.
view_published_version
(
)
self
.
_view_published_version
(
unit
)
self
.
assertEqual
(
0
,
self
.
courseware
.
num_xblock_components
)
self
.
assertEqual
(
0
,
self
.
courseware
.
num_xblock_components
)
def
_view_published_version
(
self
,
unit
):
"""
Goes to the published version, then waits for the browser to load the page.
"""
unit
.
view_published_version
()
self
.
courseware
.
wait_for_page
()
def
_verify_and_return_staff_page
(
self
):
def
_verify_and_return_staff_page
(
self
):
"""
"""
Verifies that the browser is on the staff page and returns a StaffPage.
Verifies that the browser is on the staff page and returns a StaffPage.
...
...
common/test/acceptance/tests/test_studio_general.py
View file @
f31475a2
...
@@ -113,57 +113,6 @@ class CoursePagesTest(StudioCourseTest):
...
@@ -113,57 +113,6 @@ class CoursePagesTest(StudioCourseTest):
page
.
visit
()
page
.
visit
()
@attr
(
'shard_1'
)
class
CourseSectionTest
(
StudioCourseTest
):
"""
Tests that verify the sections name editable only inside headers in Studio Course Outline that you can get to
when logged in and have a course.
"""
COURSE_ID_SEPARATOR
=
"."
def
setUp
(
self
):
"""
Install a course with no content using a fixture.
"""
super
(
CourseSectionTest
,
self
)
.
setUp
()
self
.
course_outline_page
=
CourseOutlinePage
(
self
.
browser
,
self
.
course_info
[
'org'
],
self
.
course_info
[
'number'
],
self
.
course_info
[
'run'
]
)
self
.
course_outline_page
.
visit
()
def
populate_course_fixture
(
self
,
course_fixture
):
""" Populates the course fixture with a test section """
course_fixture
.
add_children
(
XBlockFixtureDesc
(
'chapter'
,
'Test Section'
)
)
def
test_section_name_editable_in_course_outline
(
self
):
"""
Check that section name is editable on course outline page.
"""
new_name
=
u"Test Section New"
section
=
self
.
course_outline_page
.
section_at
(
0
)
self
.
assertEqual
(
section
.
name
,
u"Test Section"
)
section
.
change_name
(
new_name
)
self
.
browser
.
refresh
()
self
.
assertEqual
(
section
.
name
,
new_name
)
# TODO: re-enable when release date support is added back
# def test_section_name_not_editable_inside_modal(self):
# """
# Check that section name is not editable inside "Section Release Date" modal on course outline page.
# """
# parent_css='div.modal-window'
# self.course_outline_page.click_release_date()
# section_name = self.course_outline_page.get_section_name(parent_css)[0]
# self.assertEqual(section_name, '"Test Section"')
# self.course_outline_page.click_section_name(parent_css)
# section_name_edit_form = self.course_outline_page.section_name_edit_form_present(parent_css)
# self.assertFalse(section_name_edit_form)
@attr
(
'shard_1'
)
class
DiscussionPreviewTest
(
StudioCourseTest
):
class
DiscussionPreviewTest
(
StudioCourseTest
):
"""
"""
Tests that Inline Discussions are rendered with a custom preview in Studio
Tests that Inline Discussions are rendered with a custom preview in Studio
...
...
common/test/acceptance/tests/test_studio_outline.py
0 → 100644
View file @
f31475a2
"""
Acceptance tests for studio related to the outline page.
"""
from
bok_choy.promise
import
EmptyPromise
from
..pages.studio.overview
import
CourseOutlinePage
,
ContainerPage
,
ExpandCollapseLinkState
from
..pages.lms.courseware
import
CoursewarePage
from
..fixtures.course
import
XBlockFixtureDesc
from
acceptance.tests.base_studio_test
import
StudioCourseTest
class
CourseOutlineTest
(
StudioCourseTest
):
"""
Base class for all course outline tests
"""
COURSE_ID_SEPARATOR
=
"."
def
setUp
(
self
):
"""
Install a course with no content using a fixture.
"""
super
(
CourseOutlineTest
,
self
)
.
setUp
()
self
.
course_outline_page
=
CourseOutlinePage
(
self
.
browser
,
self
.
course_info
[
'org'
],
self
.
course_info
[
'number'
],
self
.
course_info
[
'run'
]
)
def
populate_course_fixture
(
self
,
course_fixture
):
""" Install a course with sections/problems, tabs, updates, and handouts """
course_fixture
.
add_children
(
XBlockFixtureDesc
(
'chapter'
,
'Test Section'
)
.
add_children
(
XBlockFixtureDesc
(
'sequential'
,
'Test Subsection'
)
.
add_children
(
XBlockFixtureDesc
(
'vertical'
,
'Test Unit'
)
.
add_children
(
XBlockFixtureDesc
(
'html'
,
'Test HTML Component'
),
XBlockFixtureDesc
(
'discussion'
,
'Test Discussion Component'
)
)
)
)
)
class
EditNamesTest
(
CourseOutlineTest
):
"""
Feature: Click-to-edit section/subsection names
"""
__test__
=
True
def
set_name_and_verify
(
self
,
item
,
old_name
,
new_name
,
expected_name
):
"""
Changes the display name of item from old_name to new_name, then verifies that its value is expected_name.
"""
self
.
assertEqual
(
item
.
name
,
old_name
)
item
.
change_name
(
new_name
)
self
.
assertFalse
(
item
.
in_editable_form
())
self
.
assertEqual
(
item
.
name
,
expected_name
)
def
test_edit_section_name
(
self
):
"""
Scenario: Click-to-edit section name
Given that I have created a section
When I click on the name of section
Then the section name becomes editable
And given that I have edited the section name
When I click outside of the edited section name
Then the section name saves
And becomes non-editable
"""
self
.
course_outline_page
.
visit
()
self
.
set_name_and_verify
(
self
.
course_outline_page
.
section_at
(
0
),
'Test Section'
,
'Changed'
,
'Changed'
)
def
test_edit_subsection_name
(
self
):
"""
Scenario: Click-to-edit subsection name
Given that I have created a subsection
When I click on the name of subsection
Then the subsection name becomes editable
And given that I have edited the subsection name
When I click outside of the edited subsection name
Then the subsection name saves
And becomes non-editable
"""
self
.
course_outline_page
.
visit
()
self
.
set_name_and_verify
(
self
.
course_outline_page
.
section_at
(
0
)
.
subsection_at
(
0
),
'Test Subsection'
,
'Changed'
,
'Changed'
)
def
test_edit_empty_section_name
(
self
):
"""
Scenario: Click-to-edit section name, enter empty name
Given that I have created a section
And I have clicked to edit the name of the section
And I have entered an empty section name
When I click outside of the edited section name
Then the section name does not change
And becomes non-editable
"""
self
.
course_outline_page
.
visit
()
self
.
set_name_and_verify
(
self
.
course_outline_page
.
section_at
(
0
),
'Test Section'
,
''
,
'Test Section'
)
def
test_edit_empty_subsection_name
(
self
):
"""
Scenario: Click-to-edit subsection name, enter empty name
Given that I have created a subsection
And I have clicked to edit the name of the subsection
And I have entered an empty subsection name
When I click outside of the edited subsection name
Then the subsection name does not change
And becomes non-editable
"""
self
.
course_outline_page
.
visit
()
self
.
set_name_and_verify
(
self
.
course_outline_page
.
section_at
(
0
)
.
subsection_at
(
0
),
'Test Subsection'
,
''
,
'Test Subsection'
)
class
CreateSectionsTest
(
CourseOutlineTest
):
"""
Feature: Create new sections/subsections/units
"""
__test__
=
True
def
populate_course_fixture
(
self
,
course_fixture
):
""" Start with a completely empty course to easily test adding things to it """
pass
def
test_create_new_section_from_top_button
(
self
):
"""
Scenario: Create new section from button at top of page
Given that I am on the course outline
When I click the "+ Add section" button at the top of the page
Then I see a new section added to the bottom of the page
And the display name is in its editable form.
"""
self
.
course_outline_page
.
visit
()
self
.
course_outline_page
.
add_section_from_top_button
()
self
.
assertEqual
(
len
(
self
.
course_outline_page
.
sections
()),
1
)
self
.
assertTrue
(
self
.
course_outline_page
.
section_at
(
0
)
.
in_editable_form
())
def
test_create_new_section_from_bottom_button
(
self
):
"""
Scenario: Create new section from button at bottom of page
Given that I am on the course outline
When I click the "+ Add section" button at the bottom of the page
Then I see a new section added to the bottom of the page
And the display name is in its editable form.
"""
self
.
course_outline_page
.
visit
()
self
.
course_outline_page
.
add_section_from_bottom_button
()
self
.
assertEqual
(
len
(
self
.
course_outline_page
.
sections
()),
1
)
self
.
assertTrue
(
self
.
course_outline_page
.
section_at
(
0
)
.
in_editable_form
())
def
test_create_new_subsection
(
self
):
"""
Scenario: Create new subsection
Given that I have created a section
When I click the "+ Add subsection" button in that section
Then I see a new subsection added to the bottom of the section
And the display name is in its editable form.
"""
self
.
course_outline_page
.
visit
()
self
.
course_outline_page
.
add_section_from_top_button
()
self
.
assertEqual
(
len
(
self
.
course_outline_page
.
sections
()),
1
)
self
.
course_outline_page
.
section_at
(
0
)
.
add_subsection
()
subsections
=
self
.
course_outline_page
.
section_at
(
0
)
.
subsections
()
self
.
assertEqual
(
len
(
subsections
),
1
)
self
.
assertTrue
(
subsections
[
0
]
.
in_editable_form
())
def
test_create_new_unit
(
self
):
"""
Scenario: Create new unit
Given that I have created a section
And that I have created a subsection within that section
When I click the "+ Add unit" button in that subsection
Then I am redirected to a New Unit page
And the display name is in its editable form.
"""
self
.
course_outline_page
.
visit
()
self
.
course_outline_page
.
add_section_from_top_button
()
self
.
assertEqual
(
len
(
self
.
course_outline_page
.
sections
()),
1
)
self
.
course_outline_page
.
section_at
(
0
)
.
add_subsection
()
self
.
assertEqual
(
len
(
self
.
course_outline_page
.
section_at
(
0
)
.
subsections
()),
1
)
self
.
course_outline_page
.
section_at
(
0
)
.
subsection_at
(
0
)
.
add_unit
()
unit_page
=
ContainerPage
(
self
.
browser
,
None
)
EmptyPromise
(
unit_page
.
is_browser_on_page
,
'Browser is on the unit page'
)
.
fulfill
()
self
.
assertTrue
(
unit_page
.
is_inline_editing_display_name
())
class
DeleteContentTest
(
CourseOutlineTest
):
"""
Feature: Deleting sections/subsections/units
"""
__test__
=
True
def
test_delete_section
(
self
):
"""
Scenario: Delete section
Given that I am on the course outline
When I click the delete button for a section on the course outline
Then I should receive a confirmation message, asking me if I really want to delete the section
When I click "Yes, I want to delete this component"
Then the confirmation message should close
And the section should immediately be deleted from the course outline
"""
self
.
course_outline_page
.
visit
()
self
.
assertEqual
(
len
(
self
.
course_outline_page
.
sections
()),
1
)
self
.
course_outline_page
.
section_at
(
0
)
.
delete
()
self
.
assertEqual
(
len
(
self
.
course_outline_page
.
sections
()),
0
)
def
test_cancel_delete_section
(
self
):
"""
Scenario: Cancel delete of section
Given that I clicked the delte button for a section on the course outline
And I received a confirmation message, asking me if I really want to delete the component
When I click "Cancel"
Then the confirmation message should close
And the section should remain in the course outline
"""
self
.
course_outline_page
.
visit
()
self
.
assertEqual
(
len
(
self
.
course_outline_page
.
sections
()),
1
)
self
.
course_outline_page
.
section_at
(
0
)
.
delete
(
cancel
=
True
)
self
.
assertEqual
(
len
(
self
.
course_outline_page
.
sections
()),
1
)
def
test_delete_subsection
(
self
):
"""
Scenario: Delete subsection
Given that I am on the course outline
When I click the delete button for a subsection on the course outline
Then I should receive a confirmation message, asking me if I really want to delete the subsection
When I click "Yes, I want to delete this component"
Then the confiramtion message should close
And the subsection should immediately be deleted from the course outline
"""
self
.
course_outline_page
.
visit
()
self
.
assertEqual
(
len
(
self
.
course_outline_page
.
section_at
(
0
)
.
subsections
()),
1
)
self
.
course_outline_page
.
section_at
(
0
)
.
subsection_at
(
0
)
.
delete
()
self
.
assertEqual
(
len
(
self
.
course_outline_page
.
section_at
(
0
)
.
subsections
()),
0
)
def
test_cancel_delete_subsection
(
self
):
"""
Scenario: Cancel delete of subsection
Given that I clicked the delete button for a subsection on the course outline
And I received a confirmation message, asking me if I really want to delete the subsection
When I click "cancel"
Then the confirmation message should close
And the subsection should remain in the course outline
"""
self
.
course_outline_page
.
visit
()
self
.
assertEqual
(
len
(
self
.
course_outline_page
.
section_at
(
0
)
.
subsections
()),
1
)
self
.
course_outline_page
.
section_at
(
0
)
.
subsection_at
(
0
)
.
delete
(
cancel
=
True
)
self
.
assertEqual
(
len
(
self
.
course_outline_page
.
section_at
(
0
)
.
subsections
()),
1
)
def
test_delete_unit
(
self
):
"""
Scenario: Delete unit
Given that I am on the course outline
When I click the delete button for a unit on the course outline
Then I should receive a confirmation message, asking me if I really want to delete the unit
When I click "Yes, I want to delete this unit"
Then the confirmation message should close
And the unit should immediately be deleted from the course outline
"""
self
.
course_outline_page
.
visit
()
self
.
course_outline_page
.
section_at
(
0
)
.
subsection_at
(
0
)
.
toggle_expand
()
self
.
assertEqual
(
len
(
self
.
course_outline_page
.
section_at
(
0
)
.
subsection_at
(
0
)
.
units
()),
1
)
self
.
course_outline_page
.
section_at
(
0
)
.
subsection_at
(
0
)
.
unit_at
(
0
)
.
delete
()
self
.
assertEqual
(
len
(
self
.
course_outline_page
.
section_at
(
0
)
.
subsection_at
(
0
)
.
units
()),
0
)
def
test_cancel_delete_unit
(
self
):
"""
Scenario: Cancel delete of unit
Given that I clicked the delete button for a unit on the course outline
And I received a confirmation message, asking me if I really want to delete the unit
When I click "Cancel"
Then the confirmation message should close
And the unit should remain in the course outline
"""
self
.
course_outline_page
.
visit
()
self
.
course_outline_page
.
section_at
(
0
)
.
subsection_at
(
0
)
.
toggle_expand
()
self
.
assertEqual
(
len
(
self
.
course_outline_page
.
section_at
(
0
)
.
subsection_at
(
0
)
.
units
()),
1
)
self
.
course_outline_page
.
section_at
(
0
)
.
subsection_at
(
0
)
.
unit_at
(
0
)
.
delete
(
cancel
=
True
)
self
.
assertEqual
(
len
(
self
.
course_outline_page
.
section_at
(
0
)
.
subsection_at
(
0
)
.
units
()),
1
)
def
test_delete_all_no_content_message
(
self
):
"""
Scenario: Delete all sections/subsections/units in a course, "no content" message should appear
Given that I delete all sections, subsections, and units in a course
When I visit the course outline
Then I will see a message that says, "You haven't added any content to this course yet"
Add see a + Add Section button
"""
self
.
course_outline_page
.
visit
()
self
.
assertFalse
(
self
.
course_outline_page
.
has_no_content_message
)
self
.
course_outline_page
.
section_at
(
0
)
.
delete
()
self
.
assertEqual
(
len
(
self
.
course_outline_page
.
sections
()),
0
)
self
.
assertTrue
(
self
.
course_outline_page
.
has_no_content_message
)
class
ExpandCollapseMultipleSectionsTest
(
CourseOutlineTest
):
"""
Feature: Courses with multiple sections can expand and collapse all sections.
"""
__test__
=
True
def
populate_course_fixture
(
self
,
course_fixture
):
""" Start with a course with two sections """
course_fixture
.
add_children
(
XBlockFixtureDesc
(
'chapter'
,
'Test Section'
)
.
add_children
(
XBlockFixtureDesc
(
'sequential'
,
'Test Subsection'
)
.
add_children
(
XBlockFixtureDesc
(
'vertical'
,
'Test Unit'
)
)
),
XBlockFixtureDesc
(
'chapter'
,
'Test Section 2'
)
.
add_children
(
XBlockFixtureDesc
(
'sequential'
,
'Test Subsection 2'
)
.
add_children
(
XBlockFixtureDesc
(
'vertical'
,
'Test Unit 2'
)
)
)
)
def
verify_all_sections
(
self
,
collapsed
):
"""
Verifies that all sections are collapsed if collapsed is True, otherwise all expanded.
"""
for
section
in
self
.
course_outline_page
.
sections
():
self
.
assertEqual
(
collapsed
,
section
.
is_collapsed
)
def
toggle_all_sections
(
self
):
"""
Toggles the expand collapse state of all sections.
"""
for
section
in
self
.
course_outline_page
.
sections
():
section
.
toggle_expand
()
def
test_expanded_by_default
(
self
):
"""
Scenario: The default layout for the outline page is to show sections in expanded view
Given I have a course with sections
When I navigate to the course outline page
Then I see the "Collapse All Sections" link
And all sections are expanded
"""
self
.
course_outline_page
.
visit
()
self
.
assertEquals
(
self
.
course_outline_page
.
expand_collapse_link_state
,
ExpandCollapseLinkState
.
COLLAPSE
)
self
.
verify_all_sections
(
collapsed
=
False
)
def
test_no_expand_link_for_empty_course
(
self
):
"""
Scenario: Collapse link is removed after last section of a course is deleted
Given I have a course with multiple sections
And I navigate to the course outline page
When I will confirm all alerts
And I press the "section" delete icon
Then I do not see the "Collapse All Sections" link
And I will see a message that says "You haven't added any content to this course yet"
"""
self
.
course_outline_page
.
visit
()
for
section
in
self
.
course_outline_page
.
sections
():
section
.
delete
()
self
.
assertEquals
(
self
.
course_outline_page
.
expand_collapse_link_state
,
ExpandCollapseLinkState
.
MISSING
)
self
.
assertTrue
(
self
.
course_outline_page
.
has_no_content_message
)
def
test_collapse_all_when_all_expanded
(
self
):
"""
Scenario: Collapse all sections when all sections are expanded
Given I navigate to the outline page of a course with sections
And all sections are expanded
When I click the "Collapse All Sections" link
Then I see the "Expand All Sections" link
And all sections are collapsed
"""
self
.
course_outline_page
.
visit
()
self
.
verify_all_sections
(
collapsed
=
False
)
self
.
course_outline_page
.
toggle_expand_collapse
()
self
.
assertEquals
(
self
.
course_outline_page
.
expand_collapse_link_state
,
ExpandCollapseLinkState
.
EXPAND
)
self
.
verify_all_sections
(
collapsed
=
True
)
def
test_collapse_all_when_some_expanded
(
self
):
"""
Scenario: Collapsing all sections when 1 or more sections are already collapsed
Given I navigate to the outline page of a course with sections
And all sections are expanded
When I collapse the first section
And I click the "Collapse All Sections" link
Then I see the "Expand All Sections" link
And all sections are collapsed
"""
self
.
course_outline_page
.
visit
()
self
.
verify_all_sections
(
collapsed
=
False
)
self
.
course_outline_page
.
section_at
(
0
)
.
toggle_expand
()
self
.
course_outline_page
.
toggle_expand_collapse
()
self
.
assertEquals
(
self
.
course_outline_page
.
expand_collapse_link_state
,
ExpandCollapseLinkState
.
EXPAND
)
self
.
verify_all_sections
(
collapsed
=
True
)
def
test_expand_all_when_all_collapsed
(
self
):
"""
Scenario: Expanding all sections when all sections are collapsed
Given I navigate to the outline page of a course with multiple sections
And I click the "Collapse All Sections" link
When I click the "Expand All Sections" link
Then I see the "Collapse All Sections" link
And all sections are expanded
"""
self
.
course_outline_page
.
visit
()
self
.
course_outline_page
.
toggle_expand_collapse
()
self
.
assertEquals
(
self
.
course_outline_page
.
expand_collapse_link_state
,
ExpandCollapseLinkState
.
EXPAND
)
self
.
course_outline_page
.
toggle_expand_collapse
()
self
.
assertEquals
(
self
.
course_outline_page
.
expand_collapse_link_state
,
ExpandCollapseLinkState
.
COLLAPSE
)
self
.
verify_all_sections
(
collapsed
=
False
)
def
test_expand_all_when_some_collapsed
(
self
):
"""
Scenario: Expanding all sections when 1 or more sections are already expanded
Given I navigate to the outline page of a course with multiple sections
And I click the "Collapse All Sections" link
When I expand the first section
And I click the "Expand All Sections" link
Then I see the "Collapse All Sections" link
And all sections are expanded
"""
self
.
course_outline_page
.
visit
()
self
.
course_outline_page
.
toggle_expand_collapse
()
self
.
assertEquals
(
self
.
course_outline_page
.
expand_collapse_link_state
,
ExpandCollapseLinkState
.
EXPAND
)
self
.
course_outline_page
.
section_at
(
0
)
.
toggle_expand
()
self
.
course_outline_page
.
toggle_expand_collapse
()
self
.
assertEquals
(
self
.
course_outline_page
.
expand_collapse_link_state
,
ExpandCollapseLinkState
.
COLLAPSE
)
self
.
verify_all_sections
(
collapsed
=
False
)
class
ExpandCollapseSingleSectionTest
(
CourseOutlineTest
):
"""
Feature: Courses with a single section can expand and collapse all sections.
"""
__test__
=
True
def
test_no_expand_link_for_empty_course
(
self
):
"""
Scenario: Collapse link is removed after last section of a course is deleted
Given I have a course with one section
And I navigate to the course outline page
When I will confirm all alerts
And I press the "section" delete icon
Then I do not see the "Collapse All Sections" link
And I will see a message that says "You haven't added any content to this course yet"
"""
self
.
course_outline_page
.
visit
()
self
.
course_outline_page
.
section_at
(
0
)
.
delete
()
self
.
assertEquals
(
self
.
course_outline_page
.
expand_collapse_link_state
,
ExpandCollapseLinkState
.
MISSING
)
self
.
assertTrue
(
self
.
course_outline_page
.
has_no_content_message
)
class
ExpandCollapseEmptyTest
(
CourseOutlineTest
):
"""
Feature: Courses with no sections initially can expand and collapse all sections after addition.
"""
__test__
=
True
def
populate_course_fixture
(
self
,
course_fixture
):
""" Start with an empty course """
pass
def
test_no_expand_link_for_empty_course
(
self
):
"""
Scenario: Expand/collapse for a course with no sections
Given I have a course with no sections
When I navigate to the course outline page
Then I do not see the "Collapse All Sections" link
"""
self
.
course_outline_page
.
visit
()
self
.
assertEquals
(
self
.
course_outline_page
.
expand_collapse_link_state
,
ExpandCollapseLinkState
.
MISSING
)
def
test_link_appears_after_section_creation
(
self
):
"""
Scenario: Collapse link appears after creating first section of a course
Given I have a course with no sections
When I navigate to the course outline page
And I add a section
Then I see the "Collapse All Sections" link
And all sections are expanded
"""
self
.
course_outline_page
.
visit
()
self
.
assertEquals
(
self
.
course_outline_page
.
expand_collapse_link_state
,
ExpandCollapseLinkState
.
MISSING
)
self
.
course_outline_page
.
add_section_from_top_button
()
self
.
assertEquals
(
self
.
course_outline_page
.
expand_collapse_link_state
,
ExpandCollapseLinkState
.
COLLAPSE
)
self
.
assertFalse
(
self
.
course_outline_page
.
section_at
(
0
)
.
is_collapsed
)
class
DefaultStatesEmptyTest
(
CourseOutlineTest
):
"""
Feature: Misc course outline default states/actions when starting with an empty course
"""
__test__
=
True
def
populate_course_fixture
(
self
,
course_fixture
):
""" Start with an empty course """
pass
def
test_empty_course_message
(
self
):
"""
Scenario: Empty course state
Given that I am in a course with no sections, subsections, nor units
When I visit the course outline
Then I will see a message that says "You haven't added any content to this course yet"
And see a + Add Section button
"""
self
.
course_outline_page
.
visit
()
self
.
assertTrue
(
self
.
course_outline_page
.
has_no_content_message
)
self
.
assertTrue
(
self
.
course_outline_page
.
bottom_add_section_button
.
is_present
())
class
DefaultStatesContentTest
(
CourseOutlineTest
):
"""
Feature: Misc course outline default states/actions when starting with a course with content
"""
__test__
=
True
def
test_view_live
(
self
):
"""
Scenario: View Live version from course outline
Given that I am on the course outline
When I click the "View Live" button
Then a new tab will open to the course on the LMS
"""
self
.
course_outline_page
.
visit
()
self
.
course_outline_page
.
view_live
()
courseware
=
CoursewarePage
(
self
.
browser
,
self
.
course_id
)
courseware
.
wait_for_page
()
self
.
assertEqual
(
courseware
.
num_xblock_components
,
2
)
self
.
assertEqual
(
courseware
.
xblock_component_type
(
0
),
'html'
)
self
.
assertEqual
(
courseware
.
xblock_component_type
(
1
),
'discussion'
)
class
UnitNavigationTest
(
CourseOutlineTest
):
"""
Feature: Navigate to units
"""
__test__
=
True
def
test_navigate_to_unit
(
self
):
"""
Scenario: Click unit name to navigate to unit page
Given that I have expanded a section/subsection so I can see unit names
When I click on a unit name
Then I will be taken to the appropriate unit page
"""
self
.
course_outline_page
.
visit
()
self
.
course_outline_page
.
section_at
(
0
)
.
subsection_at
(
0
)
.
toggle_expand
()
unit
=
self
.
course_outline_page
.
section_at
(
0
)
.
subsection_at
(
0
)
.
unit_at
(
0
)
.
go_to
()
self
.
assertTrue
(
unit
.
is_browser_on_page
)
common/test/acceptance/tests/test_studio_split_test.py
View file @
f31475a2
...
@@ -65,30 +65,22 @@ class SplitTestMixin(object):
...
@@ -65,30 +65,22 @@ class SplitTestMixin(object):
Promise
(
missing_groups_button_not_present
,
"Add missing groups button should not be showing."
)
.
fulfill
()
Promise
(
missing_groups_button_not_present
,
"Add missing groups button should not be showing."
)
.
fulfill
()
@attr
(
'shard_1'
)
@attr
(
'shard_1'
)
class
SplitTest
(
ContainerBase
,
SplitTestMixin
):
class
SplitTest
(
ContainerBase
):
"""
"""
Tests for creating and editing split test instances in Studio.
Tests for creating and editing split test instances in Studio.
"""
"""
__test__
=
True
__test__
=
True
def
setUp
(
self
):
super
(
SplitTest
,
self
)
.
setUp
()
# This line should be called once courseFixture is installed
self
.
course_fixture
.
_update_xblock
(
self
.
course_fixture
.
_course_location
,
{
"metadata"
:
{
u"user_partitions"
:
[
UserPartition
(
0
,
'Configuration alpha,beta'
,
'first'
,
[
Group
(
"0"
,
'alpha'
),
Group
(
"1"
,
'beta'
)])
.
to_json
(),
UserPartition
(
1
,
'Configuration 0,1,2'
,
'second'
,
[
Group
(
"0"
,
'Group 0'
),
Group
(
"1"
,
'Group 1'
),
Group
(
"2"
,
'Group 2'
)])
.
to_json
()
],
},
})
def
populate_course_fixture
(
self
,
course_fixture
):
def
populate_course_fixture
(
self
,
course_fixture
):
""" Populates the course """
course_fixture
.
add_advanced_settings
(
course_fixture
.
add_advanced_settings
(
{
u"advanced_modules"
:
{
"value"
:
[
"split_test"
]}}
{
u"advanced_modules"
:
{
"value"
:
[
"split_test"
]},
u"user_partitions"
:
{
"value"
:
[
UserPartition
(
0
,
'Configuration alpha,beta'
,
'first'
,
[
Group
(
"0"
,
'alpha'
),
Group
(
"1"
,
'beta'
)])
.
to_json
(),
UserPartition
(
1
,
'Configuration 0,1,2'
,
'second'
,
[
Group
(
"0"
,
'Group 0'
),
Group
(
"1"
,
'Group 1'
),
Group
(
"2"
,
'Group 2'
)])
.
to_json
()
]}
}
)
)
course_fixture
.
add_children
(
course_fixture
.
add_children
(
...
@@ -99,6 +91,16 @@ class SplitTest(ContainerBase, SplitTestMixin):
...
@@ -99,6 +91,16 @@ class SplitTest(ContainerBase, SplitTestMixin):
)
)
)
)
def
verify_add_missing_groups_button_not_present
(
self
,
container
):
"""
Checks that the "add missing groups" button/link is not present.
"""
def
missing_groups_button_not_present
():
button_present
=
container
.
missing_groups_button_present
()
return
(
not
button_present
,
not
button_present
)
Promise
(
missing_groups_button_not_present
,
"Add missing groups button should not be showing."
)
.
fulfill
()
def
create_poorly_configured_split_instance
(
self
):
def
create_poorly_configured_split_instance
(
self
):
"""
"""
Creates a split test instance with a missing group and an inactive group.
Creates a split test instance with a missing group and an inactive group.
...
...
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