Conversion of cms/signup.feature to bok-choy
This commit is contained in:
@@ -1,44 +0,0 @@
|
||||
@shard_2
|
||||
Feature: CMS.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 an email verification prompt
|
||||
|
||||
Scenario: Login with a valid redirect
|
||||
Given I have opened a new course in Studio
|
||||
And I am not logged in
|
||||
And I visit the url "/course/slashes:MITx+999+Robot_Super_Course"
|
||||
And I should see that the path is "/signin?next=/course/slashes%3AMITx%2B999%2BRobot_Super_Course"
|
||||
When I fill in and submit the signin form
|
||||
And I wait for "2" seconds
|
||||
Then I should see that the path is "/course/slashes:MITx+999+Robot_Super_Course"
|
||||
|
||||
Scenario: Login with an invalid redirect
|
||||
Given I have opened a new course in Studio
|
||||
And I am not logged in
|
||||
And I visit the url "/signin?next=http://www.google.com/"
|
||||
When I fill in and submit the signin form
|
||||
And I wait for "2" seconds
|
||||
Then I should see that the path is "/home/"
|
||||
|
||||
Scenario: Login with mistyped credentials
|
||||
Given I have opened a new course in Studio
|
||||
And I am not logged in
|
||||
And I visit the Studio homepage
|
||||
When I click the link with the text "Sign In"
|
||||
Then I should see that the path is "/signin"
|
||||
And I should not see a login error message
|
||||
And I fill in and submit the signin form incorrectly
|
||||
Then I should see a login error message
|
||||
And I edit the password field
|
||||
Then I should not see a login error message
|
||||
And I submit the signin form
|
||||
And I wait for "2" seconds
|
||||
Then I should see that the path is "/home/"
|
||||
@@ -1,17 +0,0 @@
|
||||
"""
|
||||
Home page for Studio when not logged in.
|
||||
"""
|
||||
|
||||
from bok_choy.page_object import PageObject
|
||||
from common.test.acceptance.pages.studio import BASE_URL
|
||||
|
||||
|
||||
class HowitworksPage(PageObject):
|
||||
"""
|
||||
Home page for Studio when not logged in.
|
||||
"""
|
||||
|
||||
url = BASE_URL + "/howitworks"
|
||||
|
||||
def is_browser_on_page(self):
|
||||
return self.q(css='body.view-howitworks').present
|
||||
@@ -1,17 +1,50 @@
|
||||
"""
|
||||
Studio Home page
|
||||
Studio Index, home and dashboard pages. These are the starting pages for users.
|
||||
"""
|
||||
|
||||
from bok_choy.page_object import PageObject
|
||||
from common.test.acceptance.pages.studio import BASE_URL
|
||||
from selenium.webdriver import ActionChains
|
||||
|
||||
from common.test.acceptance.pages.studio import BASE_URL
|
||||
from common.test.acceptance.pages.studio.login import LoginPage
|
||||
from common.test.acceptance.pages.studio.signup import SignupPage
|
||||
|
||||
|
||||
class HeaderMixin(object):
|
||||
"""
|
||||
Mixin class used for the pressing buttons in the header.
|
||||
"""
|
||||
def click_sign_up(self):
|
||||
"""
|
||||
Press the Sign Up button in the header.
|
||||
"""
|
||||
next_page = SignupPage(self.browser)
|
||||
self.q(css='.action-signup')[0].click()
|
||||
return next_page.wait_for_page()
|
||||
|
||||
def click_sign_in(self):
|
||||
"""
|
||||
Press the Sign In button in the header.
|
||||
"""
|
||||
next_page = LoginPage(self.browser)
|
||||
self.q(css='.action-signin')[0].click()
|
||||
return next_page.wait_for_page()
|
||||
|
||||
|
||||
class IndexPage(PageObject, HeaderMixin):
|
||||
"""
|
||||
Home page for Studio when not logged in.
|
||||
"""
|
||||
url = BASE_URL + "/"
|
||||
|
||||
def is_browser_on_page(self):
|
||||
return self.q(css='.wrapper-text-welcome').visible
|
||||
|
||||
|
||||
class DashboardPage(PageObject):
|
||||
"""
|
||||
Studio Home page
|
||||
Studio Dashboard page with courses.
|
||||
The user must be logged in to access this page.
|
||||
"""
|
||||
|
||||
url = BASE_URL + "/course/"
|
||||
|
||||
def is_browser_on_page(self):
|
||||
@@ -79,7 +112,7 @@ class DashboardPage(PageObject):
|
||||
|
||||
def is_new_library_form_valid(self):
|
||||
"""
|
||||
IS the new library form ready to submit?
|
||||
Is the new library form ready to submit?
|
||||
"""
|
||||
return (
|
||||
self.q(css='.wrapper-create-library .new-library-save:not(.is-disabled)').present and
|
||||
@@ -237,6 +270,13 @@ class DashboardPage(PageObject):
|
||||
return self.q(css='#settings-language-value')
|
||||
|
||||
|
||||
class HomePage(DashboardPage):
|
||||
"""
|
||||
Home page for Studio when logged in.
|
||||
"""
|
||||
url = BASE_URL + "/home/"
|
||||
|
||||
|
||||
class DashboardPageWithPrograms(DashboardPage):
|
||||
"""
|
||||
Extends DashboardPage for bok choy testing programs-related behavior.
|
||||
|
||||
@@ -1,33 +1,54 @@
|
||||
"""
|
||||
Login page for Studio.
|
||||
"""
|
||||
|
||||
from bok_choy.page_object import PageObject
|
||||
from bok_choy.promise import EmptyPromise
|
||||
|
||||
from common.test.acceptance.pages.studio import BASE_URL
|
||||
from common.test.acceptance.pages.studio.course_page import CoursePage
|
||||
|
||||
|
||||
class LoginPage(PageObject):
|
||||
class LoginMixin(object):
|
||||
"""
|
||||
Login page for Studio.
|
||||
Mixin class used for logging into the system.
|
||||
"""
|
||||
|
||||
url = BASE_URL + "/signin"
|
||||
|
||||
def is_browser_on_page(self):
|
||||
return self.q(css='body.view-signin').present
|
||||
|
||||
def login(self, email, password):
|
||||
def fill_field(self, css, value):
|
||||
"""
|
||||
Attempt to log in using `email` and `password`.
|
||||
Fill the login form field with the value.
|
||||
"""
|
||||
self.q(css=css).fill(value)
|
||||
|
||||
self.q(css='input#email').fill(email)
|
||||
self.q(css='input#password').fill(password)
|
||||
def login(self, email, password, expect_success=True):
|
||||
"""
|
||||
Attempt to log in using 'email' and 'password'.
|
||||
"""
|
||||
self.fill_field('input#email', email)
|
||||
self.fill_field('input#password', password)
|
||||
self.q(css='button#submit').first.click()
|
||||
|
||||
# Ensure that we make it to another page
|
||||
EmptyPromise(
|
||||
lambda: "login" not in self.browser.current_url,
|
||||
"redirected from the login page"
|
||||
).fulfill()
|
||||
if expect_success:
|
||||
EmptyPromise(
|
||||
lambda: "signin" not in self.browser.current_url,
|
||||
"redirected from the login page"
|
||||
).fulfill()
|
||||
|
||||
|
||||
class LoginPage(PageObject, LoginMixin):
|
||||
"""
|
||||
Login page for Studio.
|
||||
"""
|
||||
url = BASE_URL + "/signin"
|
||||
|
||||
def is_browser_on_page(self):
|
||||
return self.q(css='body.view-signin').visible
|
||||
|
||||
|
||||
class CourseOutlineSignInRedirectPage(CoursePage, LoginMixin):
|
||||
"""
|
||||
Page shown when the user tries to accesses the course while not signed in.
|
||||
"""
|
||||
url_path = "course"
|
||||
|
||||
def is_browser_on_page(self):
|
||||
return self.q(css='body.view-signin').visible
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
"""
|
||||
Signup page for studio
|
||||
"""
|
||||
from bok_choy.page_object import PageObject
|
||||
|
||||
from common.test.acceptance.pages.studio import BASE_URL
|
||||
from common.test.acceptance.pages.studio.utils import set_input_value
|
||||
from common.test.acceptance.pages.common.utils import click_css
|
||||
|
||||
|
||||
class SignupPage(PageObject):
|
||||
@@ -10,4 +16,15 @@ class SignupPage(PageObject):
|
||||
url = BASE_URL + "/signup"
|
||||
|
||||
def is_browser_on_page(self):
|
||||
return self.q(css='body.view-signup').present
|
||||
return self.q(css='body.view-signup').visible
|
||||
|
||||
def sign_up_user(self, registration_dictionary):
|
||||
"""
|
||||
Register the user.
|
||||
"""
|
||||
for css, value in registration_dictionary.iteritems():
|
||||
set_input_value(self, css, value)
|
||||
|
||||
click_css(page=self, css='#tos', require_notification=False)
|
||||
click_css(page=self, css='#submit', require_notification=False)
|
||||
self.wait_for_element_absence('#submit', 'Submit button is gone.')
|
||||
|
||||
@@ -1,37 +1,36 @@
|
||||
"""
|
||||
Acceptance tests for Studio.
|
||||
"""
|
||||
import uuid
|
||||
|
||||
from bok_choy.web_app_test import WebAppTest
|
||||
|
||||
from ...pages.studio.asset_index import AssetIndexPage
|
||||
from ...pages.studio.auto_auth import AutoAuthPage
|
||||
from ...pages.studio.course_info import CourseUpdatesPage
|
||||
from ...pages.studio.edit_tabs import PagesPage
|
||||
from ...pages.studio.import_export import ExportCoursePage, ImportCoursePage
|
||||
from ...pages.studio.howitworks import HowitworksPage
|
||||
from ...pages.studio.index import DashboardPage
|
||||
from ...pages.studio.login import LoginPage
|
||||
from ...pages.studio.users import CourseTeamPage
|
||||
from ...pages.studio.overview import CourseOutlinePage
|
||||
from ...pages.studio.settings import SettingsPage
|
||||
from ...pages.studio.settings_advanced import AdvancedSettingsPage
|
||||
from ...pages.studio.settings_graders import GradingPage
|
||||
from ...pages.studio.signup import SignupPage
|
||||
from ...pages.studio.textbook_upload import TextbookUploadPage
|
||||
from ...fixtures.course import XBlockFixtureDesc
|
||||
|
||||
from base_studio_test import StudioCourseTest
|
||||
from common.test.acceptance.fixtures.course import CourseFixture, XBlockFixtureDesc
|
||||
from common.test.acceptance.pages.studio.auto_auth import AutoAuthPage
|
||||
from common.test.acceptance.pages.studio.course_info import CourseUpdatesPage
|
||||
from common.test.acceptance.pages.studio.edit_tabs import PagesPage
|
||||
from common.test.acceptance.pages.studio.import_export import ExportCoursePage, ImportCoursePage
|
||||
from common.test.acceptance.pages.studio.index import DashboardPage, HomePage, IndexPage
|
||||
from common.test.acceptance.pages.studio.login import LoginPage, CourseOutlineSignInRedirectPage
|
||||
from common.test.acceptance.pages.studio.overview import CourseOutlinePage
|
||||
from common.test.acceptance.pages.studio.asset_index import AssetIndexPage
|
||||
from common.test.acceptance.pages.studio.settings import SettingsPage
|
||||
from common.test.acceptance.pages.studio.settings_advanced import AdvancedSettingsPage
|
||||
from common.test.acceptance.pages.studio.settings_graders import GradingPage
|
||||
from common.test.acceptance.pages.studio.signup import SignupPage
|
||||
from common.test.acceptance.pages.studio.textbook_upload import TextbookUploadPage
|
||||
from common.test.acceptance.pages.studio.users import CourseTeamPage
|
||||
from common.test.acceptance.tests.helpers import UniqueCourseTest
|
||||
|
||||
|
||||
class LoggedOutTest(WebAppTest):
|
||||
"""
|
||||
Smoke test for pages in Studio that are visible when logged out.
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
super(LoggedOutTest, self).setUp()
|
||||
self.pages = [LoginPage(self.browser), HowitworksPage(self.browser), SignupPage(self.browser)]
|
||||
self.pages = [LoginPage(self.browser), IndexPage(self.browser), SignupPage(self.browser)]
|
||||
|
||||
def test_page_existence(self):
|
||||
"""
|
||||
@@ -45,21 +44,171 @@ class LoggedOutTest(WebAppTest):
|
||||
|
||||
class LoggedInPagesTest(WebAppTest):
|
||||
"""
|
||||
Tests that verify the pages in Studio that you can get to when logged
|
||||
in and do not have a course yet.
|
||||
Verify the pages in Studio that you can get to when logged in and do not have a course yet.
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
super(LoggedInPagesTest, self).setUp()
|
||||
self.auth_page = AutoAuthPage(self.browser, staff=True)
|
||||
self.dashboard_page = DashboardPage(self.browser)
|
||||
self.home_page = HomePage(self.browser)
|
||||
|
||||
def test_dashboard_no_courses(self):
|
||||
def test_logged_in_no_courses(self):
|
||||
"""
|
||||
Make sure that you can get to the dashboard page without a course.
|
||||
Make sure that you can get to the dashboard and home pages without a course.
|
||||
"""
|
||||
self.auth_page.visit()
|
||||
self.dashboard_page.visit()
|
||||
self.home_page.visit()
|
||||
|
||||
|
||||
class SignUpAndSignInTest(UniqueCourseTest):
|
||||
"""
|
||||
Test studio sign-up and sign-in
|
||||
"""
|
||||
def setUp(self): # pylint: disable=arguments-differ
|
||||
super(SignUpAndSignInTest, self).setUp()
|
||||
self.sign_up_page = SignupPage(self.browser)
|
||||
self.login_page = LoginPage(self.browser)
|
||||
|
||||
self.course_outline_page = CourseOutlinePage(
|
||||
self.browser,
|
||||
self.course_info['org'],
|
||||
self.course_info['number'],
|
||||
self.course_info['run']
|
||||
)
|
||||
self.course_outline_sign_in_redirect_page = CourseOutlineSignInRedirectPage(
|
||||
self.browser,
|
||||
self.course_info['org'],
|
||||
self.course_info['number'],
|
||||
self.course_info['run']
|
||||
)
|
||||
|
||||
self.course_fixture = CourseFixture(
|
||||
self.course_info['org'],
|
||||
self.course_info['number'],
|
||||
self.course_info['run'],
|
||||
self.course_info['display_name'],
|
||||
)
|
||||
self.user = None
|
||||
|
||||
def install_course_fixture(self):
|
||||
"""
|
||||
Install a course fixture
|
||||
"""
|
||||
self.course_fixture.install()
|
||||
self.user = self.course_fixture.user
|
||||
|
||||
def test_sign_up_from_home(self):
|
||||
"""
|
||||
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 an email verification prompt
|
||||
"""
|
||||
index_page = IndexPage(self.browser)
|
||||
index_page.visit()
|
||||
index_page.click_sign_up()
|
||||
|
||||
unique_number = uuid.uuid4().hex[:4]
|
||||
registration_dic = {
|
||||
'#email': '{}-email@host.com'.format(unique_number),
|
||||
'#name': '{}-name'.format(unique_number),
|
||||
'#username': '{}-username'.format(unique_number),
|
||||
'#password': '{}-password'.format(unique_number),
|
||||
}
|
||||
# Register the user.
|
||||
self.sign_up_page.sign_up_user(registration_dic)
|
||||
home = HomePage(self.browser)
|
||||
home.wait_for_page()
|
||||
|
||||
def test_login_with_valid_redirect(self):
|
||||
"""
|
||||
Scenario: Login with a valid redirect
|
||||
Given I have opened a new course in Studio
|
||||
And I am not logged in
|
||||
And I visit the url "/course/slashes:MITx+999+Robot_Super_Course"
|
||||
And I should see that the path is "/signin?next=/course/slashes%3AMITx%2B999%2BRobot_Super_Course"
|
||||
When I fill in and submit the signin form
|
||||
Then I should see that the path is "/course/slashes:MITx+999+Robot_Super_Course"
|
||||
"""
|
||||
self.install_course_fixture()
|
||||
# Get the url, browser should land here after sign in.
|
||||
course_url = self.course_outline_sign_in_redirect_page.url
|
||||
self.course_outline_sign_in_redirect_page.visit()
|
||||
# Login
|
||||
self.course_outline_sign_in_redirect_page.login(self.user['email'], self.user['password'])
|
||||
self.course_outline_page.wait_for_page()
|
||||
# Verify that correct course is displayed after sign in.
|
||||
self.assertEqual(self.browser.current_url, course_url)
|
||||
|
||||
def test_login_with_invalid_redirect(self):
|
||||
"""
|
||||
Scenario: Login with an invalid redirect
|
||||
Given I have opened a new course in Studio
|
||||
And I am not logged in
|
||||
And I visit the url "/signin?next=http://www.google.com/"
|
||||
When I fill in and submit the signin form
|
||||
Then I should see that the path is "/home/"
|
||||
"""
|
||||
self.install_course_fixture()
|
||||
# Visit course
|
||||
self.course_outline_sign_in_redirect_page.visit()
|
||||
# Change redirect url
|
||||
self.browser.get(self.browser.current_url.split('=')[0] + '=http://www.google.com')
|
||||
# Login
|
||||
self.course_outline_sign_in_redirect_page.login(self.user['email'], self.user['password'])
|
||||
home = HomePage(self.browser)
|
||||
home.wait_for_page()
|
||||
self.assertEqual(self.browser.current_url, home.url)
|
||||
|
||||
def test_login_with_mistyped_credentials(self):
|
||||
"""
|
||||
Given I have opened a new course in Studio
|
||||
And I am not logged in
|
||||
And I visit the Studio homepage
|
||||
When I click the link with the text "Sign In"
|
||||
Then I should see that the path is "/signin"
|
||||
And I should not see a login error message
|
||||
And I fill in and submit the signin form incorrectly
|
||||
Then I should see a login error message
|
||||
And I edit the password field
|
||||
Then I should not see a login error message
|
||||
And I submit the signin form
|
||||
And I wait for "2" seconds
|
||||
Then I should see that the path is "/course/slashes:MITx+999+Robot_Super_Course"
|
||||
"""
|
||||
self.install_course_fixture()
|
||||
self.course_outline_sign_in_redirect_page.visit()
|
||||
# Verify login_error is not present
|
||||
self.course_outline_sign_in_redirect_page.wait_for_element_absence(
|
||||
'#login_error',
|
||||
'Login error not be present'
|
||||
)
|
||||
# Login with wrong credentials
|
||||
self.course_outline_sign_in_redirect_page.login(
|
||||
self.user['email'],
|
||||
'wrong_password',
|
||||
expect_success=False
|
||||
)
|
||||
# Verify that login error is shown
|
||||
self.course_outline_sign_in_redirect_page.wait_for_element_visibility(
|
||||
'#login_error',
|
||||
'Login error is visible'
|
||||
)
|
||||
# Change the password
|
||||
self.course_outline_sign_in_redirect_page.fill_field('input#password', 'changed_password')
|
||||
# Login error should not be visible
|
||||
self.course_outline_sign_in_redirect_page.wait_for_element_invisibility(
|
||||
'#login_error',
|
||||
'Login error is not visible'
|
||||
)
|
||||
# Login with correct credentials
|
||||
self.course_outline_sign_in_redirect_page.login(self.user['email'], self.user['password'])
|
||||
self.course_outline_page.wait_for_page()
|
||||
# Verify that correct course is displayed after sign in.
|
||||
self.assertEqual(self.browser.current_url, self.course_outline_page.url)
|
||||
|
||||
|
||||
class CoursePagesTest(StudioCourseTest):
|
||||
|
||||
Reference in New Issue
Block a user