| // Copyright 2018 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/ios/ios_util.h" |
| #import "base/test/ios/wait_util.h" |
| #import "ios/chrome/browser/ui/autofill/autofill_app_interface.h" |
| #import "ios/chrome/test/earl_grey/chrome_actions.h" |
| #import "ios/chrome/test/earl_grey/chrome_earl_grey.h" |
| #import "ios/chrome/test/earl_grey/chrome_earl_grey_ui.h" |
| #import "ios/chrome/test/earl_grey/chrome_matchers.h" |
| #import "ios/chrome/test/earl_grey/chrome_test_case.h" |
| #import "ios/testing/earl_grey/earl_grey_test.h" |
| #import "ios/testing/earl_grey/keyboard_app_interface.h" |
| #include "ios/web/public/test/element_selector.h" |
| #include "net/test/embedded_test_server/embedded_test_server.h" |
| #include "url/gurl.h" |
| |
| #if !defined(__has_feature) || !__has_feature(objc_arc) |
| #error "This file requires ARC support." |
| #endif |
| |
| using base::test::ios::kWaitForActionTimeout; |
| using chrome_test_util::AutofillSuggestionViewMatcher; |
| using chrome_test_util::ManualFallbackFormSuggestionViewMatcher; |
| using chrome_test_util::ManualFallbackKeyboardIconMatcher; |
| using chrome_test_util::ManualFallbackManageProfilesMatcher; |
| using chrome_test_util::ManualFallbackProfilesIconMatcher; |
| using chrome_test_util::ManualFallbackProfilesTableViewMatcher; |
| using chrome_test_util::ManualFallbackProfileTableViewWindowMatcher; |
| |
| namespace { |
| |
| // Using |isKeyboardDocked| requires to inject a UITextField in the window and |
| // wait for it to be shown. For performance reasons, only try to dock the |
| // keyboard in |tearDown| if it was undocked during the test. |
| bool gKeyboardUndockAttempted = false; |
| |
| constexpr char kFormElementName[] = "name"; |
| constexpr char kFormElementCity[] = "city"; |
| |
| constexpr char kFormHTMLFile[] = "/profile_form.html"; |
| |
| // Returns a matcher for a button in the ProfileTableView. Currently it returns |
| // the company one. |
| id<GREYMatcher> ProfileTableViewButtonMatcher() { |
| // The company name for autofill::test::GetFullProfile() is "Underworld". |
| return grey_buttonTitle(@"Underworld"); |
| } |
| |
| // Undocks and split the keyboard by swiping it up. Does nothing if already |
| // undocked. Some devices, like iPhone or iPad Pro, do not allow undocking or |
| // splitting, this returns NO if it is the case. |
| BOOL UndockAndSplitKeyboard() { |
| if (![ChromeEarlGrey isIPadIdiom]) { |
| return NO; |
| } |
| UITextField* textField = [KeyboardAppInterface showKeyboard]; |
| |
| // Return if already undocked. |
| if (![KeyboardAppInterface isKeyboardDocked]) { |
| // If a dummy textfield was created for this, remove it. |
| [textField removeFromSuperview]; |
| return YES; |
| } |
| |
| [[EarlGrey |
| selectElementWithMatcher:[KeyboardAppInterface keyboardWindowMatcher]] |
| performAction:[KeyboardAppInterface keyboardUndockAction]]; |
| gKeyboardUndockAttempted = YES; |
| |
| // If a dummy textfield was created for this, remove it. |
| [textField removeFromSuperview]; |
| return ![KeyboardAppInterface isKeyboardDocked]; |
| } |
| |
| // Docks the keyboard by swiping it down. Does nothing if already docked. |
| void DockKeyboard() { |
| if (![ChromeEarlGrey isIPadIdiom]) { |
| return; |
| } |
| |
| UITextField* textField = [KeyboardAppInterface showKeyboard]; |
| |
| // Return if already docked. |
| if ([KeyboardAppInterface isKeyboardDocked]) { |
| // If we created a dummy textfield for this, remove it. |
| [textField removeFromSuperview]; |
| return; |
| } |
| |
| [[EarlGrey |
| selectElementWithMatcher:[KeyboardAppInterface keyboardWindowMatcher]] |
| performAction:[KeyboardAppInterface keyboardDockAction]]; |
| |
| // If we created a dummy textfield for this, remove it. |
| [textField removeFromSuperview]; |
| |
| GREYCondition* waitForDockedKeyboard = [GREYCondition |
| conditionWithName:@"Wait For Docked Keyboard Animations" |
| block:^BOOL { |
| return [KeyboardAppInterface isKeyboardDocked]; |
| }]; |
| |
| GREYAssertTrue([waitForDockedKeyboard waitWithTimeout:kWaitForActionTimeout], |
| @"Keyboard animations still present."); |
| } |
| |
| // Waits for the keyboard to appear. Returns NO on timeout. |
| BOOL WaitForKeyboardToAppear() { |
| GREYCondition* waitForKeyboard = [GREYCondition |
| conditionWithName:@"Wait for keyboard" |
| block:^BOOL { |
| return [EarlGrey isKeyboardShownWithError:nil]; |
| }]; |
| return [waitForKeyboard waitWithTimeout:kWaitForActionTimeout]; |
| } |
| |
| } // namespace |
| |
| // Integration Tests for fallback coordinator. |
| @interface FallbackCoordinatorTestCase : ChromeTestCase |
| |
| @end |
| |
| @implementation FallbackCoordinatorTestCase |
| |
| - (void)setUp { |
| [super setUp]; |
| // If the previous run was manually stopped then the profile will be in the |
| // store and the test will fail. We clean it here for those cases. |
| [AutofillAppInterface clearProfilesStore]; |
| GREYAssertTrue(self.testServer->Start(), @"Test server failed to start."); |
| const GURL URL = self.testServer->GetURL(kFormHTMLFile); |
| [ChromeEarlGrey loadURL:URL]; |
| [ChromeEarlGrey waitForWebStateContainingText:"Profile form"]; |
| } |
| |
| - (void)tearDown { |
| if (gKeyboardUndockAttempted) { |
| gKeyboardUndockAttempted = NO; |
| DockKeyboard(); |
| } |
| |
| [AutofillAppInterface clearProfilesStore]; |
| |
| // Leaving a picker on iPads causes problems with the docking logic. This |
| // will dismiss any. |
| if ([ChromeEarlGrey isIPadIdiom]) { |
| // Tap in the web view so the popover dismisses. |
| [[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewMatcher()] |
| performAction:grey_tapAtPoint(CGPointMake(0, 0))]; |
| |
| // Verify the table view is not visible. |
| [[EarlGrey |
| selectElementWithMatcher:grey_allOf( |
| grey_kindOfClass([UITableView class]), |
| grey_not(grey_notVisible()), nil)] |
| assertWithMatcher:grey_nil()]; |
| } |
| [super tearDown]; |
| } |
| |
| // Tests that the when tapping the outside the popover on iPad, suggestions |
| // continue working. |
| - (void)testIPadTappingOutsidePopOverResumesSuggestionsCorrectly { |
| if (![ChromeEarlGrey isIPadIdiom]) { |
| EARL_GREY_TEST_SKIPPED(@"Test not applicable for iPhone."); |
| } |
| |
| // Add the profile to be tested. |
| [AutofillAppInterface saveExampleProfile]; |
| |
| // Bring up the keyboard. |
| [[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewMatcher()] |
| performAction:chrome_test_util::TapWebElementWithId(kFormElementName)]; |
| |
| // Tap on the profiles icon. |
| [[EarlGrey selectElementWithMatcher:ManualFallbackFormSuggestionViewMatcher()] |
| performAction:grey_scrollToContentEdge(kGREYContentEdgeRight)]; |
| [[EarlGrey selectElementWithMatcher:ManualFallbackProfilesIconMatcher()] |
| performAction:grey_tap()]; |
| |
| // Verify the profiles controller table view is visible. |
| [[EarlGrey selectElementWithMatcher:ManualFallbackProfilesTableViewMatcher()] |
| assertWithMatcher:grey_sufficientlyVisible()]; |
| |
| // Tap on a point outside of the popover. |
| // The way EarlGrey taps doesn't go through the window hierarchy. Because of |
| // this, the tap needs to be done in the same window as the popover. |
| [[EarlGrey |
| selectElementWithMatcher:ManualFallbackProfileTableViewWindowMatcher()] |
| performAction:grey_tapAtPoint(CGPointMake(0, 0))]; |
| |
| // Verify the profiles controller table view is NOT visible. |
| [[EarlGrey selectElementWithMatcher:ManualFallbackProfilesTableViewMatcher()] |
| assertWithMatcher:grey_notVisible()]; |
| |
| // Tap on the suggestion. |
| [[EarlGrey selectElementWithMatcher:AutofillSuggestionViewMatcher()] |
| performAction:grey_tap()]; |
| |
| // Verify Web Content was filled. |
| NSString* name = [AutofillAppInterface exampleProfileName]; |
| NSString* javaScriptCondition = [NSString |
| stringWithFormat:@"document.getElementById('%s').value === '%@'", |
| kFormElementName, name]; |
| [ChromeEarlGrey waitForJavaScriptCondition:javaScriptCondition]; |
| } |
| |
| // Tests that the manual fallback view concedes preference to the system picker |
| // for selection elements. |
| - (void)testPickerDismissesManualFallback { |
| // Add the profile to be used. |
| [AutofillAppInterface saveExampleProfile]; |
| |
| // Bring up the keyboard. |
| [[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewMatcher()] |
| performAction:chrome_test_util::TapWebElementWithId(kFormElementCity)]; |
| |
| // Tap on the profiles icon. |
| [[EarlGrey selectElementWithMatcher:ManualFallbackFormSuggestionViewMatcher()] |
| performAction:grey_scrollToContentEdge(kGREYContentEdgeRight)]; |
| [[EarlGrey selectElementWithMatcher:ManualFallbackProfilesIconMatcher()] |
| performAction:grey_tap()]; |
| |
| // Verify the profiles controller table view is visible. |
| [[EarlGrey selectElementWithMatcher:ManualFallbackProfilesTableViewMatcher()] |
| assertWithMatcher:grey_sufficientlyVisible()]; |
| |
| // Tap any option. |
| [[EarlGrey selectElementWithMatcher:ProfileTableViewButtonMatcher()] |
| performAction:grey_tap()]; |
| |
| // Verify the profiles controller table view is not visible. |
| [[EarlGrey selectElementWithMatcher:ManualFallbackProfilesTableViewMatcher()] |
| assertWithMatcher:grey_notVisible()]; |
| |
| // TODO(crbug.com/1220724): iOS 15 phones seem to act more like iPads now, |
| // dismissing the keyboard when tapping on the option above. Confirm that this |
| // is expected and either fix, or remove this comment. |
| BOOL isIOS15 = NO; |
| if (@available(iOS 15, *)) { |
| isIOS15 = YES; |
| } |
| |
| // Verify the status of the icons. |
| if ([ChromeEarlGrey isIPadIdiom] || isIOS15) { |
| // Hidden on iPad. |
| [[EarlGrey selectElementWithMatcher:ManualFallbackProfilesIconMatcher()] |
| assertWithMatcher:grey_notVisible()]; |
| [[EarlGrey selectElementWithMatcher:ManualFallbackKeyboardIconMatcher()] |
| assertWithMatcher:grey_not(grey_sufficientlyVisible())]; |
| } else { |
| [[EarlGrey selectElementWithMatcher:ManualFallbackProfilesIconMatcher()] |
| assertWithMatcher:grey_sufficientlyVisible()]; |
| [[EarlGrey selectElementWithMatcher:ManualFallbackProfilesIconMatcher()] |
| assertWithMatcher:grey_userInteractionEnabled()]; |
| [[EarlGrey selectElementWithMatcher:ManualFallbackKeyboardIconMatcher()] |
| assertWithMatcher:grey_not(grey_sufficientlyVisible())]; |
| } |
| } |
| |
| // Tests that the input accessory view continues working after a picker is |
| // present. |
| - (void)testInputAccessoryBarIsPresentAfterPickers { |
| // Add the profile to be used. |
| [AutofillAppInterface saveExampleProfile]; |
| |
| // Bring up the keyboard by tapping the city, which is the element before the |
| // picker. |
| [[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewMatcher()] |
| performAction:chrome_test_util::TapWebElementWithId(kFormElementCity)]; |
| |
| // Tap on the profiles icon. |
| [[EarlGrey selectElementWithMatcher:ManualFallbackFormSuggestionViewMatcher()] |
| performAction:grey_scrollToContentEdge(kGREYContentEdgeRight)]; |
| [[EarlGrey selectElementWithMatcher:ManualFallbackProfilesIconMatcher()] |
| performAction:grey_tap()]; |
| |
| // Verify the profiles controller table view is visible. |
| [[EarlGrey selectElementWithMatcher:ManualFallbackProfilesTableViewMatcher()] |
| assertWithMatcher:grey_sufficientlyVisible()]; |
| |
| // Tap any option. |
| [[EarlGrey selectElementWithMatcher:ProfileTableViewButtonMatcher()] |
| performAction:grey_tap()]; |
| |
| // Verify the profiles controller table view is not visible. |
| [[EarlGrey selectElementWithMatcher:ManualFallbackProfilesTableViewMatcher()] |
| assertWithMatcher:grey_notVisible()]; |
| |
| // TODO(crbug.com/1220724): iOS 15 phones seem to act more like iPads now, |
| // dismissing the keyboard when tapping on the option above. Confirm that this |
| // is expected and either fix, or remove this comment. |
| BOOL isIOS15 = NO; |
| if (@available(iOS 15, *)) { |
| isIOS15 = YES; |
| } |
| |
| // On iPad the picker is a table view in a popover, we need to dismiss that |
| // first. |
| if ([ChromeEarlGrey isIPadIdiom] || isIOS15) { |
| // Tap in the web view so the popover dismisses. |
| [[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewMatcher()] |
| performAction:grey_tapAtPoint(CGPointMake(0, 0))]; |
| |
| // Verify the table view is not visible. |
| [[EarlGrey |
| selectElementWithMatcher:grey_allOf( |
| grey_kindOfClass([UITableView class]), |
| grey_not(grey_notVisible()), nil)] |
| assertWithMatcher:grey_nil()]; |
| } |
| |
| // Bring up the regular keyboard again. |
| [[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewMatcher()] |
| performAction:chrome_test_util::TapWebElementWithId(kFormElementCity)]; |
| |
| // Wait for the accessory icon to appear. |
| GREYAssert(WaitForKeyboardToAppear(), @"Keyboard didn't appear."); |
| |
| // Verify the profiles icon is visible, and therefore also the input accessory |
| // bar. |
| [[EarlGrey selectElementWithMatcher:ManualFallbackFormSuggestionViewMatcher()] |
| performAction:grey_scrollToContentEdge(kGREYContentEdgeRight)]; |
| // Verify the status of the icons. |
| [[EarlGrey selectElementWithMatcher:ManualFallbackProfilesIconMatcher()] |
| assertWithMatcher:grey_sufficientlyVisible()]; |
| |
| // TODO(crbug.com/1227392): This doesn't appear to work on iOS15 phone. It |
| // appears the profiles icon is visible and selected (so interaction |
| // disabled), but the keyboard itself is visible. As a workaround, tap the |
| // keyboard icon and continue the test. |
| if (![ChromeEarlGrey isIPadIdiom] && isIOS15) { |
| [[EarlGrey selectElementWithMatcher:ManualFallbackKeyboardIconMatcher()] |
| performAction:grey_tap()]; |
| } |
| |
| [[EarlGrey selectElementWithMatcher:ManualFallbackProfilesIconMatcher()] |
| assertWithMatcher:grey_userInteractionEnabled()]; |
| [[EarlGrey selectElementWithMatcher:ManualFallbackKeyboardIconMatcher()] |
| assertWithMatcher:grey_not(grey_sufficientlyVisible())]; |
| } |
| |
| // Same as before but with the keyboard undocked the re-docked. |
| - (void)testRedockedInputAccessoryBarIsPresentAfterPickers { |
| // No need to run if not iPad. |
| if (![ChromeEarlGrey isIPadIdiom]) { |
| EARL_GREY_TEST_SKIPPED(@"Test not applicable for iPhone."); |
| } |
| |
| // Add the profile to be used. |
| [AutofillAppInterface saveExampleProfile]; |
| |
| // Bring up the keyboard by tapping the city, which is the element before the |
| // picker. |
| [[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewMatcher()] |
| performAction:chrome_test_util::TapWebElementWithId(kFormElementCity)]; |
| |
| if (!UndockAndSplitKeyboard()) { |
| EARL_GREY_TEST_DISABLED( |
| @"Undocking the keyboard does not work on iPhone or iPad Pro"); |
| } |
| |
| // Give the iPad 2 seconds to settle the split animation. |
| [[NSRunLoop currentRunLoop] |
| runUntilDate:[[NSDate date] dateByAddingTimeInterval:2]]; |
| |
| // When keyboard is split, icons are not visible, so we rely on timeout before |
| // docking again, because EarlGrey synchronization isn't working properly with |
| // the keyboard. |
| [ChromeEarlGrey waitForMatcher:ManualFallbackProfilesIconMatcher()]; |
| |
| DockKeyboard(); |
| |
| // Tap on the profiles icon. |
| [[EarlGrey selectElementWithMatcher:ManualFallbackFormSuggestionViewMatcher()] |
| performAction:grey_scrollToContentEdge(kGREYContentEdgeRight)]; |
| [[EarlGrey selectElementWithMatcher:ManualFallbackProfilesIconMatcher()] |
| performAction:grey_tap()]; |
| |
| // Verify the profiles controller table view is visible. |
| [[EarlGrey selectElementWithMatcher:ManualFallbackProfilesTableViewMatcher()] |
| assertWithMatcher:grey_sufficientlyVisible()]; |
| |
| // Tap any option. |
| [[EarlGrey selectElementWithMatcher:ProfileTableViewButtonMatcher()] |
| performAction:grey_tap()]; |
| |
| // Verify the profiles controller table view is not visible. |
| [[EarlGrey selectElementWithMatcher:ManualFallbackProfilesTableViewMatcher()] |
| assertWithMatcher:grey_notVisible()]; |
| |
| // On iPad the picker is a table view in a popover, we need to dismiss that |
| // first. Tap in the previous field, so the popover dismisses. |
| [[EarlGrey selectElementWithMatcher:grey_keyWindow()] |
| performAction:grey_tapAtPoint(CGPointMake(0, 0))]; |
| |
| // Verify the table view is not visible. |
| [[EarlGrey |
| selectElementWithMatcher:grey_allOf(grey_kindOfClass([UITableView class]), |
| grey_not(grey_notVisible()), nil)] |
| assertWithMatcher:grey_nil()]; |
| |
| // Bring up the regular keyboard again. |
| [[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewMatcher()] |
| performAction:chrome_test_util::TapWebElementWithId(kFormElementName)]; |
| |
| // Wait for the accessory icon to appear. |
| GREYAssert(WaitForKeyboardToAppear(), @"Keyboard didn't appear."); |
| |
| // Verify the profiles icon is visible, and therefore also the input accessory |
| // bar. |
| [[EarlGrey selectElementWithMatcher:ManualFallbackFormSuggestionViewMatcher()] |
| performAction:grey_scrollToContentEdge(kGREYContentEdgeRight)]; |
| // Verify the status of the icons. |
| [[EarlGrey selectElementWithMatcher:ManualFallbackProfilesIconMatcher()] |
| assertWithMatcher:grey_sufficientlyVisible()]; |
| [[EarlGrey selectElementWithMatcher:ManualFallbackProfilesIconMatcher()] |
| assertWithMatcher:grey_userInteractionEnabled()]; |
| [[EarlGrey selectElementWithMatcher:ManualFallbackKeyboardIconMatcher()] |
| assertWithMatcher:grey_not(grey_sufficientlyVisible())]; |
| } |
| |
| // Test the input accessory bar is present when undocking then docking the |
| // keyboard. |
| - (void)testInputAccessoryBarIsPresentAfterUndockingKeyboard { |
| if (![ChromeEarlGrey isIPadIdiom]) { |
| EARL_GREY_TEST_SKIPPED(@"Test not applicable for iPhone."); |
| } |
| |
| // Add the profile to use for verification. |
| [AutofillAppInterface saveExampleProfile]; |
| |
| // Bring up the keyboard by tapping the city, which is the element before the |
| // picker. |
| [[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewMatcher()] |
| performAction:chrome_test_util::TapWebElementWithId(kFormElementCity)]; |
| |
| if (!UndockAndSplitKeyboard()) { |
| EARL_GREY_TEST_DISABLED( |
| @"Undocking the keyboard does not work on iPhone or iPad Pro"); |
| } |
| |
| // When keyboard is split, icons are not visible, so we rely on timeout before |
| // docking again, because EarlGrey synchronization isn't working properly with |
| // the keyboard. |
| [ChromeEarlGrey waitForMatcher:ManualFallbackProfilesIconMatcher()]; |
| |
| DockKeyboard(); |
| |
| // Verify the profiles icon is visible, and therefore also the input accessory |
| // bar. |
| [[EarlGrey selectElementWithMatcher:ManualFallbackFormSuggestionViewMatcher()] |
| performAction:grey_scrollToContentEdge(kGREYContentEdgeRight)]; |
| // Verify the status of the icons. |
| [[EarlGrey selectElementWithMatcher:ManualFallbackProfilesIconMatcher()] |
| assertWithMatcher:grey_sufficientlyVisible()]; |
| [[EarlGrey selectElementWithMatcher:ManualFallbackProfilesIconMatcher()] |
| assertWithMatcher:grey_userInteractionEnabled()]; |
| [[EarlGrey selectElementWithMatcher:ManualFallbackKeyboardIconMatcher()] |
| assertWithMatcher:grey_not(grey_sufficientlyVisible())]; |
| } |
| |
| // Tests that the manual fallback view is present in incognito. |
| // Disabled due to flakiness. See crbug.com/1115321. |
| - (void)DISABLED_testIncognitoManualFallbackMenu { |
| // Add the profile to use for verification. |
| [AutofillAppInterface saveExampleProfile]; |
| |
| // Bring up the keyboard by tapping the city, which is the element before the |
| // picker. |
| [[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewMatcher()] |
| performAction:chrome_test_util::TapWebElementWithId(kFormElementCity)]; |
| |
| // Verify the profiles icon is visible. |
| [[EarlGrey selectElementWithMatcher:ManualFallbackFormSuggestionViewMatcher()] |
| performAction:grey_scrollToContentEdge(kGREYContentEdgeRight)]; |
| [[EarlGrey selectElementWithMatcher:ManualFallbackProfilesIconMatcher()] |
| assertWithMatcher:grey_sufficientlyVisible()]; |
| |
| // Open a tab in incognito. |
| [ChromeEarlGrey openNewIncognitoTab]; |
| const GURL URL = self.testServer->GetURL(kFormHTMLFile); |
| [ChromeEarlGrey loadURL:URL]; |
| [ChromeEarlGrey waitForWebStateContainingText:"Profile form"]; |
| |
| // Bring up the keyboard by tapping the city, which is the element before the |
| // picker. |
| [[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewMatcher()] |
| performAction:chrome_test_util::TapWebElementWithId(kFormElementCity)]; |
| |
| // Verify the profiles icon is visible. |
| [[EarlGrey selectElementWithMatcher:ManualFallbackFormSuggestionViewMatcher()] |
| performAction:grey_scrollToContentEdge(kGREYContentEdgeRight)]; |
| [[EarlGrey selectElementWithMatcher:ManualFallbackProfilesIconMatcher()] |
| assertWithMatcher:grey_sufficientlyVisible()]; |
| } |
| |
| // Tests the mediator stops observing objects when the incognito BVC is |
| // destroyed. Waiting for dealloc was causing a race condition with the |
| // autorelease pool, and some times a DCHECK will be hit. |
| - (void)testOpeningIncognitoTabsDoNotLeak { |
| const GURL URL = self.testServer->GetURL(kFormHTMLFile); |
| std::string webViewText("Profile form"); |
| [AutofillAppInterface saveExampleProfile]; |
| |
| [[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewMatcher()] |
| performAction:chrome_test_util::TapWebElementWithId(kFormElementCity)]; |
| |
| // Verify the profiles icon is visible. |
| [[EarlGrey selectElementWithMatcher:ManualFallbackFormSuggestionViewMatcher()] |
| performAction:grey_scrollToContentEdge(kGREYContentEdgeRight)]; |
| [[EarlGrey selectElementWithMatcher:ManualFallbackProfilesIconMatcher()] |
| assertWithMatcher:grey_sufficientlyVisible()]; |
| |
| // Open a tab in incognito. |
| [ChromeEarlGrey openNewIncognitoTab]; |
| [ChromeEarlGrey loadURL:URL]; |
| [ChromeEarlGrey waitForWebStateContainingText:webViewText]; |
| |
| [[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewMatcher()] |
| performAction:chrome_test_util::TapWebElementWithId(kFormElementCity)]; |
| |
| // Verify the profiles icon is visible. |
| [[EarlGrey selectElementWithMatcher:ManualFallbackFormSuggestionViewMatcher()] |
| performAction:grey_scrollToContentEdge(kGREYContentEdgeRight)]; |
| [[EarlGrey selectElementWithMatcher:ManualFallbackProfilesIconMatcher()] |
| assertWithMatcher:grey_sufficientlyVisible()]; |
| |
| [ChromeEarlGrey closeCurrentTab]; |
| [ChromeEarlGrey openNewTab]; |
| [ChromeEarlGrey loadURL:URL]; |
| [ChromeEarlGrey waitForWebStateContainingText:webViewText]; |
| |
| // Bring up the keyboard by tapping the city, which is the element before the |
| // picker. |
| [[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewMatcher()] |
| performAction:chrome_test_util::TapWebElementWithId(kFormElementCity)]; |
| |
| // Verify the profiles icon is visible. |
| [[EarlGrey selectElementWithMatcher:ManualFallbackFormSuggestionViewMatcher()] |
| performAction:grey_scrollToContentEdge(kGREYContentEdgeRight)]; |
| [[EarlGrey selectElementWithMatcher:ManualFallbackProfilesIconMatcher()] |
| assertWithMatcher:grey_sufficientlyVisible()]; |
| |
| // Open a tab in incognito. |
| [ChromeEarlGrey openNewIncognitoTab]; |
| [ChromeEarlGrey loadURL:URL]; |
| [ChromeEarlGrey waitForWebStateContainingText:webViewText]; |
| |
| // Bring up the keyboard by tapping the city, which is the element before the |
| // picker. |
| [[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewMatcher()] |
| performAction:chrome_test_util::TapWebElementWithId(kFormElementCity)]; |
| |
| // Open a regular tab. |
| [ChromeEarlGrey openNewTab]; |
| [ChromeEarlGrey loadURL:URL]; |
| [ChromeEarlGrey waitForWebStateContainingText:webViewText]; |
| |
| // Bring up the keyboard by tapping the city, which is the element before the |
| // picker. |
| [[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewMatcher()] |
| performAction:chrome_test_util::TapWebElementWithId(kFormElementCity)]; |
| |
| // This will fail if there is more than one profiles icon in the hierarchy. |
| [[EarlGrey selectElementWithMatcher:ManualFallbackFormSuggestionViewMatcher()] |
| performAction:grey_scrollToContentEdge(kGREYContentEdgeRight)]; |
| [[EarlGrey selectElementWithMatcher:ManualFallbackProfilesIconMatcher()] |
| assertWithMatcher:grey_sufficientlyVisible()]; |
| } |
| |
| // Tests that the manual fallback view is not duplicated after incognito. |
| - (void)testReturningFromIncognitoDoesNotDuplicatesManualFallbackMenu { |
| // Add the profile to use for verification. |
| [AutofillAppInterface saveExampleProfile]; |
| |
| // Bring up the keyboard by tapping the city, which is the element before the |
| // picker. |
| [[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewMatcher()] |
| performAction:chrome_test_util::TapWebElementWithId(kFormElementCity)]; |
| |
| // Verify the profiles icon is visible. |
| [[EarlGrey selectElementWithMatcher:ManualFallbackFormSuggestionViewMatcher()] |
| performAction:grey_scrollToContentEdge(kGREYContentEdgeRight)]; |
| [[EarlGrey selectElementWithMatcher:ManualFallbackProfilesIconMatcher()] |
| assertWithMatcher:grey_sufficientlyVisible()]; |
| |
| // Open a tab in incognito. |
| [ChromeEarlGrey openNewIncognitoTab]; |
| const GURL URL = self.testServer->GetURL(kFormHTMLFile); |
| [ChromeEarlGrey loadURL:URL]; |
| [ChromeEarlGrey waitForWebStateContainingText:"Profile form"]; |
| |
| // Bring up the keyboard by tapping the city, which is the element before the |
| // picker. |
| [[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewMatcher()] |
| performAction:chrome_test_util::TapWebElementWithId(kFormElementCity)]; |
| |
| // Open a regular tab. |
| [ChromeEarlGrey openNewTab]; |
| [ChromeEarlGrey loadURL:URL]; |
| [ChromeEarlGrey waitForWebStateContainingText:"Profile form"]; |
| |
| // Bring up the keyboard by tapping the city, which is the element before the |
| // picker. |
| [[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewMatcher()] |
| performAction:chrome_test_util::TapWebElementWithId(kFormElementCity)]; |
| |
| // This will fail if there is more than one profiles icon in the hierarchy. |
| [[EarlGrey selectElementWithMatcher:ManualFallbackFormSuggestionViewMatcher()] |
| performAction:grey_scrollToContentEdge(kGREYContentEdgeRight)]; |
| [[EarlGrey selectElementWithMatcher:ManualFallbackProfilesIconMatcher()] |
| assertWithMatcher:grey_sufficientlyVisible()]; |
| } |
| |
| @end |