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)"""WebsiteTest testing class.""" 6cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 7cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)import logging 8116680a4aac90f2aa7413d9095a592090648e557Ben Murdochimport sys 9cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)import time 10cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 11116680a4aac90f2aa7413d9095a592090648e557Ben Murdochsys.path.insert(0, '../../../../third_party/webdriver/pylib/') 12116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 13cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)from selenium.webdriver.common.action_chains import ActionChains 14cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)from selenium.webdriver.common.keys import Keys 15cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 16cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)import environment 17cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 18cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 19cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)def _IsOneSubstringOfAnother(s1, s2): 20cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) """Checks if one of the string arguements is substring of the other. 21cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 22cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) Args: 23cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) s1: The first string. 24cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) s2: The second string. 25cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) Returns: 26cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 27cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) True if one of the string arguements is substring of the other. 28cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) False otherwise. 29cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) """ 30cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return s1 in s2 or s2 in s1 31cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 32cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 33cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)class WebsiteTest: 34cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) """Handles a tested WebsiteTest.""" 35cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 36cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) class Mode: 37cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) """Test mode.""" 38cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) # Password and username are expected to be autofilled. 39cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) AUTOFILLED = 1 40cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) # Password and username are not expected to be autofilled. 41cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) NOT_AUTOFILLED = 2 42cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 43cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) def __init__(self): 44cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) pass 45cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 46cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) def __init__(self, name, username_not_auto=False): 47cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) """Creates a new WebsiteTest. 48cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 49cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) Args: 50cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) name: The website name. 51cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) username_not_auto: Username inputs in some websites (like wikipedia) are 52cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) sometimes filled with some messages and thus, the usernames are not 53cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) automatically autofilled. This flag handles that and disables us from 54cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) checking if the state of the DOM is the same as the username of 55cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) website. 56cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) """ 57cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) # Name of the website 58cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) self.name = name 59cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) # Username of the website. 60cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) self.username = None 61cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) # Password of the website. 62cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) self.password = None 63cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) # Username is not automatically filled. 64cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) self.username_not_auto = username_not_auto 65cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) # Autofilling mode. 66cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) self.mode = self.Mode.NOT_AUTOFILLED 67cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) # The |remaining_time_to_wait| limits the total time in seconds spent in 68cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) # potentially infinite loops. 69cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) self.remaining_time_to_wait = 200 70cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) # The testing Environment. 71cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) self.environment = None 72cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) # The webdriver. 73cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) self.driver = None 74116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch # Whether or not the test was run. 75116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch self.was_run = False 76cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 77cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) # Mouse/Keyboard actions. 78cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 79cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) def Click(self, selector): 80cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) """Clicks on an element. 81cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 82cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) Args: 83cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) selector: The element CSS selector. 84cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) """ 85cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) logging.info("action: Click %s" % selector) 861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci self.WaitUntilDisplayed(selector) 87cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) element = self.driver.find_element_by_css_selector(selector) 88cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) element.click() 89cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 90cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) def ClickIfClickable(self, selector): 91cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) """Clicks on an element if it's clickable: If it doesn't exist in the DOM, 92cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) it's covered by another element or it's out viewing area, nothing is 93cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) done and False is returned. Otherwise, even if the element is 100% 94cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) transparent, the element is going to receive a click and a True is 95cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) returned. 96cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 97cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) Args: 98cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) selector: The element CSS selector. 99cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 100cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) Returns: 101cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) True if the click happens. 102cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) False otherwise. 103cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) """ 104cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) logging.info("action: ClickIfVisible %s" % selector) 1051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci self.WaitUntilDisplayed(selector) 106cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) try: 107cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) element = self.driver.find_element_by_css_selector(selector) 108cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) element.click() 109cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return True 110cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) except Exception: 111cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return False 112cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 113cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) def GoTo(self, url): 114cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) """Navigates the main frame to the |url|. 115cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 116cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) Args: 117cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) url: The URL. 118cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) """ 119cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) logging.info("action: GoTo %s" % self.name) 120cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if self.environment.first_go_to: 121cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) self.environment.OpenTabAndGoToInternals(url) 122cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) self.environment.first_go_to = False 123cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) else: 124cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) self.driver.get(url) 125cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 126cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) def HoverOver(self, selector): 127cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) """Hovers over an element. 128cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 129cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) Args: 130cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) selector: The element CSS selector. 131cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) """ 132cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) logging.info("action: Hover %s" % selector) 1331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci self.WaitUntilDisplayed(selector) 134cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) element = self.driver.find_element_by_css_selector(selector) 135cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) hover = ActionChains(self.driver).move_to_element(element) 136cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) hover.perform() 137cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 138cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) def SendEnterTo(self, selector): 139cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) """Sends an enter key to an element. 140cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 141cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) Args: 142cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) selector: The element CSS selector. 143cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) """ 144cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) logging.info("action: SendEnterTo %s" % selector) 145cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) body = self.driver.find_element_by_tag_name("body") 146cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) body.send_keys(Keys.ENTER) 147cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 148cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) # Waiting/Displaying actions. 149cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 150cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) def IsDisplayed(self, selector): 151cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) """Returns False if an element doesn't exist in the DOM or is 100% 152cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) transparent. Otherwise, returns True even if it's covered by another 153cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) element or it's out viewing area. 154cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 155cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) Args: 156cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) selector: The element CSS selector. 157cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) """ 158cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) logging.info("action: IsDisplayed %s" % selector) 159cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) try: 160cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) element = self.driver.find_element_by_css_selector(selector) 161cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return element.is_displayed() 162cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) except Exception: 163cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return False 164cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 165cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) def Wait(self, duration): 166cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) """Wait for a duration in seconds. This needs to be used in potentially 167cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) infinite loops, to limit their running time. 168cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 169cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) Args: 170cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) duration: The time to wait in seconds. 171cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) """ 172cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) logging.info("action: Wait %s" % duration) 173cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) time.sleep(duration) 174cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) self.remaining_time_to_wait -= 1 175cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if self.remaining_time_to_wait < 0: 176cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) raise Exception("Tests took more time than expected for the following " 177cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) "website : %s \n" % self.name) 178cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 179cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) def WaitUntilDisplayed(self, selector, timeout=10): 180cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) """Waits until an element is displayed. 181cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 182cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) Args: 183cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) selector: The element CSS selector. 184cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) timeout: The maximum waiting time in seconds before failing. 185cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) """ 186cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if not self.IsDisplayed(selector): 187cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) self.Wait(1) 188cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) timeout = timeout - 1 189cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (timeout <= 0): 190cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) raise Exception("Error: Element %s not shown before timeout is " 191cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) "finished for the following website: %s" 192cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) % (selector, self.name)) 193cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) else: 194cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) self.WaitUntilDisplayed(selector, timeout) 195cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 196cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) # Form actions. 197cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 198cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) def FillPasswordInto(self, selector): 199cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) """If the testing mode is the Autofilled mode, compares the website 200cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) password to the DOM state. 201cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) If the testing mode is the NotAutofilled mode, checks that the DOM state 202cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) is empty. 203cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) Then, fills the input with the Website password. 204cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 205cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) Args: 206cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) selector: The password input CSS selector. 207cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 208cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) Raises: 209cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) Exception: An exception is raised if the DOM value of the password is 210cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) different than the one we expected. 211cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) """ 212cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) logging.info("action: FillPasswordInto %s" % selector) 2131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci self.WaitUntilDisplayed(selector) 214cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) password_element = self.driver.find_element_by_css_selector(selector) 215cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) # Chrome protects the password inputs and doesn't fill them until 216cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) # the user interacts with the page. To be sure that such thing has 21703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) # happened we perform |Keys.CONTROL| keypress. 21803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) action_chains = ActionChains(self.driver) 21903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) action_chains.key_down(Keys.CONTROL).key_up(Keys.CONTROL).perform() 220cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if self.mode == self.Mode.AUTOFILLED: 221cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) autofilled_password = password_element.get_attribute("value") 222cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if autofilled_password != self.password: 223cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) raise Exception("Error: autofilled password is different from the one " 224cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) "we just saved for the following website : %s p1: %s " 225cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) "p2:%s \n" % (self.name, 226cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) password_element.get_attribute("value"), 227cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) self.password)) 228cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 229cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) elif self.mode == self.Mode.NOT_AUTOFILLED: 230cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) autofilled_password = password_element.get_attribute("value") 231cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if autofilled_password: 232cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) raise Exception("Error: password is autofilled when it shouldn't be " 233cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) "for the following website : %s \n" 234cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) % self.name) 235cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 236cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) password_element.send_keys(self.password) 237cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 238cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) def FillUsernameInto(self, selector): 239cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) """If the testing mode is the Autofilled mode, compares the website 240cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) username to the input value. Then, fills the input with the website 241cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) username. 242cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 243cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) Args: 244cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) selector: The username input CSS selector. 245cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 246cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) Raises: 247cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) Exception: An exception is raised if the DOM value of the username is 248cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) different that the one we expected. 249cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) """ 250cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) logging.info("action: FillUsernameInto %s" % selector) 2511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci self.WaitUntilDisplayed(selector) 252cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) username_element = self.driver.find_element_by_css_selector(selector) 253cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 254cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (self.mode == self.Mode.AUTOFILLED and not self.username_not_auto): 255cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if not (username_element.get_attribute("value") == self.username): 256cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) raise Exception("Error: autofilled username is different form the one " 257cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) "we just saved for the following website : %s \n" % 258cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) self.name) 259cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) else: 260cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) username_element.clear() 261cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) username_element.send_keys(self.username) 262cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 263cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) def Submit(self, selector): 264cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) """Finds an element using CSS Selector and calls its submit() handler. 265cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 266cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) Args: 267cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) selector: The input CSS selector. 268cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) """ 269cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) logging.info("action: Submit %s" % selector) 2701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci self.WaitUntilDisplayed(selector) 271cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) element = self.driver.find_element_by_css_selector(selector) 272cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) element.submit() 273cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 274cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) # Login/Logout Methods 275cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 276cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) def Login(self): 277cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) """Login Method. Has to be overloaded by the WebsiteTest test.""" 278cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) raise NotImplementedError("Login is not implemented.") 279cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 280cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) def LoginWhenAutofilled(self): 281cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) """Logs in and checks that the password is autofilled.""" 282cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) self.mode = self.Mode.AUTOFILLED 283cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) self.Login() 284cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 285cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) def LoginWhenNotAutofilled(self): 286cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) """Logs in and checks that the password is not autofilled.""" 287cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) self.mode = self.Mode.NOT_AUTOFILLED 288cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) self.Login() 289cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 290cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) def Logout(self): 2916e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) """Logout Method.""" 292cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 293cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) # Tests 294cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 295cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) def WrongLoginTest(self): 296cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) """Does the wrong login test: Tries to login with a wrong password and 297cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) checks that the password is not saved. 298cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 299cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) Raises: 300cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) Exception: An exception is raised if the test fails: If there is a 301cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) problem when performing the login (ex: the login button is not 302cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) available ...), if the state of the username and password fields is 303cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) not like we expected or if the password is saved. 304cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) """ 305cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) logging.info("\nWrong Login Test for %s \n" % self.name) 3061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci try: 3071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci correct_password = self.password 3081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci self.password = self.password + "1" 3091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci self.LoginWhenNotAutofilled() 3101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci self.password = correct_password 3111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci self.Wait(2) 3121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci self.environment.SwitchToInternals() 3131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci self.environment.CheckForNewMessage( 3141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci environment.MESSAGE_SAVE, 3151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci False, 3161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci "Error: password manager thinks that a login with wrong password was " 3171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci "successful for the following website : %s \n" % self.name) 3181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci finally: 3191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci self.environment.SwitchFromInternals() 320cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 321cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) def SuccessfulLoginTest(self): 322cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) """Does the successful login when the password is not expected to be 323cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) autofilled test: Checks that the password is not autofilled, tries to login 324cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) with a right password and checks if the password is saved. Then logs out. 325cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 326cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) Raises: 327cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) Exception: An exception is raised if the test fails: If there is a 328cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) problem when performing the login and the logout (ex: the login 329cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) button is not available ...), if the state of the username and 330cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) password fields is not like we expected or if the password is not 331cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) saved. 332cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) """ 333cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) logging.info("\nSuccessful Login Test for %s \n" % self.name) 3341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci try: 3351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci self.LoginWhenNotAutofilled() 3361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci self.Wait(2) 3371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci self.environment.SwitchToInternals() 3381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci self.environment.CheckForNewMessage( 3391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci environment.MESSAGE_SAVE, 3401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci True, 3411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci "Error: password manager hasn't detected a successful login for the " 3421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci "following website : %s \n" 3431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci % self.name) 3441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci finally: 3451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci self.environment.SwitchFromInternals() 3461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci self.Logout() 347cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 348cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) def SuccessfulLoginWithAutofilledPasswordTest(self): 349cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) """Does the successful login when the password is expected to be autofilled 350cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) test: Checks that the password is autofilled, tries to login with the 351cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) autofilled password and checks if the password is saved. Then logs out. 352cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 353cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) Raises: 354cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) Exception: An exception is raised if the test fails: If there is a 355cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) problem when performing the login and the logout (ex: the login 356cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) button is not available ...), if the state of the username and 357cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) password fields is not like we expected or if the password is not 358cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) saved. 359cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) """ 360cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) logging.info("\nSuccessful Login With Autofilled Password" 361cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) " Test %s \n" % self.name) 3621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci try: 3631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci self.LoginWhenAutofilled() 3641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci self.Wait(2) 3651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci self.environment.SwitchToInternals() 3661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci self.environment.CheckForNewMessage( 3671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci environment.MESSAGE_SAVE, 3681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci True, 3691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci "Error: password manager hasn't detected a successful login for the " 3701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci "following website : %s \n" 3711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci % self.name) 3721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci finally: 3731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci self.environment.SwitchFromInternals() 3741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci self.Logout() 375cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 376cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) def PromptTest(self): 377cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) """Does the prompt test: Tries to login with a wrong password and 378cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) checks that the prompt is not shown. Then tries to login with a right 379cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) password and checks that the prompt is not shown. 380cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 381cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) Raises: 382cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) Exception: An exception is raised if the test fails: If there is a 383cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) problem when performing the login (ex: the login button is not 384cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) available ...), if the state of the username and password fields is 385cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) not like we expected or if the prompt is not shown for the right 386cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) password or is shown for a wrong one. 387cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) """ 388cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) logging.info("\nPrompt Test for %s \n" % self.name) 3891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci try: 3901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci correct_password = self.password 3911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci self.password = self.password + "1" 3921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci self.LoginWhenNotAutofilled() 3931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci self.password = correct_password 3941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci self.Wait(2) 3951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci self.environment.SwitchToInternals() 3961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci self.environment.CheckForNewMessage( 3971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci environment.MESSAGE_ASK, 3981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci False, 3991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci "Error: password manager thinks that a login with wrong password was " 4001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci "successful for the following website : %s \n" % self.name) 4011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci self.environment.SwitchFromInternals() 4021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 4031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci self.LoginWhenNotAutofilled() 4041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci self.Wait(2) 4051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci self.environment.SwitchToInternals() 4061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci self.environment.CheckForNewMessage( 4071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci environment.MESSAGE_ASK, 4081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci True, 4091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci "Error: password manager hasn't detected a successful login for the " 4101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci "following website : %s \n" % self.name) 4111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci finally: 4121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci self.environment.SwitchFromInternals() 413