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
ffee7517
Commit
ffee7517
authored
Nov 13, 2014
by
Will Daly
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add Selenium tests for the combined login/registration form.
parent
d0c06dda
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
314 additions
and
5 deletions
+314
-5
common/test/acceptance/pages/lms/course_about.py
+1
-1
common/test/acceptance/pages/lms/login_and_register.py
+166
-4
common/test/acceptance/tests/lms/test_lms.py
+135
-0
lms/envs/bok_choy.env.json
+12
-0
No files found.
common/test/acceptance/pages/lms/course_about.py
View file @
ffee7517
...
...
@@ -3,7 +3,7 @@ Course about page (with registration button)
"""
from
.course_page
import
CoursePage
from
.register
import
RegisterPage
from
.
login_and_
register
import
RegisterPage
class
CourseAboutPage
(
CoursePage
):
...
...
common/test/acceptance/pages/lms/register.py
→
common/test/acceptance/pages/lms/
login_and_
register.py
View file @
ffee7517
"""
Registration page (create a new account)
"""
"""Login and Registration pages """
from
bok_choy.page_object
import
PageObject
from
urllib
import
urlencode
from
bok_choy.page_object
import
PageObject
,
unguarded
from
bok_choy.promise
import
Promise
,
EmptyPromise
from
.
import
BASE_URL
from
.dashboard
import
DashboardPage
...
...
@@ -48,6 +48,7 @@ class RegisterPage(PageObject):
self
.
q
(
css
=
'input#name'
)
.
fill
(
full_name
)
self
.
q
(
css
=
'input#tos-yes'
)
.
first
.
click
()
self
.
q
(
css
=
'input#honorcode-yes'
)
.
first
.
click
()
self
.
q
(
css
=
"#country option[value='US']"
)
.
first
.
click
()
def
submit
(
self
):
"""
...
...
@@ -59,3 +60,164 @@ class RegisterPage(PageObject):
dashboard
=
DashboardPage
(
self
.
browser
)
dashboard
.
wait_for_page
()
return
dashboard
class
CombinedLoginAndRegisterPage
(
PageObject
):
"""Interact with combined login and registration page.
This page is currently hidden behind the feature flag
`ENABLE_COMBINED_LOGIN_REGISTRATION`, which is enabled
in the bok choy settings.
When enabled, the new page is available from either
`/account/login` or `/account/register`.
Users can reach this page while attempting to enroll
in a course, in which case users will be auto-enrolled
when they successfully authenticate (unless the course
has been paywalled).
"""
def
__init__
(
self
,
browser
,
start_page
=
"register"
,
course_id
=
None
):
"""Initialize the page.
Arguments:
browser (Browser): The browser instance.
Keyword Args:
start_page (str): Whether to start on the login or register page.
course_id (unicode): If provided, load the page as if the user
is trying to enroll in a course.
"""
super
(
CombinedLoginAndRegisterPage
,
self
)
.
__init__
(
browser
)
self
.
_course_id
=
course_id
if
start_page
not
in
[
"register"
,
"login"
]:
raise
ValueError
(
"Start page must be either 'register' or 'login'"
)
self
.
_start_page
=
start_page
@property
def
url
(
self
):
"""Return the URL for the combined login/registration page. """
url
=
"{base}/account/{login_or_register}"
.
format
(
base
=
BASE_URL
,
login_or_register
=
self
.
_start_page
)
# These are the parameters that would be included if the user
# were trying to enroll in a course.
if
self
.
_course_id
is
not
None
:
url
+=
"?{params}"
.
format
(
params
=
urlencode
({
"course_id"
:
self
.
_course_id
,
"enrollment_action"
:
"enroll"
})
)
return
url
def
is_browser_on_page
(
self
):
"""Check whether the combined login/registration page has loaded. """
return
(
self
.
q
(
css
=
"#register-option"
)
.
is_present
()
and
self
.
q
(
css
=
"#login-option"
)
.
is_present
()
and
self
.
current_form
is
not
None
)
def
toggle_form
(
self
):
"""Toggle between the login and registration forms. """
old_form
=
self
.
current_form
# Toggle the form
self
.
q
(
css
=
".form-toggle:not(:checked)"
)
.
click
()
# Wait for the form to change before returning
EmptyPromise
(
lambda
:
self
.
current_form
!=
old_form
,
"Finish toggling to the other form"
)
.
fulfill
()
def
register
(
self
,
email
=
""
,
password
=
""
,
username
=
""
,
full_name
=
""
,
country
=
""
,
terms_of_service
=
False
):
"""Fills in and submits the registration form.
Requires that the "register" form is visible.
This does NOT wait for the next page to load,
so the caller should wait for the next page
(or errors if that's the expected behavior.)
Keyword Arguments:
email (unicode): The user's email address.
password (unicode): The user's password.
username (unicode): The user's username.
full_name (unicode): The user's full name.
country (unicode): Two-character country code.
terms_of_service (boolean): If True, agree to the terms of service and honor code.
"""
# Fill in the form
self
.
q
(
css
=
"#register-email"
)
.
fill
(
email
)
self
.
q
(
css
=
"#register-password"
)
.
fill
(
password
)
self
.
q
(
css
=
"#register-username"
)
.
fill
(
username
)
self
.
q
(
css
=
"#register-name"
)
.
fill
(
full_name
)
if
country
:
self
.
q
(
css
=
"#register-country option[value='{country}']"
.
format
(
country
=
country
))
.
click
()
if
(
terms_of_service
):
self
.
q
(
css
=
"#register-honor_code"
)
.
click
()
# Submit it
self
.
q
(
css
=
".register-button"
)
.
click
()
def
login
(
self
,
email
=
""
,
password
=
""
,
remember_me
=
True
):
"""Fills in and submits the login form.
Requires that the "login" form is visible.
This does NOT wait for the next page to load,
so the caller should wait for the next page
(or errors if that's the expected behavior).
Keyword Arguments:
email (unicode): The user's email address.
password (unicode): The user's password.
remember_me (boolean): If True, check the "remember me" box.
"""
# Fill in the form
self
.
q
(
css
=
"#login-email"
)
.
fill
(
email
)
self
.
q
(
css
=
"#login-password"
)
.
fill
(
password
)
if
remember_me
:
self
.
q
(
css
=
"#login-remember"
)
.
click
()
# Submit it
self
.
q
(
css
=
".login-button"
)
.
click
()
@property
@unguarded
def
current_form
(
self
):
"""Return the form that is currently visible to the user.
Returns:
Either "register", "login", or "password-reset" if a valid
form is loaded.
If we can't find any of these forms on the page, return None.
"""
if
self
.
q
(
css
=
".register-button"
)
.
visible
:
return
"register"
elif
self
.
q
(
css
=
".login-button"
)
.
visible
:
return
"login"
elif
self
.
q
(
css
=
".js-reset"
)
.
visible
:
return
"password-reset"
@property
def
errors
(
self
):
"""Return a list of errors displayed to the user. """
return
self
.
q
(
css
=
".submission-error li"
)
.
text
def
wait_for_errors
(
self
):
"""Wait for errors to be visible, then return them. """
def
_check_func
():
errors
=
self
.
errors
return
(
bool
(
errors
),
errors
)
return
Promise
(
_check_func
,
"Errors are visible"
)
.
fulfill
()
common/test/acceptance/tests/lms/test_lms.py
View file @
ffee7517
...
...
@@ -5,10 +5,12 @@ End-to-end tests for the LMS.
from
textwrap
import
dedent
from
unittest
import
skip
from
nose.plugins.attrib
import
attr
from
bok_choy.web_app_test
import
WebAppTest
from
..helpers
import
UniqueCourseTest
,
load_data_str
from
...pages.lms.auto_auth
import
AutoAuthPage
from
...pages.common.logout
import
LogoutPage
from
...pages.lms.find_courses
import
FindCoursesPage
from
...pages.lms.course_about
import
CourseAboutPage
from
...pages.lms.course_info
import
CourseInfoPage
...
...
@@ -19,6 +21,7 @@ from ...pages.lms.dashboard import DashboardPage
from
...pages.lms.problem
import
ProblemPage
from
...pages.lms.video.video
import
VideoPage
from
...pages.lms.courseware
import
CoursewarePage
from
...pages.lms.login_and_register
import
CombinedLoginAndRegisterPage
from
...fixtures.course
import
CourseFixture
,
XBlockFixtureDesc
,
CourseUpdateDesc
...
...
@@ -64,6 +67,138 @@ class RegistrationTest(UniqueCourseTest):
self
.
assertIn
(
self
.
course_info
[
'display_name'
],
course_names
)
@attr
(
'shard_1'
)
class
LoginFromCombinedPageTest
(
UniqueCourseTest
):
"""Test that we can log in using the combined login/registration page. """
def
setUp
(
self
):
"""Initialize the page objects and create a test course. """
super
(
LoginFromCombinedPageTest
,
self
)
.
setUp
()
self
.
login_page
=
CombinedLoginAndRegisterPage
(
self
.
browser
,
start_page
=
"login"
,
course_id
=
self
.
course_id
)
self
.
dashboard_page
=
DashboardPage
(
self
.
browser
)
# Create a course to enroll in
CourseFixture
(
self
.
course_info
[
'org'
],
self
.
course_info
[
'number'
],
self
.
course_info
[
'run'
],
self
.
course_info
[
'display_name'
]
)
.
install
()
def
test_login_success
(
self
):
# Create a user account
email
,
password
=
self
.
_create_unique_user
()
# Navigate to the login page and try to log in
self
.
login_page
.
visit
()
.
login
(
email
=
email
,
password
=
password
)
# Expect that we reach the dashboard and we're auto-enrolled in the course
course_names
=
self
.
dashboard_page
.
wait_for_page
()
.
available_courses
self
.
assertIn
(
self
.
course_info
[
"display_name"
],
course_names
)
def
test_login_failure
(
self
):
# Navigate to the login page
self
.
login_page
.
visit
()
# User account does not exist
self
.
login_page
.
login
(
email
=
"nobody@nowhere.com"
,
password
=
"password"
)
# Verify that an error is displayed
self
.
assertIn
(
"Email or password is incorrect."
,
self
.
login_page
.
wait_for_errors
())
def
test_toggle_to_register_form
(
self
):
self
.
login_page
.
visit
()
.
toggle_form
()
self
.
assertEqual
(
self
.
login_page
.
current_form
,
"register"
)
def
_create_unique_user
(
self
):
username
=
"test_{uuid}"
.
format
(
uuid
=
self
.
unique_id
[
0
:
6
])
email
=
"{user}@example.com"
.
format
(
user
=
username
)
password
=
"password"
# Create the user (automatically logs us in)
AutoAuthPage
(
self
.
browser
,
username
=
username
,
email
=
email
,
password
=
password
)
.
visit
()
# Log out
LogoutPage
(
self
.
browser
)
.
visit
()
return
(
email
,
password
)
@attr
(
'shard_1'
)
class
RegisterFromCombinedPageTest
(
UniqueCourseTest
):
"""Test that we can register a new user from the combined login/registration page. """
def
setUp
(
self
):
"""Initialize the page objects and create a test course. """
super
(
RegisterFromCombinedPageTest
,
self
)
.
setUp
()
self
.
register_page
=
CombinedLoginAndRegisterPage
(
self
.
browser
,
start_page
=
"register"
,
course_id
=
self
.
course_id
)
self
.
dashboard_page
=
DashboardPage
(
self
.
browser
)
# Create a course to enroll in
CourseFixture
(
self
.
course_info
[
'org'
],
self
.
course_info
[
'number'
],
self
.
course_info
[
'run'
],
self
.
course_info
[
'display_name'
]
)
.
install
()
def
test_register_success
(
self
):
# Navigate to the registration page
self
.
register_page
.
visit
()
# Fill in the form and submit it
username
=
"test_{uuid}"
.
format
(
uuid
=
self
.
unique_id
[
0
:
6
])
email
=
"{user}@example.com"
.
format
(
user
=
username
)
self
.
register_page
.
register
(
email
=
email
,
password
=
"password"
,
username
=
username
,
full_name
=
"Test User"
,
country
=
"US"
,
terms_of_service
=
True
)
# Expect that we reach the dashboard and we're auto-enrolled in the course
course_names
=
self
.
dashboard_page
.
wait_for_page
()
.
available_courses
self
.
assertIn
(
self
.
course_info
[
"display_name"
],
course_names
)
def
test_register_failure
(
self
):
# Navigate to the registration page
self
.
register_page
.
visit
()
# Enter a blank for the username field, which is required
# Don't agree to the terms of service / honor code.
# Don't specify a country code, which is required.
username
=
"test_{uuid}"
.
format
(
uuid
=
self
.
unique_id
[
0
:
6
])
email
=
"{user}@example.com"
.
format
(
user
=
username
)
self
.
register_page
.
register
(
email
=
email
,
password
=
"password"
,
username
=
""
,
full_name
=
"Test User"
,
terms_of_service
=
False
)
# Verify that the expected errors are displayed.
errors
=
self
.
register_page
.
wait_for_errors
()
self
.
assertIn
(
u'The Username field cannot be empty.'
,
errors
)
self
.
assertIn
(
u'You must agree to the edX Terms of Service and Honor Code.'
,
errors
)
self
.
assertIn
(
u'The Country field cannot be empty.'
,
errors
)
def
test_toggle_to_login_form
(
self
):
self
.
register_page
.
visit
()
.
toggle_form
()
self
.
assertEqual
(
self
.
register_page
.
current_form
,
"login"
)
class
LanguageTest
(
WebAppTest
):
"""
Tests that the change language functionality on the dashboard works
...
...
lms/envs/bok_choy.env.json
View file @
ffee7517
...
...
@@ -69,6 +69,7 @@
"ENABLE_INSTRUCTOR_ANALYTICS"
:
true
,
"ENABLE_S3_GRADE_DOWNLOADS"
:
true
,
"ENABLE_THIRD_PARTY_AUTH"
:
true
,
"ENABLE_COMBINED_LOGIN_REGISTRATION"
:
true
,
"PREVIEW_LMS_BASE"
:
"localhost:8003"
,
"SUBDOMAIN_BRANDING"
:
false
,
"SUBDOMAIN_COURSE_LISTINGS"
:
false
...
...
@@ -82,6 +83,17 @@
"MEDIA_URL"
:
""
,
"MKTG_URL_LINK_MAP"
:
{},
"PLATFORM_NAME"
:
"edX"
,
"REGISTRATION_EXTRA_FIELDS"
:
{
"level_of_education"
:
"optional"
,
"gender"
:
"optional"
,
"year_of_birth"
:
"optional"
,
"mailing_address"
:
"optional"
,
"goals"
:
"optional"
,
"honor_code"
:
"required"
,
"terms_of_service"
:
"hidden"
,
"city"
:
"hidden"
,
"country"
:
"required"
},
"SEGMENT_IO_LMS"
:
true
,
"SERVER_EMAIL"
:
"devops@example.com"
,
"SESSION_COOKIE_DOMAIN"
:
null
,
...
...
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