Commit dab69c8f authored by sullivan's avatar sullivan Committed by Commit bot

Revert of Revert of Add support for codepen to...

Revert of Revert of  Add support for codepen to form_based_credentials_background (patchset #9 of https://codereview.chromium.org/485743002/)

Reason for revert:
I believe the flakiness may have been fixed by https://codereview.chromium.org/520683002

BUG=

Review URL: https://codereview.chromium.org/531733004

Cr-Commit-Position: refs/heads/master@{#292950}
parent afba6145
11752daf3b27c9ced2d530b5241cab7e5b109dd9 3a0f9c995a41e058857af7d9c2e265b046ba96e6
\ No newline at end of file \ No newline at end of file
# Copyright 2014 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
from telemetry.core.backends import form_based_credentials_backend
class CodePenCredentialsBackend(
form_based_credentials_backend.FormBasedCredentialsBackend):
@property
def logged_in_javascript(self):
"""Evaluates to true iff already logged in."""
return 'document.querySelector(".login-area") === null'
@property
def credentials_type(self):
return 'codepen'
@property
def url(self):
return 'https://codepen.io/login'
@property
def login_form_id(self):
return 'login-login-form'
@property
def login_button_javascript(self):
return """
LoginSettings.timeOnPageStartTime = 0;
document.getElementById("log-in-button").click();
"""
@property
def login_input_id(self):
return 'login-email-field'
@property
def password_input_id(self):
return 'login-password-field_'
# Copyright 2014 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
from telemetry.core.backends import form_based_credentials_backend_unittest_base
from telemetry.core.backends import codepen_credentials_backend
class TestCodePenCredentialsBackend(
form_based_credentials_backend_unittest_base.
FormBasedCredentialsBackendUnitTestBase):
def setUp(self):
self._credentials_type = 'codepen'
def testLoginUsingMock(self):
backend = codepen_credentials_backend.CodePenCredentialsBackend()
self._LoginUsingMock(backend, backend.url, backend.login_input_id,
backend.password_input_id, backend.login_form_id,
backend.logged_in_javascript)
...@@ -7,10 +7,12 @@ from telemetry.core.backends import form_based_credentials_backend ...@@ -7,10 +7,12 @@ from telemetry.core.backends import form_based_credentials_backend
class FacebookCredentialsBackend( class FacebookCredentialsBackend(
form_based_credentials_backend.FormBasedCredentialsBackend): form_based_credentials_backend.FormBasedCredentialsBackend):
def IsAlreadyLoggedIn(self, tab):
return tab.EvaluateJavaScript( @property
'document.getElementById("fbNotificationsList")!== null || ' def logged_in_javascript(self):
'document.getElementById("m_home_notice")!== null') """Evaluates to true iff already logged in."""
return ('document.getElementById("fbNotificationsList")!== null || '
'document.getElementById("m_home_notice")!== null')
@property @property
def credentials_type(self): def credentials_type(self):
......
...@@ -13,6 +13,7 @@ class TestFacebookCredentialsBackend( ...@@ -13,6 +13,7 @@ class TestFacebookCredentialsBackend(
self._credentials_type = 'facebook' self._credentials_type = 'facebook'
def testLoginUsingMock(self): def testLoginUsingMock(self):
self._LoginUsingMock( backend = facebook_credentials_backend.FacebookCredentialsBackend()
facebook_credentials_backend.FacebookCredentialsBackend(), self._LoginUsingMock(backend, backend.url, backend.login_input_id,
'http://www.facebook.com/', 'email', 'pass') backend.password_input_id, backend.login_form_id,
backend.logged_in_javascript)
...@@ -6,32 +6,12 @@ import logging ...@@ -6,32 +6,12 @@ import logging
from telemetry.core import util from telemetry.core import util
def _WaitForLoginFormToLoad(backend, login_form_id, tab):
def IsFormLoadedOrAlreadyLoggedIn():
return (tab.EvaluateJavaScript(
'document.querySelector("#%s")!== null' % login_form_id) or
backend.IsAlreadyLoggedIn(tab))
# Wait until the form is submitted and the page completes loading.
util.WaitFor(IsFormLoadedOrAlreadyLoggedIn, 60)
def _SubmitFormAndWait(form_id, tab):
tab.ExecuteJavaScript(
'document.getElementById("%s").submit();' % form_id)
def FinishedLoading():
return not tab.EvaluateJavaScript(
'document.querySelector("#%s") !== null' % form_id)
# Wait until the form is submitted and the page completes loading.
util.WaitFor(FinishedLoading, 60)
class FormBasedCredentialsBackend(object): class FormBasedCredentialsBackend(object):
def __init__(self): def __init__(self):
self._logged_in = False self._logged_in = False
def IsAlreadyLoggedIn(self, tab): def IsAlreadyLoggedIn(self, tab):
raise NotImplementedError() return tab.EvaluateJavaScript(self.logged_in_javascript)
@property @property
def credentials_type(self): def credentials_type(self):
...@@ -45,6 +25,11 @@ class FormBasedCredentialsBackend(object): ...@@ -45,6 +25,11 @@ class FormBasedCredentialsBackend(object):
def login_form_id(self): def login_form_id(self):
raise NotImplementedError() raise NotImplementedError()
@property
def login_button_javascript(self):
"""Some sites have custom JS to log in."""
return None
@property @property
def login_input_id(self): def login_input_id(self):
raise NotImplementedError() raise NotImplementedError()
...@@ -53,6 +38,11 @@ class FormBasedCredentialsBackend(object): ...@@ -53,6 +38,11 @@ class FormBasedCredentialsBackend(object):
def password_input_id(self): def password_input_id(self):
raise NotImplementedError() raise NotImplementedError()
@property
def logged_in_javascript(self):
"""Evaluates to true iff already logged in."""
raise NotImplementedError()
def IsLoggedIn(self): def IsLoggedIn(self):
return self._logged_in return self._logged_in
...@@ -62,7 +52,31 @@ class FormBasedCredentialsBackend(object): ...@@ -62,7 +52,31 @@ class FormBasedCredentialsBackend(object):
""" """
self._logged_in = False self._logged_in = False
def LoginNeeded(self, tab, config): def _WaitForLoginState(self, action_runner):
"""Waits until it can detect either the login form, or already logged in."""
condition = '(document.querySelector("#%s") !== null) || (%s)' % (
self.login_form_id, self.logged_in_javascript)
action_runner.WaitForJavaScriptCondition(condition, 60)
def _SubmitLoginFormAndWait(self, action_runner, tab, username, password):
"""Submits the login form and waits for the navigation."""
tab.WaitForDocumentReadyStateToBeInteractiveOrBetter()
email_id = 'document.querySelector("#%s #%s").value = "%s"; ' % (
self.login_form_id, self.login_input_id, username)
password = 'document.querySelector("#%s #%s").value = "%s"; ' % (
self.login_form_id, self.password_input_id, password)
tab.ExecuteJavaScript(email_id)
tab.ExecuteJavaScript(password)
if self.login_button_javascript:
tab.ExecuteJavaScript(self.login_button_javascript)
else:
tab.ExecuteJavaScript(
'document.getElementById("%s").submit();' % self.login_form_id)
# Wait for the form element to disappear as confirmation of the navigation.
action_runner.WaitForNavigate()
def LoginNeeded(self, tab, action_runner, config):
"""Logs in to a test account. """Logs in to a test account.
Raises: Raises:
...@@ -86,23 +100,14 @@ class FormBasedCredentialsBackend(object): ...@@ -86,23 +100,14 @@ class FormBasedCredentialsBackend(object):
try: try:
logging.info('Loading %s...', url) logging.info('Loading %s...', url)
tab.Navigate(url) tab.Navigate(url)
_WaitForLoginFormToLoad(self, self.login_form_id, tab) self._WaitForLoginState(action_runner)
if self.IsAlreadyLoggedIn(tab): if self.IsAlreadyLoggedIn(tab):
self._logged_in = True self._logged_in = True
return True return True
tab.WaitForDocumentReadyStateToBeInteractiveOrBetter() self._SubmitLoginFormAndWait(
logging.info('Loaded page: %s', url) action_runner, tab, config['username'], config['password'])
email_id = 'document.querySelector("#%s").%s.value = "%s"; ' % (
self.login_form_id, self.login_input_id, config['username'])
password = 'document.querySelector("#%s").%s.value = "%s"; ' % (
self.login_form_id, self.password_input_id, config['password'])
tab.ExecuteJavaScript(email_id)
tab.ExecuteJavaScript(password)
_SubmitFormAndWait(self.login_form_id, tab)
self._logged_in = True self._logged_in = True
return True return True
......
...@@ -95,18 +95,23 @@ class FormBasedCredentialsBackendUnitTestBase(unittest.TestCase): ...@@ -95,18 +95,23 @@ class FormBasedCredentialsBackendUnitTestBase(unittest.TestCase):
raise NotImplementedError() raise NotImplementedError()
def _LoginUsingMock(self, backend, login_page_url, email_element_id, def _LoginUsingMock(self, backend, login_page_url, email_element_id,
password_element_id): # pylint: disable=R0201 password_element_id, form_element_id,
already_logged_in_js): # pylint: disable=R0201
tab = simple_mock.MockObject() tab = simple_mock.MockObject()
ar = simple_mock.MockObject()
config = {'username': 'blah', config = {'username': 'blah',
'password': 'blargh'} 'password': 'blargh'}
tab.ExpectCall('Navigate', login_page_url) tab.ExpectCall('Navigate', login_page_url)
tab.ExpectCall('EvaluateJavaScript', _).WillReturn(False) tab.ExpectCall('EvaluateJavaScript', already_logged_in_js).WillReturn(False)
tab.ExpectCall('EvaluateJavaScript', _).WillReturn(True)
tab.ExpectCall('EvaluateJavaScript', _).WillReturn(False)
tab.ExpectCall('WaitForDocumentReadyStateToBeInteractiveOrBetter') tab.ExpectCall('WaitForDocumentReadyStateToBeInteractiveOrBetter')
ar.ExpectCall('WaitForJavaScriptCondition',
'(document.querySelector("#%s") !== null) || (%s)' % (
form_element_id, already_logged_in_js), 60)
ar.ExpectCall('WaitForNavigate')
def VerifyEmail(js): def VerifyEmail(js):
assert email_element_id in js assert email_element_id in js
assert 'blah' in js assert 'blah' in js
...@@ -118,10 +123,10 @@ class FormBasedCredentialsBackendUnitTestBase(unittest.TestCase): ...@@ -118,10 +123,10 @@ class FormBasedCredentialsBackendUnitTestBase(unittest.TestCase):
tab.ExpectCall('ExecuteJavaScript', _).WhenCalled(VerifyPw) tab.ExpectCall('ExecuteJavaScript', _).WhenCalled(VerifyPw)
def VerifySubmit(js): def VerifySubmit(js):
assert '.submit' in js assert '.submit' in js or '.click' in js
tab.ExpectCall('ExecuteJavaScript', _).WhenCalled(VerifySubmit) tab.ExpectCall('ExecuteJavaScript', _).WhenCalled(VerifySubmit)
# Checking for form still up. # Checking for form still up.
tab.ExpectCall('EvaluateJavaScript', _).WillReturn(False) tab.ExpectCall('EvaluateJavaScript', _).WillReturn(False)
backend.LoginNeeded(tab, config) backend.LoginNeeded(tab, ar, config)
...@@ -7,9 +7,11 @@ from telemetry.core.backends import form_based_credentials_backend ...@@ -7,9 +7,11 @@ from telemetry.core.backends import form_based_credentials_backend
class GoogleCredentialsBackend( class GoogleCredentialsBackend(
form_based_credentials_backend.FormBasedCredentialsBackend): form_based_credentials_backend.FormBasedCredentialsBackend):
def IsAlreadyLoggedIn(self, tab):
return tab.EvaluateJavaScript( @property
'document.getElementById("gb")!== null') def logged_in_javascript(self):
"""Evaluates to true iff already logged in."""
return 'document.getElementById("gb")!== null'
@property @property
def credentials_type(self): def credentials_type(self):
......
...@@ -14,4 +14,5 @@ class TestGoogleCredentialsBackend( ...@@ -14,4 +14,5 @@ class TestGoogleCredentialsBackend(
def testLoginUsingMock(self): def testLoginUsingMock(self):
backend = google_credentials_backend.GoogleCredentialsBackend() backend = google_credentials_backend.GoogleCredentialsBackend()
self._LoginUsingMock(backend, backend.url, backend.login_input_id, self._LoginUsingMock(backend, backend.url, backend.login_input_id,
backend.password_input_id) backend.password_input_id, backend.login_form_id,
backend.logged_in_javascript)
...@@ -7,8 +7,10 @@ import logging ...@@ -7,8 +7,10 @@ import logging
import os import os
from telemetry.core import util from telemetry.core import util
from telemetry.core.backends import codepen_credentials_backend
from telemetry.core.backends import facebook_credentials_backend from telemetry.core.backends import facebook_credentials_backend
from telemetry.core.backends import google_credentials_backend from telemetry.core.backends import google_credentials_backend
from telemetry.page.actions import action_runner
from telemetry.unittest import options_for_unittests from telemetry.unittest import options_for_unittests
...@@ -24,6 +26,7 @@ class BrowserCredentials(object): ...@@ -24,6 +26,7 @@ class BrowserCredentials(object):
if backends is None: if backends is None:
backends = [ backends = [
codepen_credentials_backend.CodePenCredentialsBackend(),
facebook_credentials_backend.FacebookCredentialsBackend(), facebook_credentials_backend.FacebookCredentialsBackend(),
google_credentials_backend.GoogleCredentialsBackend()] google_credentials_backend.GoogleCredentialsBackend()]
...@@ -55,8 +58,9 @@ class BrowserCredentials(object): ...@@ -55,8 +58,9 @@ class BrowserCredentials(object):
'Unrecognized credentials type: %s', credentials_type) 'Unrecognized credentials type: %s', credentials_type)
if credentials_type not in self._credentials: if credentials_type not in self._credentials:
return False return False
runner = action_runner.ActionRunner(tab)
return self._backends[credentials_type].LoginNeeded( return self._backends[credentials_type].LoginNeeded(
tab, self._credentials[credentials_type]) tab, runner, self._credentials[credentials_type])
def LoginNoLongerNeeded(self, tab, credentials_type): def LoginNoLongerNeeded(self, tab, credentials_type):
assert credentials_type in self._backends assert credentials_type in self._backends
......
...@@ -23,7 +23,7 @@ class BackendStub(object): ...@@ -23,7 +23,7 @@ class BackendStub(object):
self.login_no_longer_needed_called = None self.login_no_longer_needed_called = None
self.credentials_type = credentials_type self.credentials_type = credentials_type
def LoginNeeded(self, config, tab): def LoginNeeded(self, config, _, tab):
self.login_needed_called = (config, tab) self.login_needed_called = (config, tab)
return True return True
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment