Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 # Copyright 2014 The Chromium Authors. All rights reserved. | 1 # Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
| 4 | 4 |
| 5 """WebsiteTest testing class.""" | 5 """WebsiteTest testing class.""" |
| 6 | 6 |
| 7 import logging | 7 import logging |
| 8 import time | 8 import time |
| 9 | 9 |
| 10 from selenium.webdriver.common.action_chains import ActionChains | 10 from selenium.webdriver.common.action_chains import ActionChains |
| 11 from selenium.webdriver.common.keys import Keys | 11 from selenium.webdriver.common.keys import Keys |
| 12 | 12 |
| 13 import environment | 13 import environment |
| 14 | 14 |
| 15 | 15 SCRIPT_DEBUG = 9 # TODO(vabr) -- make this consistent with run_tests.py. |
| 16 def _IsOneSubstringOfAnother(s1, s2): | 16 |
| 17 """Checks if one of the string arguements is substring of the other. | 17 class WebsiteTest: |
| 18 | 18 """WebsiteTest testing class. |
| 19 Args: | 19 |
| 20 s1: The first string. | 20 Represents one website, defines some generic operations on that site. |
| 21 s2: The second string. | 21 To customise for a particular website, this class needs to be inherited |
| 22 Returns: | 22 and the Login() method overridden. |
| 23 | |
| 24 True if one of the string arguements is substring of the other. | |
| 25 False otherwise. | |
| 26 """ | 23 """ |
| 27 return s1 in s2 or s2 in s1 | 24 |
| 28 | 25 # Possible values of self.autofill_expectation. |
| 29 | 26 AUTOFILLED = 1 # Expect password and username to be autofilled. |
| 30 class WebsiteTest: | 27 NOT_AUTOFILLED = 2 # Expect password and username not to be autofilled. |
| 31 """Handles a tested WebsiteTest.""" | 28 |
| 32 | 29 # The maximal accumulated time to spend in waiting for website UI |
| 33 class Mode: | 30 # interaction. |
| 34 """Test mode.""" | 31 MAX_WAIT_TIME_IN_SECONDS = 200 |
| 35 # Password and username are expected to be autofilled. | 32 |
| 36 AUTOFILLED = 1 | 33 # Types of test to be passed to self.RunTest(). |
| 37 # Password and username are not expected to be autofilled. | 34 TEST_TYPE_PROMPT_FAIL = 1 |
| 38 NOT_AUTOFILLED = 2 | 35 TEST_TYPE_PROMPT_SUCCESS = 2 |
| 39 | 36 TEST_TYPE_SAVE_AND_AUTOFILL = 3 |
| 40 def __init__(self): | |
| 41 pass | |
| 42 | 37 |
| 43 def __init__(self, name, username_not_auto=False): | 38 def __init__(self, name, username_not_auto=False): |
| 44 """Creates a new WebsiteTest. | 39 """Creates a new WebsiteTest. |
| 45 | 40 |
| 46 Args: | 41 Args: |
| 47 name: The website name. | 42 name: The website name, identifying it in the test results. |
| 48 username_not_auto: Username inputs in some websites (like wikipedia) are | 43 username_not_auto: Expect that the tested website fills username field |
| 49 sometimes filled with some messages and thus, the usernames are not | 44 on load, and Chrome cannot autofill in that case. |
| 50 automatically autofilled. This flag handles that and disables us from | 45 """ |
| 51 checking if the state of the DOM is the same as the username of | |
| 52 website. | |
| 53 """ | |
| 54 # Name of the website | |
| 55 self.name = name | 46 self.name = name |
| 56 # Username of the website. | |
| 57 self.username = None | 47 self.username = None |
| 58 # Password of the website. | |
| 59 self.password = None | 48 self.password = None |
| 60 # Username is not automatically filled. | |
| 61 self.username_not_auto = username_not_auto | 49 self.username_not_auto = username_not_auto |
| 62 # Autofilling mode. | 50 |
| 63 self.mode = self.Mode.NOT_AUTOFILLED | 51 # Specify, whether it is expected that credentials get autofilled. |
| 64 # The |remaining_time_to_wait| limits the total time in seconds spent in | 52 self.autofill_expectation = WebsiteTest.NOT_AUTOFILLED |
| 65 # potentially infinite loops. | 53 self.remaining_seconds_to_wait = WebsiteTest.MAX_WAIT_TIME_IN_SECONDS |
| 66 self.remaining_time_to_wait = 200 | 54 # The testing Environment, if added to any. |
| 67 # The testing Environment. | |
| 68 self.environment = None | 55 self.environment = None |
| 69 # The webdriver. | 56 # The webdriver from the environment. |
| 70 self.driver = None | 57 self.driver = None |
| 71 # Whether or not the test was run. | |
| 72 self.was_run = False | |
| 73 | 58 |
| 74 # Mouse/Keyboard actions. | 59 # Mouse/Keyboard actions. |
| 75 | 60 |
| 76 def Click(self, selector): | 61 def Click(self, selector): |
| 77 """Clicks on an element. | 62 """Clicks on the element described by |selector|. |
| 78 | 63 |
| 79 Args: | 64 Args: |
| 80 selector: The element CSS selector. | 65 selector: The clicked element's CSS selector. |
| 81 """ | 66 """ |
| 82 logging.info("action: Click %s" % selector) | 67 |
| 83 self.WaitUntilDisplayed(selector) | 68 logging.log(SCRIPT_DEBUG, "action: Click %s" % selector) |
| 84 element = self.driver.find_element_by_css_selector(selector) | 69 element = self.WaitUntilDisplayed(selector) |
| 85 element.click() | 70 element.click() |
| 86 | 71 |
| 87 def ClickIfClickable(self, selector): | 72 def ClickIfClickable(self, selector): |
| 88 """Clicks on an element if it's clickable: If it doesn't exist in the DOM, | 73 """Clicks on the element described by |selector| if it is clickable. |
| 89 it's covered by another element or it's out viewing area, nothing is | 74 |
| 90 done and False is returned. Otherwise, even if the element is 100% | 75 What is clickable defines the driver's find_element_by_css_selector |
|
msramek
2015/03/27 11:37:07
Nit: is defined by
vabr (Chromium)
2015/03/27 12:14:43
Tried to simplify even more by reordering the sent
| |
| 91 transparent, the element is going to receive a click and a True is | 76 method -- anything for which it does not throw, is clickable. To be |
| 92 returned. | 77 clickable, the element must: |
| 93 | 78 * exist in the DOM, |
| 94 Args: | 79 * be not covered by another element |
| 95 selector: The element CSS selector. | 80 * be inside the visible area. |
| 81 Note that transparency does not influence clickability. | |
| 82 | |
| 83 Args: | |
| 84 selector: The clicked element's CSS selector. | |
| 96 | 85 |
| 97 Returns: | 86 Returns: |
| 98 True if the click happens. | 87 True if the element is clickable (and was clicked on). |
| 99 False otherwise. | 88 False otherwise. |
| 100 """ | 89 """ |
| 101 logging.info("action: ClickIfVisible %s" % selector) | 90 |
| 102 self.WaitUntilDisplayed(selector) | 91 logging.log(SCRIPT_DEBUG, "action: ClickIfVisible %s" % selector) |
| 92 element = self.WaitUntilDisplayed(selector) | |
| 103 try: | 93 try: |
| 104 element = self.driver.find_element_by_css_selector(selector) | |
| 105 element.click() | 94 element.click() |
| 106 return True | 95 return True |
| 107 except Exception: | 96 except Exception: |
| 108 return False | 97 return False |
| 109 | 98 |
| 110 def GoTo(self, url): | 99 def GoTo(self, url): |
| 111 """Navigates the main frame to the |url|. | 100 """Navigates the main frame to |url|. |
| 112 | 101 |
| 113 Args: | 102 Args: |
| 114 url: The URL. | 103 url: The URL of where to go to. |
| 115 """ | 104 """ |
| 116 logging.info("action: GoTo %s" % self.name) | 105 |
| 117 if self.environment.first_go_to: | 106 logging.log(SCRIPT_DEBUG, "action: GoTo %s" % self.name) |
| 118 self.environment.OpenTabAndGoToInternals(url) | 107 self.driver.get(url) |
| 119 self.environment.first_go_to = False | |
| 120 else: | |
| 121 self.driver.get(url) | |
| 122 | 108 |
| 123 def HoverOver(self, selector): | 109 def HoverOver(self, selector): |
| 124 """Hovers over an element. | 110 """Hovers over the element described by |selector|. |
| 125 | 111 |
| 126 Args: | 112 Args: |
| 127 selector: The element CSS selector. | 113 selector: The CSS selector of the element to hover over. |
| 128 """ | 114 """ |
| 129 logging.info("action: Hover %s" % selector) | 115 |
| 130 self.WaitUntilDisplayed(selector) | 116 logging.log(SCRIPT_DEBUG, "action: Hover %s" % selector) |
| 131 element = self.driver.find_element_by_css_selector(selector) | 117 element = self.WaitUntilDisplayed(selector) |
| 132 hover = ActionChains(self.driver).move_to_element(element) | 118 hover = ActionChains(self.driver).move_to_element(element) |
| 133 hover.perform() | 119 hover.perform() |
| 134 | 120 |
| 135 # Waiting/Displaying actions. | 121 # Waiting/Displaying actions. |
| 136 | 122 |
| 137 def IsDisplayed(self, selector): | 123 def _ReturnElementIfDisplayed(self, selector): |
| 138 """Returns False if an element doesn't exist in the DOM or is 100% | 124 """Returns the element described by |selector|, if displayed. |
| 139 transparent. Otherwise, returns True even if it's covered by another | 125 |
| 140 element or it's out viewing area. | 126 Note: This takes neither overlapping among elements nor position with |
| 141 | 127 regards to the visible area into account. |
| 142 Args: | 128 |
| 143 selector: The element CSS selector. | 129 Args: |
| 144 """ | 130 selector: The CSS selector of the checked element. |
| 145 logging.info("action: IsDisplayed %s" % selector) | 131 |
| 132 Returns: | |
| 133 The element if disaplayed, None otherwise. | |
|
msramek
2015/03/27 11:37:07
Nit: *-a
vabr (Chromium)
2015/03/27 12:14:43
Done.
| |
| 134 """ | |
| 135 | |
| 146 try: | 136 try: |
| 147 element = self.driver.find_element_by_css_selector(selector) | 137 element = self.driver.find_element_by_css_selector(selector) |
| 148 return element.is_displayed() | 138 return element if element.is_displayed() else None |
| 149 except Exception: | 139 except Exception: |
| 150 return False | 140 return None |
| 141 | |
| 142 def IsDisplayed(self, selector): | |
| 143 """Check if the element described by |selector| is displayed. | |
| 144 | |
| 145 Note: This takes neither overlapping among elements nor position with | |
| 146 regards to the visible area into account. | |
| 147 | |
| 148 Args: | |
| 149 selector: The CSS selector of the checked element. | |
| 150 | |
| 151 Returns: | |
| 152 True if the element is in the DOM and less than 100% transparent. | |
| 153 False otherwise. | |
| 154 """ | |
| 155 | |
| 156 logging.log(SCRIPT_DEBUG, "action: IsDisplayed %s" % selector) | |
| 157 return self._ReturnElementIfDisplayed(selector) is not None | |
| 151 | 158 |
| 152 def Wait(self, duration): | 159 def Wait(self, duration): |
| 153 """Wait for a duration in seconds. This needs to be used in potentially | 160 """Wait for |duration| in seconds. |
| 154 infinite loops, to limit their running time. | 161 |
| 162 To avoid deadlocks, the accummulated waiting time for the whole object does | |
| 163 not exceed MAX_WAIT_TIME_IN_SECONDS. | |
| 155 | 164 |
| 156 Args: | 165 Args: |
| 157 duration: The time to wait in seconds. | 166 duration: The time to wait in seconds. |
| 158 """ | 167 |
| 159 logging.info("action: Wait %s" % duration) | 168 Throws: |
| 169 Exception in case the accummulated waiting limit is exceeded. | |
|
msramek
2015/03/27 11:37:07
Nit: You usually write "<class>: <desc>", see e.g.
vabr (Chromium)
2015/03/27 12:14:43
Also, I usually write Raises. Such C++-ism! (And C
| |
| 170 """ | |
| 171 | |
| 172 logging.log(SCRIPT_DEBUG, "action: Wait %s" % duration) | |
| 173 self.remaining_seconds_to_wait -= duration | |
| 174 if self.remaining_seconds_to_wait < 0: | |
| 175 raise Exception("Waiting limit exceeded for website : %s" % self.name) | |
| 160 time.sleep(duration) | 176 time.sleep(duration) |
| 161 self.remaining_time_to_wait -= 1 | 177 |
| 162 if self.remaining_time_to_wait < 0: | 178 # TODO(vabr): Pull this out into some website-utils and use in Environment |
| 163 raise Exception("Tests took more time than expected for the following " | 179 # also? |
| 164 "website : %s \n" % self.name) | 180 def WaitUntilDisplayed(self, selector): |
| 165 | 181 """Waits until the element described by |selector| is displayed. |
| 166 def WaitUntilDisplayed(self, selector, timeout=10): | 182 |
| 167 """Waits until an element is displayed. | 183 Args: |
| 168 | 184 selector: The CSS selector of the element to wait for. |
| 169 Args: | 185 |
| 170 selector: The element CSS selector. | 186 Returns: |
| 171 timeout: The maximum waiting time in seconds before failing. | 187 The displayed element. |
| 172 """ | 188 """ |
| 173 if not self.IsDisplayed(selector): | 189 |
| 190 element = self._ReturnElementIfDisplayed(selector) | |
| 191 while not element: | |
| 174 self.Wait(1) | 192 self.Wait(1) |
| 175 timeout = timeout - 1 | 193 element = self._ReturnElementIfDisplayed(selector) |
| 176 if (timeout <= 0): | 194 return element |
| 177 raise Exception("Error: Element %s not shown before timeout is " | |
| 178 "finished for the following website: %s" | |
| 179 % (selector, self.name)) | |
| 180 else: | |
| 181 self.WaitUntilDisplayed(selector, timeout) | |
| 182 | 195 |
| 183 # Form actions. | 196 # Form actions. |
| 184 | 197 |
| 185 def FillPasswordInto(self, selector): | 198 def FillPasswordInto(self, selector): |
| 186 """If the testing mode is the Autofilled mode, compares the website | 199 """Ensures that the selected element's value is the saved password. |
| 187 password to the DOM state. | 200 |
| 188 If the testing mode is the NotAutofilled mode, checks that the DOM state | 201 Depending on self.autofill_expectation, this either checks that the |
| 189 is empty. | 202 element already has the password autofilled, or checks that the value |
| 190 Then, fills the input with the Website password. | 203 is empty and replaces it with the password. |
| 191 | 204 |
| 192 Args: | 205 Args: |
| 193 selector: The password input CSS selector. | 206 selector: The CSS selector for the filled element. |
| 194 | 207 |
| 195 Raises: | 208 Raises: |
| 196 Exception: An exception is raised if the DOM value of the password is | 209 Exception: An exception is raised if the element's value is different |
| 197 different than the one we expected. | 210 from the expectation. |
| 198 """ | 211 """ |
| 199 logging.info("action: FillPasswordInto %s" % selector) | 212 |
| 200 self.WaitUntilDisplayed(selector) | 213 logging.log(SCRIPT_DEBUG, "action: FillPasswordInto %s" % selector) |
| 201 password_element = self.driver.find_element_by_css_selector(selector) | 214 password_element = self.WaitUntilDisplayed(selector) |
| 215 | |
| 202 # Chrome protects the password inputs and doesn't fill them until | 216 # Chrome protects the password inputs and doesn't fill them until |
| 203 # the user interacts with the page. To be sure that such thing has | 217 # the user interacts with the page. To be sure that such thing has |
| 204 # happened we perform |Keys.CONTROL| keypress. | 218 # happened we perform |Keys.CONTROL| keypress. |
| 205 action_chains = ActionChains(self.driver) | 219 action_chains = ActionChains(self.driver) |
| 206 action_chains.key_down(Keys.CONTROL).key_up(Keys.CONTROL).perform() | 220 action_chains.key_down(Keys.CONTROL).key_up(Keys.CONTROL).perform() |
| 207 if self.mode == self.Mode.AUTOFILLED: | 221 |
| 208 autofilled_password = password_element.get_attribute("value") | 222 if self.autofill_expectation == WebsiteTest.AUTOFILLED: |
| 209 if autofilled_password != self.password: | 223 if password_element.get_attribute("value") != self.password: |
| 210 raise Exception("Error: autofilled password is different from the one " | 224 raise Exception("Error: autofilled password is different from the saved" |
| 211 "we just saved for the following website : %s p1: %s " | 225 " one on website : %s" % self.name) |
|
msramek
2015/03/27 11:37:07
Nit: No space in front of the colon here or space
vabr (Chromium)
2015/03/27 12:14:43
Done. Fully agree, also fixed this elsewhere! :)
| |
| 212 "p2:%s \n" % (self.name, | 226 elif self.autofill_expectation == WebsiteTest.NOT_AUTOFILLED: |
| 213 password_element.get_attribute("value"), | 227 if password_element.get_attribute("value"): |
| 214 self.password)) | 228 raise Exception("Error: password value unexpectedly not empty on" |
| 215 | 229 "website: %s" % self.name) |
| 216 elif self.mode == self.Mode.NOT_AUTOFILLED: | |
| 217 autofilled_password = password_element.get_attribute("value") | |
| 218 if autofilled_password: | |
| 219 raise Exception("Error: password is autofilled when it shouldn't be " | |
| 220 "for the following website : %s \n" | |
| 221 % self.name) | |
| 222 | |
| 223 password_element.send_keys(self.password) | 230 password_element.send_keys(self.password) |
| 224 | 231 |
| 225 def FillUsernameInto(self, selector): | 232 def FillUsernameInto(self, selector): |
| 226 """If the testing mode is the Autofilled mode, compares the website | 233 """Ensures that the selected element's value is the saved username. |
| 227 username to the input value. Then, fills the input with the website | 234 |
| 235 Depending on self.autofill_expectation, this either checks that the | |
| 236 element already has the username autofilled, or checks that the value | |
| 237 is empty and replaces it with the password. If self.username_not_auto | |
| 238 is true, it skips the checks and just overwrites the value with the | |
| 228 username. | 239 username. |
| 229 | 240 |
| 230 Args: | 241 Args: |
| 231 selector: The username input CSS selector. | 242 selector: The CSS selector for the filled element. |
| 232 | 243 |
| 233 Raises: | 244 Raises: |
| 234 Exception: An exception is raised if the DOM value of the username is | 245 Exception: An exception is raised if the element's value is different |
| 235 different that the one we expected. | 246 from the expectation. |
| 236 """ | 247 """ |
| 237 logging.info("action: FillUsernameInto %s" % selector) | 248 |
| 238 self.WaitUntilDisplayed(selector) | 249 logging.log(SCRIPT_DEBUG, "action: FillUsernameInto %s" % selector) |
| 239 username_element = self.driver.find_element_by_css_selector(selector) | 250 username_element = self.WaitUntilDisplayed(selector) |
| 240 | 251 |
| 241 if (self.mode == self.Mode.AUTOFILLED and not self.username_not_auto): | 252 if not self.username_not_auto: |
| 242 if not (username_element.get_attribute("value") == self.username): | 253 if self.autofill_expectation == WebsiteTest.AUTOFILLED: |
| 243 raise Exception("Error: autofilled username is different form the one " | 254 if username_element.get_attribute("value") != self.username: |
| 244 "we just saved for the following website : %s \n" % | 255 raise Exception("Error: filled username different from the saved" |
| 245 self.name) | 256 " one on website : %s" % self.name) |
| 246 else: | 257 return |
| 247 username_element.clear() | 258 if self.autofill_expectation == WebsiteTest.NOT_AUTOFILLED: |
| 248 username_element.send_keys(self.username) | 259 if username_element.get_attribute("value"): |
| 260 raise Exception("Error: username value unexpectedly not empty on" | |
| 261 "website: %s" % self.name) | |
| 262 | |
| 263 username_element.clear() | |
| 264 username_element.send_keys(self.username) | |
| 249 | 265 |
| 250 def Submit(self, selector): | 266 def Submit(self, selector): |
| 251 """Finds an element using CSS Selector and calls its submit() handler. | 267 """Finds an element using CSS |selector| and calls its submit() handler. |
| 252 | 268 |
| 253 Args: | 269 Args: |
| 254 selector: The input CSS selector. | 270 selector: The CSS selector for the element to call submit() on. |
| 255 """ | 271 """ |
| 256 logging.info("action: Submit %s" % selector) | 272 |
| 257 self.WaitUntilDisplayed(selector) | 273 logging.log(SCRIPT_DEBUG, "action: Submit %s" % selector) |
| 258 element = self.driver.find_element_by_css_selector(selector) | 274 element = self.WaitUntilDisplayed(selector) |
| 259 element.submit() | 275 element.submit() |
| 260 | 276 |
| 261 # Login/Logout Methods | 277 # Login/Logout methods |
| 262 | 278 |
| 263 def Login(self): | 279 def Login(self): |
| 264 """Login Method. Has to be overloaded by the WebsiteTest test.""" | 280 """Login Method. Has to be overridden by the WebsiteTest test.""" |
| 281 | |
| 265 raise NotImplementedError("Login is not implemented.") | 282 raise NotImplementedError("Login is not implemented.") |
| 266 | 283 |
| 267 def LoginWhenAutofilled(self): | 284 def LoginWhenAutofilled(self): |
| 268 """Logs in and checks that the password is autofilled.""" | 285 """Logs in and checks that the password is autofilled.""" |
| 269 self.mode = self.Mode.AUTOFILLED | 286 |
| 287 self.autofill_expectation = WebsiteTest.AUTOFILLED | |
| 270 self.Login() | 288 self.Login() |
| 271 | 289 |
| 272 def LoginWhenNotAutofilled(self): | 290 def LoginWhenNotAutofilled(self): |
| 273 """Logs in and checks that the password is not autofilled.""" | 291 """Logs in and checks that the password is not autofilled.""" |
| 274 self.mode = self.Mode.NOT_AUTOFILLED | 292 |
| 293 self.autofill_expectation = WebsiteTest.NOT_AUTOFILLED | |
| 275 self.Login() | 294 self.Login() |
| 276 | 295 |
| 277 def Logout(self): | 296 def Logout(self): |
| 278 """Logout Method.""" | 297 self.environment.DeleteCookies() |
| 279 | 298 |
| 280 # Tests | 299 # Test scenarios |
| 281 | 300 |
| 282 def WrongLoginTest(self): | 301 def PromptFailTest(self): |
| 283 """Does the wrong login test: Tries to login with a wrong password and | 302 """Checks that prompt is not shown on a failed login attempt. |
| 284 checks that the password is not saved. | 303 |
| 285 | 304 Tries to login with a wrong password and checks that the password |
| 286 Raises: | 305 is not offered for saving. |
| 287 Exception: An exception is raised if the test fails: If there is a | 306 |
| 288 problem when performing the login (ex: the login button is not | 307 Raises: |
| 289 available ...), if the state of the username and password fields is | 308 Exception: An exception is raised if the test fails. |
| 290 not like we expected or if the password is saved. | 309 """ |
| 291 """ | 310 |
| 292 logging.info("\nWrong Login Test for %s \n" % self.name) | 311 logging.log(SCRIPT_DEBUG, "PromptFailTest for %s" % self.name) |
| 293 try: | 312 correct_password = self.password |
| 294 correct_password = self.password | 313 # Hardcoded random wrong password. Chosen by fair `pwgen` call. |
| 295 # Hardcoded random wrong password. Chosen by fair `pwgen` call. | 314 # For details, see: http://xkcd.com/221/. |
| 296 # For details, see: http://xkcd.com/221/. | 315 self.password = "ChieF2ae" |
| 297 self.password = "ChieF2ae" | 316 self.LoginWhenNotAutofilled() |
| 298 self.LoginWhenNotAutofilled() | 317 self.password = correct_password |
| 299 self.password = correct_password | 318 self.environment.CheckForNewString( |
| 300 self.Wait(2) | 319 [environment.MESSAGE_ASK, environment.MESSAGE_SAVE], |
| 301 self.environment.SwitchToInternals() | 320 False, |
| 302 self.environment.CheckForNewMessage( | 321 "Error: did not detect wrong login on website : %s" % self.name) |
| 303 environment.MESSAGE_SAVE, | 322 |
| 304 False, | 323 def PromptSuccessTest(self): |
| 305 "Error: password manager thinks that a login with wrong password was " | 324 """Checks that prompt is shown on a successful login attempt. |
| 306 "successful for the following website : %s \n" % self.name) | 325 |
| 307 finally: | 326 Tries to login with a correct password and checks that the password |
| 308 self.environment.SwitchFromInternals() | 327 is offered for saving. Chrome cannot have the auto-save option on |
| 309 | 328 when running this test. |
| 310 def SuccessfulLoginTest(self): | 329 |
| 311 """Does the successful login when the password is not expected to be | 330 Raises: |
| 312 autofilled test: Checks that the password is not autofilled, tries to login | 331 Exception: An exception is raised if the test fails. |
| 313 with a right password and checks if the password is saved. Then logs out. | 332 """ |
| 314 | 333 |
| 315 Raises: | 334 logging.log(SCRIPT_DEBUG, "PromptSuccessTest for %s" % self.name) |
| 316 Exception: An exception is raised if the test fails: If there is a | 335 if not self.environment.show_prompt: |
| 317 problem when performing the login and the logout (ex: the login | 336 raise Exception("Switch off auto-save during PromptSuccessTest.") |
| 318 button is not available ...), if the state of the username and | 337 self.LoginWhenNotAutofilled() |
| 319 password fields is not like we expected or if the password is not | 338 self.environment.CheckForNewString( |
| 320 saved. | 339 [environment.MESSAGE_ASK], |
| 321 """ | 340 True, |
| 322 logging.info("\nSuccessful Login Test for %s \n" % self.name) | 341 "Error: did not detect login success on website : %s" % self.name) |
| 323 try: | 342 |
| 324 self.LoginWhenNotAutofilled() | 343 def SaveAndAutofillTest(self): |
| 325 self.Wait(2) | 344 """Checks that a correct password is saved and autofilled. |
| 326 self.environment.SwitchToInternals() | 345 |
| 327 self.environment.CheckForNewMessage( | 346 Tries to login with a correct password and checks that the password |
| 328 environment.MESSAGE_SAVE, | 347 is saved and autofilled on next visit. Chrome must have the auto-save |
| 329 True, | 348 option on when running this test. |
| 330 "Error: password manager hasn't detected a successful login for the " | 349 |
| 331 "following website : %s \n" | 350 Raises: |
| 332 % self.name) | 351 Exception: An exception is raised if the test fails. |
| 333 finally: | 352 """ |
| 334 self.environment.SwitchFromInternals() | 353 |
| 335 self.Logout() | 354 logging.log(SCRIPT_DEBUG, "SaveAndAutofillTest for %s" % self.name) |
| 336 | 355 if self.environment.show_prompt: |
| 337 def SuccessfulLoginWithAutofilledPasswordTest(self): | 356 raise Exception("Switch off auto-save during PromptSuccessTest.") |
| 338 """Does the successful login when the password is expected to be autofilled | 357 self.LoginWhenNotAutofilled() |
| 339 test: Checks that the password is autofilled, tries to login with the | 358 self.environment.CheckForNewString( |
| 340 autofilled password and checks if the password is saved. Then logs out. | 359 [environment.MESSAGE_SAVE], |
| 341 | 360 True, |
| 342 Raises: | 361 "Error: did not detect login success on website : %s" % self.name) |
| 343 Exception: An exception is raised if the test fails: If there is a | 362 self.Logout() |
| 344 problem when performing the login and the logout (ex: the login | 363 self.LoginWhenAutofilled() |
| 345 button is not available ...), if the state of the username and | 364 self.environment.CheckForNewString( |
| 346 password fields is not like we expected or if the password is not | 365 [environment.MESSAGE_SAVE], |
| 347 saved. | 366 True, |
| 348 """ | 367 "Error: failed autofilled login on website : %s" % self.name) |
| 349 logging.info("\nSuccessful Login With Autofilled Password" | 368 |
| 350 " Test %s \n" % self.name) | 369 def RunTest(self, test_type): |
| 351 try: | 370 """Runs test according to the |test_type|. |
| 352 self.LoginWhenAutofilled() | 371 |
| 353 self.Wait(2) | 372 Raises: |
| 354 self.environment.SwitchToInternals() | 373 Exception: If |test_type| is not one of the TEST_TYPE_* constants. |
| 355 self.environment.CheckForNewMessage( | 374 """ |
| 356 environment.MESSAGE_SAVE, | 375 |
| 357 True, | 376 if test_type == WebsiteTest.TEST_TYPE_PROMPT_FAIL: |
| 358 "Error: password manager hasn't detected a successful login for the " | 377 self.PromptFailTest() |
| 359 "following website : %s \n" | 378 elif test_type == WebsiteTest.TEST_TYPE_PROMPT_SUCCESS: |
| 360 % self.name) | 379 self.PromptSuccessTest() |
| 361 finally: | 380 elif test_type == WebsiteTest.TEST_TYPE_SAVE_AND_AUTOFILL: |
| 362 self.environment.SwitchFromInternals() | 381 self.SaveAndAutofillTest() |
| 363 self.Logout() | 382 else: |
| 364 | 383 raise Exception("Unknown test type {}.".format(test_type)) |
| 365 def PromptTest(self): | |
| 366 """Does the prompt test: Tries to login with a wrong password and | |
| 367 checks that the prompt is not shown. Then tries to login with a right | |
| 368 password and checks that the prompt is not shown. | |
| 369 | |
| 370 Raises: | |
| 371 Exception: An exception is raised if the test fails: If there is a | |
| 372 problem when performing the login (ex: the login button is not | |
| 373 available ...), if the state of the username and password fields is | |
| 374 not like we expected or if the prompt is not shown for the right | |
| 375 password or is shown for a wrong one. | |
| 376 """ | |
| 377 logging.info("\nPrompt Test for %s \n" % self.name) | |
| 378 try: | |
| 379 correct_password = self.password | |
| 380 self.password = self.password + "1" | |
| 381 self.LoginWhenNotAutofilled() | |
| 382 self.password = correct_password | |
| 383 self.Wait(2) | |
| 384 self.environment.SwitchToInternals() | |
| 385 self.environment.CheckForNewMessage( | |
| 386 environment.MESSAGE_ASK, | |
| 387 False, | |
| 388 "Error: password manager thinks that a login with wrong password was " | |
| 389 "successful for the following website : %s \n" % self.name) | |
| 390 self.environment.SwitchFromInternals() | |
| 391 | |
| 392 self.LoginWhenNotAutofilled() | |
| 393 self.Wait(2) | |
| 394 self.environment.SwitchToInternals() | |
| 395 self.environment.CheckForNewMessage( | |
| 396 environment.MESSAGE_ASK, | |
| 397 True, | |
| 398 "Error: password manager hasn't detected a successful login for the " | |
| 399 "following website : %s \n" % self.name) | |
| 400 finally: | |
| 401 self.environment.SwitchFromInternals() | |
| OLD | NEW |