1// Copyright 2016 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/mac/foundation_util.h" 6#include "base/strings/sys_string_conversions.h" 7#import "base/test/ios/wait_util.h" 8#include "ios/chrome/grit/ios_strings.h" 9#import "ios/chrome/test/earl_grey/chrome_actions.h" 10#import "ios/chrome/test/earl_grey/chrome_earl_grey.h" 11#import "ios/chrome/test/earl_grey/chrome_earl_grey_app_interface.h" 12#import "ios/chrome/test/earl_grey/chrome_matchers.h" 13#import "ios/chrome/test/earl_grey/chrome_test_case.h" 14#import "ios/chrome/test/scoped_eg_synchronization_disabler.h" 15#import "ios/testing/earl_grey/earl_grey_test.h" 16#import "ios/web/public/deprecated/crw_js_injection_receiver.h" 17#include "ios/web/public/test/element_selector.h" 18#import "ios/web/public/web_state.h" 19#include "net/test/embedded_test_server/embedded_test_server.h" 20 21#if !defined(__has_feature) || !__has_feature(objc_arc) 22#error "This file requires ARC support." 23#endif 24 25using base::test::ios::kWaitForUIElementTimeout; 26using base::test::ios::WaitUntilConditionOrTimeout; 27 28using chrome_test_util::TapWebElementWithId; 29using chrome_test_util::WebViewMatcher; 30 31namespace { 32 33const char kFormElementId1[] = "username"; 34const char kFormElementId2[] = "otherstuff"; 35 36// If an element is focused in the webview, returns its ID. Returns an empty 37// NSString otherwise. 38NSString* GetFocusedElementId() { 39 NSString* js = @"(function() {" 40 " return document.activeElement.id;" 41 "})();"; 42 return [ChromeEarlGrey executeJavaScript:js]; 43} 44 45// Verifies that |elementId| is the selected element in the web page. 46void AssertElementIsFocused(const std::string& element_id) { 47 NSString* description = 48 [NSString stringWithFormat:@"Timeout waiting for the focused element in " 49 @"the webview to be \"%@\"", 50 base::SysUTF8ToNSString(element_id.c_str())]; 51 ConditionBlock condition = ^{ 52 return base::SysNSStringToUTF8(GetFocusedElementId()) == element_id; 53 }; 54 GREYAssert(WaitUntilConditionOrTimeout(10, condition), description); 55} 56 57} // namespace 58 59// Tests autofill's keyboard and keyboard's accessories handling. 60@interface FormInputTestCase : ChromeTestCase 61@end 62 63@implementation FormInputTestCase 64 65// Tests finding the correct "next" and "previous" form assist controls in the 66// iOS built-in form assist view. 67- (void)testFindDefaultFormAssistControls { 68 // This test is not relevant on iPads: 69 // the previous and next buttons are not shown in our keyboard input 70 // accessory. Instead, they appear in the native keyboard's shortcut bar (to 71 // the left and right of the QuickType suggestions). 72 if ([ChromeEarlGrey isIPadIdiom]) { 73 EARL_GREY_TEST_SKIPPED(@"Skipped for iPad (no hidden toolbar in tablet)"); 74 } 75 76 GREYAssertTrue(self.testServer->Start(), @"Test server failed to start."); 77 GURL URL = self.testServer->GetURL("/multi_field_form.html"); 78 [ChromeEarlGrey loadURL:URL]; 79 80 [ChromeEarlGrey waitForWebStateContainingText:"hello!"]; 81 82 // Opening the keyboard from a webview blocks EarlGrey's synchronization. 83 { 84 ScopedSynchronizationDisabler disabler; 85 86 // Brings up the keyboard by tapping on one of the form's field. 87 [[EarlGrey selectElementWithMatcher:WebViewMatcher()] 88 performAction:TapWebElementWithId(kFormElementId1)]; 89 90 id<GREYMatcher> nextButtonMatcher = 91 chrome_test_util::ButtonWithAccessibilityLabelId( 92 IDS_IOS_AUTOFILL_ACCNAME_NEXT_FIELD); 93 id<GREYMatcher> previousButtonMatcher = 94 chrome_test_util::ButtonWithAccessibilityLabelId( 95 IDS_IOS_AUTOFILL_ACCNAME_PREVIOUS_FIELD); 96 id<GREYMatcher> closeButtonMatcher = 97 chrome_test_util::ButtonWithAccessibilityLabelId( 98 IDS_IOS_AUTOFILL_ACCNAME_HIDE_KEYBOARD); 99 100 // Wait until the keyboard's "Next" button appeared. 101 NSString* description = 102 @"Wait for the keyboard's \"Next\" button to appear."; 103 ConditionBlock condition = ^{ 104 NSError* error = nil; 105 [[EarlGrey selectElementWithMatcher:nextButtonMatcher] 106 assertWithMatcher:grey_notNil() 107 error:&error]; 108 return (error == nil); 109 }; 110 GREYAssert(WaitUntilConditionOrTimeout(kWaitForUIElementTimeout, condition), 111 description); 112 base::test::ios::SpinRunLoopWithMinDelay(base::TimeDelta::FromSeconds(1)); 113 114 // Verifies that the taped element is focused. 115 AssertElementIsFocused(kFormElementId1); 116 117 // Tap the "Next" button. 118 [[EarlGrey selectElementWithMatcher:nextButtonMatcher] 119 performAction:grey_tap()]; 120 AssertElementIsFocused(kFormElementId2); 121 122 // Tap the "Previous" button. 123 [[EarlGrey selectElementWithMatcher:previousButtonMatcher] 124 performAction:grey_tap()]; 125 AssertElementIsFocused(kFormElementId1); 126 127 // Tap the "Close" button. 128 [[EarlGrey selectElementWithMatcher:closeButtonMatcher] 129 performAction:grey_tap()]; 130 } 131} 132 133@end 134