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
3257a7ba
Commit
3257a7ba
authored
Oct 06, 2013
by
Will Daly
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Refactored navigation feature
Fixed grading tests
parent
4bb9dcf1
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
237 additions
and
186 deletions
+237
-186
cms/djangoapps/contentstore/features/common.py
+9
-25
cms/djangoapps/contentstore/features/component_settings_editor_helpers.py
+9
-7
cms/djangoapps/contentstore/features/grading.py
+25
-13
cms/djangoapps/contentstore/features/video-editor.py
+20
-13
common/djangoapps/terrain/course_helpers.py
+6
-6
common/djangoapps/terrain/ui_helpers.py
+46
-3
lms/djangoapps/courseware/features/navigation.feature
+12
-11
lms/djangoapps/courseware/features/navigation.py
+110
-108
No files found.
cms/djangoapps/contentstore/features/common.py
View file @
3257a7ba
...
...
@@ -2,7 +2,7 @@
# pylint: disable=W0621
from
lettuce
import
world
,
step
from
nose.tools
import
assert_true
,
assert_in
,
assert_false
# pylint: disable=E0611
from
nose.tools
import
assert_true
,
assert_
equal
,
assert_
in
,
assert_false
# pylint: disable=E0611
from
auth.authz
import
get_user_by_email
,
get_course_groupname_for_role
from
django.conf
import
settings
...
...
@@ -64,32 +64,16 @@ def select_new_course(_step, whom):
@step
(
u'I press the "([^"]*)" notification button$'
)
def
press_the_notification_button
(
_step
,
name
):
# TODO: fix up this code. Selenium is not dealing well with css transforms,
# as it thinks that the notification and the buttons are always visible
# First wait for the notification to pop up
notification_css
=
'div#page-notification div.wrapper-notification'
world
.
wait_for_visible
(
notification_css
)
# You would think that the above would have worked, but it doesn't.
# Brute force wait for now.
world
.
wait
(
.
5
)
# Now make sure the button is there
# Because the notification uses a CSS transition,
# Selenium will always report it as being visible.
# This makes it very difficult to successfully click
# the "Save" button at the UI level.
# Instead, we use JavaScript to reliably click
# the button.
btn_css
=
'div#page-notification a.action-
%
s'
%
name
.
lower
()
world
.
wait_for_visible
(
btn_css
)
# You would think that the above would have worked, but it doesn't.
# Brute force wait for now.
world
.
wait
(
.
5
)
if
world
.
is_firefox
():
# This is done to explicitly make the changes save on firefox.
# It will remove focus from the previously focused element
world
.
trigger_event
(
btn_css
,
event
=
'focus'
)
world
.
browser
.
execute_script
(
"$('{}').click()"
.
format
(
btn_css
))
else
:
world
.
css_click
(
btn_css
)
world
.
trigger_event
(
btn_css
,
event
=
'focus'
)
world
.
browser
.
execute_script
(
"$('{}').click()"
.
format
(
btn_css
))
world
.
wait_for_ajax_complete
()
...
...
cms/djangoapps/contentstore/features/component_settings_editor_helpers.py
View file @
3257a7ba
...
...
@@ -2,7 +2,7 @@
#pylint: disable=C0111
from
lettuce
import
world
from
nose.tools
import
assert_equal
# pylint: disable=E0611
from
nose.tools
import
assert_equal
,
assert_true
# pylint: disable=E0611
from
terrain.steps
import
reload_the_page
...
...
@@ -12,9 +12,13 @@ def create_component_instance(step, component_button_css, category,
has_multiple_templates
=
True
):
click_new_component_button
(
step
,
component_button_css
)
if
category
in
(
'problem'
,
'html'
):
def
animation_done
(
_driver
):
return
world
.
browser
.
evaluate_script
(
"$('div.new-component').css('display')"
)
==
'none'
script
=
"$('div.new-component').css('display')"
return
world
.
browser
.
evaluate_script
(
script
)
==
'none'
world
.
wait_for
(
animation_done
)
if
has_multiple_templates
:
...
...
@@ -23,10 +27,7 @@ def create_component_instance(step, component_button_css, category,
if
category
in
(
'video'
,):
world
.
wait_for_xmodule
()
assert_equal
(
1
,
len
(
world
.
css_find
(
expected_css
)),
"Component instance with css {css} was not created successfully"
.
format
(
css
=
expected_css
))
assert_true
(
world
.
is_css_present
(
expected_css
))
@world.absorb
...
...
@@ -34,7 +35,8 @@ def click_new_component_button(step, component_button_css):
step
.
given
(
'I have clicked the new unit button'
)
world
.
wait_for_requirejs
(
[
"jquery"
,
"js/models/course"
,
"coffee/src/models/module"
,
"coffee/src/views/unit"
,
"jquery.ui"
])
"coffee/src/views/unit"
,
"jquery.ui"
]
)
world
.
css_click
(
component_button_css
)
...
...
cms/djangoapps/contentstore/features/grading.py
View file @
3257a7ba
...
...
@@ -6,7 +6,7 @@ from common import *
from
terrain.steps
import
reload_the_page
from
selenium.common.exceptions
import
(
InvalidElementStateException
,
WebDriverException
)
from
nose.tools
import
assert_in
,
assert_not_in
# pylint: disable=E0611
from
nose.tools
import
assert_in
,
assert_not_in
,
assert_equal
,
assert_not_equal
# pylint: disable=E0611
@step
(
u'I am viewing the grading settings'
)
...
...
@@ -36,7 +36,7 @@ def delete_grade(step):
def
view_grade_slider
(
step
,
how_many
):
grade_slider_css
=
'.grade-specific-bar'
all_grades
=
world
.
css_find
(
grade_slider_css
)
assert
len
(
all_grades
)
==
int
(
how_many
)
assert
_equal
(
len
(
all_grades
),
int
(
how_many
)
)
@step
(
u'I move a grading section'
)
...
...
@@ -51,7 +51,7 @@ def confirm_change(step):
range_css
=
'.range'
all_ranges
=
world
.
css_find
(
range_css
)
for
i
in
range
(
len
(
all_ranges
)):
assert
world
.
css_html
(
range_css
,
index
=
i
)
!=
'0-50'
assert
_not_equal
(
world
.
css_html
(
range_css
,
index
=
i
),
'0-50'
)
@step
(
u'I change assignment type "([^"]*)" to "([^"]*)"$'
)
...
...
@@ -59,7 +59,7 @@ def change_assignment_name(step, old_name, new_name):
name_id
=
'#course-grading-assignment-name'
index
=
get_type_index
(
old_name
)
f
=
world
.
css_find
(
name_id
)[
index
]
assert
index
!=
-
1
assert
_not_equal
(
index
,
-
1
)
for
count
in
range
(
len
(
old_name
)):
f
.
_element
.
send_keys
(
Keys
.
END
,
Keys
.
BACK_SPACE
)
f
.
_element
.
send_keys
(
new_name
)
...
...
@@ -78,7 +78,10 @@ def main_course_page(step):
def
see_assignment_name
(
step
,
do_not
,
name
):
assignment_menu_css
=
'ul.menu > li > a'
# First assert that it is there, make take a bit to redraw
assert
world
.
css_find
(
assignment_menu_css
)
assert_true
(
world
.
css_find
(
assignment_menu_css
),
msg
=
"Could not find assignment menu"
)
assignment_menu
=
world
.
css_find
(
assignment_menu_css
)
allnames
=
[
item
.
html
for
item
in
assignment_menu
]
...
...
@@ -113,7 +116,7 @@ def populate_course(step):
def
changes_not_persisted
(
step
):
reload_the_page
(
step
)
name_id
=
'#course-grading-assignment-name'
assert
(
world
.
css_value
(
name_id
)
==
'Homework'
)
assert
_equal
(
world
.
css_value
(
name_id
),
'Homework'
)
@step
(
u'I see the assignment type "(.*)"$'
)
...
...
@@ -121,7 +124,7 @@ def i_see_the_assignment_type(_step, name):
assignment_css
=
'#course-grading-assignment-name'
assignments
=
world
.
css_find
(
assignment_css
)
types
=
[
ele
[
'value'
]
for
ele
in
assignments
]
assert
name
in
types
assert
_in
(
name
,
types
)
@step
(
u'I change the highest grade range to "(.*)"$'
)
...
...
@@ -135,15 +138,15 @@ def change_grade_range(_step, range_name):
def
i_see_highest_grade_range
(
_step
,
range_name
):
range_css
=
'span.letter-grade'
grade
=
world
.
css_find
(
range_css
)
.
first
assert
grade
.
value
==
range_name
,
"{0} != {1}"
.
format
(
grade
.
value
,
range_name
)
assert
_equal
(
grade
.
value
,
range_name
)
@step
(
u'I cannot edit the "Fail" grade range$'
)
def
cannot_edit_fail
(
_step
):
range_css
=
'span.letter-grade'
ranges
=
world
.
css_find
(
range_css
)
assert
len
(
ranges
)
==
2
assert
ranges
.
last
.
value
!=
'Failure'
assert
_equal
(
len
(
ranges
),
2
)
assert
_not_equal
(
ranges
.
last
.
value
,
'Failure'
)
# try to change the grade range -- this should throw an exception
try
:
...
...
@@ -153,14 +156,23 @@ def cannot_edit_fail(_step):
# check to be sure that nothing has changed
ranges
=
world
.
css_find
(
range_css
)
assert
len
(
ranges
)
==
2
assert
ranges
.
last
.
value
!=
'Failure'
assert
_equal
(
len
(
ranges
),
2
)
assert
_not_equal
(
ranges
.
last
.
value
,
'Failure'
)
@step
(
u'I change the grace period to "(.*)"$'
)
def
i_change_grace_period
(
_step
,
grace_period
):
grace_period_css
=
'#course-grading-graceperiod'
ele
=
world
.
css_find
(
grace_period_css
)
.
first
# Sometimes it takes a moment for the JavaScript
# to populate the field. If we don't wait for
# this to happen, then we can end up with
# an invalid value (e.g. "00:0048:00")
# which prevents us from saving.
assert_true
(
world
.
css_has_value
(
grace_period_css
,
"00:00"
,
allow_blank
=
False
))
# Set the new grace period
ele
.
value
=
grace_period
...
...
@@ -168,7 +180,7 @@ def i_change_grace_period(_step, grace_period):
def
the_grace_period_is
(
_step
,
grace_period
):
grace_period_css
=
'#course-grading-graceperiod'
ele
=
world
.
css_find
(
grace_period_css
)
.
first
assert
ele
.
value
==
grace_period
assert
_equal
(
ele
.
value
,
grace_period
)
def
get_type_index
(
name
):
...
...
cms/djangoapps/contentstore/features/video-editor.py
View file @
3257a7ba
...
...
@@ -32,18 +32,21 @@ def shows_captions(_step, show_captions):
@step
(
'I see the correct video settings and default values$'
)
def
correct_video_settings
(
_step
):
world
.
verify_all_setting_entries
([[
'Display Name'
,
'Video'
,
False
],
[
'Download Track'
,
''
,
False
],
[
'Download Video'
,
''
,
False
],
[
'End Time'
,
'0'
,
False
],
[
'HTML5 Timed Transcript'
,
''
,
False
],
[
'Show Captions'
,
'True'
,
False
],
[
'Start Time'
,
'0'
,
False
],
[
'Video Sources'
,
''
,
False
],
[
'Youtube ID'
,
'OEoXaMPEzfM'
,
False
],
[
'Youtube ID for .75x speed'
,
''
,
False
],
[
'Youtube ID for 1.25x speed'
,
''
,
False
],
[
'Youtube ID for 1.5x speed'
,
''
,
False
]])
expected_entries
=
[
[
'Display Name'
,
'Video'
,
False
],
[
'Download Track'
,
''
,
False
],
[
'Download Video'
,
''
,
False
],
[
'End Time'
,
'0'
,
False
],
[
'HTML5 Timed Transcript'
,
''
,
False
],
[
'Show Captions'
,
'True'
,
False
],
[
'Start Time'
,
'0'
,
False
],
[
'Video Sources'
,
''
,
False
],
[
'Youtube ID'
,
'OEoXaMPEzfM'
,
False
],
[
'Youtube ID for .75x speed'
,
''
,
False
],
[
'Youtube ID for 1.25x speed'
,
''
,
False
],
[
'Youtube ID for 1.5x speed'
,
''
,
False
]
]
world
.
verify_all_setting_entries
(
expected_entries
)
@step
(
'my video display name change is persisted on save$'
)
...
...
@@ -52,4 +55,8 @@ def video_name_persisted(step):
reload_the_page
(
step
)
world
.
wait_for_xmodule
()
world
.
edit_component
()
world
.
verify_setting_entry
(
world
.
get_setting_entry
(
'Display Name'
),
'Display Name'
,
'3.4'
,
True
)
world
.
verify_setting_entry
(
world
.
get_setting_entry
(
'Display Name'
),
'Display Name'
,
'3.4'
,
True
)
common/djangoapps/terrain/course_helpers.py
View file @
3257a7ba
...
...
@@ -41,13 +41,13 @@ def log_in(username='robot', password='test', email='robot@edx.org', name='Robot
@world.absorb
def
register_by_course_id
(
course_id
,
is_staff
=
False
):
create_user
(
'robot'
,
'password'
)
u
=
User
.
objects
.
get
(
username
=
'robot'
)
def
register_by_course_id
(
course_id
,
username
=
'robot'
,
password
=
'test'
,
is_staff
=
False
):
create_user
(
username
,
password
)
u
ser
=
User
.
objects
.
get
(
username
=
username
)
if
is_staff
:
u
.
is_staff
=
True
u
.
save
()
CourseEnrollment
.
enroll
(
u
,
course_id
)
u
ser
.
is_staff
=
True
u
ser
.
save
()
CourseEnrollment
.
enroll
(
u
ser
,
course_id
)
@world.absorb
...
...
common/djangoapps/terrain/ui_helpers.py
View file @
3257a7ba
...
...
@@ -34,7 +34,7 @@ def wait(seconds):
def
wait_for_js_variable_truthy
(
variable
):
"""
Using Selenium's `execute_async_script` function, poll the Javascript
envi
or
nment until the given variable is defined and truthy. This process
envi
ro
nment until the given variable is defined and truthy. This process
guards against page reloads, and seamlessly retries on the next page.
"""
js
=
"""
...
...
@@ -194,8 +194,51 @@ def is_css_not_present(css_selector, wait_time=5):
@world.absorb
def
css_has_text
(
css_selector
,
text
,
index
=
0
):
return
world
.
css_text
(
css_selector
,
index
=
index
)
==
text
def
css_has_text
(
css_selector
,
text
,
index
=
0
,
strip
=
False
,
allow_blank
=
True
):
"""
Return a boolean indicating whether the element with `css_selector`
has `text`.
If `strip` is True, strip whitespace at beginning/end of both
strings before comparing.
If `allow_blank` is False, wait for the element to have non-empty
text before making the assertion. This is useful for elements
that are populated by JavaScript after the page loads.
If there are multiple elements matching the css selector,
use `index` to indicate which one.
"""
if
not
allow_blank
:
world
.
wait_for
(
lambda
_
:
world
.
css_text
(
css_selector
,
index
=
index
))
actual_text
=
world
.
css_text
(
css_selector
,
index
=
index
)
if
strip
:
actual_text
=
actual_text
.
strip
()
text
=
text
.
strip
()
return
actual_text
==
text
@world.absorb
def
css_has_value
(
css_selector
,
value
,
index
=
0
,
allow_blank
=
False
):
"""
Return a boolean indicating whether the element with
`css_selector` has the specified `value`.
If `allow_blank` is False, wait for the element to have
a value that is a non-empty string.
If there are multiple elements matching the css selector,
use `index` to indicate which one.
"""
if
not
allow_blank
:
world
.
wait_for
(
lambda
_
:
world
.
css_value
(
css_selector
,
index
=
index
))
return
world
.
css_value
(
css_selector
,
index
=
index
)
==
value
@world.absorb
...
...
lms/djangoapps/courseware/features/navigation.feature
View file @
3257a7ba
@shard_1
Feature
:
LMS.Navigate Course
As a student in an edX course
In order to
view the course properly
In order to
access courseware
I want to be able to navigate through the content
Scenario
:
I
can navigate to a section
Given
I am viewing a course with multiple sections
When
I
click on section
"2"
Then
I s
hould see the content of section
"2"
When
I
navigate to a section
Then
I s
ee the content of the section
Scenario
:
I
can navigate to subsections
Given
I am viewing a section with multiple subsections
When
I
click on subsection
"2"
Then
I s
hould see the content of subsection
"2"
When
I
navigate to a subsection
Then
I s
ee the content of the subsection
Scenario
:
I
can navigate to sequences
Given
I am viewing a section with multiple sequences
When
I
click on sequence
"2"
Then
I s
hould see the content of sequence
"2"
When
I
navigate to an item in a sequence
Then
I s
ee the content of the sequence item
Scenario
:
I
can
go back to where I was after I log out and back in
Scenario
:
I
can
return to the last section I visited
Given
I am viewing a course with multiple sections
When
I click on section
"2"
And
I return later
Then
I should see that I was most recently in section
"2"
When
I navigate to a section
And
I see the content of the section
And
I return to the courseware
Then
I see that I was most recently in the subsection
lms/djangoapps/courseware/features/navigation.py
View file @
3257a7ba
...
...
@@ -2,37 +2,39 @@
#pylint: disable=W0621
from
lettuce
import
world
,
step
from
django.contrib.auth.models
import
User
from
lettuce.django
import
django_url
from
student.models
import
CourseEnrollment
from
common
import
course_id
,
course_location
from
problems_setup
import
PROBLEM_DICT
TEST_SECTION_NAME
=
'Test Section'
TEST_SUBSECTION_NAME
=
'Test Subsection'
from
nose.tools
import
assert_in
@step
(
u'I am viewing a course with multiple sections'
)
def
view_course_multiple_sections
(
step
):
create_course
()
# Add a section to the course to contain problems
section1
=
world
.
ItemFactory
.
create
(
parent_location
=
course_location
(
world
.
scenario_dict
[
'COURSE'
]
.
number
),
display_name
=
section_name
(
1
))
# Add a section to the course to contain problems
section2
=
world
.
ItemFactory
.
create
(
parent_location
=
course_location
(
world
.
scenario_dict
[
'COURSE'
]
.
number
),
display_name
=
section_name
(
2
))
section1
=
world
.
ItemFactory
.
create
(
parent_location
=
course_location
(
world
.
scenario_dict
[
'COURSE'
]
.
number
),
display_name
=
"Test Section 1"
)
section2
=
world
.
ItemFactory
.
create
(
parent_location
=
course_location
(
world
.
scenario_dict
[
'COURSE'
]
.
number
),
display_name
=
"Test Section 2"
)
place1
=
world
.
ItemFactory
.
create
(
parent_location
=
section1
.
location
,
category
=
'sequential'
,
display_name
=
subsection_name
(
1
))
place1
=
world
.
ItemFactory
.
create
(
parent_location
=
section1
.
location
,
category
=
'sequential'
,
display_name
=
"Test Subsection 1"
)
place2
=
world
.
ItemFactory
.
create
(
parent_location
=
section2
.
location
,
category
=
'sequential'
,
display_name
=
subsection_name
(
2
))
place2
=
world
.
ItemFactory
.
create
(
parent_location
=
section2
.
location
,
category
=
'sequential'
,
display_name
=
"Test Subsection 2"
)
add_problem_to_course_section
(
'model_course'
,
'multiple choice'
,
place1
.
location
)
add_problem_to_course_section
(
'model_course'
,
'drop down'
,
place2
.
location
)
add_problem_to_course_section
(
place1
.
location
,
"Problem 1"
)
add_problem_to_course_section
(
place2
.
location
,
"Problem 2"
)
create_user_and_visit_course
()
...
...
@@ -41,19 +43,24 @@ def view_course_multiple_sections(step):
def
view_course_multiple_subsections
(
step
):
create_course
()
# Add a section to the course to contain problems
section1
=
world
.
ItemFactory
.
create
(
parent_location
=
course_location
(
world
.
scenario_dict
[
'COURSE'
]
.
number
),
display_name
=
section_name
(
1
))
section1
=
world
.
ItemFactory
.
create
(
parent_location
=
course_location
(
world
.
scenario_dict
[
'COURSE'
]
.
number
),
display_name
=
"Test Section 1"
)
place1
=
world
.
ItemFactory
.
create
(
parent_location
=
section1
.
location
,
category
=
'sequential'
,
display_name
=
subsection_name
(
1
))
place1
=
world
.
ItemFactory
.
create
(
parent_location
=
section1
.
location
,
category
=
'sequential'
,
display_name
=
"Test Subsection 1"
)
place2
=
world
.
ItemFactory
.
create
(
parent_location
=
section1
.
location
,
display_name
=
subsection_name
(
2
))
place2
=
world
.
ItemFactory
.
create
(
parent_location
=
section1
.
location
,
display_name
=
"Test Subsection 2"
)
add_problem_to_course_section
(
'model_course'
,
'multiple choice'
,
place1
.
location
)
add_problem_to_course_section
(
'model_course'
,
'drop down'
,
place2
.
location
)
add_problem_to_course_section
(
place1
.
location
,
"Problem 3"
)
add_problem_to_course_section
(
place2
.
location
,
"Problem 4"
)
create_user_and_visit_course
()
...
...
@@ -61,121 +68,116 @@ def view_course_multiple_subsections(step):
@step
(
u'I am viewing a section with multiple sequences'
)
def
view_course_multiple_sequences
(
step
):
create_course
()
# Add a section to the course to contain problems
section1
=
world
.
ItemFactory
.
create
(
parent_location
=
course_location
(
world
.
scenario_dict
[
'COURSE'
]
.
number
),
display_name
=
section_name
(
1
))
place1
=
world
.
ItemFactory
.
create
(
parent_location
=
section1
.
location
,
category
=
'sequential'
,
display_name
=
subsection_name
(
1
))
section1
=
world
.
ItemFactory
.
create
(
parent_location
=
course_location
(
world
.
scenario_dict
[
'COURSE'
]
.
number
),
display_name
=
"Test Section 1"
)
add_problem_to_course_section
(
'model_course'
,
'multiple choice'
,
place1
.
location
)
add_problem_to_course_section
(
'model_course'
,
'drop down'
,
place1
.
location
)
place1
=
world
.
ItemFactory
.
create
(
parent_location
=
section1
.
location
,
category
=
'sequential'
,
display_name
=
"Test Subsection 1"
)
add_problem_to_course_section
(
place1
.
location
,
"Problem 5"
)
add_problem_to_course_section
(
place1
.
location
,
"Problem 6"
)
create_user_and_visit_course
()
@step
(
u'I
click on section "([^"]*)"$
'
)
def
click_on_section
(
step
,
section
):
@step
(
u'I
navigate to a section
'
)
def
when_i_navigate_to_a_section
(
step
):
section_css
=
'h3[tabindex="-1"]'
world
.
css_click
(
section_css
)
subid
=
"ui-accordion-accordion-panel-{}"
.
format
(
str
(
int
(
section
)
-
1
))
subid
=
"ui-accordion-accordion-panel-1"
world
.
wait_for_visible
(
"#"
+
subid
)
subsection_css
=
"ul.ui-accordion-content-active[id='{}'] > li > a"
.
format
(
subid
)
world
.
css_click
(
subsection_css
)
@step
(
u'I
click on subsection "([^"]*)"$
'
)
def
click_on_subsection
(
step
,
subsection
):
@step
(
u'I
navigate to a subsection
'
)
def
when_i_navigate_to_a_subsection
(
step
):
subsection_css
=
'ul[id="ui-accordion-accordion-panel-0"]> li > a'
world
.
css_click
(
subsection_css
,
index
=
(
int
(
subsection
)
-
1
)
)
world
.
css_click
(
subsection_css
,
index
=
1
)
@step
(
u'I
click on sequence "([^"]*)"$
'
)
def
click_on_sequence
(
step
,
sequence
):
sequence_css
=
'a[data-element="
%
s"]'
%
sequence
@step
(
u'I
navigate to an item in a sequence
'
)
def
when_i_navigate_to_an_item_in_a_sequence
(
step
):
sequence_css
=
'a[data-element="
2"]'
world
.
css_click
(
sequence_css
)
@step
(
u'I should see the content of (?:sub)?section "([^"]*)"$'
)
def
see_section_content
(
step
,
section
):
world
.
wait
(
0.5
)
if
section
==
"2"
:
text
=
'The correct answer is Option 2'
elif
section
==
"1"
:
text
=
'The correct answer is Choice 3'
step
.
given
(
'I should see "'
+
text
+
'" somewhere on the page'
)
@step
(
u'I see the content of the section'
)
def
then_i_see_the_content_of_the_section
(
step
):
wait_for_problem
(
'PROBLEM 2'
)
@step
(
u'I should see the content of sequence "([^"]*)"$'
)
def
see_sequence_content
(
step
,
sequence
):
step
.
given
(
'I should see the content of section "2"'
)
@step
(
u'I return later'
)
def
return_to_course
(
step
):
step
.
given
(
'I visit the homepage'
)
world
.
click_link
(
"View Course"
)
world
.
click_link
(
"Courseware"
)
@step
(
u'I see the content of the subsection'
)
def
then_i_see_the_content_of_the_subsection
(
step
):
wait_for_problem
(
'PROBLEM 4'
)
@step
(
u'I should see that I was most recently in section "([^"]*)"$'
)
def
see_recent_section
(
step
,
section
):
step
.
given
(
'I should see "You were most recently in
%
s" somewhere on the page'
%
subsection_name
(
int
(
section
)))
#####################
# HELPERS
#####################
@step
(
u'I see the content of the sequence item'
)
def
then_i_see_the_content_of_the_sequence_item
(
step
):
wait_for_problem
(
'PROBLEM 6'
)
def
section_name
(
section
):
return
TEST_SECTION_NAME
+
str
(
section
)
@step
(
u'I return to the courseware'
)
def
and_i_return_to_the_courseware
(
step
):
world
.
visit
(
'/'
)
world
.
click_link
(
"View Course"
)
world
.
click_link
(
"Courseware"
)
def
subsection_name
(
section
):
return
TEST_SUBSECTION_NAME
+
str
(
section
)
@step
(
u'I see that I was most recently in the subsection'
)
def
then_i_see_that_i_was_most_recently_in_the_subsection
(
step
):
message
=
world
.
css_text
(
'section.course-content > p'
)
assert_in
(
"You were most recently in Test Subsection 2"
,
message
)
def
create_course
():
world
.
clear_courses
()
world
.
scenario_dict
[
'COURSE'
]
=
world
.
CourseFactory
.
create
(
org
=
'edx'
,
number
=
'model_course'
,
display_name
=
'Test Course'
)
world
.
scenario_dict
[
'COURSE'
]
=
world
.
CourseFactory
.
create
(
org
=
'edx'
,
number
=
'999'
,
display_name
=
'Test Course'
)
def
create_user_and_visit_course
():
world
.
create_user
(
'robot'
,
'test'
)
u
=
User
.
objects
.
get
(
username
=
'robot'
)
world
.
register_by_course_id
(
'edx/999/Test_Course'
)
world
.
log_in
()
world
.
visit
(
'/courses/edx/999/Test_Course/courseware/'
)
CourseEnrollment
.
enroll
(
u
,
course_id
(
world
.
scenario_dict
[
'COURSE'
]
.
number
))
world
.
log_in
(
username
=
'robot'
,
password
=
'test'
)
chapter_name
=
(
TEST_SECTION_NAME
+
"1"
)
.
replace
(
" "
,
"_"
)
section_name
=
(
TEST_SUBSECTION_NAME
+
"1"
)
.
replace
(
" "
,
"_"
)
url
=
django_url
(
'/courses/edx/model_course/Test_Course/courseware/
%
s/
%
s'
%
(
chapter_name
,
section_name
))
def
add_problem_to_course_section
(
parent_location
,
display_name
):
"""
Add a problem to the course at `parent_location` (a `Location` instance)
world
.
browser
.
visit
(
url
)
def
add_problem_to_course_section
(
course
,
problem_type
,
parent_location
,
extraMeta
=
None
):
'''
Add a problem to the course we have created using factories.
'''
assert
(
problem_type
in
PROBLEM_DICT
)
`display_name` is the name of the problem to display, which
is useful to identify which problem we're looking at.
"""
# Generate the problem XML using capa.tests.response_xml_factory
factory_dict
=
PROBLEM_DICT
[
problem_type
]
# Since this is just a placeholder, we always use multiple choice.
factory_dict
=
PROBLEM_DICT
[
'multiple choice'
]
problem_xml
=
factory_dict
[
'factory'
]
.
build_xml
(
**
factory_dict
[
'kwargs'
])
metadata
=
{
'rerandomize'
:
'always'
}
if
not
'metadata'
in
factory_dict
else
factory_dict
[
'metadata'
]
if
extraMeta
:
metadata
=
dict
(
metadata
,
**
extraMeta
)
# Create a problem item using our generated XML
# We set rerandomize=always in the metadata so that the "Reset" button
# will appear.
world
.
ItemFactory
.
create
(
parent_location
=
parent_location
,
category
=
'problem'
,
display_name
=
str
(
problem_type
),
data
=
problem_xml
,
metadata
=
metadata
)
# Add the problem
world
.
ItemFactory
.
create
(
parent_location
=
parent_location
,
category
=
'problem'
,
display_name
=
display_name
,
data
=
problem_xml
)
def
wait_for_problem
(
display_name
):
"""
Wait for the problem with `display_name` to appear on the page.
"""
wait_func
=
lambda
_
:
world
.
css_has_text
(
'h2.problem-header'
,
display_name
,
strip
=
True
)
world
.
wait_for
(
wait_func
)
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