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

Side by Side Diff: chrome/browser/ui/webui/options/autofill_options_interactive_uitest.cc

Issue 819193003: Fix list focus after tab key in chrome://settings/autofillEditAddress page. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Add tests. Created 5 years, 11 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
OLDNEW
(Empty)
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/strings/stringprintf.h"
6 #include "chrome/browser/chrome_notification_types.h"
7 #include "chrome/browser/ui/browser_window.h"
8 #include "chrome/browser/ui/chrome_pages.h"
9 #include "chrome/browser/ui/tabs/tab_strip_model.h"
10 #include "chrome/common/url_constants.h"
11 #include "chrome/test/base/in_process_browser_test.h"
12 #include "chrome/test/base/interactive_test_utils.h"
13 #include "content/public/test/browser_test_utils.h"
14
15 namespace autofill_options_ui_test {
16
17 namespace {
18
19 // This class tests the autofill options settings.
20 // This test is part of the interactive_ui_tests instead of browser_tests
21 // because it is necessary to emulate pushing the tab key.
22 class AutofillOptionsWebUITest : public InProcessBrowserTest {
23 public:
24 AutofillOptionsWebUITest() {}
25
26 // Navigate to the autofillEditAddress page.
27 void SetUpOnMainThread() override {
28 const GURL url = chrome::GetSettingsUrl(
29 chrome::kAutofillEditAddressSubPage);
30 ui_test_utils::NavigateToURL(browser(), url);
31 }
32
33 protected:
34 const std::string kEditAddressOverlaySelector =
35 "#autofill-edit-address-overlay";
36
37 content::RenderFrameHost* GetActiveFrame() {
38 return GetActiveWebContents()->GetFocusedFrame();
39 }
40
41 content::RenderViewHost* GetRenderViewHost() {
42 return GetActiveWebContents()->GetRenderViewHost();
43 }
44
45 content::WebContents* GetActiveWebContents() {
46 return browser()->tab_strip_model()->GetActiveWebContents();
47 }
48
49 // Returns true if element contains document.activeElement.
50 bool GetContainsActiveElement(std::string element_selector) {
51 std::string script = base::StringPrintf(
52 "domAutomationController.send("
53 "document.querySelector('%s').contains(document.activeElement));",
54 element_selector.c_str());
55 bool result;
56 EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
57 GetActiveFrame(),
58 script,
59 &result));
60 return result;
61 }
62
63 // Returns the number of items in the list.
64 int GetListSize(std::string list_selector) {
65 std::string script = base::StringPrintf(
66 "domAutomationController.send("
67 "document.querySelector('%s').items.length);",
68 list_selector.c_str());
69 int length = -1;
70 EXPECT_TRUE(content::ExecuteScriptAndExtractInt(
71 GetActiveFrame(),
72 script,
73 &length));
74 return length;
75 }
76
77 // Focus the first input field of the first list item.
78 void FocusFirstListItemInput(std::string list_selector) {
79 std::string script = base::StringPrintf(
80 "document.querySelector('%s input').focus();",
81 list_selector.c_str());
82 EXPECT_TRUE(content::ExecuteScript(GetActiveFrame(), script));
83 }
84
85 // Returns the text of the first item in the list.
86 std::string GetFirstListItemText(std::string list_selector) {
87 // EXPECT_TRUE will fail if there is no first item or first item does not
88 // have 'input'.
89 std::string script = base::StringPrintf(
90 "domAutomationController.send("
91 "document.querySelector('%s input').value);",
92 list_selector.c_str());
93 std::string result;
94 EXPECT_TRUE(content::ExecuteScriptAndExtractString(
95 GetActiveFrame(),
96 script,
97 &result));
98 return result;
99 }
100
101 // Returns true if the first item in the list has 'selected' attribute.
102 bool GetFirstListItemSelected(std::string list_selector) {
103 // EXPECT_TRUE will fail if there is no first item.
104 std::string script = base::StringPrintf(
105 "domAutomationController.send("
106 "document.querySelector('%s').items[0].hasAttribute('selected'));",
107 list_selector.c_str());
108 bool result = false;
109 EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
110 GetActiveFrame(),
111 script,
112 &result));
113 return result;
114 }
115
116 // Returns true if a row delete button ('X' button) is focused.
117 bool GetDeleteButtonFocused() {
118 std::string script =
119 "domAutomationController.send("
120 "document.activeElement.classList.contains('row-delete-button'));";
121 bool result = false;
122 EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
123 GetActiveFrame(),
124 script,
125 &result));
126 return result;
127 }
128
129 // Insert text into currently focused element.
130 void InsertText(std::string text) {
131 std::string script = base::StringPrintf(
132 "document.execCommand('insertText', false, '%s');",
133 text.c_str());
134 EXPECT_TRUE(content::ExecuteScript(GetActiveFrame(), script));
135 }
136
137 // Press and release a key in the browser. This will wait for the element on
138 // the page to change.
139 bool PressKey(ui::KeyboardCode key_code, bool shift) {
140 return ui_test_utils::SendKeyPressAndWait(
141 browser(),
142 key_code,
143 false,
144 shift,
145 false,
146 false,
147 content::NOTIFICATION_FOCUS_CHANGED_IN_PAGE,
148 content::Source<content::RenderViewHost>(GetRenderViewHost()));
149 }
150
151 // Verifies that everything is the way it should be after list item is
152 // added or edited.
153 void VerifyEditAddressListPostConditions(std::string list_selector,
154 std::string input_text) {
155 // Verify that neither the list nor any of its children still have focus.
156 EXPECT_FALSE(GetContainsActiveElement(list_selector));
157
158 // Verify that focus moved to a different element of the overlay.
159 EXPECT_TRUE(GetContainsActiveElement(kEditAddressOverlaySelector));
160
161 // Verify that list has exactly two items. They will be the item that was
162 // just added/modified + the placeholder.
163 EXPECT_EQ(GetListSize(list_selector), 2);
164
165 // Verify that the first list item has the string that was inserted.
166 EXPECT_EQ(GetFirstListItemText(list_selector), input_text);
167
168 // Verify that the first list item is the selected item in the list.
169 EXPECT_TRUE(GetFirstListItemSelected(list_selector));
170 }
171
172 // Make sure that when text is entered in the placeholder of an empty list and
173 // the tab key is pressed:
174 // + Focus leaves the list and goes to a different element on the page.
175 // + The text stays added and a new placeholder is created.
176 // + The list item with the newly added text is the selected list item (not
177 // the placeholder).
178 //
179 // Added to prevent http://crbug.com/440760 from regressing again.
180 void TestEditAddressListTabKeyAddItem(std::string list_selector,
181 std::string input_text) {
182 // Focus the input field and insert test string.
183 FocusFirstListItemInput(list_selector);
184 InsertText(input_text);
185
186 // Press tab key to move to next element after the list.
187 PressKey(ui::VKEY_TAB, false);
188
189 // Make sure everything ended up the way it should be.
190 VerifyEditAddressListPostConditions(list_selector, input_text);
191 }
192
193 // Depends on state set up by TestEditAddressListTabKeyAddItem. Should be
194 // called immediately after that method.
195 //
196 // Make sure that when a list item's text is edited and the tab key is
197 // pressed twice:
198 // + After the first tab press the item's delete button is focused.
199 // + After the second tab press focus leaves the list and goes to a
200 // different element on the page.
201 // + The edited text persists.
202 // + The edited list item is the selected list item.
203 //
204 // Added to prevent http://crbug.com/443491 from regressing again.
205 void TestEditAddressListTabKeyEditItem(std::string list_selector,
206 std::string input_text) {
207 // Press shift+tab to move back to the first item in the list.
208 PressKey(ui::VKEY_TAB, true);
209 // Verify that the first item in the list is focused.
210 EXPECT_TRUE(GetContainsActiveElement(list_selector + " input"));
211
212 // Insert modified text in the first list item.
213 input_text = "second" + input_text;
214 InsertText(input_text);
215
216 // Press tab key to focus the list item's delete button.
217 PressKey(ui::VKEY_TAB, false);
218 EXPECT_TRUE(GetDeleteButtonFocused());
219
220 // Press tab key again to move to next element after the list.
221 PressKey(ui::VKEY_TAB, false);
222
223 // Make sure everything ended up the way it should be.
224 VerifyEditAddressListPostConditions(list_selector, input_text);
225 }
226
227 void TestEditAddressListTabKey(std::string field_name,
228 std::string input_text) {
229 std::string list_selector = kEditAddressOverlaySelector + " [field=" +
230 field_name + "]";
231
232 TestEditAddressListTabKeyAddItem(list_selector, input_text);
233 TestEditAddressListTabKeyEditItem(list_selector, input_text);
234 }
235
236 private:
237 DISALLOW_COPY_AND_ASSIGN(AutofillOptionsWebUITest);
238 };
239
240 } // namespace
241
242 // Test the 'fullName' InlineEditableItemList in autofillEditAddress overlay.
243 IN_PROC_BROWSER_TEST_F(AutofillOptionsWebUITest,
244 TestEditAddressNameListTabKey) {
245 TestEditAddressListTabKey("fullName", "Test Name");
246 }
247
248 // TODO(bondd): After tab is pressed, phone list waits for a validation
249 // callback before repopulating the list. It's not clear to me how to wait for
250 // that here on the C++ testing side. Disabling phone list test for now.
251 /*
252 // Test the 'phone' InlineEditableItemList in autofillEditAddress overlay.
253 IN_PROC_BROWSER_TEST_F(AutofillOptionsWebUITest,
254 TestEditAddressPhoneListTabKey) {
255 TestEditAddressListTabKey("phone", "123-456-7890");
256 }
257 */
258
259 // Test the 'email' InlineEditableItemList in autofillEditAddress overlay.
260 IN_PROC_BROWSER_TEST_F(AutofillOptionsWebUITest,
261 TestEditAddressEmailListTabKey) {
262 TestEditAddressListTabKey("email", "test@example.com");
263 }
264
265 } // namespace autofill_options_ui_test
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698