- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / test / functional / autofill.py
1 #!/usr/bin/env python
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
4 # found in the LICENSE file.
5
6 import logging
7 import os
8 import pickle
9 import re
10 import simplejson
11
12 import pyauto_functional  # Must be imported before pyauto
13 import pyauto
14 import test_utils
15 from selenium.webdriver.common.keys import Keys
16 from selenium.webdriver.common.action_chains import ActionChains
17 from webdriver_pages import settings
18
19
20 class AutofillTest(pyauto.PyUITest):
21   """Tests that autofill UI works correctly. Also contains a manual test for
22      the crowdsourcing server."""
23
24   def setUp(self):
25     pyauto.PyUITest.setUp(self)
26     self._driver = self.NewWebDriver()
27
28   def AutofillCrowdsourcing(self):
29     """Test able to send POST request of web form to Autofill server.
30
31     The Autofill server processes the data offline, so it can take a few days
32     for the result to be detectable. Manual verification is required.
33     """
34     # HTML file needs to be run from a specific http:// url to be able to verify
35     # the results a few days later by visiting the same url.
36     url = 'http://www.corp.google.com/~dyu/autofill/crowdsourcing-test.html'
37     # Autofill server captures 2.5% of the data posted.
38     # Looping 1000 times is a safe minimum to exceed the server's threshold or
39     # noise.
40     for i in range(1000):
41       fname = 'David'
42       lname = 'Yu'
43       email = 'david.yu@gmail.com'
44       # Submit form to collect crowdsourcing data for Autofill.
45       self.NavigateToURL(url, 0, 0)
46       profile = {'fn': fname, 'ln': lname, 'em': email}
47       js = ''.join(['document.getElementById("%s").value = "%s";' %
48                     (key, value) for key, value in profile.iteritems()])
49       js += 'document.getElementById("testform").submit();'
50       self.ExecuteJavascript(js)
51
52   def _SelectOptionXpath(self, value):
53     """Returns an xpath query used to select an item from a dropdown list.
54     Args:
55       value: Option selected for the drop-down list field.
56
57     Returns:
58       The value of the xpath query.
59     """
60     return '//option[@value="%s"]' % value
61
62   def testPostalCodeAndStateLabelsBasedOnCountry(self):
63     """Verify postal code and state labels based on selected country."""
64     data_file = os.path.join(self.DataDir(), 'autofill', 'functional',
65                              'state_zip_labels.txt')
66     test_data = simplejson.loads(open(data_file).read())
67
68     page = settings.AutofillEditAddressDialog.FromNavigation(self._driver)
69     # Initial check of State and ZIP labels.
70     self.assertEqual('State', page.GetStateLabel())
71     self.assertEqual('ZIP code', page.GetPostalCodeLabel())
72
73     for country_code in test_data:
74       page.Fill(country_code=country_code)
75
76       # Compare postal code labels.
77       actual_postal_label = page.GetPostalCodeLabel()
78       self.assertEqual(
79           test_data[country_code]['postalCodeLabel'],
80           actual_postal_label,
81           msg=('Postal code label "%s" does not match Country "%s"' %
82                (actual_postal_label, country_code)))
83
84       # Compare state labels.
85       actual_state_label = page.GetStateLabel()
86       self.assertEqual(
87           test_data[country_code]['stateLabel'],
88           actual_state_label,
89           msg=('State label "%s" does not match Country "%s"' %
90                (actual_state_label, country_code)))
91
92   def testNoDuplicatePhoneNumsInPrefs(self):
93     """Test duplicate phone numbers entered in prefs are removed."""
94     page = settings.AutofillEditAddressDialog.FromNavigation(self._driver)
95     non_duplicates = ['111-1111', '222-2222']
96     duplicates = ['111-1111']
97     page.Fill(phones=non_duplicates + duplicates)
98     self.assertEqual(non_duplicates, page.GetPhones(),
99         msg='Duplicate phone number in prefs unexpectedly saved.')
100
101   def testDisplayLineItemForEntriesWithNoCCNum(self):
102     """Verify Autofill creates a line item for CC entries with no CC number."""
103     self.NavigateToURL('chrome://settings-frame/autofillEditCreditCard')
104     self._driver.find_element_by_id('name-on-card').send_keys('Jane Doe')
105     query_month = self._SelectOptionXpath('12')
106     query_year = self._SelectOptionXpath('2014')
107     self._driver.find_element_by_id('expiration-month').find_element_by_xpath(
108         query_month).click()
109     self._driver.find_element_by_id('expiration-year').find_element_by_xpath(
110         query_year).click()
111     self._driver.find_element_by_id(
112         'autofill-edit-credit-card-apply-button').click()
113     # Refresh the page to ensure the UI is up-to-date.
114     self._driver.refresh()
115     list_entry = self._driver.find_element_by_class_name('autofill-list-item')
116     self.assertTrue(list_entry.is_displayed)
117     self.assertEqual('Jane Doe', list_entry.text,
118                      msg='Saved CC line item not same as what was entered.')
119
120   def _GetElementList(self, container_elem, fields_to_select):
121     """Returns all sub elements of specific characteristics.
122
123     Args:
124       container_elem: An element that contains other elements.
125       fields_to_select: A list of fields to select with strings that
126                         help create an xpath string, which in turn identifies
127                         the elements needed.
128                         For example: ['input', 'button']
129                         ['div[@id]', 'button[@disabled]']
130                         ['*[class="example"]']
131
132     Returns:
133       List of all subelements found in the container element.
134     """
135     self.assertTrue(fields_to_select, msg='No fields specified for selection.')
136     fields_to_select = ['.//' + field for field in fields_to_select]
137     xpath_arg = ' | '.join(fields_to_select)
138     field_elems = container_elem.find_elements_by_xpath(xpath_arg)
139     return field_elems
140
141   def _GetElementInfo(self, element):
142     """Returns visual comprehensive info about an element.
143
144     This function identifies the text of the correspoinding label when tab
145     ordering fails.
146     This info consists of:
147       The labels, buttons, ids, placeholder attribute values, or the element id.
148
149     Args:
150       element: The target element.
151
152     Returns:
153       A string that identifies the element in the page.
154     """
155     element_info = ''
156     if element.tag_name == 'button':
157       element_info = element.text
158     element_info = (element_info or element.get_attribute('id') or
159         element.get_attribute('placeholder') or
160         element.get_attribute('class') or element.id)
161     return '%s: %s' % (element.tag_name, element_info)
162
163   def _LoadPageAndGetFieldList(self):
164     """Navigate to autofillEditAddress page and finds the elements with focus.
165
166     These elements are of input, select, and button types.
167
168     Returns:
169       A list with all elements that can receive focus.
170     """
171     url = 'chrome://settings-frame/autofillEditAddress'
172     self._driver.get(url)
173     container_elem = self._driver.find_element_by_id(
174         'autofill-edit-address-overlay')
175     # The container element contains input, select and button fields. Some of
176     # the buttons are disabled so they are ignored.
177     field_list = self._GetElementList(container_elem,
178                                       ['input', 'select',
179                                        'button[not(@disabled)]'])
180     self.assertTrue(field_list, 'No fields found in "%s".' % url)
181     return field_list
182
183   def testTabOrderForEditAddress(self):
184     """Verify the TAB ordering for Edit Address page is correct."""
185     tab_press = ActionChains(self._driver).send_keys(Keys.TAB)
186     field_list = self._LoadPageAndGetFieldList()
187
188     # Creates a dictionary where a field key returns the value of the next field
189     # in the field list. The last field of the field list is mapped to the first
190     # field of the field list.
191     field_nextfield_dict = dict(
192         zip(field_list, field_list[1:] + field_list[:1]))
193
194     # Wait until a field of |field_list| has received the focus.
195     self.WaitUntil(lambda:
196                    self._driver.switch_to_active_element().id in
197                    [f.id for f in field_list])
198     # The first field is expected to receive the focus.
199     self.assertEqual(self._driver.switch_to_active_element().id,
200                      field_list[0].id,
201                      msg='The first field did not receive tab focus.')
202     for field in field_list:
203       tab_press.perform()
204       # Wait until a field of |field_list|, other than the current field, has
205       # received the focus.
206       self.WaitUntil(lambda:
207                      self._driver.switch_to_active_element().id != field.id and
208                      self._driver.switch_to_active_element().id in
209                      [f.id for f in field_list])
210
211       self.assertEqual(self._driver.switch_to_active_element().id,
212                        field_nextfield_dict[field].id,
213                        msg=('The TAB ordering is broken. Previous field: "%s"\n'
214                             'Field expected to receive focus: "%s"\n'
215                             'Field that received focus instead: "%s"')
216                        % (self._GetElementInfo(field),
217                           self._GetElementInfo(field_nextfield_dict[field]),
218                           self._GetElementInfo(
219                               self._driver.switch_to_active_element())))
220
221
222 if __name__ == '__main__':
223   pyauto_functional.Main()