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

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: renaming 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
OLDNEW
(Empty)
1 """WebsiteTest testing class."""
2
3 import logging
4 import time
5
6 from selenium.common.exceptions import NoSuchElementException
7 from selenium.common.exceptions import StaleElementReferenceException
8 from selenium.webdriver.common.action_chains import ActionChains
9 from selenium.webdriver.common.keys import Keys
10
11
12 def _IsOneSubstringOfAnother(s1, s2):
13 """Checks if one of the string arguements is substring of the other.
14
15 Args:
16 s1: The first string.
17 s2: The second string.
18 Returns:
19
20 True if one of the string arguements is substring of the other.
21 False otherwise.
22 """
23 return s1 in s2 or s2 in s1
24
25
26 class WebsiteTest:
27 """Handles a tested WebsiteTest."""
28
29 class Mode:
30 """Test mode."""
31 # Password and username are expected to be autofilled.
32 AUTOFILLED = 1
33 # Password and username are not expected to be autofilled.
34 NOT_AUTOFILLED = 2
35
36 def __init__(self):
37 pass
38
39 def __init__(
40 self, name, username=None, password=None,
vabr (Chromium) 2014/05/20 14:47:25 Please remove username and password, you don't use
rchtara 2014/05/22 08:44:38 There not used, but they are useful: if someone wh
41 username_not_auto=False):
42 """Creates a new WebsiteTest.
43
44 Args:
45 name: The website name.
46 username: The website username. If it's None, the username is going to be
47 replaced with the value in the usernames and passwords file.
48 password: The website password. If it's None, the password is going to be
49 replaced with the value in the usernames and passwords file.
50 username_not_auto: Username inputs in some websites (like wikipedia) are
51 sometimes filled with some messages and thus, the usernames are not
52 automatically autofilled. This flag handles that and disables us from
53 checking if the state of the DOM is the same as the username of
54 website.
55 """
56 # Name of the website
57 self.name = name
58 # Username of the website.
59 self.username = username
60 # Password of the website.
61 self.password = password
62 # Username is not automatically filled.
63 self.username_not_auto = username_not_auto
64 # Autofilling mode.
65 self.mode = self.Mode.NOT_AUTOFILLED
66 # The |remaining_time_to_wait| limits the total time spent in waiting, but
vabr (Chromium) 2014/05/20 14:47:25 nit: "spent in waiting, but ... running." -> "spen
rchtara 2014/05/22 08:44:38 Done.
67 # does not include the time spent running.
68 self.remaining_time_to_wait = 200
69 # The testing Environment.
70 self.environment = None
71 # The webdriver.
72 self.driver = None
73
74 # Mouse/Keyboard actions.
75
76 def Click(self, selector):
77 """Clicks on an element.
78
79 Args:
80 selector: The element CSS selector.
81 """
82 logging.info("action: Click %s" % selector)
83 element = self.driver.find_element_by_css_selector(selector)
84 element.click()
85
86 def ClickIfVisible(self, selector):
87 """Clicks on an element, if it's visible.
vabr (Chromium) 2014/05/20 14:47:25 I'm not sure I understand what's meant by "visible
rchtara 2014/05/22 08:44:38 Done.
88
89 Args:
90 selector: The element CSS selector.
91
92 Returns:
93 True if the element is visible.
94 False otherwise.
95 """
96 logging.info("action: ClickIfVisible %s" % selector)
97 try:
98 element = self.driver.find_element_by_css_selector(selector)
99 element.click()
100 return True
101 except NoSuchElementException:
102 return False
103 except StaleElementReferenceException:
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 """Checks if an element is displayed.
144
145 Args:
146 selector: The element CSS selector.
147
148 Returns:
149 True if the element is visible.
vabr (Chromium) 2014/05/20 14:47:25 Please be consistent with any changes you make abo
rchtara 2014/05/22 08:44:38 Done.
150 False otherwise.
151 """
152 logging.info("action: IsDisplayed %s" % selector)
153 try:
154 element = self.driver.find_element_by_css_selector(selector)
155 return element.is_displayed()
156 except NoSuchElementException:
157 return False
158 except StaleElementReferenceException:
159 return False
160
161 def Wait(self, duration):
162 """Wait for a duration in seconds.
vabr (Chromium) 2014/05/20 14:47:25 Please comment on the intended use-case: this need
rchtara 2014/05/22 08:44:38 Done.
163
164 Args:
165 duration: The time to wait in seconds.
166 """
167 logging.info("action: Wait %s" % duration)
168 time.sleep(duration)
169 self.remaining_time_to_wait -= 1
170 if self.remaining_time_to_wait < 0:
171 raise Exception("Tests took more time than expected for the following "
172 "website : %s \n" % self.name)
173
174 def WaitUntilDisplayed(self, selector, timeout=10):
175 """Waits until an element is displayed.
176
177 Args:
178 selector: The element CSS selector.
179 timeout: The maximum waiting time in seconds before failing.
180 """
181 if not self.IsDisplayed(selector):
182 self.Wait(1)
183 timeout = timeout - 1
184 if (timeout <= 0):
185 raise Exception("Error: Element %s not shown before timeout is "
186 "finished for the following website: %s"
187 % (selector, self.name))
188 else:
189 self.WaitUntilDisplayed(selector, timeout)
190
191 # Form actions.
192
193 def FillPasswordInto(self, selector):
194 """If the testing mode is the Autofilled mode, compares the website
195 password to the DOM state.
196 If the testing mode is the NotAutofilled mode, checks that the DOM state
197 is empty.
198 Then, fills the input with the Website password.
199
200 Args:
201 selector: The password input CSS selector.
202
203 Raises:
204 Exception: An exception is raised if the DOM value of the password is
205 different than the one we expected.
206 """
207 logging.info("action: FillPasswordInto %s" % selector)
208 password_element = self.driver.find_element_by_css_selector(selector)
209 if self.mode == self.Mode.AUTOFILLED:
210 autofilled_password = password_element.get_attribute("value")
211 if autofilled_password != self.password:
212 raise Exception("Error: autofilled password is different from the one "
213 "we just saved for the following website : %s p1: %s "
214 "p2:%s \n" % (self.name,
215 password_element.get_attribute("value"),
216 self.password))
217
218 elif self.mode == self.Mode.NOT_AUTOFILLED:
219 autofilled_password = password_element.get_attribute("value")
220 password_element.send_keys(autofilled_password)
vabr (Chromium) 2014/05/20 14:47:25 Unless we raise an exception in the next step, |au
rchtara 2014/05/22 08:44:38 Done.
221 if autofilled_password:
222 raise Exception("Error: password is autofilled when it shouldn't be "
223 "for the following website : %s \n"
224 % self.name)
225
226 password_element.send_keys(self.password)
227
228 def FillUsernameInto(self, selector):
229 """If the testing mode is the Autofilled mode, compares the website
230 username to the input value. Then, fills the input with the website
231 username.
232
233 Args:
234 selector: The username input CSS selector.
235
236 Raises:
237 Exception: An exception is raised if the DOM value of the username is
238 different that the one we expected.
239 """
240 logging.info("action: FillUsernameInto %s" % selector)
241 username_element = self.driver.find_element_by_css_selector(selector)
242
243 if (self.mode == self.Mode.AUTOFILLED and not self.username_not_auto):
244 if not (username_element.get_attribute("value") == self.username):
245 raise Exception("Error: autofilled username is different form the one "
246 "we just saved for the following website : %s \n" %
247 self.name)
248 # Chrome protects the password inputs and doesn't fill them until
vabr (Chromium) 2014/05/20 14:47:25 This assumes that FillUsernameInto is always calle
rchtara 2014/05/22 08:44:38 Thanks :)
249 # the user interacts with the page. If we fill the username, we don't
250 # have this problem anymore. Otherwise, we just click on the username.
251 username_element.click()
252 else:
253 username_element.clear()
254 username_element.send_keys(self.username)
255
256 def Submit(self, selector):
257 """Finds an element using CSS Selector and calls its submit() handler.
258
259 Args:
260 selector: The input CSS selector.
261 """
262 logging.info("action: Submit %s" % selector)
263 element = self.driver.find_element_by_css_selector(selector)
264 element.submit()
265
266 # Login/Logout Methods
267
268 def Login(self):
269 """Login Method. Has to be overloaded by the WebsiteTest test."""
270 raise NotImplementedError("Login is not implemented.")
271
272 def LoginWhenAutofilled(self):
273 """Logs in and checks that the password is autofilled."""
274 self.mode = self.Mode.AUTOFILLED
275 self.Login()
276
277 def LoginWhenNotAutofilled(self):
278 """Logs in and checks that the password is not autofilled."""
279 self.mode = self.Mode.NOT_AUTOFILLED
280 self.Login()
281
282 def Logout(self):
283 """Logout Method. Has to be overloaded by the Website test."""
284 raise NotImplementedError("Logout is not implemented.")
285
286 # Tests
287
288 def WrongLoginTest(self):
289 """Does the wrong login test: Tries to login with a wrong password and
290 checks that the prompt is not shown.
291
292 Raises:
293 Exception: An exception is raised if the test fail.
vabr (Chromium) 2014/05/20 14:47:25 nit: fails
vabr (Chromium) 2014/05/20 14:47:25 Actually, "test fails" is confusing in this case:
rchtara 2014/05/22 08:44:38 Done.
rchtara 2014/05/22 08:44:38 Done.
294 """
295 logging.info("\nWrong Login Test for %s \n" % self.name)
296 correct_password = self.password
297 self.password = self.password + "1"
298 self.LoginWhenNotAutofilled()
299 self.password = correct_password
300 self.Wait(2)
301 self.environment.SwitchToInternals()
302 self.environment.CheckPrompt(
303 "Message: Decision: SAVE the password",
304 False,
305 "Error: password manager thinks that a login with wrong password was "
306 "successful for the following website : %s \n" % self.name)
307 self.environment.SwitchFromInternals()
308
309 def SuccessfulLoginTest(self):
310 """Does the successful login when the password is not expected to be
311 autofilled test: Checks that the password is not autofilled, tries to login
312 with a right password and checks if the that the prompt is shown. Then logs
313 out.
314
315 Raises:
316 Exception: An exception is raised if the test fail.
317 """
318 logging.info("\nSuccessful Login Test for %s \n" % self.name)
319 self.LoginWhenNotAutofilled()
320 self.Wait(2)
321 self.environment.SwitchToInternals()
322 self.environment.CheckPrompt(
323 "Message: Decision: SAVE the password",
324 True,
325 "Error: password manager hasn't detected a successful login for the "
326 "following website : %s \n"
327 % self.name)
328 self.environment.SwitchFromInternals()
329 self.Logout()
330
331 def SuccessfulLoginWithAutofilledPasswordTest(self):
332 """Does the successful login when the password is expected to be autofilled
333 test: Checks that the password is autofilled, tries to login with a right
334 password and checks if the that the prompt is shown. Then logs out.
335
336 Raises:
337 Exception: An exception is raised if the test fail.
338 """
339 logging.info("\nSuccessful Login With Autofilled Password"
340 " Test %s \n" % self.name)
341 self.LoginWhenAutofilled()
342 self.Wait(2)
343 self.environment.SwitchToInternals()
344 self.environment.CheckPrompt(
345 "Message: Decision: SAVE the password",
346 True,
347 "Error: password manager hasn't detected a successful login for the "
348 "following website : %s \n"
349 % self.name)
350 self.environment.SwitchFromInternals()
351 self.Logout()
352
353 def PromptTest(self):
354 """Does the wrong login test: Tries to login with a wrong password and
vabr (Chromium) 2014/05/20 14:47:25 Did you forget to change the doc string?
rchtara 2014/05/22 08:44:38 Done.
355 checks that the prompt is not shown.
356
357 Raises:
358 Exception: An exception is raised if the test fail.
359 """
360 logging.info("\nWrong Login Test for %s \n" % self.name)
vabr (Chromium) 2014/05/20 14:47:25 Did you forget to change the log message?
rchtara 2014/05/22 08:44:38 Done.
361 correct_password = self.password
362 self.password = self.password + "1"
363 self.LoginWhenNotAutofilled()
364 self.password = correct_password
365 self.Wait(2)
366 self.environment.SwitchToInternals()
367 self.environment.CheckPrompt(
368 "Message: Decision: ASK the user",
369 False,
370 "Error: password manager thinks that a login with wrong password was "
371 "successful for the following website : %s \n" % self.name)
372 self.environment.SwitchFromInternals()
373
374 self.LoginWhenNotAutofilled()
375 self.Wait(2)
376 self.environment.SwitchToInternals()
377 self.environment.CheckPrompt(
378 "Message: Decision: ASK the user",
379 True,
380 "Error: password manager thinks that a login with wrong password was "
381 "successful for the following website : %s \n" % self.name)
382 self.environment.SwitchFromInternals()
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698