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 The driver's find_element_by_css_selector method defines what is clickable |
91 transparent, the element is going to receive a click and a True is | 76 -- anything for which it does not throw, is clickable. To be clickable, |
92 returned. | 77 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 displayed, None otherwise. |
| 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 Raises: |
| 169 Exception: In case the accummulated waiting limit is exceeded. |
| 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) |
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 |