environment.py revision cedac228d2dd51db4b79ea1e72c7f249408ee061
1cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)# Copyright 2014 The Chromium Authors. All rights reserved.
2cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)# Use of this source code is governed by a BSD-style license that can be
3cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)# found in the LICENSE file.
4cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
5cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)"""The testing Environment class."""
6cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
7cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)import logging
8cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)import shutil
9cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)import time
10cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
11cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)from selenium import webdriver
12cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)from selenium.common.exceptions import NoSuchElementException
13cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)from selenium.common.exceptions import WebDriverException
14cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)from selenium.webdriver.chrome.options import Options
15cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)from xml.etree import ElementTree
16cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
17cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)# Message strings to look for in chrome://password-manager-internals
18cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)MESSAGE_ASK = "Message: Decision: ASK the user"
19cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)MESSAGE_SAVE = "Message: Decision: SAVE the password"
20cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
21cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
22cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)class Environment:
23cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  """Sets up the testing Environment. """
24cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
25cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  def __init__(self, chrome_path, chromedriver_path, profile_path,
26cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)               passwords_path, enable_automatic_password_saving,
27cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)               numeric_level=None, log_to_console=False, log_file=""):
28cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    """Creates a new testing Environment.
29cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
30cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    Args:
31cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      chrome_path: The chrome binary file.
32cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      chromedriver_path: The chromedriver binary file.
33cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      profile_path: The chrome testing profile folder.
34cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      passwords_path: The usernames and passwords file.
35cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      enable_automatic_password_saving: If True, the passwords are going to be
36cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          saved without showing the prompt.
37cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      numeric_level: The log verbosity.
38cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      log_to_console: If True, the debug logs will be shown on the console.
39cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      log_file: The file where to store the log. If it's empty, the log will
40cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            not be stored.
41cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
42cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    Raises:
43cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      Exception: An exception is raised if |profile_path| folder could not be
44cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      removed.
45cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    """
46cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    # Setting up the login.
47cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if numeric_level is not None:
48cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      if log_file:
49cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        # Set up logging to file.
50cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        logging.basicConfig(level=numeric_level,
51cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                            filename=log_file,
52cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                            filemode='w')
53cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
54cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        if log_to_console:
55cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          console = logging.StreamHandler()
56cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          console.setLevel(numeric_level)
57cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          # Add the handler to the root logger.
58cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          logging.getLogger('').addHandler(console)
59cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
60cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      elif log_to_console:
61cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        logging.basicConfig(level=numeric_level)
62cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
63cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    # Cleaning the chrome testing profile folder.
64cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    try:
65cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      shutil.rmtree(profile_path)
66cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    except Exception, e:
67cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      # The tests execution can continue, but this make them less stable.
68cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      logging.error("Error: Could not wipe the chrome profile directory (%s). \
69cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          This affects the stability of the tests. Continuing to run tests."
70cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          % e)
71cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    options = Options()
72cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if enable_automatic_password_saving:
73cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      options.add_argument("enable-automatic-password-saving")
74cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    # Chrome path.
75cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    options.binary_location = chrome_path
76cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    # Chrome testing profile path.
77cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    options.add_argument("user-data-dir=%s" % profile_path)
78cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
79cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    # The webdriver. It's possible to choose the port the service is going to
80cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    # run on. If it's left to 0, a free port will be found.
81cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    self.driver = webdriver.Chrome(chromedriver_path, 0, options)
82cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    # The password internals window.
83cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    self.internals_window = self.driver.current_window_handle
84cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    # Password internals page.
85cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    self.internals_page = "chrome://password-manager-internals/"
86cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    # The Website window.
87cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    self.website_window = None
88cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    # The WebsiteTests list.
89cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    self.websitetests = []
90cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    # An xml tree filled with logins and passwords.
91cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    self.passwords_tree = ElementTree.parse(passwords_path).getroot()
92cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    # The enabled WebsiteTests list.
93cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    self.working_tests = []
94cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    # Map messages to the number of their appearance in the log.
95cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    self.message_count = dict()
96cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    self.message_count[MESSAGE_ASK] = 0
97cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    self.message_count[MESSAGE_SAVE] = 0
98cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    # The tests needs two tabs to work. A new tab is opened with the first
99cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    # GoTo. This is why we store here whether or not it's the first time to
100cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    # execute GoTo.
101cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    self.first_go_to = True
102cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
103cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  def AddWebsiteTest(self, websitetest, disabled=False):
104cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    """Adds a WebsiteTest to the testing Environment.
105cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
106cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    Args:
107cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      websitetest: The WebsiteTest instance to be added.
108cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      disabled: Whether test is disabled.
109cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    """
110cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    websitetest.environment = self
111cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    websitetest.driver = self.driver
112cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if self.passwords_tree is not None:
113cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      if not websitetest.username:
114cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        username_tag = (
115cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            self.passwords_tree.find(
116cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                ".//*[@name='%s']/username" % websitetest.name))
117cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        if username_tag.text:
118cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          websitetest.username = username_tag.text
119cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      if not websitetest.password:
120cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        password_tag = (
121cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            self.passwords_tree.find(
122cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                ".//*[@name='%s']/password" % websitetest.name))
123cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        if password_tag.text:
124cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          websitetest.password = password_tag.text
125cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    self.websitetests.append(websitetest)
126cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if not disabled:
127cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      self.working_tests.append(websitetest.name)
128cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
129cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  def RemoveAllPasswords(self):
130cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    """Removes all the stored passwords."""
131cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    logging.info("\nRemoveAllPasswords\n")
132cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    self.driver.get("chrome://settings/passwords")
133cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    self.driver.switch_to_frame("settings")
134cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    while True:
135cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      try:
136cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        self.driver.execute_script("document.querySelector('"
137cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          "#saved-passwords-list .row-delete-button').click()")
138cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        time.sleep(1)
139cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      except NoSuchElementException:
140cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        break
141cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      except WebDriverException:
142cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        break
143cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
144cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  def OpenTabAndGoToInternals(self, url):
145cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    """If there is no |self.website_window|, opens a new tab and navigates to
146cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    |url| in the new tab. Navigates to the passwords internals page in the
147cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    first tab. Raises an exception otherwise.
148cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
149cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    Args:
150cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      url: Url to go to in the new tab.
151cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
152cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    Raises:
153cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      Exception: An exception is raised if |self.website_window| already
154cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          exists.
155cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    """
156cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if self.website_window:
157cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      raise Exception("Error: The window was already opened.")
158cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
159cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    self.driver.get("chrome://newtab")
160cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    # There is no straightforward way to open a new tab with chromedriver.
161cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    # One work-around is to go to a website, insert a link that is going
162cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    # to be opened in a new tab, click on it.
163cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    a = self.driver.execute_script(
164cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        "var a = document.createElement('a');"
165cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        "a.target = '_blank';"
166cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        "a.href = arguments[0];"
167cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        "a.innerHTML = '.';"
168cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        "document.body.appendChild(a);"
169cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        "return a;",
170cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        url)
171cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
172cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    a.click()
173cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    time.sleep(1)
174cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
175cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    self.website_window = self.driver.window_handles[-1]
176cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    self.driver.get(self.internals_page)
177cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    self.driver.switch_to_window(self.website_window)
178cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
179cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  def SwitchToInternals(self):
180cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    """Switches from the Website window to internals tab."""
181cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    self.driver.switch_to_window(self.internals_window)
182cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
183cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  def SwitchFromInternals(self):
184cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    """Switches from internals tab to the Website window."""
185cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    self.driver.switch_to_window(self.website_window)
186cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
187cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  def _DidMessageAppearUntilTimeout(self, log_message, timeout):
188cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    """Checks whether the save password prompt is shown.
189cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
190cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    Args:
191cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      log_message: Log message to look for in the password internals.
192cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      timeout: There is some delay between the login and the password
193cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          internals update. The method checks periodically during the first
194cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          |timeout| seconds if the internals page reports the prompt being
195cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          shown. If the prompt is not reported shown within the first
196cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          |timeout| seconds, it is considered not shown at all.
197cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
198cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    Returns:
199cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      True if the save password prompt is shown.
200cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      False otherwise.
201cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    """
202cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    log = self.driver.find_element_by_css_selector("#log-entries")
203cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    count = log.text.count(log_message)
204cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
205cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if count > self.message_count[log_message]:
206cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      self.message_count[log_message] = count
207cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      return True
208cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    elif timeout > 0:
209cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      time.sleep(1)
210cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      return self._DidMessageAppearUntilTimeout(log_message, timeout - 1)
211cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    else:
212cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      return False
213cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
214cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  def CheckForNewMessage(self, log_message, message_should_show_up,
215cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                         error_message, timeout=3):
216cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    """Detects whether the save password prompt is shown.
217cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
218cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    Args:
219cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      log_message: Log message to look for in the password internals. The
220cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          only valid values are the constants MESSAGE_* defined at the
221cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          beginning of this file.
222cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      message_should_show_up: Whether or not the message is expected to be
223cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          shown.
224cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      error_message: Error message for the exception.
225cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      timeout: There is some delay between the login and the password
226cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          internals update. The method checks periodically during the first
227cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          |timeout| seconds if the internals page reports the prompt being
228cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          shown. If the prompt is not reported shown within the first
229cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          |timeout| seconds, it is considered not shown at all.
230cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
231cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    Raises:
232cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      Exception: An exception is raised in case the result does not match the
233cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          expectation
234cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    """
235cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (self._DidMessageAppearUntilTimeout(log_message, timeout) !=
236cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        message_should_show_up):
237cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      raise Exception(error_message)
238cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
239cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  def AllTests(self, prompt_test):
240cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    """Runs the tests on all the WebsiteTests.
241cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
242cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    Args:
243cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      prompt_test: If True, tests caring about showing the save-password
244cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          prompt are going to be run, otherwise tests which don't care about
245cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          the prompt are going to be run.
246cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
247cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    Raises:
248cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      Exception: An exception is raised if the tests fail.
249cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    """
250cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if prompt_test:
251cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      self.PromptTestList(self.websitetests)
252cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    else:
253cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      self.TestList(self.websitetests)
254cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
255cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  def WorkingTests(self, prompt_test):
256cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    """Runs the tests on all the enabled WebsiteTests.
257cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
258cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    Args:
259cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      prompt_test: If True, tests caring about showing the save-password
260cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          prompt are going to be run, otherwise tests which don't care about
261cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          the prompt are going to be executed.
262cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
263cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    Raises:
264cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      Exception: An exception is raised if the tests fail.
265cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    """
266cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    self.Test(self.working_tests, prompt_test)
267cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
268cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  def Test(self, tests, prompt_test):
269cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    """Runs the tests on websites named in |tests|.
270cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
271cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    Args:
272cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      tests: A list of the names of the WebsiteTests that are going to be
273cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          tested.
274cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      prompt_test: If True, tests caring about showing the save-password
275cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          prompt are going to be run, otherwise tests which don't care about
276cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          the prompt are going to be executed.
277cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
278cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    Raises:
279cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      Exception: An exception is raised if the tests fail.
280cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    """
281cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    websitetests = []
282cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    for websitetest in self.websitetests:
283cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      if websitetest.name in tests:
284cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        websitetests.append(websitetest)
285cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
286cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if prompt_test:
287cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      self.PromptTestList(websitetests)
288cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    else:
289cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      self.TestList(websitetests)
290cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
291cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  def TestList(self, websitetests):
292cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    """Runs the tests on the websites in |websitetests|.
293cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
294cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    Args:
295cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      websitetests: A list of WebsiteTests that are going to be tested.
296cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
297cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    Raises:
298cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      Exception: An exception is raised if the tests fail.
299cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    """
300cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    self.RemoveAllPasswords()
301cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
302cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    for websitetest in websitetests:
303cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      websitetest.WrongLoginTest()
304cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      websitetest.SuccessfulLoginTest()
305cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      websitetest.SuccessfulLoginWithAutofilledPasswordTest()
306cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
307cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    self.RemoveAllPasswords()
308cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    for websitetest in websitetests:
309cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      websitetest.SuccessfulLoginTest()
310cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
311cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  def PromptTestList(self, websitetests):
312cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    """Runs the prompt tests on the websites in |websitetests|.
313cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
314cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    Args:
315cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      websitetests: A list of WebsiteTests that are going to be tested.
316cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
317cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    Raises:
318cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      Exception: An exception is raised if the tests fail.
319cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    """
320cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    self.RemoveAllPasswords()
321cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
322cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    for websitetest in websitetests:
323cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      websitetest.PromptTest()
324cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
325cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  def Quit(self):
326cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    """Closes the tests."""
327cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    # Close the webdriver.
328cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    self.driver.quit()
329