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

Side by Side Diff: chrome/test/functional/autofill.py

Issue 10855253: Convert the autofill pyauto tests to browser tests, and remove all the supporting automation hooks … (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: review comments Created 8 years, 4 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 | Annotate | Revision Log
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be 3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file. 4 # found in the LICENSE file.
5 5
6 import logging 6 import logging
7 import os 7 import os
8 import pickle 8 import pickle
9 import re 9 import re
10 import simplejson 10 import simplejson
11 11
12 import autofill_dataset_converter
13 import autofill_dataset_generator
14 import pyauto_functional # Must be imported before pyauto 12 import pyauto_functional # Must be imported before pyauto
15 import pyauto 13 import pyauto
16 import test_utils 14 import test_utils
17 from selenium.webdriver.common.keys import Keys 15 from selenium.webdriver.common.keys import Keys
18 from selenium.webdriver.common.action_chains import ActionChains 16 from selenium.webdriver.common.action_chains import ActionChains
19 from webdriver_pages import settings 17 from webdriver_pages import settings
20 18
21 19
22 class AutofillTest(pyauto.PyUITest): 20 class AutofillTest(pyauto.PyUITest):
23 """Tests that autofill works correctly""" 21 """Tests that autofill UI works correctly. Also contains a manual test for
22 the crowdsourcing server."""
24 23
25 def setUp(self): 24 def setUp(self):
26 pyauto.PyUITest.setUp(self) 25 pyauto.PyUITest.setUp(self)
27 self._driver = self.NewWebDriver() 26 self._driver = self.NewWebDriver()
28 27
29 def Debug(self):
30 """Test method for experimentation.
31
32 This method will not run automatically.
33 """
34 while True:
35 raw_input('Hit <enter> to dump info.. ')
36 self.pprint(self.GetAutofillProfile())
37
38 def testFillProfile(self):
39 """Test filling profiles and overwriting with new profiles."""
40 profiles = [{'NAME_FIRST': ['Bob',],
41 'NAME_LAST': ['Smith',], 'ADDRESS_HOME_ZIP': ['94043',],},
42 {'EMAIL_ADDRESS': ['sue@example.com',],
43 'COMPANY_NAME': ['Company X',],}]
44 credit_cards = [{'CREDIT_CARD_NUMBER': '6011111111111117',
45 'CREDIT_CARD_EXP_MONTH': '12',
46 'CREDIT_CARD_EXP_4_DIGIT_YEAR': '2011'},
47 {'CREDIT_CARD_NAME': 'Bob C. Smith'}]
48
49 self.FillAutofillProfile(profiles=profiles, credit_cards=credit_cards)
50 profile = self.GetAutofillProfile()
51 self.assertEqual(profiles, profile['profiles'])
52 self.assertEqual(credit_cards, profile['credit_cards'])
53
54 profiles = [ {'NAME_FIRST': ['Larry']}]
55 self.FillAutofillProfile(profiles=profiles)
56 profile = self.GetAutofillProfile()
57 self.assertEqual(profiles, profile['profiles'])
58 self.assertEqual(credit_cards, profile['credit_cards'])
59
60 def testFillProfileMultiValue(self):
61 """Test filling a profile with multi-value data."""
62 profile_expected = [{'NAME_FIRST': ['Bob', 'Joe'],
63 'NAME_LAST': ['Smith', 'Jones'],
64 'ADDRESS_HOME_ZIP': ['94043',],},]
65
66 self.FillAutofillProfile(profiles=profile_expected)
67 profile_actual = self.GetAutofillProfile()
68 self.assertEqual(profile_expected, profile_actual['profiles'])
69
70 def testFillProfileCrazyCharacters(self):
71 """Test filling profiles with unicode strings and crazy characters."""
72 # Adding autofill profiles.
73 file_path = os.path.join(self.DataDir(), 'autofill', 'functional',
74 'crazy_autofill.txt')
75 profiles = self.EvalDataFrom(file_path)
76 self.FillAutofillProfile(profiles=profiles)
77 self.assertEqual(profiles, self.GetAutofillProfile()['profiles'],
78 msg='Autofill profile data does not match.')
79
80 # Adding credit cards.
81 file_path = os.path.join(self.DataDir(), 'autofill', 'functional',
82 'crazy_creditcards.txt')
83 test_data = self.EvalDataFrom(file_path)
84 credit_cards_input = test_data['input']
85 self.FillAutofillProfile(credit_cards=credit_cards_input)
86
87 self.assertEqual(test_data['expected'],
88 self.GetAutofillProfile()['credit_cards'],
89 msg='Autofill credit card data does not match.')
90
91 def testGetProfilesEmpty(self):
92 """Test getting profiles when none have been filled."""
93 profile = self.GetAutofillProfile()
94 self.assertEqual([], profile['profiles'])
95 self.assertEqual([], profile['credit_cards'])
96
97 def testAutofillInvalid(self):
98 """Test filling in invalid values for profiles are saved as-is.
99
100 Phone information entered into the prefs UI is not validated or rejected
101 except for duplicates.
102 """
103 # First try profiles with invalid ZIP input.
104 without_invalid = {'NAME_FIRST': ['Will',],
105 'ADDRESS_HOME_CITY': ['Sunnyvale',],
106 'ADDRESS_HOME_STATE': ['CA',],
107 'ADDRESS_HOME_ZIP': ['my_zip',],
108 'ADDRESS_HOME_COUNTRY': ['United States',]}
109 # Add invalid data for phone field.
110 with_invalid = without_invalid.copy()
111 with_invalid['PHONE_HOME_WHOLE_NUMBER'] = ['Invalid_Phone_Number',]
112 self.FillAutofillProfile(profiles=[with_invalid])
113 self.assertNotEqual(
114 [without_invalid], self.GetAutofillProfile()['profiles'],
115 msg='Phone data entered into prefs UI is validated.')
116
117 def testAutofillPrefsStringSavedAsIs(self):
118 """Test invalid credit card numbers typed in prefs should be saved as-is."""
119 credit_card = {'CREDIT_CARD_NUMBER': 'Not_0123-5Checked'}
120 self.FillAutofillProfile(credit_cards=[credit_card])
121 self.assertEqual([credit_card],
122 self.GetAutofillProfile()['credit_cards'],
123 msg='Credit card number in prefs not saved as-is.')
124
125 def _WaitForWebpageFormReadyToFillIn(self, form_profile, tab_index, windex):
126 """Waits until an autofill form on a webpage is ready to be filled in.
127
128 A call to NavigateToURL() may return before all form elements on the page
129 are ready to be accessed. This function waits until they are ready to be
130 filled in.
131
132 Args:
133 form_profile: A dictionary representing an autofill profile in which the
134 keys are strings corresponding to webpage element IDs.
135 tab_index: The index of the tab containing the webpage form to check.
136 windex: The index of the window containing the webpage form to check.
137 """
138 field_check_code = ''.join(
139 ['if (!document.getElementById("%s")) ready = "false";' %
140 key for key in form_profile.keys()])
141 js = """
142 var ready = 'true';
143 if (!document.getElementById("testform"))
144 ready = 'false';
145 %s
146 window.domAutomationController.send(ready);
147 """ % field_check_code
148 self.assertTrue(
149 self.WaitUntil(lambda: self.ExecuteJavascript(js, tab_index, windex),
150 expect_retval='true'),
151 msg='Timeout waiting for webpage form to be ready to be filled in.')
152
153 def _FillFormAndSubmit(self, datalist, filename, tab_index=0, windex=0):
154 """Navigate to the form, input values into the fields, and submit the form.
155
156 If multiple profile dictionaries are specified as input, this function will
157 repeatedly navigate to the form, fill it out, and submit it, once for each
158 specified profile dictionary.
159
160 Args:
161 datalist: A list of dictionaries, where each dictionary represents the
162 key/value pairs for profiles or credit card values.
163 filename: HTML form website file. The file is the basic file name and not
164 the path to the file. File is assumed to be located in
165 autofill/functional directory of the data folder.
166 tab_index: Integer index of the tab to work on; defaults to 0 (first tab).
167 windex: Integer index of the browser window to work on; defaults to 0
168 (first window).
169 """
170 url = self.GetHttpURLForDataPath('autofill', 'functional', filename)
171 for profile in datalist:
172 self.NavigateToURL(url)
173 self._WaitForWebpageFormReadyToFillIn(profile, tab_index, windex)
174 # Fill in and submit the form.
175 js = ''.join(['document.getElementById("%s").value = "%s";' %
176 (key, value) for key, value in profile.iteritems()])
177 js += 'document.getElementById("testform").submit();'
178 self.SubmitAutofillForm(js, tab_index=tab_index, windex=windex)
179
180 def _LuhnCreditCardNumberValidator(self, number):
181 """Validates whether a number is valid or invalid using the Luhn test.
182
183 Validation example:
184 1. Example number: 49927398716
185 2. Reverse the digits: 61789372994
186 3. Sum the digits in the odd-numbered position for s1:
187 6 + 7 + 9 + 7 + 9 + 4 = 42
188 4. Take the digits in the even-numbered position: 1, 8, 3, 2, 9
189 4.1. Two times each digit in the even-numbered position: 2, 16, 6, 4, 18
190 4.2. For each resulting value that is now 2 digits, add the digits
191 together: 2, 7, 6, 4, 9
192 (0 + 2 = 2, 1 + 6 = 7, 0 + 6 = 6, 0 + 4 = 4, 1 + 8 = 9)
193 4.3. Sum together the digits for s2: 2 + 7 + 6 + 4 + 9 = 28
194 5. Sum together s1 + s2 and if the sum ends in zero, the number passes the
195 Luhn test: 42 + 28 = 70 which is a valid credit card number.
196
197 Args:
198 number: the credit card number being validated, as a string.
199
200 Returns:
201 boolean whether the credit card number is valid or not.
202 """
203 # Filters out non-digit characters.
204 number = re.sub('[^0-9]', '', number)
205 reverse = [int(ch) for ch in str(number)][::-1]
206 # The divmod of the function splits a number into two digits, ready for
207 # summing.
208 return ((sum(reverse[0::2]) + sum(sum(divmod(d*2, 10))
209 for d in reverse[1::2])) % 10 == 0)
210
211 def testInvalidCreditCardNumberIsNotAggregated(self):
212 """Test credit card info with an invalid number is not aggregated.
213
214 When filling out a form with an invalid credit card number (one that
215 does not pass the Luhn test) the credit card info should not be saved into
216 Autofill preferences.
217 """
218 invalid_cc_info = {'CREDIT_CARD_NAME': 'Bob Smith',
219 'CREDIT_CARD_NUMBER': '4408 0412 3456 7890',
220 'CREDIT_CARD_EXP_MONTH': '12',
221 'CREDIT_CARD_EXP_4_DIGIT_YEAR': '2014'}
222
223 cc_number = invalid_cc_info['CREDIT_CARD_NUMBER']
224 self._FillFormAndSubmit([invalid_cc_info], 'autofill_creditcard_form.html',
225 tab_index=0, windex=0)
226 self.assertFalse(self._LuhnCreditCardNumberValidator(cc_number),
227 msg='This test requires an invalid credit card number.')
228 cc_infobar = self.GetBrowserInfo()['windows'][0]['tabs'][0]['infobars']
229 self.assertFalse(
230 cc_infobar, msg='Save credit card infobar offered to save CC info.')
231
232 def testWhitespacesAndSeparatorCharsStrippedForValidCCNums(self):
233 """Test whitespaces and separator chars are stripped for valid CC numbers.
234
235 The credit card numbers used in this test pass the Luhn test.
236 For reference: http://www.merriampark.com/anatomycc.htm
237 """
238 credit_card_info = [{'CREDIT_CARD_NAME': 'Bob Smith',
239 'CREDIT_CARD_NUMBER': '4408 0412 3456 7893',
240 'CREDIT_CARD_EXP_MONTH': '12',
241 'CREDIT_CARD_EXP_4_DIGIT_YEAR': '2014'},
242 {'CREDIT_CARD_NAME': 'Jane Doe',
243 'CREDIT_CARD_NUMBER': '4417-1234-5678-9113',
244 'CREDIT_CARD_EXP_MONTH': '10',
245 'CREDIT_CARD_EXP_4_DIGIT_YEAR': '2013'}]
246
247 url = self.GetHttpURLForDataPath(
248 'autofill', 'functional', 'autofill_creditcard_form.html')
249 for cc_info in credit_card_info:
250 self.assertTrue(
251 self._LuhnCreditCardNumberValidator(cc_info['CREDIT_CARD_NUMBER']),
252 msg='This test requires a valid credit card number.')
253 self.NavigateToURL(url)
254 self._WaitForWebpageFormReadyToFillIn(cc_info, 0, 0)
255 # Fill in and submit the form.
256 js = ''.join(['document.getElementById("%s").value = "%s";' %
257 (key, value) for key, value in cc_info.iteritems()])
258 js += 'document.getElementById("testform").submit();'
259 self.SubmitAutofillForm(js, tab_index=0, windex=0)
260
261 # Verify the filled-in credit card number against the aggregated number.
262 aggregated_cc_1 = (
263 self.GetAutofillProfile()['credit_cards'][0]['CREDIT_CARD_NUMBER'])
264 aggregated_cc_2 = (
265 self.GetAutofillProfile()['credit_cards'][1]['CREDIT_CARD_NUMBER'])
266 self.assertFalse((' ' in aggregated_cc_1 or ' ' in aggregated_cc_2 or
267 '-' in aggregated_cc_1 or '-' in aggregated_cc_2),
268 msg='Whitespaces or separator chars not stripped.')
269
270 def testAggregatesMinValidProfile(self):
271 """Test that Autofill aggregates a minimum valid profile.
272
273 The minimum required address fields must be specified: First Name,
274 Last Name, Address Line 1, City, Zip Code, and State.
275 """
276 profile = {'NAME_FIRST': 'Bob',
277 'NAME_LAST': 'Smith',
278 'ADDRESS_HOME_LINE1': '1234 H St.',
279 'ADDRESS_HOME_CITY': 'Mountain View',
280 'ADDRESS_HOME_STATE': 'CA',
281 'ADDRESS_HOME_ZIP': '95110'}
282 self._FillFormAndSubmit(
283 [profile], 'duplicate_profiles_test.html', tab_index=0, windex=0)
284 self.assertTrue(self.GetAutofillProfile()['profiles'],
285 msg='Profile with minimum address values not aggregated.')
286
287 def testProfilesNotAggregatedWithNoAddress(self):
288 """Test Autofill does not aggregate profiles with no address info.
289
290 The minimum required address fields must be specified: First Name,
291 Last Name, Address Line 1, City, Zip Code, and State.
292 """
293 profile = {'NAME_FIRST': 'Bob',
294 'NAME_LAST': 'Smith',
295 'EMAIL_ADDRESS': 'bsmith@example.com',
296 'COMPANY_NAME': 'Company X',
297 'ADDRESS_HOME_CITY': 'Mountain View',
298 'PHONE_HOME_WHOLE_NUMBER': '650-555-4567',}
299 self._FillFormAndSubmit(
300 [profile], 'duplicate_profiles_test.html', tab_index=0, windex=0)
301 self.assertFalse(self.GetAutofillProfile()['profiles'],
302 msg='Profile with no address info was aggregated.')
303
304 def testProfilesNotAggregatedWithInvalidEmail(self):
305 """Test Autofill does not aggregate profiles with an invalid email."""
306 profile = {'NAME_FIRST': 'Bob',
307 'NAME_LAST': 'Smith',
308 'EMAIL_ADDRESS': 'garbage',
309 'ADDRESS_HOME_LINE1': '1234 H St.',
310 'ADDRESS_HOME_CITY': 'San Jose',
311 'ADDRESS_HOME_STATE': 'CA',
312 'ADDRESS_HOME_ZIP': '95110',
313 'COMPANY_NAME': 'Company X',
314 'PHONE_HOME_WHOLE_NUMBER': '408-871-4567',}
315 self._FillFormAndSubmit(
316 [profile], 'duplicate_profiles_test.html', tab_index=0, windex=0)
317 self.assertFalse(self.GetAutofillProfile()['profiles'],
318 msg='Profile with invalid email was aggregated.')
319
320 def testComparePhoneNumbers(self):
321 """Test phone fields parse correctly from a given profile.
322
323 The high level key presses execute the following: Select the first text
324 field, invoke the autofill popup list, select the first profile within the
325 list, and commit to the profile to populate the form.
326 """
327 profile_path = os.path.join(self.DataDir(), 'autofill', 'functional',
328 'phone_pinput_autofill.txt')
329 profile_expected_path = os.path.join(
330 self.DataDir(), 'autofill', 'functional',
331 'phone_pexpected_autofill.txt')
332 profiles = self.EvalDataFrom(profile_path)
333 profiles_expected = self.EvalDataFrom(profile_expected_path)
334 self.FillAutofillProfile(profiles=profiles)
335 url = self.GetHttpURLForDataPath(
336 'autofill', 'functional', 'form_phones.html')
337 for profile_expected in profiles_expected:
338 self.NavigateToURL(url)
339 self.assertTrue(self.AutofillPopulateForm('NAME_FIRST'),
340 msg='Autofill form could not be populated.')
341 form_values = {}
342 for key, value in profile_expected.iteritems():
343 js_returning_field_value = (
344 'var field_value = document.getElementById("%s").value;'
345 'window.domAutomationController.send(field_value);'
346 ) % key
347 form_values[key] = self.ExecuteJavascript(
348 js_returning_field_value, 0, 0)
349 self.assertEqual(
350 [form_values[key]], value,
351 msg=('Original profile not equal to expected profile at key: "%s"\n'
352 'Expected: "%s"\nReturned: "%s"' % (
353 key, value, [form_values[key]])))
354
355 def testProfileSavedWithValidCountryPhone(self):
356 """Test profile is saved if phone number is valid in selected country.
357
358 The data file contains two profiles with valid phone numbers and two
359 profiles with invalid phone numbers from their respective country.
360 """
361 profiles_list = self.EvalDataFrom(
362 os.path.join(self.DataDir(), 'autofill', 'functional',
363 'phonechecker.txt'))
364 self._FillFormAndSubmit(profiles_list, 'autofill_test_form.html',
365 tab_index=0, windex=0)
366 num_profiles = len(self.GetAutofillProfile()['profiles'])
367 self.assertEqual(2, num_profiles,
368 msg='Expected 2 profiles, but got %d.' % num_profiles)
369
370 def testCharsStrippedForAggregatedPhoneNumbers(self):
371 """Test aggregated phone numbers are standardized (not saved "as-is")."""
372 profiles_list = self.EvalDataFrom(
373 os.path.join(self.DataDir(), 'autofill', 'functional',
374 'phonecharacters.txt'))
375 self._FillFormAndSubmit(profiles_list, 'autofill_test_form.html',
376 tab_index=0, windex=0)
377 us_phone = self.GetAutofillProfile()[
378 'profiles'][0]['PHONE_HOME_WHOLE_NUMBER']
379 de_phone = self.GetAutofillProfile()[
380 'profiles'][1]['PHONE_HOME_WHOLE_NUMBER']
381 self.assertEqual(
382 ['+1 408-871-4567',], us_phone,
383 msg='Aggregated US phone number %s not standardized.' % us_phone)
384 self.assertEqual(
385 ['+49 40/808179000',], de_phone,
386 msg='Aggregated Germany phone number %s not standardized.' % de_phone)
387
388 def testAppendCountryCodeForAggregatedPhones(self):
389 """Test Autofill appends country codes to aggregated phone numbers.
390
391 The country code is added for the following case:
392 The phone number contains the correct national number size and
393 is a valid format.
394 """
395 profile = {'NAME_FIRST': 'Bob',
396 'NAME_LAST': 'Smith',
397 'ADDRESS_HOME_LINE1': '1234 H St.',
398 'ADDRESS_HOME_CITY': 'San Jose',
399 'ADDRESS_HOME_STATE': 'CA',
400 'ADDRESS_HOME_ZIP': '95110',
401 'ADDRESS_HOME_COUNTRY': 'Germany',
402 'PHONE_HOME_WHOLE_NUMBER': '(08) 450 777-777',}
403
404 self._FillFormAndSubmit(
405 [profile], 'autofill_test_form.html', tab_index=0, windex=0)
406 de_phone = self.GetAutofillProfile()[
407 'profiles'][0]['PHONE_HOME_WHOLE_NUMBER']
408 self.assertEqual(
409 '+49', de_phone[0][:3],
410 msg='Country code missing from phone number %s.' % de_phone)
411
412 def testCCInfoNotStoredWhenAutocompleteOff(self):
413 """Test CC info not offered to be saved when autocomplete=off for CC field.
414
415 If the credit card number field has autocomplete turned off, then the credit
416 card infobar should not offer to save the credit card info. The credit card
417 number must be a valid Luhn number.
418 """
419 credit_card_info = {'CREDIT_CARD_NAME': 'Bob Smith',
420 'CREDIT_CARD_NUMBER': '4408041234567893',
421 'CREDIT_CARD_EXP_MONTH': '12',
422 'CREDIT_CARD_EXP_4_DIGIT_YEAR': '2014'}
423
424 self._FillFormAndSubmit(
425 [credit_card_info], 'cc_autocomplete_off_test.html',
426 tab_index=0, windex=0)
427 cc_infobar = self.GetBrowserInfo()['windows'][0]['tabs'][0]['infobars']
428 self.assertFalse(cc_infobar,
429 msg='Save credit card infobar offered to save CC info.')
430
431 def testNoAutofillForReadOnlyFields(self):
432 """Test that Autofill does not fill in read-only fields."""
433 profile = {'NAME_FIRST': ['Bob',],
434 'NAME_LAST': ['Smith',],
435 'EMAIL_ADDRESS': ['bsmith@gmail.com',],
436 'ADDRESS_HOME_LINE1': ['1234 H St.',],
437 'ADDRESS_HOME_CITY': ['San Jose',],
438 'ADDRESS_HOME_STATE': ['CA',],
439 'ADDRESS_HOME_ZIP': ['95110',],
440 'COMPANY_NAME': ['Company X',],
441 'PHONE_HOME_WHOLE_NUMBER': ['408-871-4567',],}
442
443 self.FillAutofillProfile(profiles=[profile])
444 url = self.GetHttpURLForDataPath(
445 'autofill', 'functional', 'read_only_field_test.html')
446 self.NavigateToURL(url)
447 self.assertTrue(self.AutofillPopulateForm('firstname'),
448 msg='Autofill form could not be populated.')
449 js_return_readonly_field = (
450 'var field_value = document.getElementById("email").value;'
451 'window.domAutomationController.send(field_value);')
452 readonly_field_value = self.ExecuteJavascript(
453 js_return_readonly_field, 0, 0)
454 js_return_addrline1_field = (
455 'var field_value = document.getElementById("address").value;'
456 'window.domAutomationController.send(field_value);')
457 addrline1_field_value = self.ExecuteJavascript(
458 js_return_addrline1_field, 0, 0)
459 self.assertNotEqual(
460 readonly_field_value, profile['EMAIL_ADDRESS'][0],
461 'Autofill filled in value "%s" for a read-only field.'
462 % readonly_field_value)
463 self.assertEqual(
464 addrline1_field_value, profile['ADDRESS_HOME_LINE1'][0],
465 'Unexpected value "%s" in the Address field.' % addrline1_field_value)
466
467 def testFormFillableOnReset(self):
468 """Test form is fillable from a profile after form was reset.
469
470 Steps:
471 1. Fill form using a saved profile.
472 2. Reset the form.
473 3. Fill form using a saved profile.
474 """
475 profile = {'NAME_FIRST': ['Bob',],
476 'NAME_LAST': ['Smith',],
477 'EMAIL_ADDRESS': ['bsmith@gmail.com',],
478 'ADDRESS_HOME_LINE1': ['1234 H St.',],
479 'ADDRESS_HOME_CITY': ['San Jose',],
480 'PHONE_HOME_WHOLE_NUMBER': ['4088714567',],}
481
482 self.FillAutofillProfile(profiles=[profile])
483 url = self.GetHttpURLForDataPath(
484 'autofill', 'functional', 'autofill_test_form.html')
485 self.NavigateToURL(url)
486 # Fill form using an address profile.
487 self.assertTrue(self.AutofillPopulateForm('NAME_FIRST'),
488 msg='Autofill form could not be populated.')
489 # Reset the form.
490 self.ExecuteJavascript('document.getElementById("testform").reset();'
491 'window.domAutomationController.send("done");',
492 0, 0)
493 # Fill in the form using an Autofill profile.
494 self.assertTrue(self.AutofillPopulateForm('NAME_FIRST'),
495 msg='Autofill form could not be populated.')
496 # Verify value in fields match value in the profile dictionary.
497 form_values = {}
498 for key, value in profile.iteritems():
499 js_returning_field_value = (
500 'var field_value = document.getElementById("%s").value;'
501 'window.domAutomationController.send(field_value);'
502 ) % key
503 form_values[key] = self.ExecuteJavascript(
504 js_returning_field_value, 0, 0)
505 self.assertEqual(
506 [form_values[key]], value,
507 msg=('Original profile not equal to expected profile at key: "%s"\n'
508 'Expected: "%s"\nReturned: "%s"' % (
509 key, value, [form_values[key]])))
510
511 def testDistinguishMiddleInitialWithinName(self):
512 """Test Autofill distinguishes a middle initial in a name."""
513 profile = {'NAME_FIRST': ['Bob',],
514 'NAME_MIDDLE': ['Leo',],
515 'NAME_LAST': ['Smith',],
516 'EMAIL_ADDRESS': ['bsmith@gmail.com',],
517 'ADDRESS_HOME_LINE1': ['1234 H St.',],
518 'ADDRESS_HOME_CITY': ['San Jose',],
519 'PHONE_HOME_WHOLE_NUMBER': ['4088714567',],}
520
521 middle_initial = profile['NAME_MIDDLE'][0][0]
522 self.FillAutofillProfile(profiles=[profile])
523 url = self.GetHttpURLForDataPath(
524 'autofill', 'functional', 'autofill_middleinit_form.html')
525 self.NavigateToURL(url)
526 # Fill form using an address profile.
527 self.assertTrue(self.AutofillPopulateForm('NAME_FIRST'),
528 msg='Autofill form could not be populated.')
529 js_return_middleinit_field = (
530 'var field_value = document.getElementById("NAME_MIDDLE").value;'
531 'window.domAutomationController.send(field_value);')
532 middleinit_field_value = self.ExecuteJavascript(
533 js_return_middleinit_field, 0, 0)
534 self.assertEqual(middleinit_field_value, middle_initial,
535 msg=('Middle initial "%s" not distinguished from "%s".' %
536 (middleinit_field_value, profile['NAME_MIDDLE'])))
537
538 def testMultipleEmailFilledByOneUserGesture(self):
539 """Test forms with multiple email addresses are filled properly.
540
541 Entire form should be filled with one user gesture.
542 """
543 profile = {'NAME_FIRST': ['Bob',],
544 'NAME_LAST': ['Smith',],
545 'EMAIL_ADDRESS': ['bsmith@gmail.com',],
546 'PHONE_HOME_WHOLE_NUMBER': ['4088714567',],}
547
548 self.FillAutofillProfile(profiles=[profile])
549 url = self.GetHttpURLForDataPath(
550 'autofill', 'functional', 'autofill_confirmemail_form.html')
551 self.NavigateToURL(url)
552 # Fill form using an address profile.
553 self.assertTrue(self.AutofillPopulateForm('NAME_FIRST'),
554 msg='Autofill form could not be populated.')
555 js_return_confirmemail_field = (
556 'var field_value = document.getElementById("EMAIL_CONFIRM").value;'
557 'window.domAutomationController.send(field_value);')
558 confirmemail_field_value = self.ExecuteJavascript(
559 js_return_confirmemail_field, 0, 0)
560 self.assertEqual([confirmemail_field_value], profile['EMAIL_ADDRESS'],
561 msg=('Confirmation Email address "%s" not equal to Email\n'
562 'address "%s".' % ([confirmemail_field_value],
563 profile['EMAIL_ADDRESS'])))
564
565 def testProfileWithEmailInOtherFieldNotSaved(self):
566 """Test profile not aggregated if email found in non-email field."""
567 profile = {'NAME_FIRST': 'Bob',
568 'NAME_LAST': 'Smith',
569 'ADDRESS_HOME_LINE1': 'bsmith@gmail.com',
570 'ADDRESS_HOME_CITY': 'San Jose',
571 'ADDRESS_HOME_STATE': 'CA',
572 'ADDRESS_HOME_ZIP': '95110',
573 'COMPANY_NAME': 'Company X',
574 'PHONE_HOME_WHOLE_NUMBER': '408-871-4567',}
575 self._FillFormAndSubmit(
576 [profile], 'duplicate_profiles_test.html', tab_index=0, windex=0)
577 self.assertFalse(self.GetAutofillProfile()['profiles'],
578 msg='Profile with email in a non-email field was '
579 'aggregated.')
580
581 def FormFillLatencyAfterSubmit(self):
582 """Test latency time on form submit with lots of stored Autofill profiles.
583
584 This test verifies when a profile is selected from the Autofill dictionary
585 that consists of thousands of profiles, the form does not hang after being
586 submitted.
587
588 The high level key presses execute the following: Select the first text
589 field, invoke the autofill popup list, select the first profile within the
590 list, and commit to the profile to populate the form.
591
592 This test is partially automated. The bulk of the work is done, such as
593 generating 1500 plus profiles, inserting those profiles into Autofill,
594 selecting a profile from the list. The tester will need to click on the
595 submit button and check if the browser hangs.
596 """
597 # HTML file needs to be run from a http:// url.
598 url = self.GetHttpURLForDataPath(
599 'autofill', 'functional', 'latency_after_submit_test.html')
600 # Run the generator script to generate the dictionary list needed for the
601 # profiles.
602 gen = autofill_dataset_generator.DatasetGenerator(
603 logging_level=logging.ERROR)
604 list_of_dict = gen.GenerateDataset(num_of_dict_to_generate=1501)
605 self.FillAutofillProfile(profiles=list_of_dict)
606 self.NavigateToURL(url)
607 self.assertTrue(self.AutofillPopulateForm('NAME_FIRST'),
608 msg='Autofill form could not be populated.')
609 # TODO(dyu): add automated form hang or crash verification.
610 raw_input(
611 'Verify the test manually. Test hang time after submitting the form.')
612
613
614 def AutofillCrowdsourcing(self): 28 def AutofillCrowdsourcing(self):
615 """Test able to send POST request of web form to Autofill server. 29 """Test able to send POST request of web form to Autofill server.
616 30
617 The Autofill server processes the data offline, so it can take a few days 31 The Autofill server processes the data offline, so it can take a few days
618 for the result to be detectable. Manual verification is required. 32 for the result to be detectable. Manual verification is required.
619 """ 33 """
620 # HTML file needs to be run from a specific http:// url to be able to verify 34 # HTML file needs to be run from a specific http:// url to be able to verify
621 # the results a few days later by visiting the same url. 35 # the results a few days later by visiting the same url.
622 url = 'http://www.corp.google.com/~dyu/autofill/crowdsourcing-test.html' 36 url = 'http://www.corp.google.com/~dyu/autofill/crowdsourcing-test.html'
623 # Adding crowdsourcing Autofill profile.
624 file_path = os.path.join(self.DataDir(), 'autofill', 'functional',
625 'crowdsource_autofill.txt')
626 profiles = self.EvalDataFrom(file_path)
627 self.FillAutofillProfile(profiles=profiles)
628 # Autofill server captures 2.5% of the data posted. 37 # Autofill server captures 2.5% of the data posted.
629 # Looping 1000 times is a safe minimum to exceed the server's threshold or 38 # Looping 1000 times is a safe minimum to exceed the server's threshold or
630 # noise. 39 # noise.
631 for i in range(1000): 40 for i in range(1000):
632 fname = self.GetAutofillProfile()['profiles'][0]['NAME_FIRST'][0] 41 fname = 'David'
633 lname = self.GetAutofillProfile()['profiles'][0]['NAME_LAST'][0] 42 lname = 'Yu'
634 email = self.GetAutofillProfile()['profiles'][0]['EMAIL_ADDRESS'][0] 43 email = 'david.yu@gmail.com'
635 # Submit form to collect crowdsourcing data for Autofill. 44 # Submit form to collect crowdsourcing data for Autofill.
636 self.NavigateToURL(url, 0, 0) 45 self.NavigateToURL(url, 0, 0)
637 profile = {'fn': fname, 'ln': lname, 'em': email} 46 profile = {'fn': fname, 'ln': lname, 'em': email}
638 self._WaitForWebpageFormReadyToFillIn(profile, 0, 0)
639 js = ''.join(['document.getElementById("%s").value = "%s";' % 47 js = ''.join(['document.getElementById("%s").value = "%s";' %
640 (key, value) for key, value in profile.iteritems()]) 48 (key, value) for key, value in profile.iteritems()])
641 js += 'document.getElementById("testform").submit();' 49 js += 'document.getElementById("testform").submit();'
642 self.SubmitAutofillForm(js, tab_index=0, windex=0) 50 self.ExecuteJavascript(js)
643
644 def testSameAddressProfilesAddInPrefsDontMerge(self):
645 """Test profiles added through prefs with same address do not merge."""
646 profileA = {'NAME_FIRST': ['John',],
647 'NAME_LAST': ['Doe',],
648 'ADDRESS_HOME_LINE1': ['123 Cherry St',],
649 'ADDRESS_HOME_CITY': ['Mountain View',],
650 'ADDRESS_HOME_STATE': ['CA',],
651 'ADDRESS_HOME_ZIP': ['94043',],
652 'PHONE_HOME_WHOLE_NUMBER': ['650-555-1234',],}
653 profileB = {'NAME_FIRST': ['Jane',],
654 'NAME_LAST': ['Smith',],
655 'ADDRESS_HOME_LINE1': ['123 Cherry St',],
656 'ADDRESS_HOME_CITY': ['Mountain View',],
657 'ADDRESS_HOME_STATE': ['CA',],
658 'ADDRESS_HOME_ZIP': ['94043',],
659 'PHONE_HOME_WHOLE_NUMBER': ['650-253-1234',],}
660
661 profiles_list = [profileA, profileB]
662 self.FillAutofillProfile(profiles=profiles_list)
663 self.assertEqual(2, len(self.GetAutofillProfile()['profiles']),
664 msg='Profiles in prefs with same address merged.')
665
666 def testMergeAggregatedProfilesWithSameAddress(self):
667 """Test that profiles merge for aggregated data with same address.
668
669 The criterion for when two profiles are expected to be merged is when their
670 'Address Line 1' and 'City' data match. When two profiles are merged, any
671 remaining address fields are expected to be overwritten. Any non-address
672 fields should accumulate multi-valued data.
673 """
674 self._AggregateProfilesIntoAutofillPrefs('dataset_2.txt')
675 # Expecting 3 profiles out of the original 14 within Autofill preferences
676 self.assertEqual(3, len(self.GetAutofillProfile()['profiles']),
677 msg='Aggregated profiles did not merge correctly.')
678
679 def testProfilesNotMergedWhenNoMinAddressData(self):
680 """Test profiles are not merged without mininum address values.
681
682 Mininum address values needed during aggregation are: address line 1, city,
683 state, and zip code.
684
685 Profiles are merged when data for address line 1 and city match.
686 """
687 self._AggregateProfilesIntoAutofillPrefs('dataset_no_address.txt')
688 self.assertFalse(self.GetAutofillProfile()['profiles'],
689 msg='Profile with no min address data was merged.')
690
691 def MergeAggregatedDuplicatedProfiles(self):
692 """Test Autofill ability to merge duplicate profiles and throw away junk."""
693 num_of_profiles = self._AggregateProfilesIntoAutofillPrefs('dataset.txt')
694 # Verify total number of inputted profiles is greater than the final number
695 # of profiles after merging.
696 self.assertTrue(
697 num_of_profiles > len(self.GetAutofillProfile()['profiles']))
698
699 def _AggregateProfilesIntoAutofillPrefs(self, data):
700 """Aggregate profiles from forms into Autofill preferences.
701
702 Args:
703 data: Name of the data set file.
704
705 Returns:
706 Number of profiles in the dictionary list.
707 """
708 # HTML file needs to be run from a http:// url.
709 url = self.GetHttpURLForDataPath(
710 'autofill', 'functional', 'duplicate_profiles_test.html')
711 # Run the parser script to generate the dictionary list needed for the
712 # profiles.
713 c = autofill_dataset_converter.DatasetConverter(
714 os.path.abspath(
715 os.path.join(self.DataDir(), 'autofill', 'functional', data)),
716 logging_level=logging.INFO) # Set verbosity to INFO, WARNING, ERROR.
717 list_of_dict = c.Convert()
718
719 for profile in list_of_dict:
720 self.NavigateToURL(url)
721 self._WaitForWebpageFormReadyToFillIn(profile, 0, 0)
722 js = ''.join(['document.getElementById("%s").value = "%s";' %
723 (key, value) for key, value in profile.iteritems()])
724 js += 'document.getElementById("testform").submit();'
725 self.SubmitAutofillForm(js, tab_index=0, windex=0)
726 return len(list_of_dict)
727 51
728 def _SelectOptionXpath(self, value): 52 def _SelectOptionXpath(self, value):
729 """Returns an xpath query used to select an item from a dropdown list. 53 """Returns an xpath query used to select an item from a dropdown list.
730 Args: 54 Args:
731 value: Option selected for the drop-down list field. 55 value: Option selected for the drop-down list field.
732 56
733 Returns: 57 Returns:
734 The value of the xpath query. 58 The value of the xpath query.
735 """ 59 """
736 return '//option[@value="%s"]' % value 60 return '//option[@value="%s"]' % value
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
892 'Field expected to receive focus: "%s"\n' 216 'Field expected to receive focus: "%s"\n'
893 'Field that received focus instead: "%s"') 217 'Field that received focus instead: "%s"')
894 % (self._GetElementInfo(field), 218 % (self._GetElementInfo(field),
895 self._GetElementInfo(field_nextfield_dict[field]), 219 self._GetElementInfo(field_nextfield_dict[field]),
896 self._GetElementInfo( 220 self._GetElementInfo(
897 self._driver.switch_to_active_element()))) 221 self._driver.switch_to_active_element())))
898 222
899 223
900 if __name__ == '__main__': 224 if __name__ == '__main__':
901 pyauto_functional.Main() 225 pyauto_functional.Main()
OLDNEW
« no previous file with comments | « chrome/test/functional/PYAUTO_TESTS ('k') | chrome/test/functional/autofill_dataset_converter.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698