OLD | NEW |
| (Empty) |
1 # -*- coding: utf-8 -*- | |
2 # Copyright 2014 The Chromium Authors. All rights reserved. | |
3 # Use of this source code is governed by a BSD-style license that can be | |
4 # found in the LICENSE file. | |
5 | |
6 """Automated tests for many websites""" | |
7 | |
8 import argparse | |
9 import logging | |
10 | |
11 from environment import Environment | |
12 from websitetest import WebsiteTest | |
13 | |
14 | |
15 class TypeOfTestedWebsites: | |
16 """An enum to specify which groups of tests to run.""" | |
17 # Runs only the disabled tests. | |
18 DISABLED_TESTS = 0 | |
19 # Runs only the enabled tests. | |
20 ENABLED_TESTS = 1 | |
21 # Runs all the tests. | |
22 ALL_TESTS = 2 | |
23 # Runs a specified list of tests. | |
24 LIST_OF_TESTS = 3 | |
25 | |
26 def __init__(self): | |
27 pass | |
28 | |
29 | |
30 class Facebook(WebsiteTest): | |
31 | |
32 def Login(self): | |
33 self.GoTo("https://www.facebook.com") | |
34 self.FillUsernameInto("[name='email']") | |
35 self.FillPasswordInto("[name='pass']") | |
36 self.Submit("[name='pass']") | |
37 | |
38 | |
39 class Google(WebsiteTest): | |
40 | |
41 def Login(self): | |
42 self.GoTo("https://accounts.google.com/ServiceLogin?sacu=1&continue=") | |
43 self.FillUsernameInto("#Email") | |
44 self.FillPasswordInto("#Passwd") | |
45 self.Submit("#Passwd") | |
46 | |
47 | |
48 class Linkedin(WebsiteTest): | |
49 | |
50 def Login(self): | |
51 self.GoTo("https://www.linkedin.com") | |
52 self.FillUsernameInto("#session_key-login") | |
53 self.FillPasswordInto("#session_password-login") | |
54 self.Submit("#session_password-login") | |
55 | |
56 | |
57 class Mailru(WebsiteTest): | |
58 | |
59 def Login(self): | |
60 self.GoTo("https://mail.ru") | |
61 self.FillUsernameInto("#mailbox__login") | |
62 self.FillPasswordInto("#mailbox__password") | |
63 self.Submit("#mailbox__password") | |
64 | |
65 | |
66 class Nytimes(WebsiteTest): | |
67 | |
68 def Login(self): | |
69 self.GoTo("https://myaccount.nytimes.com/auth/login") | |
70 self.FillUsernameInto("#userid") | |
71 self.FillPasswordInto("#password") | |
72 self.Submit("#password") | |
73 | |
74 | |
75 class Pinterest(WebsiteTest): | |
76 | |
77 def Login(self): | |
78 self.GoTo("https://www.pinterest.com/login/") | |
79 self.FillUsernameInto("[name='username_or_email']") | |
80 self.FillPasswordInto("[name='password']") | |
81 self.Submit("[name='password']") | |
82 | |
83 | |
84 class Reddit(WebsiteTest): | |
85 | |
86 def Login(self): | |
87 self.GoTo("http://www.reddit.com") | |
88 self.Click(".user .login-required") | |
89 self.FillUsernameInto("#user_login") | |
90 self.FillPasswordInto("#passwd_login") | |
91 self.Wait(2) | |
92 self.Submit("#passwd_login") | |
93 | |
94 | |
95 class Tumblr(WebsiteTest): | |
96 | |
97 def Login(self): | |
98 self.GoTo("https://www.tumblr.com/login") | |
99 self.FillUsernameInto("#signup_email") | |
100 self.FillPasswordInto("#signup_password") | |
101 self.Submit("#signup_password") | |
102 | |
103 | |
104 class Twitter(WebsiteTest): | |
105 | |
106 def Login(self): | |
107 self.GoTo("https:///twitter.com") | |
108 self.FillUsernameInto("#signin-email") | |
109 self.FillPasswordInto("#signin-password") | |
110 self.Submit("#signin-password") | |
111 | |
112 | |
113 class Wikipedia(WebsiteTest): | |
114 | |
115 def Login(self): | |
116 self.GoTo("https://en.wikipedia.org/w/index.php?title=Special:UserLogin") | |
117 self.FillUsernameInto("#wpName1") | |
118 self.FillPasswordInto("#wpPassword1") | |
119 self.Submit("#wpPassword1") | |
120 | |
121 | |
122 class Yahoo(WebsiteTest): | |
123 | |
124 def Login(self): | |
125 self.GoTo("https://login.yahoo.com") | |
126 self.FillUsernameInto("#username") | |
127 self.FillPasswordInto("#passwd") | |
128 self.Submit("#passwd") | |
129 | |
130 | |
131 class Yandex(WebsiteTest): | |
132 | |
133 def Login(self): | |
134 self.GoTo("https://mail.yandex.com") | |
135 self.FillUsernameInto("#b-mail-domik-username11") | |
136 self.FillPasswordInto("#b-mail-domik-password11") | |
137 self.Click(".b-mail-button__button") | |
138 | |
139 | |
140 # Disabled tests. | |
141 | |
142 | |
143 # Bug not reproducible without test. | |
144 class Amazon(WebsiteTest): | |
145 | |
146 def Login(self): | |
147 self.GoTo( | |
148 "https://www.amazon.com/ap/signin?openid.assoc_handle=usflex" | |
149 "&openid.mode=checkid_setup&openid.ns=http%3A%2F%2Fspecs.openid.net" | |
150 "%2Fauth%2F2.0") | |
151 self.FillUsernameInto("[name='email']") | |
152 self.FillPasswordInto("[name='password']") | |
153 self.Click("#signInSubmit-input") | |
154 | |
155 | |
156 # Password not saved. | |
157 class Ask(WebsiteTest): | |
158 | |
159 def Login(self): | |
160 self.GoTo("http://www.ask.com/answers/browse?qsrc=321&q=&o=0&l=dir#") | |
161 while not self.IsDisplayed("[name='username']"): | |
162 self.Click("#a16CnbSignInText") | |
163 self.Wait(1) | |
164 self.FillUsernameInto("[name='username']") | |
165 self.FillPasswordInto("[name='password']") | |
166 self.Click(".signin_show.signin_submit") | |
167 | |
168 | |
169 # Password not saved. | |
170 class Baidu(WebsiteTest): | |
171 | |
172 def Login(self): | |
173 self.GoTo("https://passport.baidu.com") | |
174 self.FillUsernameInto("[name='userName']") | |
175 self.FillPasswordInto("[name='password']") | |
176 self.Submit("[name='password']") | |
177 | |
178 | |
179 # http://crbug.com/368690 | |
180 class Cnn(WebsiteTest): | |
181 | |
182 def Login(self): | |
183 self.GoTo("http://www.cnn.com") | |
184 self.Wait(5) | |
185 while not self.IsDisplayed(".cnnOvrlyBtn.cnnBtnLogIn"): | |
186 self.ClickIfClickable("#hdr-auth .no-border.no-pad-right a") | |
187 self.Wait(1) | |
188 | |
189 self.Click(".cnnOvrlyBtn.cnnBtnLogIn") | |
190 self.FillUsernameInto("#cnnOverlayEmail1l") | |
191 self.FillPasswordInto("#cnnOverlayPwd") | |
192 self.Click(".cnnOvrlyBtn.cnnBtnLogIn") | |
193 self.Click(".cnnOvrlyBtn.cnnBtnLogIn") | |
194 self.Wait(5) | |
195 | |
196 | |
197 # http://crbug.com/368690 | |
198 class Ebay(WebsiteTest): | |
199 | |
200 def Login(self): | |
201 self.GoTo("https://signin.ebay.com/") | |
202 self.FillUsernameInto("[name='userid']") | |
203 self.FillPasswordInto("[name='pass']") | |
204 self.Submit("[name='pass']") | |
205 | |
206 | |
207 # Iframe, password saved but not autofileld. | |
208 class Espn(WebsiteTest): | |
209 | |
210 def Login(self): | |
211 self.GoTo("http://espn.go.com/") | |
212 while not self.IsDisplayed("#cboxLoadedContent iframe"): | |
213 self.Click("#signin .cbOverlay") | |
214 self.Wait(1) | |
215 frame = self.driver.find_element_by_css_selector("#cboxLoadedContent " | |
216 "iframe") | |
217 self.driver.switch_to_frame(frame) | |
218 self.FillUsernameInto("#username") | |
219 self.FillPasswordInto("#password") | |
220 while self.IsDisplayed("#password"): | |
221 self.ClickIfClickable("#submitBtn") | |
222 self.Wait(1) | |
223 | |
224 | |
225 # http://crbug.com/367768 | |
226 class Live(WebsiteTest): | |
227 | |
228 def Login(self): | |
229 self.GoTo("https://login.live.com") | |
230 self.FillUsernameInto("[name='login']") | |
231 self.FillPasswordInto("[name='passwd']") | |
232 self.Submit("[name='passwd']") | |
233 | |
234 | |
235 # http://crbug.com/368690 | |
236 class One63(WebsiteTest): | |
237 | |
238 def Login(self): | |
239 self.GoTo("http://www.163.com") | |
240 self.HoverOver("#js_N_navHighlight") | |
241 self.FillUsernameInto("#js_loginframe_username") | |
242 self.FillPasswordInto(".ntes-loginframe-label-ipt[type='password']") | |
243 self.Click(".ntes-loginframe-btn") | |
244 | |
245 | |
246 # http://crbug.com/368690 | |
247 class Vube(WebsiteTest): | |
248 | |
249 def Login(self): | |
250 self.GoTo("https://vube.com") | |
251 self.Click("[vube-login='']") | |
252 self.FillUsernameInto("[ng-model='login.user']") | |
253 self.FillPasswordInto("[ng-model='login.pass']") | |
254 while (self.IsDisplayed("[ng-model='login.pass']") | |
255 and not self.IsDisplayed(".prompt.alert")): | |
256 self.ClickIfClickable("[ng-click='login()']") | |
257 self.Wait(1) | |
258 | |
259 | |
260 def Tests(environment): | |
261 | |
262 | |
263 # Working tests. | |
264 | |
265 | |
266 environment.AddWebsiteTest(Facebook("facebook")) | |
267 | |
268 environment.AddWebsiteTest(Google("google")) | |
269 | |
270 environment.AddWebsiteTest(Linkedin("linkedin")) | |
271 | |
272 environment.AddWebsiteTest(Mailru("mailru")) | |
273 | |
274 environment.AddWebsiteTest(Nytimes("nytimes")) | |
275 | |
276 environment.AddWebsiteTest(Pinterest("pinterest")) | |
277 | |
278 environment.AddWebsiteTest(Reddit("reddit", username_not_auto=True)) | |
279 | |
280 environment.AddWebsiteTest(Tumblr("tumblr", username_not_auto=True)) | |
281 | |
282 environment.AddWebsiteTest(Twitter("twitter")) | |
283 | |
284 environment.AddWebsiteTest(Wikipedia("wikipedia", username_not_auto=True)) | |
285 | |
286 environment.AddWebsiteTest(Yahoo("yahoo", username_not_auto=True)) | |
287 | |
288 environment.AddWebsiteTest(Yandex("yandex")) | |
289 | |
290 # Disabled tests. | |
291 | |
292 | |
293 # Bug not reproducible without test. | |
294 environment.AddWebsiteTest(Amazon("amazon"), disabled=True) | |
295 | |
296 # Password not saved. | |
297 environment.AddWebsiteTest(Ask("ask"), disabled=True) | |
298 | |
299 # Password not saved. | |
300 environment.AddWebsiteTest(Baidu("baidu"), disabled=True) | |
301 | |
302 # http://crbug.com/368690 | |
303 environment.AddWebsiteTest(Cnn("cnn"), disabled=True) | |
304 | |
305 # http://crbug.com/368690 | |
306 environment.AddWebsiteTest(Ebay("ebay"), disabled=True) | |
307 | |
308 # Iframe, password saved but not autofileld. | |
309 environment.AddWebsiteTest(Espn("espn"), disabled=True) | |
310 | |
311 # http://crbug.com/367768 | |
312 environment.AddWebsiteTest(Live("live", username_not_auto=True), | |
313 disabled=True) | |
314 | |
315 # http://crbug.com/368690 | |
316 environment.AddWebsiteTest(One63("163"), disabled=True) | |
317 | |
318 # http://crbug.com/368690 | |
319 environment.AddWebsiteTest(Vube("vube"), disabled=True) | |
320 | |
321 def saveResults(environment_tests_results, environment_save_path): | |
322 """Save the test results in an xml file. | |
323 | |
324 Args: | |
325 environment_tests_results: A list of the TestResults that are going to be | |
326 saved. | |
327 environment_save_path: The file where the results are going to be saved. | |
328 If it's None, the results are not going to be stored. | |
329 Raises: | |
330 Exception: An exception is raised if the file is not found. | |
331 """ | |
332 if environment_save_path: | |
333 xml = "<result>" | |
334 for test_result in environment_tests_results: | |
335 xml += ("<test name='%s' successful='%s' type='%s'>%s</test>" | |
336 % (test_result.name, str(test_result.successful), | |
337 test_result.test_type, test_result.message)) | |
338 xml += "</result>" | |
339 with open(environment_save_path, "w") as save_file: | |
340 save_file.write(xml) | |
341 | |
342 def RunTests(chrome_path, chromedriver_path, profile_path, | |
343 environment_passwords_path, enable_automatic_password_saving, | |
344 environment_numeric_level, log_to_console, environment_log_file, | |
345 environment_tested_websites, tests=None): | |
346 | |
347 """Runs the the tests | |
348 | |
349 Args: | |
350 chrome_path: The chrome binary file. | |
351 chromedriver_path: The chromedriver binary file. | |
352 profile_path: The chrome testing profile folder. | |
353 environment_passwords_path: The usernames and passwords file. | |
354 enable_automatic_password_saving: If True, the passwords are going to be | |
355 saved without showing the prompt. | |
356 environment_numeric_level: The log verbosity. | |
357 log_to_console: If True, the debug logs will be shown on the console. | |
358 environment_log_file: The file where to store the log. If it's empty, the | |
359 log is not stored. | |
360 environment_tested_websites: One of the TypeOfTestedWebsites values, | |
361 indicating which group of tests to run. | |
362 tests: Specifies which tests to run. Ignored unless | |
363 |environment_tested_websites| is equal to LIST_OF_TESTS. | |
364 | |
365 Returns: | |
366 The results of tests as list of TestResults. | |
367 Raises: | |
368 Exception: An exception is raised if one of the tests fails. | |
369 """ | |
370 | |
371 environment = Environment(chrome_path, chromedriver_path, profile_path, | |
372 environment_passwords_path, | |
373 enable_automatic_password_saving, | |
374 environment_numeric_level, | |
375 log_to_console, | |
376 environment_log_file) | |
377 | |
378 # Test which care about the save-password prompt need the prompt | |
379 # to be shown. Automatic password saving results in no prompt. | |
380 run_prompt_tests = not enable_automatic_password_saving | |
381 | |
382 Tests(environment) | |
383 | |
384 if environment_tested_websites == TypeOfTestedWebsites.ALL_TESTS: | |
385 environment.AllTests(run_prompt_tests) | |
386 elif environment_tested_websites == TypeOfTestedWebsites.DISABLED_TESTS: | |
387 environment.DisabledTests(run_prompt_tests) | |
388 elif environment_tested_websites == TypeOfTestedWebsites.LIST_OF_TESTS: | |
389 environment.Test(tests, run_prompt_tests) | |
390 elif environment_tested_websites == TypeOfTestedWebsites.ENABLED_TESTS: | |
391 environment.WorkingTests(run_prompt_tests) | |
392 else: | |
393 raise Exception("Error: |environment_tested_websites| has to be one of the" | |
394 "TypeOfTestedWebsites values") | |
395 | |
396 | |
397 environment.Quit() | |
398 return environment.tests_results | |
399 | |
400 # Tests setup. | |
401 if __name__ == "__main__": | |
402 parser = argparse.ArgumentParser( | |
403 description="Password Manager automated tests help.") | |
404 | |
405 parser.add_argument( | |
406 "--chrome-path", action="store", dest="chrome_path", | |
407 help="Set the chrome path (required).", nargs=1, required=True) | |
408 parser.add_argument( | |
409 "--chromedriver-path", action="store", dest="chromedriver_path", | |
410 help="Set the chromedriver path (required).", nargs=1, required=True) | |
411 parser.add_argument( | |
412 "--profile-path", action="store", dest="profile_path", | |
413 help="Set the profile path (required). You just need to choose a " | |
414 "temporary empty folder. If the folder is not empty all its content " | |
415 "is going to be removed.", | |
416 nargs=1, required=True) | |
417 | |
418 parser.add_argument( | |
419 "--passwords-path", action="store", dest="passwords_path", | |
420 help="Set the usernames/passwords path (required).", nargs=1, | |
421 required=True) | |
422 parser.add_argument("--all", action="store_true", dest="all", | |
423 help="Run all tests.") | |
424 parser.add_argument("--disabled", action="store_true", dest="disabled", | |
425 help="Run only disabled tests.") | |
426 parser.add_argument("--log", action="store", nargs=1, dest="log_level", | |
427 help="Set log level.") | |
428 parser.add_argument("--log-screen", action="store_true", dest="log_screen", | |
429 help="Show log on the screen.") | |
430 parser.add_argument("--log-file", action="store", dest="log_file", | |
431 help="Write the log in a file.", nargs=1) | |
432 parser.add_argument("--save-path", action="store", nargs=1, dest="save_path", | |
433 help="Write the results in a file.") | |
434 parser.add_argument("tests", help="Tests to be run.", nargs="*") | |
435 | |
436 args = parser.parse_args() | |
437 | |
438 passwords_path = args.passwords_path[0] | |
439 | |
440 if args.all: | |
441 tested_websites = TypeOfTestedWebsites.ALL_TESTS | |
442 elif args.disabled: | |
443 tested_websites = TypeOfTestedWebsites.DISABLED_TESTS | |
444 elif args.tests: | |
445 tested_websites = TypeOfTestedWebsites.LIST_OF_TESTS | |
446 else: | |
447 tested_websites = TypeOfTestedWebsites.ENABLED_TESTS | |
448 | |
449 numeric_level = None | |
450 if args.log_level: | |
451 numeric_level = getattr(logging, args.log_level[0].upper(), None) | |
452 if not isinstance(numeric_level, int): | |
453 raise ValueError("Invalid log level: %s" % args.log_level[0]) | |
454 | |
455 log_file = None | |
456 if args.log_file: | |
457 log_file = args.log_file[0] | |
458 | |
459 save_path = None | |
460 if args.save_path: | |
461 save_path = args.save_path[0] | |
462 | |
463 # Run the test without enable-automatic-password-saving to check whether or | |
464 # not the prompt is shown in the way we expected. | |
465 tests_results = RunTests(args.chrome_path[0], | |
466 args.chromedriver_path[0], | |
467 args.profile_path[0], | |
468 passwords_path, | |
469 False, | |
470 numeric_level, | |
471 args.log_screen, | |
472 log_file, | |
473 tested_websites, | |
474 args.tests) | |
475 | |
476 # Run the test with enable-automatic-password-saving to check whether or not | |
477 # the passwords is stored in the the way we expected. | |
478 tests_results += RunTests(args.chrome_path[0], | |
479 args.chromedriver_path[0], | |
480 args.profile_path[0], | |
481 passwords_path, | |
482 True, | |
483 numeric_level, | |
484 args.log_screen, | |
485 log_file, | |
486 tested_websites, | |
487 args.tests) | |
488 | |
489 saveResults(tests_results, save_path) | |
OLD | NEW |