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
f056f062
Commit
f056f062
authored
Jan 07, 2013
by
Jay Zoldak
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Set up the framework for running lettuce tests against studio
parent
7377f4bd
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
475 additions
and
1 deletions
+475
-1
.gitignore
+2
-0
cms/djangoapps/contentstore/features/common.py
+128
-0
cms/djangoapps/contentstore/features/courses.feature
+14
-0
cms/djangoapps/contentstore/features/courses.py
+50
-0
cms/djangoapps/contentstore/features/factories.py
+32
-0
cms/djangoapps/contentstore/features/section.feature
+27
-0
cms/djangoapps/contentstore/features/section.py
+82
-0
cms/djangoapps/contentstore/features/signup.feature
+13
-0
cms/djangoapps/contentstore/features/signup.py
+24
-0
cms/djangoapps/contentstore/features/subsection.feature
+18
-0
cms/djangoapps/contentstore/features/subsection.py
+40
-0
cms/envs/acceptance.py
+38
-0
lms/djangoapps/terrain/browser.py
+3
-1
lms/djangoapps/terrain/steps.py
+4
-0
No files found.
.gitignore
View file @
f056f062
...
...
@@ -27,3 +27,4 @@ lms/lib/comment_client/python
nosetests.xml
cover_html/
.idea/
chromedriver.log
\ No newline at end of file
cms/djangoapps/contentstore/features/common.py
0 → 100644
View file @
f056f062
from
lettuce
import
world
,
step
from
factories
import
*
from
django.core.management
import
call_command
from
lettuce.django
import
django_url
from
django.conf
import
settings
from
django.core.management
import
call_command
from
nose.tools
import
assert_true
from
nose.tools
import
assert_equal
import
xmodule.modulestore.django
from
logging
import
getLogger
logger
=
getLogger
(
__name__
)
########### STEP HELPERS ##############
@step
(
'I (?:visit|access|open) the Studio homepage$'
)
def
i_visit_the_studio_homepage
(
step
):
# To make this go to port 8001, put
# LETTUCE_SERVER_PORT = 8001
# in your settings.py file.
world
.
browser
.
visit
(
django_url
(
'/'
))
assert
world
.
browser
.
is_element_present_by_css
(
'body.no-header'
,
10
)
@step
(
'I am logged into Studio$'
)
def
i_am_logged_into_studio
(
step
):
log_into_studio
()
@step
(
'I confirm the alert$'
)
def
i_confirm_with_ok
(
step
):
world
.
browser
.
get_alert
()
.
accept
()
@step
(
u'I press the "([^"]*)" delete icon$'
)
def
i_press_the_category_delete_icon
(
step
,
category
):
if
category
==
'section'
:
css
=
'a.delete-button.delete-section-button span.delete-icon'
elif
category
==
'subsection'
:
css
=
'a.delete-button.delete-subsection-button span.delete-icon'
else
:
assert
False
,
'Invalid category:
%
s'
%
category
css_click
(
css
)
####### HELPER FUNCTIONS ##############
def
create_studio_user
(
uname
=
'robot'
,
em
=
'robot+studio@edx.org'
,
password
=
'test'
):
studio_user
=
UserFactory
.
build
(
username
=
uname
,
email
=
em
)
studio_user
.
set_password
(
password
)
studio_user
.
save
()
registration
=
RegistrationFactory
(
user
=
studio_user
)
registration
.
register
(
studio_user
)
registration
.
activate
()
user_profile
=
UserProfileFactory
(
user
=
studio_user
)
def
flush_xmodule_store
():
# Flush and initialize the module store
# It needs the templates because it creates new records
# by cloning from the template.
# Note that if your test module gets in some weird state
# (though it shouldn't), do this manually
# from the bash shell to drop it:
# $ mongo test_xmodule --eval "db.dropDatabase()"
xmodule
.
modulestore
.
django
.
_MODULESTORES
=
{}
xmodule
.
modulestore
.
django
.
modulestore
()
.
collection
.
drop
()
xmodule
.
templates
.
update_templates
()
def
assert_css_with_text
(
css
,
text
):
assert_true
(
world
.
browser
.
is_element_present_by_css
(
css
,
5
))
assert_equal
(
world
.
browser
.
find_by_css
(
css
)
.
text
,
text
)
def
css_click
(
css
):
world
.
browser
.
find_by_css
(
css
)
.
first
.
click
()
def
css_fill
(
css
,
value
):
world
.
browser
.
find_by_css
(
css
)
.
first
.
fill
(
value
)
def
clear_courses
():
flush_xmodule_store
()
def
fill_in_course_info
(
name
=
'Robot Super Course'
,
org
=
'MITx'
,
num
=
'101'
):
css_fill
(
'.new-course-name'
,
name
)
css_fill
(
'.new-course-org'
,
org
)
css_fill
(
'.new-course-number'
,
num
)
def
log_into_studio
(
uname
=
'robot'
,
email
=
'robot+studio@edx.org'
,
password
=
'test'
):
create_studio_user
(
uname
,
email
)
world
.
browser
.
cookies
.
delete
()
world
.
browser
.
visit
(
django_url
(
'/'
))
world
.
browser
.
is_element_present_by_css
(
'body.no-header'
,
10
)
login_form
=
world
.
browser
.
find_by_css
(
'form#login_form'
)
login_form
.
find_by_name
(
'email'
)
.
fill
(
email
)
login_form
.
find_by_name
(
'password'
)
.
fill
(
password
)
login_form
.
find_by_name
(
'submit'
)
.
click
()
assert_true
(
world
.
browser
.
is_element_present_by_css
(
'.new-course-button'
,
5
))
def
create_a_course
():
css_click
(
'a.new-course-button'
)
fill_in_course_info
()
css_click
(
'input.new-course-save'
)
assert_true
(
world
.
browser
.
is_element_present_by_css
(
'a#courseware-tab'
,
5
))
def
add_section
(
name
=
'My Section'
):
link_css
=
'a.new-courseware-section-button'
css_click
(
link_css
)
name_css
=
'.new-section-name'
save_css
=
'.new-section-name-save'
css_fill
(
name_css
,
name
)
css_click
(
save_css
)
def
add_subsection
(
name
=
'Subsection One'
):
css
=
'a.new-subsection-item'
css_click
(
css
)
name_css
=
'input.new-subsection-name-input'
save_css
=
'input.new-subsection-name-save'
css_fill
(
name_css
,
name
)
css_click
(
save_css
)
\ No newline at end of file
cms/djangoapps/contentstore/features/courses.feature
0 → 100644
View file @
f056f062
Feature
:
Create Course
In order offer a course on the edX platform
As a course author
I want to create courses
Scenario
:
Create a course
Given
There are no courses
And
I am logged into Studio
When
I click the New Course button
And
I fill in the new course information
And
I press the
"Save"
button
Then
the Courseware page has loaded in Studio
And
I see a link for adding a new section
\ No newline at end of file
cms/djangoapps/contentstore/features/courses.py
0 → 100644
View file @
f056f062
from
lettuce
import
world
,
step
from
common
import
*
############### ACTIONS ####################
@step
(
'There are no courses$'
)
def
no_courses
(
step
):
clear_courses
()
@step
(
'I click the New Course button$'
)
def
i_click_new_course
(
step
):
css_click
(
'.new-course-button'
)
@step
(
'I fill in the new course information$'
)
def
i_fill_in_a_new_course_information
(
step
):
fill_in_course_info
()
@step
(
'I create a new course$'
)
def
i_create_a_course
(
step
):
create_a_course
()
@step
(
'I click the course link in My Courses$'
)
def
i_click_the_course_link_in_my_courses
(
step
):
course_css
=
'span.class-name'
css_click
(
course_css
)
############ ASSERTIONS ###################
@step
(
'the Courseware page has loaded in Studio$'
)
def
courseware_page_has_loaded_in_studio
(
step
):
courseware_css
=
'a#courseware-tab'
assert
world
.
browser
.
is_element_present_by_css
(
courseware_css
)
@step
(
'I see the course listed in My Courses$'
)
def
i_see_the_course_in_my_courses
(
step
):
course_css
=
'span.class-name'
assert_css_with_text
(
course_css
,
'Robot Super Course'
)
@step
(
'the course is loaded$'
)
def
course_is_loaded
(
step
):
class_css
=
'a.class-name'
assert_css_with_text
(
class_css
,
'Robot Super Course'
)
@step
(
'I am on the "([^"]*)" tab$'
)
def
i_am_on_tab
(
step
,
tab_name
):
header_css
=
'div.inner-wrapper h1'
assert_css_with_text
(
header_css
,
tab_name
)
@step
(
'I see a link for adding a new section$'
)
def
i_see_new_section_link
(
step
):
link_css
=
'a.new-courseware-section-button'
assert_css_with_text
(
link_css
,
'New Section'
)
cms/djangoapps/contentstore/features/factories.py
0 → 100644
View file @
f056f062
import
factory
from
student.models
import
User
,
UserProfile
,
Registration
from
datetime
import
datetime
import
uuid
class
UserProfileFactory
(
factory
.
Factory
):
FACTORY_FOR
=
UserProfile
user
=
None
name
=
'Robot Studio'
courseware
=
'course.xml'
class
RegistrationFactory
(
factory
.
Factory
):
FACTORY_FOR
=
Registration
user
=
None
activation_key
=
uuid
.
uuid4
()
.
hex
class
UserFactory
(
factory
.
Factory
):
FACTORY_FOR
=
User
username
=
'robot-studio'
email
=
'robot+studio@edx.org'
password
=
'test'
first_name
=
'Robot'
last_name
=
'Studio'
is_staff
=
False
is_active
=
True
is_superuser
=
False
last_login
=
datetime
.
now
()
date_joined
=
datetime
.
now
()
\ No newline at end of file
cms/djangoapps/contentstore/features/section.feature
0 → 100644
View file @
f056f062
Feature
:
Create Section
In order offer a course on the edX platform
As a course author
I want to create and edit sections
Scenario
:
Add a new section to a course
Given
I have opened a new course in Studio
When
I click the New Section link
And
I enter the section name and click save
Then
I see my section on the Courseware page
And
I see a release date for my section
And
I see a link to create a new subsection
Scenario
:
Edit section release date
Given
I have opened a new course in Studio
And
I have added a new section
When
I click the Edit link for the release date
And
I save a new section release date
Then
the section release date is updated
Scenario
:
Delete section
Given
I have opened a new course in Studio
And
I have added a new section
When
I press the
"section"
delete icon
And
I confirm the alert
Then
the section does not exist
\ No newline at end of file
cms/djangoapps/contentstore/features/section.py
0 → 100644
View file @
f056f062
from
lettuce
import
world
,
step
from
common
import
*
############### ACTIONS ####################
@step
(
'I have opened a new course in Studio$'
)
def
i_have_opened_a_new_course
(
step
):
clear_courses
()
log_into_studio
()
create_a_course
()
@step
(
'I click the new section link$'
)
def
i_click_new_section_link
(
step
):
link_css
=
'a.new-courseware-section-button'
css_click
(
link_css
)
@step
(
'I enter the section name and click save$'
)
def
i_save_section_name
(
step
):
name_css
=
'.new-section-name'
save_css
=
'.new-section-name-save'
css_fill
(
name_css
,
'My Section'
)
css_click
(
save_css
)
@step
(
'I have added a new section$'
)
def
i_have_added_new_section
(
step
):
add_section
()
@step
(
'I click the Edit link for the release date$'
)
def
i_click_the_edit_link_for_the_release_date
(
step
):
button_css
=
'div.section-published-date a.edit-button'
css_click
(
button_css
)
@step
(
'I save a new section release date$'
)
def
i_save_a_new_section_release_date
(
step
):
date_css
=
'input.start-date.date.hasDatepicker'
time_css
=
'input.start-time.time.ui-timepicker-input'
css_fill
(
date_css
,
'12/25/2013'
)
# click here to make the calendar go away
css_click
(
time_css
)
css_fill
(
time_css
,
'12:00am'
)
css_click
(
'a.save-button'
)
############ ASSERTIONS ###################
@step
(
'I see my section on the Courseware page$'
)
def
i_see_my_section_on_the_courseware_page
(
step
):
section_css
=
'span.section-name-span'
assert_css_with_text
(
section_css
,
'My Section'
)
@step
(
'the section does not exist$'
)
def
section_does_not_exist
(
step
):
css
=
'span.section-name-span'
assert
world
.
browser
.
is_element_not_present_by_css
(
css
)
@step
(
'I see a release date for my section$'
)
def
i_see_a_release_date_for_my_section
(
step
):
import
re
css
=
'span.published-status'
assert
world
.
browser
.
is_element_present_by_css
(
css
)
status_text
=
world
.
browser
.
find_by_css
(
css
)
.
text
# e.g. 11/06/2012 at 16:25
msg
=
'Will Release:'
date_regex
=
'[01][0-9]
\
/[0-3][0-9]
\
/[12][0-9][0-9][0-9]'
time_regex
=
'[0-2][0-9]:[0-5][0-9]'
match_string
=
'
%
s
%
s at
%
s'
%
(
msg
,
date_regex
,
time_regex
)
assert
re
.
match
(
match_string
,
status_text
)
@step
(
'I see a link to create a new subsection$'
)
def
i_see_a_link_to_create_a_new_subsection
(
step
):
css
=
'a.new-subsection-item'
assert
world
.
browser
.
is_element_present_by_css
(
css
)
@step
(
'the section release date picker is not visible$'
)
def
the_section_release_date_picker_not_visible
(
step
):
css
=
'div.edit-subsection-publish-settings'
assert
False
,
world
.
browser
.
find_by_css
(
css
)
.
visible
@step
(
'the section release date is updated$'
)
def
the_section_release_date_is_updated
(
step
):
css
=
'span.published-status'
status_text
=
world
.
browser
.
find_by_css
(
css
)
.
text
assert
status_text
==
'Will Release: 12/25/2013 at 12:00am'
cms/djangoapps/contentstore/features/signup.feature
0 → 100644
View file @
f056f062
Feature
:
Sign in
In order to use the edX content
As a new user
I want to signup for a student account
Scenario
:
Sign up from the homepage
Given
I visit the Studio homepage
When
I click the link with the text
"Sign up"
And
I fill in the registration form
And
I press the
"Create My Account"
button on the registration form
Then
I should see be on the studio home page
And
I should see the message
"please click on the activation link in your email."
\ No newline at end of file
cms/djangoapps/contentstore/features/signup.py
0 → 100644
View file @
f056f062
from
lettuce
import
world
,
step
@step
(
'I fill in the registration form$'
)
def
i_fill_in_the_registration_form
(
step
):
register_form
=
world
.
browser
.
find_by_css
(
'form#register_form'
)
register_form
.
find_by_name
(
'email'
)
.
fill
(
'robot+studio@edx.org'
)
register_form
.
find_by_name
(
'password'
)
.
fill
(
'test'
)
register_form
.
find_by_name
(
'username'
)
.
fill
(
'robot-studio'
)
register_form
.
find_by_name
(
'name'
)
.
fill
(
'Robot Studio'
)
register_form
.
find_by_name
(
'terms_of_service'
)
.
check
()
@step
(
'I press the "([^"]*)" button on the registration form$'
)
def
i_press_the_button_on_the_registration_form
(
step
,
button
):
register_form
=
world
.
browser
.
find_by_css
(
'form#register_form'
)
register_form
.
find_by_value
(
button
)
.
click
()
@step
(
'I should see be on the studio home page$'
)
def
i_should_see_be_on_the_studio_home_page
(
step
):
assert
world
.
browser
.
find_by_css
(
'div.inner-wrapper'
)
@step
(
u'I should see the message "([^"]*)"$'
)
def
i_should_see_the_message
(
step
,
msg
):
assert
world
.
browser
.
is_text_present
(
msg
,
5
)
\ No newline at end of file
cms/djangoapps/contentstore/features/subsection.feature
0 → 100644
View file @
f056f062
Feature
:
Create Subsection
In order offer a course on the edX platform
As a course author
I want to create and edit subsections
Scenario
:
Add a new subsection to a section
Given
I have opened a new course section in Studio
When
I click the New Subsection link
And
I enter the subsection name and click save
Then
I see my subsection on the Courseware page
Scenario
:
Delete a subsection
Given
I have opened a new course section in Studio
And
I have added a new subsection
And
I see my subsection on the Courseware page
When
I press the
"subsection"
delete icon
And
I confirm the alert
Then
the subsection does not exist
cms/djangoapps/contentstore/features/subsection.py
0 → 100644
View file @
f056f062
from
lettuce
import
world
,
step
from
common
import
*
############### ACTIONS ####################
@step
(
'I have opened a new course section in Studio$'
)
def
i_have_opened_a_new_course_section
(
step
):
clear_courses
()
log_into_studio
()
create_a_course
()
add_section
()
@step
(
'I click the New Subsection link'
)
def
i_click_the_new_subsection_link
(
step
):
css
=
'a.new-subsection-item'
css_click
(
css
)
@step
(
'I enter the subsection name and click save$'
)
def
i_save_subsection_name
(
step
):
name_css
=
'input.new-subsection-name-input'
save_css
=
'input.new-subsection-name-save'
css_fill
(
name_css
,
'Subsection One'
)
css_click
(
save_css
)
@step
(
'I have added a new subsection$'
)
def
i_have_added_a_new_subsection
(
step
):
add_subsection
()
############ ASSERTIONS ###################
@step
(
'I see my subsection on the Courseware page$'
)
def
i_see_my_subsection_on_the_courseware_page
(
step
):
css
=
'span.subsection-name'
assert
world
.
browser
.
is_element_present_by_css
(
css
)
css
=
'span.subsection-name-value'
assert_css_with_text
(
css
,
'Subsection One'
)
@step
(
'the subsection does not exist$'
)
def
the_subsection_does_not_exist
(
step
):
css
=
'span.subsection-name'
assert
world
.
browser
.
is_element_not_present_by_css
(
css
)
\ No newline at end of file
cms/envs/acceptance.py
0 → 100644
View file @
f056f062
"""
This config file extends the test environment configuration
so that we can run the lettuce acceptance tests.
"""
from
.test
import
*
# You need to start the server in debug mode,
# otherwise the browser will not render the pages correctly
DEBUG
=
True
# Show the courses that are in the data directory
COURSES_ROOT
=
ENV_ROOT
/
"data"
DATA_DIR
=
COURSES_ROOT
# MODULESTORE = {
# 'default': {
# 'ENGINE': 'xmodule.modulestore.xml.XMLModuleStore',
# 'OPTIONS': {
# 'data_dir': DATA_DIR,
# 'default_class': 'xmodule.hidden_module.HiddenDescriptor',
# }
# }
# }
# Set this up so that rake lms[acceptance] and running the
# harvest command both use the same (test) database
# which they can flush without messing up your dev db
DATABASES
=
{
'default'
:
{
'ENGINE'
:
'django.db.backends.sqlite3'
,
'NAME'
:
ENV_ROOT
/
"db"
/
"test_mitx.db"
,
'TEST_NAME'
:
ENV_ROOT
/
"db"
/
"test_mitx.db"
,
}
}
# Include the lettuce app for acceptance testing, including the 'harvest' django-admin command
INSTALLED_APPS
+=
(
'lettuce.django'
,)
LETTUCE_APPS
=
(
'contentstore'
,)
LETTUCE_SERVER_PORT
=
8001
lms/djangoapps/terrain/browser.py
View file @
f056f062
...
...
@@ -11,7 +11,7 @@ from django.core.management import call_command
@before.harvest
def
initial_setup
(
server
):
# Launch firefox
world
.
browser
=
Browser
(
'
firefox
'
)
world
.
browser
=
Browser
(
'
chrome
'
)
@before.each_scenario
def
reset_data
(
scenario
):
...
...
@@ -24,3 +24,4 @@ def reset_data(scenario):
def
teardown_browser
(
total
):
# Quit firefox
world
.
browser
.
quit
()
pass
\ No newline at end of file
lms/djangoapps/terrain/steps.py
View file @
f056f062
...
...
@@ -44,6 +44,10 @@ def and_i_press_the_button(step, value):
button_css
=
'input[value="
%
s"]'
%
value
world
.
browser
.
find_by_css
(
button_css
)
.
first
.
click
()
@step
(
u'I click the link with the text "([^"]*)"$'
)
def
click_the_link_with_the_text_group1
(
step
,
linktext
):
world
.
browser
.
find_link_by_text
(
linktext
)
.
first
.
click
()
@step
(
'I should see that the path is "([^"]*)"$'
)
def
i_should_see_that_the_path_is
(
step
,
path
):
assert
world
.
browser
.
url
==
django_url
(
path
)
...
...
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