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
2ce1540a
Commit
2ce1540a
authored
Aug 25, 2014
by
zubair-arbi
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
update/cleanup code + move verify_ordering and drag method to studio utils
parent
b6a23306
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
105 additions
and
163 deletions
+105
-163
common/test/acceptance/pages/studio/container.py
+1
-23
common/test/acceptance/pages/studio/overview.py
+44
-78
common/test/acceptance/pages/studio/utils.py
+45
-0
common/test/acceptance/tests/base_studio_test.py
+3
-24
common/test/acceptance/tests/test_studio_bad_data.py
+2
-1
common/test/acceptance/tests/test_studio_container.py
+4
-4
common/test/acceptance/tests/test_studio_outline.py
+6
-33
No files found.
common/test/acceptance/pages/studio/container.py
View file @
2ce1540a
...
...
@@ -6,9 +6,7 @@ from bok_choy.page_object import PageObject
from
bok_choy.promise
import
Promise
,
EmptyPromise
from
.
import
BASE_URL
from
selenium.webdriver.common.action_chains
import
ActionChains
from
utils
import
click_css
,
wait_for_notification
,
confirm_prompt
from
utils
import
click_css
,
confirm_prompt
class
ContainerPage
(
PageObject
):
...
...
@@ -220,26 +218,6 @@ class ContainerPage(PageObject):
return
self
.
q
(
css
=
prefix
+
XBlockWrapper
.
BODY_SELECTOR
)
.
map
(
lambda
el
:
XBlockWrapper
(
self
.
browser
,
el
.
get_attribute
(
'data-locator'
)))
.
results
def
drag
(
self
,
source_index
,
target_index
):
"""
Gets the drag handle with index source_index (relative to the vertical layout of the page)
and drags it to the location of the drag handle with target_index.
This should drag the element with the source_index drag handle BEFORE the
one with the target_index drag handle.
"""
draggables
=
self
.
q
(
css
=
'.drag-handle'
)
source
=
draggables
[
source_index
]
target
=
draggables
[
target_index
]
action
=
ActionChains
(
self
.
browser
)
# When dragging before the target element, must take into account that the placeholder
# will appear in the place where the target used to be.
placeholder_height
=
40
action
.
click_and_hold
(
source
)
.
move_to_element_with_offset
(
target
,
0
,
placeholder_height
)
.
release
()
.
perform
()
wait_for_notification
(
self
)
def
duplicate
(
self
,
source_index
):
"""
Duplicate the item with index source_index (based on vertical placement in page).
...
...
common/test/acceptance/pages/studio/overview.py
View file @
2ce1540a
...
...
@@ -12,7 +12,7 @@ from selenium.webdriver.common.action_chains import ActionChains
from
.course_page
import
CoursePage
from
.container
import
ContainerPage
from
.utils
import
set_input_value_and_save
,
set_input_value
,
click_css
,
confirm_prompt
,
wait_for_notification
from
.utils
import
set_input_value_and_save
,
set_input_value
,
click_css
,
confirm_prompt
class
CourseOutlineItem
(
object
):
...
...
@@ -256,6 +256,9 @@ class CourseOutlineChild(PageObject, CourseOutlineItem):
"""
A page object that will be used as a child of :class:`CourseOutlineContainer`.
"""
url
=
None
BODY_SELECTOR
=
'.outline-item'
def
__init__
(
self
,
browser
,
locator
):
super
(
CourseOutlineChild
,
self
)
.
__init__
(
browser
)
self
.
locator
=
locator
...
...
@@ -270,6 +273,39 @@ class CourseOutlineChild(PageObject, CourseOutlineItem):
click_css
(
self
,
self
.
_bounded_selector
(
'.delete-button'
),
require_notification
=
False
)
confirm_prompt
(
self
,
cancel
)
def
_bounded_selector
(
self
,
selector
):
"""
Return `selector`, but limited to this particular `CourseOutlineChild` context
"""
return
'{}[data-locator="{}"] {}'
.
format
(
self
.
BODY_SELECTOR
,
self
.
locator
,
selector
)
@property
def
name
(
self
):
titles
=
self
.
q
(
css
=
self
.
_bounded_selector
(
self
.
NAME_SELECTOR
))
.
text
if
titles
:
return
titles
[
0
]
else
:
return
None
@property
def
children
(
self
):
"""
Will return any first-generation descendant items of this item.
"""
descendants
=
self
.
q
(
css
=
self
.
_bounded_selector
(
self
.
BODY_SELECTOR
))
.
map
(
lambda
el
:
CourseOutlineChild
(
self
.
browser
,
el
.
get_attribute
(
'data-locator'
)))
.
results
# Now remove any non-direct descendants.
grandkids
=
[]
for
descendant
in
descendants
:
grandkids
.
extend
(
descendant
.
children
)
grand_locators
=
[
grandkid
.
locator
for
grandkid
in
grandkids
]
return
[
descendant
for
descendant
in
descendants
if
not
descendant
.
locator
in
grand_locators
]
class
CourseOutlineUnit
(
CourseOutlineChild
):
"""
...
...
@@ -289,8 +325,11 @@ class CourseOutlineUnit(CourseOutlineChild):
def
is_browser_on_page
(
self
):
return
self
.
q
(
css
=
self
.
BODY_SELECTOR
)
.
present
def
children
(
self
):
return
self
.
q
(
css
=
self
.
_bounded_selector
(
self
.
BODY_SELECTOR
))
.
map
(
lambda
el
:
CourseOutlineUnit
(
self
.
browser
,
el
.
get_attribute
(
'data-locator'
)))
.
results
class
CourseOutlineSubsection
(
CourseOutlineC
hild
,
CourseOutlineContainer
):
class
CourseOutlineSubsection
(
CourseOutlineC
ontainer
,
CourseOutlineChild
):
"""
:class`.PageObject` that wraps a subsection block on the Studio Course Outline page.
"""
...
...
@@ -326,7 +365,7 @@ class CourseOutlineSubsection(CourseOutlineChild, CourseOutlineContainer):
self
.
q
(
css
=
self
.
_bounded_selector
(
self
.
ADD_BUTTON_SELECTOR
))
.
click
()
class
CourseOutlineSection
(
CourseOutlineC
hild
,
CourseOutlineContainer
):
class
CourseOutlineSection
(
CourseOutlineC
ontainer
,
CourseOutlineChild
):
"""
:class`.PageObject` that wraps a section block on the Studio Course Outline page.
"""
...
...
@@ -512,85 +551,12 @@ class CourseOutlinePage(CoursePage, CourseOutlineContainer):
subsection
.
toggle_expand
()
@property
def
outline_item
s
(
self
):
def
xblock
s
(
self
):
"""
Return a list of xblocks loaded on the outline page.
"""
return
self
.
_get_outline_items
()
def
_get_outline_items
(
self
,
prefix
=
""
):
return
self
.
q
(
css
=
prefix
+
OutlineWrapper
.
BODY_SELECTOR
)
.
map
(
lambda
el
:
OutlineWrapper
(
self
.
browser
,
el
.
get_attribute
(
'data-locator'
)))
.
results
def
drag
(
self
,
source_index
,
target_index
):
"""
Gets the drag handle with index source_index (relative to the vertical layout of the page)
and drags it to the location of the drag handle with target_index.
This should drag the element with the source_index drag handle BEFORE the
one with the target_index drag handle.
"""
draggables
=
self
.
q
(
css
=
'.drag-handle'
)
source
=
draggables
[
source_index
]
target
=
draggables
[
target_index
]
action
=
ActionChains
(
self
.
browser
)
# When dragging before the target element, must take into account that the placeholder
# will appear in the place where the target used to be.
placeholder_height
=
40
action
.
click_and_hold
(
source
)
.
move_to_element_with_offset
(
target
,
0
,
placeholder_height
)
.
release
()
.
perform
()
wait_for_notification
(
self
)
class
OutlineWrapper
(
PageObject
):
"""
A PageObject representing a wrapper around course outline items shown on the Course Outline page.
"""
url
=
None
BODY_SELECTOR
=
'.outline-item'
NAME_SELECTOR
=
'.item-title'
def
__init__
(
self
,
browser
,
locator
):
super
(
OutlineWrapper
,
self
)
.
__init__
(
browser
)
self
.
locator
=
locator
def
is_browser_on_page
(
self
):
return
self
.
q
(
css
=
'{}[data-locator="{}"]'
.
format
(
self
.
BODY_SELECTOR
,
self
.
locator
))
.
present
def
_bounded_selector
(
self
,
selector
):
"""
Return `selector`, but limited to this particular `CourseOutlineChild` context
"""
return
'{}[data-locator="{}"] {}'
.
format
(
self
.
BODY_SELECTOR
,
self
.
locator
,
selector
)
return
self
.
children
(
CourseOutlineChild
)
@property
def
name
(
self
):
titles
=
self
.
q
(
css
=
self
.
_bounded_selector
(
self
.
NAME_SELECTOR
))
.
text
if
titles
:
return
titles
[
0
]
else
:
return
None
@property
def
children
(
self
):
"""
Will return any first-generation descendant items of this item.
"""
descendants
=
self
.
q
(
css
=
self
.
_bounded_selector
(
self
.
BODY_SELECTOR
))
.
map
(
lambda
el
:
OutlineWrapper
(
self
.
browser
,
el
.
get_attribute
(
'data-locator'
)))
.
results
# Now remove any non-direct descendants.
grandkids
=
[]
for
descendant
in
descendants
:
grandkids
.
extend
(
descendant
.
children
)
grand_locators
=
[
grandkid
.
locator
for
grandkid
in
grandkids
]
return
[
descendant
for
descendant
in
descendants
if
not
descendant
.
locator
in
grand_locators
]
class
CourseOutlineModal
(
object
):
MODAL_SELECTOR
=
".wrapper-modal-window"
...
...
common/test/acceptance/pages/studio/utils.py
View file @
2ce1540a
...
...
@@ -148,3 +148,48 @@ def set_input_value_and_save(page, css, value):
Sets the text field with given label (display name) to the specified value, and presses Save.
"""
set_input_value
(
page
,
css
,
value
)
.
send_keys
(
Keys
.
ENTER
)
def
drag
(
page
,
source_index
,
target_index
,
placeholder_height
=
0
):
"""
Gets the drag handle with index source_index (relative to the vertical layout of the page)
and drags it to the location of the drag handle with target_index.
This should drag the element with the source_index drag handle BEFORE the
one with the target_index drag handle.
"""
draggables
=
page
.
q
(
css
=
'.drag-handle'
)
source
=
draggables
[
source_index
]
target
=
draggables
[
target_index
]
action
=
ActionChains
(
page
.
browser
)
action
.
click_and_hold
(
source
)
.
move_to_element_with_offset
(
target
,
0
,
placeholder_height
)
if
placeholder_height
==
0
:
action
.
release
(
target
)
.
perform
()
else
:
action
.
release
()
.
perform
()
wait_for_notification
(
page
)
def
verify_ordering
(
test_class
,
page
,
expected_orderings
):
"""
Verifies the expected ordering of xblocks on the page.
"""
xblocks
=
page
.
xblocks
blocks_checked
=
set
()
for
expected_ordering
in
expected_orderings
:
for
xblock
in
xblocks
:
parent
=
expected_ordering
.
keys
()[
0
]
if
xblock
.
name
==
parent
:
blocks_checked
.
add
(
parent
)
children
=
xblock
.
children
expected_length
=
len
(
expected_ordering
.
get
(
parent
))
test_class
.
assertEqual
(
expected_length
,
len
(
children
),
"Number of children incorrect for group {0}. Expected {1} but got {2}."
.
format
(
parent
,
expected_length
,
len
(
children
)))
for
idx
,
expected
in
enumerate
(
expected_ordering
.
get
(
parent
)):
test_class
.
assertEqual
(
expected
,
children
[
idx
]
.
name
)
blocks_checked
.
add
(
expected
)
break
test_class
.
assertEqual
(
len
(
blocks_checked
),
len
(
xblocks
))
common/test/acceptance/tests/base_studio_test.py
View file @
2ce1540a
...
...
@@ -2,6 +2,7 @@ from ..pages.studio.auto_auth import AutoAuthPage
from
..fixtures.course
import
CourseFixture
from
.helpers
import
UniqueCourseTest
from
..pages.studio.overview
import
CourseOutlinePage
from
..pages.studio.utils
import
verify_ordering
class
StudioCourseTest
(
UniqueCourseTest
):
"""
...
...
@@ -84,28 +85,6 @@ class ContainerBase(StudioCourseTest):
subsection
=
self
.
outline
.
section
(
section_name
)
.
subsection
(
subsection_name
)
return
subsection
.
toggle_expand
()
.
unit
(
unit_name
)
.
go_to
()
def
verify_ordering
(
self
,
container
,
expected_orderings
):
"""
Verifies the expected ordering of xblocks on the page.
"""
xblocks
=
container
.
xblocks
blocks_checked
=
set
()
for
expected_ordering
in
expected_orderings
:
for
xblock
in
xblocks
:
parent
=
expected_ordering
.
keys
()[
0
]
if
xblock
.
name
==
parent
:
blocks_checked
.
add
(
parent
)
children
=
xblock
.
children
expected_length
=
len
(
expected_ordering
.
get
(
parent
))
self
.
assertEqual
(
expected_length
,
len
(
children
),
"Number of children incorrect for group {0}. Expected {1} but got {2}."
.
format
(
parent
,
expected_length
,
len
(
children
)))
for
idx
,
expected
in
enumerate
(
expected_ordering
.
get
(
parent
)):
self
.
assertEqual
(
expected
,
children
[
idx
]
.
name
)
blocks_checked
.
add
(
expected
)
break
self
.
assertEqual
(
len
(
blocks_checked
),
len
(
xblocks
))
def
do_action_and_verify
(
self
,
action
,
expected_ordering
):
"""
Perform the supplied action and then verify the resulting ordering.
...
...
@@ -113,8 +92,8 @@ class ContainerBase(StudioCourseTest):
container
=
self
.
go_to_nested_container_page
()
action
(
container
)
self
.
verify_ordering
(
container
,
expected_ordering
)
verify_ordering
(
self
,
container
,
expected_ordering
)
# Reload the page to see that the change was persisted.
container
=
self
.
go_to_nested_container_page
()
self
.
verify_ordering
(
container
,
expected_ordering
)
verify_ordering
(
self
,
container
,
expected_ordering
)
common/test/acceptance/tests/test_studio_bad_data.py
View file @
2ce1540a
from
nose.plugins.attrib
import
attr
from
.base_studio_test
import
ContainerBase
from
..fixtures.course
import
XBlockFixtureDesc
from
..pages.studio.utils
import
verify_ordering
@attr
(
'shard_1'
)
...
...
@@ -38,7 +39,7 @@ class BadComponentTest(ContainerBase):
displaying the components on the unit page.
"""
unit
=
self
.
go_to_unit_page
()
self
.
verify_ordering
(
unit
,
[{
""
:
[
"Unit HTML"
,
"Unit Problem"
]}])
verify_ordering
(
self
,
unit
,
[{
""
:
[
"Unit HTML"
,
"Unit Problem"
]}])
@attr
(
'shard_1'
)
...
...
common/test/acceptance/tests/test_studio_container.py
View file @
2ce1540a
...
...
@@ -8,7 +8,7 @@ from nose.plugins.attrib import attr
from
..fixtures.course
import
XBlockFixtureDesc
from
..pages.studio.component_editor
import
ComponentEditorView
from
..pages.studio.html_component_editor
import
HtmlComponentEditorView
from
..pages.studio.utils
import
add_discussion
from
..pages.studio.utils
import
add_discussion
,
drag
from
..pages.lms.courseware
import
CoursewarePage
from
..pages.lms.staff_view
import
StaffPage
...
...
@@ -75,7 +75,7 @@ class DragAndDropTest(NestedVerticalTest):
def
drag_and_verify
(
self
,
source
,
target
,
expected_ordering
):
self
.
do_action_and_verify
(
lambda
(
container
):
container
.
drag
(
source
,
target
),
lambda
(
container
):
drag
(
container
,
source
,
target
,
40
),
expected_ordering
)
...
...
@@ -133,9 +133,9 @@ class DragAndDropTest(NestedVerticalTest):
first_handle
=
self
.
group_a_item_1_handle
# Drag newly added video component to top.
container
.
drag
(
first_handle
+
3
,
first_handle
)
drag
(
container
,
first_handle
+
3
,
first_handle
,
40
)
# Drag duplicated component to top.
container
.
drag
(
first_handle
+
2
,
first_handle
)
drag
(
container
,
first_handle
+
2
,
first_handle
,
40
)
duplicate_label
=
self
.
duplicate_label
.
format
(
self
.
group_a_item_1
)
...
...
common/test/acceptance/tests/test_studio_outline.py
View file @
2ce1540a
...
...
@@ -9,7 +9,7 @@ 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.studio.utils
import
add_discussion
,
drag
,
verify_ordering
from
..pages.lms.courseware
import
CoursewarePage
from
..pages.lms.course_nav
import
CourseNavPage
from
..pages.lms.staff_view
import
StaffPage
...
...
@@ -49,37 +49,10 @@ class CourseOutlineTest(StudioCourseTest):
XBlockFixtureDesc
(
'html'
,
'Test HTML Component'
),
XBlockFixtureDesc
(
'discussion'
,
'Test Discussion Component'
)
)
),
XBlockFixtureDesc
(
'sequential'
,
"DropS"
)
.
add_children
(
XBlockFixtureDesc
(
'vertical'
,
"DropV"
)
.
add_children
(
XBlockFixtureDesc
(
'problem'
,
'Drop Problem 1'
,
data
=
load_data_str
(
'multiple_choice.xml'
)),
)
)
)
)
def
verify_ordering
(
self
,
outline_page
,
expected_orderings
):
"""
Verifies the expected ordering of xblocks on the page.
"""
xblocks
=
outline_page
.
outline_items
blocks_checked
=
set
()
for
expected_ordering
in
expected_orderings
:
for
xblock
in
xblocks
:
parent
=
expected_ordering
.
keys
()[
0
]
if
xblock
.
name
==
parent
:
blocks_checked
.
add
(
parent
)
children
=
xblock
.
children
expected_length
=
len
(
expected_ordering
.
get
(
parent
))
self
.
assertEqual
(
expected_length
,
len
(
children
),
"Number of children incorrect for group {0}. Expected {1} but got {2}."
.
format
(
parent
,
expected_length
,
len
(
children
)))
for
idx
,
expected
in
enumerate
(
expected_ordering
.
get
(
parent
)):
self
.
assertEqual
(
expected
,
children
[
idx
]
.
name
)
blocks_checked
.
add
(
expected
)
break
self
.
assertEqual
(
len
(
blocks_checked
),
len
(
xblocks
))
def
do_action_and_verify
(
self
,
outline_page
,
action
,
expected_ordering
):
"""
Perform the supplied action and then verify the resulting ordering.
...
...
@@ -88,12 +61,12 @@ class CourseOutlineTest(StudioCourseTest):
outline_page
=
self
.
course_outline_page
.
visit
()
action
(
outline_page
)
self
.
verify_ordering
(
outline_page
,
expected_ordering
)
verify_ordering
(
self
,
outline_page
,
expected_ordering
)
# Reload the page and expand all subsections to see that the change was persisted.
course_
outline_page
=
self
.
course_outline_page
.
visit
()
course_
outline_page
.
q
(
css
=
'.outline-item.outline-subsection.is-collapsed .ui-toggle-expansion'
)
.
click
()
self
.
verify_ordering
(
course_
outline_page
,
expected_ordering
)
outline_page
=
self
.
course_outline_page
.
visit
()
outline_page
.
q
(
css
=
'.outline-item.outline-subsection.is-collapsed .ui-toggle-expansion'
)
.
click
()
verify_ordering
(
self
,
outline_page
,
expected_ordering
)
@attr
(
'shard_2'
)
...
...
@@ -132,7 +105,7 @@ class CourseOutlineDragAndDropTest(CourseOutlineTest):
def
drag_and_verify
(
self
,
source
,
target
,
expected_ordering
,
outline_page
=
None
):
self
.
do_action_and_verify
(
outline_page
,
lambda
(
outline
):
outline
.
drag
(
source
,
target
),
lambda
(
outline
):
drag
(
outline
,
source
,
target
),
expected_ordering
)
...
...
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