Index: chrome/browser/ui/webui/options/autofill_options_interactive_uitest.cc |
diff --git a/chrome/browser/ui/webui/options/autofill_options_interactive_uitest.cc b/chrome/browser/ui/webui/options/autofill_options_interactive_uitest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..6437a5db238aca9f7c8329febb65870778f51288 |
--- /dev/null |
+++ b/chrome/browser/ui/webui/options/autofill_options_interactive_uitest.cc |
@@ -0,0 +1,262 @@ |
+// Copyright 2014 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. |
+ |
+#include "base/strings/stringprintf.h" |
+#include "chrome/browser/chrome_notification_types.h" |
+#include "chrome/browser/ui/browser_window.h" |
+#include "chrome/browser/ui/chrome_pages.h" |
+#include "chrome/browser/ui/tabs/tab_strip_model.h" |
+#include "chrome/common/url_constants.h" |
+#include "chrome/test/base/in_process_browser_test.h" |
+#include "chrome/test/base/interactive_test_utils.h" |
+#include "content/public/test/browser_test_utils.h" |
+ |
+namespace autofill_options_ui_test { |
+ |
+namespace { |
+ |
+// This class tests the autofill options settings. |
Dan Beam
2015/01/23 22:46:14
nit: capitalize Autofill when it's not used as a v
bondd
2015/01/29 19:01:02
Done.
|
+// This test is part of the interactive_ui_tests instead of browser_tests |
+// because it is necessary to emulate pushing the tab key. |
Dan Beam
2015/01/23 22:46:14
i think it's actually because focus is hard to sha
bondd
2015/01/29 19:01:02
Acknowledged.
|
+class AutofillOptionsWebUITest : public InProcessBrowserTest { |
+ public: |
+ AutofillOptionsWebUITest() {} |
+ |
+ // Navigate to the autofillEditAddress page. |
+ void SetUpOnMainThread() override { |
+ const GURL url = chrome::GetSettingsUrl("autofillEditAddress"); |
+ ui_test_utils::NavigateToURL(browser(), url); |
+ } |
+ |
+ protected: |
+ const std::string kEditAddressOverlaySelector = |
+ "#autofill-edit-address-overlay"; |
+ |
+ content::RenderFrameHost* GetActiveFrame() { |
+ return GetActiveWebContents()->GetFocusedFrame(); |
+ } |
+ |
+ content::RenderViewHost* GetRenderViewHost() { |
+ return GetActiveWebContents()->GetRenderViewHost(); |
+ } |
+ |
+ content::WebContents* GetActiveWebContents() { |
+ return browser()->tab_strip_model()->GetActiveWebContents(); |
+ } |
+ |
+ // Returns true if element contains document.activeElement. |
+ bool ContainsActiveElement(const std::string& element_selector) { |
+ std::string script = base::StringPrintf( |
+ "domAutomationController.send(" |
+ "document.querySelector('%s').contains(document.activeElement));", |
+ element_selector.c_str()); |
+ bool result; |
+ EXPECT_TRUE(content::ExecuteScriptAndExtractBool( |
+ GetActiveFrame(), |
+ script, |
+ &result)); |
+ return result; |
+ } |
+ |
+ // Returns the number of items in the list. |
+ int GetListSize(const std::string& list_selector) { |
+ std::string script = base::StringPrintf( |
+ "domAutomationController.send(" |
+ "document.querySelector('%s').items.length);", |
+ list_selector.c_str()); |
+ int length = -1; |
+ EXPECT_TRUE(content::ExecuteScriptAndExtractInt( |
+ GetActiveFrame(), |
+ script, |
+ &length)); |
+ return length; |
+ } |
+ |
+ // Focus the first input field of the first list item. |
+ void FocusFirstListItemInput(const std::string& list_selector) { |
+ std::string script = base::StringPrintf( |
+ "document.querySelector('%s input').focus();", |
+ list_selector.c_str()); |
+ EXPECT_TRUE(content::ExecuteScript(GetActiveFrame(), script)); |
+ } |
+ |
+ // Returns the text of the first item in the list. |
+ std::string GetFirstListItemText(const std::string& list_selector) { |
+ // EXPECT_TRUE will fail if there is no first item or first item does not |
+ // have 'input'. |
+ std::string script = base::StringPrintf( |
+ "domAutomationController.send(" |
+ "document.querySelector('%s input').value);", |
+ list_selector.c_str()); |
+ std::string result; |
+ EXPECT_TRUE(content::ExecuteScriptAndExtractString( |
+ GetActiveFrame(), |
+ script, |
+ &result)); |
+ return result; |
+ } |
+ |
+ // Returns true if the first item in the list has 'selected' attribute. |
+ bool GetFirstListItemSelected(const std::string& list_selector) { |
+ // EXPECT_TRUE will fail if there is no first item. |
+ std::string script = base::StringPrintf( |
+ "domAutomationController.send(" |
+ "document.querySelector('%s').items[0].hasAttribute('selected'));", |
+ list_selector.c_str()); |
+ bool result = false; |
+ EXPECT_TRUE(content::ExecuteScriptAndExtractBool( |
+ GetActiveFrame(), |
+ script, |
+ &result)); |
+ return result; |
+ } |
+ |
+ // Returns true if a row delete button ('X' button) is focused. |
+ bool GetDeleteButtonFocused() { |
+ std::string script = |
+ "domAutomationController.send(" |
+ "document.activeElement.classList.contains('row-delete-button'));"; |
+ bool result = false; |
+ EXPECT_TRUE(content::ExecuteScriptAndExtractBool( |
+ GetActiveFrame(), |
+ script, |
+ &result)); |
+ return result; |
+ } |
+ |
+ // Insert text into currently focused element. |
+ void InsertText(const std::string& text) { |
Dan Beam
2015/01/23 22:46:14
nit: ASSERT_EQ(std::string::npos, text.find("'"));
bondd
2015/01/29 19:01:02
Done.
|
+ std::string script = base::StringPrintf( |
+ "document.execCommand('insertText', false, '%s');", |
+ text.c_str()); |
+ EXPECT_TRUE(content::ExecuteScript(GetActiveFrame(), script)); |
+ } |
+ |
+ // Press and release tab key in the browser. This will wait for the element on |
+ // the page to change. |
+ bool PressTab(bool shift) { |
+ return ui_test_utils::SendKeyPressAndWait( |
+ browser(), |
+ ui::VKEY_TAB, |
+ false, |
+ shift, |
+ false, |
+ false, |
+ content::NOTIFICATION_FOCUS_CHANGED_IN_PAGE, |
+ content::Source<content::RenderViewHost>(GetRenderViewHost())); |
+ } |
+ |
+ // Verifies that everything is the way it should be after list item is |
+ // added or edited. |
+ void VerifyEditAddressListPostConditions(const std::string& list_selector, |
+ std::string input_text) { |
Dan Beam
2015/01/23 22:46:14
make input_text const-ref
bondd
2015/01/29 19:01:02
Done.
|
+ // Verify that neither the list nor any of its children still have focus. |
+ EXPECT_FALSE(ContainsActiveElement(list_selector)); |
+ |
+ // Verify that focus moved to a different element of the overlay. |
+ EXPECT_TRUE(ContainsActiveElement(kEditAddressOverlaySelector)); |
+ |
+ // Verify that list has exactly two items. They will be the item that was |
+ // just added/modified + the placeholder. |
+ EXPECT_EQ(2, GetListSize(list_selector)); |
+ |
+ // Verify that the first list item has the string that was inserted. |
+ EXPECT_EQ(input_text, GetFirstListItemText(list_selector)); |
+ |
+ // Verify that the first list item is the selected item in the list. |
+ EXPECT_TRUE(GetFirstListItemSelected(list_selector)); |
+ } |
+ |
+ // Make sure that when text is entered in the placeholder of an empty list and |
+ // the tab key is pressed: |
+ // + Focus leaves the list and goes to a different element on the page. |
+ // + The text stays added and a new placeholder is created. |
+ // + The list item with the newly added text is the selected list item (not |
+ // the placeholder). |
+ // |
+ // Added to prevent http://crbug.com/440760 from regressing again. |
+ void TestEditAddressListTabKeyAddItem(const std::string& list_selector, |
+ const std::string& input_text) { |
+ // Focus the input field and insert test string. |
+ FocusFirstListItemInput(list_selector); |
+ InsertText(input_text); |
+ |
+ // Press tab key to move to next element after the list. |
+ PressTab(false); |
+ |
+ // Make sure everything ended up the way it should be. |
+ VerifyEditAddressListPostConditions(list_selector, input_text); |
+ } |
+ |
+ // Depends on state set up by TestEditAddressListTabKeyAddItem. Should be |
+ // called immediately after that method. |
+ // |
+ // Make sure that when a list item's text is edited and the tab key is |
+ // pressed twice: |
+ // + After the first tab press the item's delete button is focused. |
+ // + After the second tab press focus leaves the list and goes to a |
+ // different element on the page. |
+ // + The edited text persists. |
+ // + The edited list item is the selected list item. |
+ // |
+ // Added to prevent http://crbug.com/443491 from regressing again. |
+ void TestEditAddressListTabKeyEditItem(const std::string& list_selector, |
+ const std::string& input_text) { |
+ // Press shift+tab to move back to the first item in the list. |
+ PressTab(true); |
+ // Verify that the first item in the list is focused. |
+ EXPECT_TRUE(ContainsActiveElement(list_selector + " input")); |
+ |
+ // Insert modified text in the first list item. |
+ std::string second_input = "second" + input_text; |
+ InsertText(second_input); |
+ |
+ // Press tab key to focus the list item's delete button. |
+ PressTab(false); |
+ EXPECT_TRUE(GetDeleteButtonFocused()); |
+ |
+ // Press tab key again to move to next element after the list. |
+ PressTab(false); |
+ |
+ // Make sure everything ended up the way it should be. |
+ VerifyEditAddressListPostConditions(list_selector, second_input); |
+ } |
+ |
+ void TestEditAddressListTabKey(const std::string& field_name, |
+ const std::string& input_text) { |
+ std::string list_selector = kEditAddressOverlaySelector + " [field=" + |
+ field_name + "]"; |
+ |
+ TestEditAddressListTabKeyAddItem(list_selector, input_text); |
+ TestEditAddressListTabKeyEditItem(list_selector, input_text); |
+ } |
+ |
+ private: |
+ DISALLOW_COPY_AND_ASSIGN(AutofillOptionsWebUITest); |
+}; |
+ |
+} // namespace |
+ |
+// Test the 'fullName' InlineEditableItemList in autofillEditAddress overlay. |
+IN_PROC_BROWSER_TEST_F(AutofillOptionsWebUITest, |
+ TestEditAddressNameListTabKey) { |
+ TestEditAddressListTabKey("fullName", "Test Name"); |
+} |
+ |
+// TODO(bondd): After tab is pressed, phone list waits for a validation |
+// callback before repopulating the list. It's not clear to me how to wait for |
+// that here on the C++ testing side. Disabling phone list test for now. |
Dan Beam
2015/01/23 22:46:14
when the validation result comes back does the foc
bondd
2015/01/29 19:01:02
Done.
|
+// Test the 'phone' InlineEditableItemList in autofillEditAddress overlay. |
+IN_PROC_BROWSER_TEST_F(AutofillOptionsWebUITest, |
+ DISABLED_TestEditAddressPhoneListTabKey) { |
+ TestEditAddressListTabKey("phone", "123-456-7890"); |
+} |
+ |
+// Test the 'email' InlineEditableItemList in autofillEditAddress overlay. |
+IN_PROC_BROWSER_TEST_F(AutofillOptionsWebUITest, |
+ TestEditAddressEmailListTabKey) { |
+ TestEditAddressListTabKey("email", "test@example.com"); |
+} |
+ |
+} // namespace autofill_options_ui_test |