summaryrefslogtreecommitdiffstats
path: root/chrome/test/functional/autofill.py
blob: 57d071c1e4e1dbb60eb2aaa653bd51ed2498df98 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
#!/usr/bin/python
# Copyright (c) 2010 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import logging
import os
import pickle

import dataset_converter
import pyauto_functional  # Must be imported before pyauto
import pyauto


class AutoFillTest(pyauto.PyUITest):
  """Tests that autofill works correctly"""

  def Debug(self):
    """Test method for experimentation.

    This method will not run automatically.
    """
    import pprint
    pp = pprint.PrettyPrinter(indent=2)
    while True:
      raw_input('Hit <enter> to dump info.. ')
      info = self.GetAutoFillProfile()
      pp.pprint(info)

  def testFillProfile(self):
    """Test filling profiles and overwriting with new profiles."""
    profiles = [{'NAME_FIRST': 'Bob',
                 'NAME_LAST': 'Smith', 'ADDRESS_HOME_ZIP': '94043',},
                {'EMAIL_ADDRESS': 'sue@example.com',
                 'COMPANY_NAME': 'Company X',}]
    credit_cards = [{'CREDIT_CARD_NUMBER': '6011111111111117',
                     'CREDIT_CARD_EXP_MONTH': '12',
                     'CREDIT_CARD_EXP_4_DIGIT_YEAR': '2011'},
                    {'CREDIT_CARD_NAME': 'Bob C. Smith'}]

    self.FillAutoFillProfile(profiles=profiles, credit_cards=credit_cards)
    profile = self.GetAutoFillProfile()
    self.assertEqual(profiles, profile['profiles'])
    self.assertEqual(credit_cards, profile['credit_cards'])

    profiles = [ {'NAME_FIRST': 'Larry'}]
    self.FillAutoFillProfile(profiles=profiles)
    profile = self.GetAutoFillProfile()
    self.assertEqual(profiles, profile['profiles'])
    self.assertEqual(credit_cards, profile['credit_cards'])

  def testFillProfileCrazyCharacters(self):
    """Test filling profiles with unicode strings and crazy characters."""
    # Adding autofill profiles.
    file_path = os.path.join(self.DataDir(), 'autofill', 'crazy_autofill.txt')
    profiles = self.EvalDataFrom(file_path)
    self.FillAutoFillProfile(profiles=profiles)

    self.assertEqual(profiles, self.GetAutoFillProfile()['profiles'])

    # Adding credit cards.
    file_path = os.path.join(self.DataDir(), 'autofill',
                             'crazy_creditcards.txt')
    test_data = self.EvalDataFrom(file_path)
    credit_cards_input = test_data['input']
    self.FillAutoFillProfile(credit_cards=credit_cards_input)
    self.assertEqual(test_data['expected'],
                     self.GetAutoFillProfile()['credit_cards'])

  def testGetProfilesEmpty(self):
    """Test getting profiles when none have been filled."""
    profile = self.GetAutoFillProfile()
    self.assertEqual([], profile['profiles'])
    self.assertEqual([], profile['credit_cards'])

  def testAutofillInvalid(self):
    """Test filling in invalid values for profiles and credit cards."""
    # First try profiles with invalid input.
    without_invalid = {'NAME_FIRST': u'Will',
                       'ADDRESS_HOME_CITY': 'Sunnyvale',
                       'ADDRESS_HOME_STATE': 'CA',
                       'ADDRESS_HOME_ZIP': 'my_zip',
                       'ADDRESS_HOME_COUNTRY': 'USA'}
    # Add some invalid fields.
    with_invalid = without_invalid.copy()
    with_invalid['PHONE_HOME_WHOLE_NUMBER'] = 'Invalid_Phone_Number'
    with_invalid['PHONE_FAX_WHOLE_NUMBER'] = 'Invalid_Fax_Number'
    self.FillAutoFillProfile(profiles=[with_invalid])
    self.assertEqual([without_invalid],
                     self.GetAutoFillProfile()['profiles'])

    # Then try credit cards with invalid input.  Should strip off all non-digits
    credit_card = {'CREDIT_CARD_NUMBER': 'Not_0123-5Checked'}
    expected_credit_card = {'CREDIT_CARD_NUMBER': '01235'}
    self.FillAutoFillProfile(credit_cards=[credit_card])
    self.assertEqual([expected_credit_card],
                     self.GetAutoFillProfile()['credit_cards'])

  def testFilterIncompleteAddresses(self):
    """Test Autofill filters out profile with incomplete address info."""
    profile = {'NAME_FIRST': 'Bob',
               'NAME_LAST': 'Smith',
               'EMAIL_ADDRESS': 'bsmith@example.com',
               'COMPANY_NAME': 'Company X',
               'PHONE_HOME_WHOLE_NUMBER': '650-123-4567',}
    url = self.GetHttpURLForDataPath(
        os.path.join('autofill', 'dup-profiles-test.html'))
    self.NavigateToURL(url)
    for key, value in profile.iteritems():
      script = ('document.getElementById("%s").value = "%s"; '
                'window.domAutomationController.send("done");') % (key, value)
      self.ExecuteJavascript(script, 0, 0)
    js_code = """
      document.getElementById("merge_dup").submit();
      window.addEventListener("unload", function() {
        window.domAutomationController.send("done");
      });
    """
    self.ExecuteJavascript(js_code, 0, 0)
    self.assertEqual([], self.GetAutoFillProfile()['profiles'])

  def testFilterMalformedEmailAddresses(self):
    """Test Autofill filters out malformed email address during form submit."""
    profile = {'NAME_FIRST': 'Bob',
               'NAME_LAST': 'Smith',
               'EMAIL_ADDRESS': 'garbage',
               'ADDRESS_HOME_LINE1': '1234 H St.',
               'ADDRESS_HOME_CITY': 'San Jose',
               'ADDRESS_HOME_STATE': 'CA',
               'ADDRESS_HOME_ZIP': '95110',
               'COMPANY_NAME': 'Company X',
               'PHONE_HOME_WHOLE_NUMBER': '408-123-4567',}
    url = self.GetHttpURLForDataPath(
        os.path.join('autofill', 'dup-profiles-test.html'))
    self.NavigateToURL(url)
    for key, value in profile.iteritems():
      script = ('document.getElementById("%s").value = "%s"; '
                'window.domAutomationController.send("done");') % (key, value)
      self.ExecuteJavascript(script, 0, 0)
    js_code = """
      document.getElementById("merge_dup").submit();
      window.addEventListener("unload", function() {
        window.domAutomationController.send("done");
      });
    """
    self.ExecuteJavascript(js_code, 0, 0)
    if 'EMAIL_ADDRESS' in self.GetAutoFillProfile()['profiles'][0]:
      raise KeyError('TEST FAIL: Malformed email address is saved in profiles.')

  def testAutofillCrowdsourcing(self):
    """Test able to send POST request of web form to Autofill server.

    The Autofill server processes the data offline, so it can take a few days
    for the result to be detectable. Manual verification is required.
    """
    # HTML file needs to be run from a specific http:// url to be able to verify
    # the results a few days later by visiting the same url.
    url = 'http://www.corp.google.com/~dyu/autofill/crowdsourcing-test.html'
    # Adding crowdsourcing Autofill profile.
    file_path = os.path.join(self.DataDir(), 'autofill',
                             'crowdsource_autofill.txt')
    profiles = self.EvalDataFrom(file_path)
    self.FillAutoFillProfile(profiles=profiles)
    # Autofill server captures 2.5% of the data posted.
    # Looping 1000 times is a safe minimum to exceed the server's threshold or
    # noise.
    for i in range(1000):
      fname = self.GetAutoFillProfile()['profiles'][0]['NAME_FIRST']
      lname = self.GetAutoFillProfile()['profiles'][0]['NAME_LAST']
      email = self.GetAutoFillProfile()['profiles'][0]['EMAIL_ADDRESS']
      # Submit form to collect crowdsourcing data for Autofill.
      self.NavigateToURL(url, 0, 0)
      fname_field = ('document.getElementById("fn").value = "%s"; '
                     'window.domAutomationController.send("done");') % fname
      lname_field = ('document.getElementById("ln").value = "%s"; '
                     'window.domAutomationController.send("done");') % lname
      email_field = ('document.getElementById("em").value = "%s"; '
                     'window.domAutomationController.send("done");') % email
      self.ExecuteJavascript(fname_field, 0, 0);
      self.ExecuteJavascript(lname_field, 0, 0);
      self.ExecuteJavascript(email_field, 0, 0);
      self.ExecuteJavascript('document.getElementById("frmsubmit").submit();'
                             'window.domAutomationController.send("done");',
                             0, 0)

  def testMergeDuplicateProfilesInAutofill(self):
    """Test Autofill ability to merge duplicate profiles and throw away junk."""
    # HTML file needs to be run from a http:// url.
    url = self.GetHttpURLForDataPath(
        os.path.join('autofill', 'duplicate_profiles_test.html'))
    # Run the parser script to generate the dictionary list needed for the
    # profiles.
    c = dataset_converter.DatasetConverter(
        os.path.join(self.DataDir(), 'autofill', 'dataset.txt'),
        logging_level=logging.INFO)  # Set verbosity to INFO, WARNING, ERROR.
    list_of_dict = c.Convert()

    for profile in list_of_dict:
      self.NavigateToURL(url)
      for key, value in profile.iteritems():
        script = ('document.getElementById("%s").value = "%s"; '
                  'window.domAutomationController.send("done");') % (key, value)
        self.ExecuteJavascript(script, 0, 0)
      self.ExecuteJavascript('document.getElementById("merge_dup").submit();'
                             'window.domAutomationController.send("done");',
                             0, 0)
    # Verify total number of inputted profiles is greater than the final number
    # of profiles after merging.
    self.assertTrue(
        len(list_of_dict) > len(self.GetAutoFillProfile()['profiles']))
    # Write profile dictionary to a file.
    merged_profile = os.path.join(self.DataDir(), 'autofill',
                                  'merged-profiles.txt')
    profile_dict = self.GetAutoFillProfile()['profiles']
    output = open(merged_profile, 'wb')
    pickle.dump(profile_dict, output)
    output.close()


if __name__ == '__main__':
  pyauto_functional.Main()