OLD | NEW |
| (Empty) |
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() | |
OLD | NEW |