Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(193)

Side by Side Diff: components/test/data/password_manager/websitetest.py

Issue 273523004: Password Manager testing automation (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: copyright Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « components/test/data/password_manager/tests.py ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 # found in the LICENSE file.
4
5 """WebsiteTest testing class."""
6
7 import logging
8 import time
9
10 from selenium.webdriver.common.action_chains import ActionChains
11 from selenium.webdriver.common.keys import Keys
12
13 import environment
14
15
16 def _IsOneSubstringOfAnother(s1, s2):
17 """Checks if one of the string arguements is substring of the other.
18
19 Args:
20 s1: The first string.
21 s2: The second string.
22 Returns:
23
24 True if one of the string arguements is substring of the other.
25 False otherwise.
26 """
27 return s1 in s2 or s2 in s1
28
29
30 class WebsiteTest:
31 """Handles a tested WebsiteTest."""
32
33 class Mode:
34 """Test mode."""
35 # Password and username are expected to be autofilled.
36 AUTOFILLED = 1
37 # Password and username are not expected to be autofilled.
38 NOT_AUTOFILLED = 2
39
40 def __init__(self):
41 pass
42
43 def __init__(self, name, username_not_auto=False):
44 """Creates a new WebsiteTest.
45
46 Args:
47 name: The website name.
48 username_not_auto: Username inputs in some websites (like wikipedia) are
49 sometimes filled with some messages and thus, the usernames are not
50 automatically autofilled. This flag handles that and disables us from
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
56 # Username of the website.
57 self.username = None
58 # Password of the website.
59 self.password = None
60 # Username is not automatically filled.
61 self.username_not_auto = username_not_auto
62 # Autofilling mode.
63 self.mode = self.Mode.NOT_AUTOFILLED
64 # The |remaining_time_to_wait| limits the total time in seconds spent in
65 # potentially infinite loops.
66 self.remaining_time_to_wait = 200
67 # The testing Environment.
68 self.environment = None
69 # The webdriver.
70 self.driver = None
71
72 # Mouse/Keyboard actions.
73
74 def Click(self, selector):
75 """Clicks on an element.
76
77 Args:
78 selector: The element CSS selector.
79 """
80 logging.info("action: Click %s" % selector)
81 element = self.driver.find_element_by_css_selector(selector)
82 element.click()
83
84 def ClickIfClickable(self, selector):
85 """Clicks on an element if it's clickable: If it doesn't exist in the DOM,
86 it's covered by another element or it's out viewing area, nothing is
87 done and False is returned. Otherwise, even if the element is 100%
88 transparent, the element is going to receive a click and a True is
89 returned.
90
91 Args:
92 selector: The element CSS selector.
93
94 Returns:
95 True if the click happens.
96 False otherwise.
97 """
98 logging.info("action: ClickIfVisible %s" % selector)
99 try:
100 element = self.driver.find_element_by_css_selector(selector)
101 element.click()
102 return True
103 except Exception:
104 return False
105
106 def GoTo(self, url):
107 """Navigates the main frame to the |url|.
108
109 Args:
110 url: The URL.
111 """
112 logging.info("action: GoTo %s" % self.name)
113 if self.environment.first_go_to:
114 self.environment.OpenTabAndGoToInternals(url)
115 self.environment.first_go_to = False
116 else:
117 self.driver.get(url)
118
119 def HoverOver(self, selector):
120 """Hovers over an element.
121
122 Args:
123 selector: The element CSS selector.
124 """
125 logging.info("action: Hover %s" % selector)
126 element = self.driver.find_element_by_css_selector(selector)
127 hover = ActionChains(self.driver).move_to_element(element)
128 hover.perform()
129
130 def SendEnterTo(self, selector):
131 """Sends an enter key to an element.
132
133 Args:
134 selector: The element CSS selector.
135 """
136 logging.info("action: SendEnterTo %s" % selector)
137 body = self.driver.find_element_by_tag_name("body")
138 body.send_keys(Keys.ENTER)
139
140 # Waiting/Displaying actions.
141
142 def IsDisplayed(self, selector):
143 """Returns False if an element doesn't exist in the DOM or is 100%
144 transparent. Otherwise, returns True even if it's covered by another
145 element or it's out viewing area.
146
147 Args:
148 selector: The element CSS selector.
149 """
150 logging.info("action: IsDisplayed %s" % selector)
151 try:
152 element = self.driver.find_element_by_css_selector(selector)
153 return element.is_displayed()
154 except Exception:
155 return False
156
157 def Wait(self, duration):
158 """Wait for a duration in seconds. This needs to be used in potentially
159 infinite loops, to limit their running time.
160
161 Args:
162 duration: The time to wait in seconds.
163 """
164 logging.info("action: Wait %s" % duration)
165 time.sleep(duration)
166 self.remaining_time_to_wait -= 1
167 if self.remaining_time_to_wait < 0:
168 raise Exception("Tests took more time than expected for the following "
169 "website : %s \n" % self.name)
170
171 def WaitUntilDisplayed(self, selector, timeout=10):
172 """Waits until an element is displayed.
173
174 Args:
175 selector: The element CSS selector.
176 timeout: The maximum waiting time in seconds before failing.
177 """
178 if not self.IsDisplayed(selector):
179 self.Wait(1)
180 timeout = timeout - 1
181 if (timeout <= 0):
182 raise Exception("Error: Element %s not shown before timeout is "
183 "finished for the following website: %s"
184 % (selector, self.name))
185 else:
186 self.WaitUntilDisplayed(selector, timeout)
187
188 # Form actions.
189
190 def FillPasswordInto(self, selector):
191 """If the testing mode is the Autofilled mode, compares the website
192 password to the DOM state.
193 If the testing mode is the NotAutofilled mode, checks that the DOM state
194 is empty.
195 Then, fills the input with the Website password.
196
197 Args:
198 selector: The password input CSS selector.
199
200 Raises:
201 Exception: An exception is raised if the DOM value of the password is
202 different than the one we expected.
203 """
204 logging.info("action: FillPasswordInto %s" % selector)
205
206 password_element = self.driver.find_element_by_css_selector(selector)
207 # Chrome protects the password inputs and doesn't fill them until
208 # the user interacts with the page. To be sure that such thing has
209 # happened we click on the password fields or one of its ancestors.
210 element = password_element
211 while True:
212 try:
213 element.click()
214 break
215 except Exception:
216 try:
217 element = element.parent
218 except AttributeError:
219 raise Exception("Error: unable to find a clickable element to "
220 "release the password protection for the following website: %s \n"
221 % (self.name))
222
223 if self.mode == self.Mode.AUTOFILLED:
224 autofilled_password = password_element.get_attribute("value")
225 if autofilled_password != self.password:
226 raise Exception("Error: autofilled password is different from the one "
227 "we just saved for the following website : %s p1: %s "
228 "p2:%s \n" % (self.name,
229 password_element.get_attribute("value"),
230 self.password))
231
232 elif self.mode == self.Mode.NOT_AUTOFILLED:
233 autofilled_password = password_element.get_attribute("value")
234 if autofilled_password:
235 raise Exception("Error: password is autofilled when it shouldn't be "
236 "for the following website : %s \n"
237 % self.name)
238
239 password_element.send_keys(self.password)
240
241 def FillUsernameInto(self, selector):
242 """If the testing mode is the Autofilled mode, compares the website
243 username to the input value. Then, fills the input with the website
244 username.
245
246 Args:
247 selector: The username input CSS selector.
248
249 Raises:
250 Exception: An exception is raised if the DOM value of the username is
251 different that the one we expected.
252 """
253 logging.info("action: FillUsernameInto %s" % selector)
254 username_element = self.driver.find_element_by_css_selector(selector)
255
256 if (self.mode == self.Mode.AUTOFILLED and not self.username_not_auto):
257 if not (username_element.get_attribute("value") == self.username):
258 raise Exception("Error: autofilled username is different form the one "
259 "we just saved for the following website : %s \n" %
260 self.name)
261 else:
262 username_element.clear()
263 username_element.send_keys(self.username)
264
265 def Submit(self, selector):
266 """Finds an element using CSS Selector and calls its submit() handler.
267
268 Args:
269 selector: The input CSS selector.
270 """
271 logging.info("action: Submit %s" % selector)
272 element = self.driver.find_element_by_css_selector(selector)
273 element.submit()
274
275 # Login/Logout Methods
276
277 def Login(self):
278 """Login Method. Has to be overloaded by the WebsiteTest test."""
279 raise NotImplementedError("Login is not implemented.")
280
281 def LoginWhenAutofilled(self):
282 """Logs in and checks that the password is autofilled."""
283 self.mode = self.Mode.AUTOFILLED
284 self.Login()
285
286 def LoginWhenNotAutofilled(self):
287 """Logs in and checks that the password is not autofilled."""
288 self.mode = self.Mode.NOT_AUTOFILLED
289 self.Login()
290
291 def Logout(self):
292 """Logout Method. Has to be overloaded by the Website test."""
293 raise NotImplementedError("Logout is not implemented.")
294
295 # Tests
296
297 def WrongLoginTest(self):
298 """Does the wrong login test: Tries to login with a wrong password and
299 checks that the password is not saved.
300
301 Raises:
302 Exception: An exception is raised if the test fails: If there is a
303 problem when performing the login (ex: the login button is not
304 available ...), if the state of the username and password fields is
305 not like we expected or if the password is saved.
306 """
307 logging.info("\nWrong Login Test for %s \n" % self.name)
308 correct_password = self.password
309 self.password = self.password + "1"
310 self.LoginWhenNotAutofilled()
311 self.password = correct_password
312 self.Wait(2)
313 self.environment.SwitchToInternals()
314 self.environment.CheckForNewMessage(
315 environment.MESSAGE_SAVE,
316 False,
317 "Error: password manager thinks that a login with wrong password was "
318 "successful for the following website : %s \n" % self.name)
319 self.environment.SwitchFromInternals()
320
321 def SuccessfulLoginTest(self):
322 """Does the successful login when the password is not expected to be
323 autofilled test: Checks that the password is not autofilled, tries to login
324 with a right password and checks if the password is saved. Then logs out.
325
326 Raises:
327 Exception: An exception is raised if the test fails: If there is a
328 problem when performing the login and the logout (ex: the login
329 button is not available ...), if the state of the username and
330 password fields is not like we expected or if the password is not
331 saved.
332 """
333 logging.info("\nSuccessful Login Test for %s \n" % self.name)
334 self.LoginWhenNotAutofilled()
335 self.Wait(2)
336 self.environment.SwitchToInternals()
337 self.environment.CheckForNewMessage(
338 environment.MESSAGE_SAVE,
339 True,
340 "Error: password manager hasn't detected a successful login for the "
341 "following website : %s \n"
342 % self.name)
343 self.environment.SwitchFromInternals()
344 self.Logout()
345
346 def SuccessfulLoginWithAutofilledPasswordTest(self):
347 """Does the successful login when the password is expected to be autofilled
348 test: Checks that the password is autofilled, tries to login with the
349 autofilled password and checks if the password is saved. Then logs out.
350
351 Raises:
352 Exception: An exception is raised if the test fails: If there is a
353 problem when performing the login and the logout (ex: the login
354 button is not available ...), if the state of the username and
355 password fields is not like we expected or if the password is not
356 saved.
357 """
358 logging.info("\nSuccessful Login With Autofilled Password"
359 " Test %s \n" % self.name)
360 self.LoginWhenAutofilled()
361 self.Wait(2)
362 self.environment.SwitchToInternals()
363 self.environment.CheckForNewMessage(
364 environment.MESSAGE_SAVE,
365 True,
366 "Error: password manager hasn't detected a successful login for the "
367 "following website : %s \n"
368 % self.name)
369 self.environment.SwitchFromInternals()
370 self.Logout()
371
372 def PromptTest(self):
373 """Does the prompt test: Tries to login with a wrong password and
374 checks that the prompt is not shown. Then tries to login with a right
375 password and checks that the prompt is not shown.
376
377 Raises:
378 Exception: An exception is raised if the test fails: If there is a
379 problem when performing the login (ex: the login button is not
380 available ...), if the state of the username and password fields is
381 not like we expected or if the prompt is not shown for the right
382 password or is shown for a wrong one.
383 """
384 logging.info("\nPrompt Test for %s \n" % self.name)
385 correct_password = self.password
386 self.password = self.password + "1"
387 self.LoginWhenNotAutofilled()
388 self.password = correct_password
389 self.Wait(2)
390 self.environment.SwitchToInternals()
391 self.environment.CheckForNewMessage(
392 environment.MESSAGE_ASK,
393 False,
394 "Error: password manager thinks that a login with wrong password was "
395 "successful for the following website : %s \n" % self.name)
396 self.environment.SwitchFromInternals()
397
398 self.LoginWhenNotAutofilled()
399 self.Wait(2)
400 self.environment.SwitchToInternals()
401 self.environment.CheckForNewMessage(
402 environment.MESSAGE_ASK,
403 True,
404 "Error: password manager thinks that a login with wrong password was "
405 "successful for the following website : %s \n" % self.name)
406 self.environment.SwitchFromInternals()
OLDNEW
« no previous file with comments | « components/test/data/password_manager/tests.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698