Merge pull request #8262 from open-craft/tpa-pipeline-consolidation
Cleanup of third-party login and auto-enrollment
This commit is contained in:
@@ -80,7 +80,7 @@ class FieldsMixin(object):
|
||||
query = self.q(css='.u-field-{} .u-field-message'.format(field_id))
|
||||
return query.text[0] if query.present else None
|
||||
|
||||
def wait_for_messsage(self, field_id, message):
|
||||
def wait_for_message(self, field_id, message):
|
||||
"""
|
||||
Wait for a message to appear in a field.
|
||||
"""
|
||||
|
||||
@@ -187,10 +187,14 @@ class CombinedLoginAndRegisterPage(PageObject):
|
||||
"""
|
||||
# Fill in the form
|
||||
self.wait_for_element_visibility('#register-email', 'Email field is shown')
|
||||
self.q(css="#register-email").fill(email)
|
||||
self.q(css="#register-name").fill(full_name)
|
||||
self.q(css="#register-username").fill(username)
|
||||
self.q(css="#register-password").fill(password)
|
||||
if email:
|
||||
self.q(css="#register-email").fill(email)
|
||||
if full_name:
|
||||
self.q(css="#register-name").fill(full_name)
|
||||
if username:
|
||||
self.q(css="#register-username").fill(username)
|
||||
if password:
|
||||
self.q(css="#register-password").fill(password)
|
||||
if country:
|
||||
self.q(css="#register-country option[value='{country}']".format(country=country)).click()
|
||||
if (terms_of_service):
|
||||
@@ -220,6 +224,16 @@ class CombinedLoginAndRegisterPage(PageObject):
|
||||
# Submit it
|
||||
self.q(css=".login-button").click()
|
||||
|
||||
def click_third_party_dummy_provider(self):
|
||||
"""Clicks on the Dummy third party provider login button.
|
||||
|
||||
Requires that the "login" form is visible.
|
||||
This does NOT wait for the ensuing page[s] to load.
|
||||
Only the "Dummy" provider is used for bok choy because it is the only
|
||||
one that doesn't send traffic to external servers.
|
||||
"""
|
||||
self.q(css="button.{}-Dummy".format(self.current_form)).click()
|
||||
|
||||
def password_reset(self, email):
|
||||
"""Navigates to, fills in, and submits the password reset form.
|
||||
|
||||
@@ -268,6 +282,21 @@ class CombinedLoginAndRegisterPage(PageObject):
|
||||
elif self.q(css=".js-reset").visible:
|
||||
return "password-reset"
|
||||
|
||||
@property
|
||||
def email_value(self):
|
||||
""" Current value of the email form field """
|
||||
return self.q(css="#register-email").attrs('value')[0]
|
||||
|
||||
@property
|
||||
def full_name_value(self):
|
||||
""" Current value of the full_name form field """
|
||||
return self.q(css="#register-name").attrs('value')[0]
|
||||
|
||||
@property
|
||||
def username_value(self):
|
||||
""" Current value of the username form field """
|
||||
return self.q(css="#register-username").attrs('value')[0]
|
||||
|
||||
@property
|
||||
def errors(self):
|
||||
"""Return a list of errors displayed to the user. """
|
||||
@@ -294,3 +323,15 @@ class CombinedLoginAndRegisterPage(PageObject):
|
||||
success = self.success
|
||||
return (bool(success), success)
|
||||
return Promise(_check_func, "Success message is visible").fulfill()
|
||||
|
||||
@unguarded # Because we go from this page -> temporary page -> this page again when testing the Dummy provider
|
||||
def wait_for_auth_status_message(self):
|
||||
"""Wait for a status message to be visible following third_party registration, then return it."""
|
||||
def _check_func():
|
||||
"""Return third party auth status notice message."""
|
||||
for selector in ['.already-authenticated-msg p', '.status p']:
|
||||
msg_element = self.q(css=selector)
|
||||
if msg_element.visible:
|
||||
return (True, msg_element.text[0])
|
||||
return (False, None)
|
||||
return Promise(_check_func, "Result of third party auth is visible").fulfill()
|
||||
|
||||
@@ -177,6 +177,7 @@ class AccountSettingsPageTest(AccountSettingsTestMixin, WebAppTest):
|
||||
{
|
||||
'title': 'Connected Accounts',
|
||||
'fields': [
|
||||
'Dummy',
|
||||
'Facebook',
|
||||
'Google',
|
||||
]
|
||||
@@ -211,7 +212,7 @@ class AccountSettingsPageTest(AccountSettingsTestMixin, WebAppTest):
|
||||
|
||||
for new_value in new_valid_values:
|
||||
self.assertEqual(self.account_settings_page.value_for_text_field(field_id, new_value), new_value)
|
||||
self.account_settings_page.wait_for_messsage(field_id, success_message)
|
||||
self.account_settings_page.wait_for_message(field_id, success_message)
|
||||
if assert_after_reload:
|
||||
self.browser.refresh()
|
||||
self.assertEqual(self.account_settings_page.value_for_text_field(field_id), new_value)
|
||||
@@ -227,7 +228,7 @@ class AccountSettingsPageTest(AccountSettingsTestMixin, WebAppTest):
|
||||
|
||||
for new_value in new_values:
|
||||
self.assertEqual(self.account_settings_page.value_for_dropdown_field(field_id, new_value), new_value)
|
||||
self.account_settings_page.wait_for_messsage(field_id, success_message)
|
||||
self.account_settings_page.wait_for_message(field_id, success_message)
|
||||
if reloads_on_save:
|
||||
self.account_settings_page.wait_for_loading_indicator()
|
||||
else:
|
||||
@@ -242,7 +243,7 @@ class AccountSettingsPageTest(AccountSettingsTestMixin, WebAppTest):
|
||||
self.assertEqual(self.account_settings_page.title_for_field(field_id), title)
|
||||
self.assertEqual(self.account_settings_page.link_title_for_link_field(field_id), link_title)
|
||||
self.account_settings_page.click_on_link_in_link_field(field_id)
|
||||
self.account_settings_page.wait_for_messsage(field_id, success_message)
|
||||
self.account_settings_page.wait_for_message(field_id, success_message)
|
||||
|
||||
def test_username_field(self):
|
||||
"""
|
||||
|
||||
@@ -18,6 +18,7 @@ from ..helpers import (
|
||||
select_option_by_value,
|
||||
element_has_text
|
||||
)
|
||||
from ...pages.lms.account_settings import AccountSettingsPage
|
||||
from ...pages.lms.auto_auth import AutoAuthPage
|
||||
from ...pages.lms.create_mode import ModeCreationPage
|
||||
from ...pages.common.logout import LogoutPage
|
||||
@@ -131,6 +132,46 @@ class LoginFromCombinedPageTest(UniqueCourseTest):
|
||||
self.login_page.wait_for_errors()
|
||||
)
|
||||
|
||||
def test_third_party_login(self):
|
||||
"""
|
||||
Test that we can login using third party credentials, and that the
|
||||
third party account gets linked to the edX account.
|
||||
"""
|
||||
# Create a user account
|
||||
email, password = self._create_unique_user()
|
||||
|
||||
# Navigate to the login page and try to log in using "Dummy" provider
|
||||
self.login_page.visit()
|
||||
self.login_page.click_third_party_dummy_provider()
|
||||
|
||||
# The user will be redirected somewhere and then back to the login page:
|
||||
msg_text = self.login_page.wait_for_auth_status_message()
|
||||
self.assertIn("You have successfully signed into Dummy", msg_text)
|
||||
self.assertIn("To link your accounts, sign in now using your edX password", msg_text)
|
||||
|
||||
# Now login with username and password:
|
||||
self.login_page.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)
|
||||
|
||||
# Now logout and check that we can log back in instantly (because the account is linked):
|
||||
LogoutPage(self.browser).visit()
|
||||
|
||||
self.login_page.visit()
|
||||
self.login_page.click_third_party_dummy_provider()
|
||||
|
||||
self.dashboard_page.wait_for_page()
|
||||
|
||||
# Now unlink the account (To test the account settings view and also to prevent cross-test side effects)
|
||||
account_settings = AccountSettingsPage(self.browser).visit()
|
||||
field_id = "auth-dummy"
|
||||
account_settings.wait_for_field(field_id)
|
||||
self.assertEqual("Unlink", account_settings.link_title_for_link_field(field_id))
|
||||
account_settings.click_on_link_in_link_field(field_id)
|
||||
account_settings.wait_for_message(field_id, "Successfully unlinked")
|
||||
|
||||
def _create_unique_user(self):
|
||||
"""
|
||||
Create a new user with a unique name and email.
|
||||
@@ -226,6 +267,50 @@ class RegisterFromCombinedPageTest(UniqueCourseTest):
|
||||
self.register_page.visit().toggle_form()
|
||||
self.assertEqual(self.register_page.current_form, "login")
|
||||
|
||||
def test_third_party_register(self):
|
||||
"""
|
||||
Test that we can register using third party credentials, and that the
|
||||
third party account gets linked to the edX account.
|
||||
"""
|
||||
# Navigate to the register page and try to authenticate using the "Dummy" provider
|
||||
self.register_page.visit()
|
||||
self.register_page.click_third_party_dummy_provider()
|
||||
|
||||
# The user will be redirected somewhere and then back to the register page:
|
||||
msg_text = self.register_page.wait_for_auth_status_message()
|
||||
self.assertEqual(self.register_page.current_form, "register")
|
||||
self.assertIn("You've successfully signed into Dummy", msg_text)
|
||||
self.assertIn("We just need a little more information", msg_text)
|
||||
|
||||
# Now the form should be pre-filled with the data from the Dummy provider:
|
||||
self.assertEqual(self.register_page.email_value, "adama@fleet.colonies.gov")
|
||||
self.assertEqual(self.register_page.full_name_value, "William Adama")
|
||||
self.assertIn("Galactica1", self.register_page.username_value)
|
||||
|
||||
# Set country, accept the terms, and submit the form:
|
||||
self.register_page.register(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)
|
||||
|
||||
# Now logout and check that we can log back in instantly (because the account is linked):
|
||||
LogoutPage(self.browser).visit()
|
||||
|
||||
login_page = CombinedLoginAndRegisterPage(self.browser, start_page="login")
|
||||
login_page.visit()
|
||||
login_page.click_third_party_dummy_provider()
|
||||
|
||||
self.dashboard_page.wait_for_page()
|
||||
|
||||
# Now unlink the account (To test the account settings view and also to prevent cross-test side effects)
|
||||
account_settings = AccountSettingsPage(self.browser).visit()
|
||||
field_id = "auth-dummy"
|
||||
account_settings.wait_for_field(field_id)
|
||||
self.assertEqual("Unlink", account_settings.link_title_for_link_field(field_id))
|
||||
account_settings.click_on_link_in_link_field(field_id)
|
||||
account_settings.wait_for_message(field_id, "Successfully unlinked")
|
||||
|
||||
|
||||
@attr('shard_4')
|
||||
class PayAndVerifyTest(EventsTestMixin, UniqueCourseTest):
|
||||
|
||||
@@ -2468,59 +2468,6 @@ CREATE TABLE `shoppingcart_registrationcoderedemption` (
|
||||
CONSTRAINT `registration_code_id_refs_id_4d01e47b` FOREIGN KEY (`registration_code_id`) REFERENCES `shoppingcart_courseregistrationcode` (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
DROP TABLE IF EXISTS `social_auth_association`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `social_auth_association` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`server_url` varchar(255) NOT NULL,
|
||||
`handle` varchar(255) NOT NULL,
|
||||
`secret` varchar(255) NOT NULL,
|
||||
`issued` int(11) NOT NULL,
|
||||
`lifetime` int(11) NOT NULL,
|
||||
`assoc_type` varchar(64) NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
DROP TABLE IF EXISTS `social_auth_code`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `social_auth_code` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`email` varchar(75) NOT NULL,
|
||||
`code` varchar(32) NOT NULL,
|
||||
`verified` tinyint(1) NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `email` (`email`,`code`),
|
||||
KEY `social_auth_code_65da3d2c` (`code`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
DROP TABLE IF EXISTS `social_auth_nonce`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `social_auth_nonce` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`server_url` varchar(255) NOT NULL,
|
||||
`timestamp` int(11) NOT NULL,
|
||||
`salt` varchar(65) NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
DROP TABLE IF EXISTS `social_auth_usersocialauth`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `social_auth_usersocialauth` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`user_id` int(11) NOT NULL,
|
||||
`provider` varchar(32) NOT NULL,
|
||||
`uid` varchar(255) NOT NULL,
|
||||
`extra_data` longtext NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `provider` (`provider`,`uid`),
|
||||
KEY `social_auth_usersocialauth_fbfc09f1` (`user_id`),
|
||||
CONSTRAINT `user_id_refs_id_60fa311b` FOREIGN KEY (`user_id`) REFERENCES `auth_user` (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
DROP TABLE IF EXISTS `south_migrationhistory`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
|
||||
Binary file not shown.
Reference in New Issue
Block a user