blob: 237b0033b863995b5dbec42dab15724e80e9eac0 [file] [log] [blame]
// Copyright 2020 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.
#import <UIKit/UIKit.h>
#import <XCTest/XCTest.h>
#include <memory>
#import "base/test/ios/wait_util.h"
#include "components/strings/grit/components_strings.h"
#import "ios/chrome/browser/passwords/password_manager_app_interface.h"
#import "ios/chrome/browser/ui/authentication/signin_earl_grey.h"
#import "ios/chrome/browser/ui/authentication/signin_earl_grey_ui_test_util.h"
#import "ios/chrome/browser/ui/infobars/banners/infobar_banner_constants.h"
#include "ios/chrome/grit/ios_strings.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_app_interface.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/web_http_server_chrome_test_case.h"
#import "ios/public/provider/chrome/browser/signin/fake_chrome_identity.h"
#import "ios/testing/earl_grey/earl_grey_test.h"
#include "net/test/embedded_test_server/default_handlers.h"
#include "ui/base/l10n/l10n_util.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
constexpr char kFormUsername[] = "un";
constexpr char kFormPassword[] = "pw";
NSString* const kSavedCredentialLabel = @"Eguser, Hidden, Password";
namespace {
using base::test::ios::kWaitForActionTimeout;
using base::test::ios::kWaitForUIElementTimeout;
using base::test::ios::WaitUntilConditionOrTimeout;
using base::test::ios::kWaitForActionTimeout;
using chrome_test_util::TapWebElementWithId;
using chrome_test_util::UseSuggestedPasswordMatcher;
id<GREYMatcher> PasswordInfobar(int prompt_id) {
NSString* bannerLabel =
[NSString stringWithFormat:@"%@,%@", l10n_util::GetNSString(prompt_id),
kSavedCredentialLabel];
return grey_allOf(grey_accessibilityID(kInfobarBannerViewIdentifier),
grey_accessibilityLabel(bannerLabel), nil);
}
id<GREYMatcher> PasswordInfobarButton(int button_id) {
return chrome_test_util::ButtonWithAccessibilityLabelId(button_id);
}
id<GREYMatcher> SuggestPasswordChip() {
return grey_allOf(
grey_accessibilityLabel(l10n_util::GetNSString(IDS_IOS_SUGGEST_PASSWORD)),
nil);
}
BOOL WaitForKeyboardToAppear() {
GREYCondition* waitForKeyboard = [GREYCondition
conditionWithName:@"Wait for keyboard"
block:^BOOL {
return [EarlGrey isKeyboardShownWithError:nil];
}];
return [waitForKeyboard waitWithTimeout:kWaitForActionTimeout];
}
} // namespace
@interface PasswordControllerEGTest : WebHttpServerChromeTestCase
@end
@implementation PasswordControllerEGTest
- (void)setUp {
[super setUp];
// Set up server.
net::test_server::RegisterDefaultHandlers(self.testServer);
GREYAssertTrue(self.testServer->Start(), @"Server did not start.");
}
- (void)tearDown {
[PasswordManagerAppInterface clearCredentials];
[super tearDown];
}
#pragma mark - Helper methods
// Loads simple page on localhost.
- (void)loadLoginPage {
// Loads simple page. It is on localhost so it is considered a secure context.
[ChromeEarlGrey loadURL:self.testServer->GetURL("/simple_login_form.html")];
[ChromeEarlGrey waitForWebStateContainingText:"Login form."];
}
#pragma mark - Tests
// Tests that save password prompt is shown on new login.
// TODO(crbug.com/1192446): Reenable this test.
- (void)DISABLED_testSavePromptAppearsOnFormSubmission {
[self loadLoginPage];
// Simulate user interacting with fields.
[[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewMatcher()]
performAction:chrome_test_util::TapWebElementWithId(kFormUsername)];
[[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewMatcher()]
performAction:chrome_test_util::TapWebElementWithId(kFormPassword)];
[[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewMatcher()]
performAction:chrome_test_util::TapWebElementWithId("submit_button")];
// Wait until the save password prompt becomes visible.
[ChromeEarlGrey
waitForUIElementToAppearWithMatcher:
PasswordInfobar(IDS_IOS_PASSWORD_MANAGER_SAVE_PASSWORD_PROMPT)];
[[EarlGrey selectElementWithMatcher:PasswordInfobarButton(
IDS_IOS_PASSWORD_MANAGER_SAVE_BUTTON)]
performAction:grey_tap()];
// Wait until the save password infobar disappears.
[ChromeEarlGrey
waitForUIElementToDisappearWithMatcher:
PasswordInfobar(IDS_IOS_PASSWORD_MANAGER_SAVE_PASSWORD_PROMPT)];
int credentialsCount = [PasswordManagerAppInterface storedCredentialsCount];
GREYAssertEqual(1, credentialsCount, @"Wrong number of stored credentials.");
}
// Tests that update password prompt is shown on submitting the new password
// for an already stored login.
// TODO(crbug.com/1330896): Test fails on simulator.
#if TARGET_IPHONE_SIMULATOR
#define MAYBE_testUpdatePromptAppearsOnFormSubmission \
DISABLED_testUpdatePromptAppearsOnFormSubmission
#else
#define MAYBE_testUpdatePromptAppearsOnFormSubmission \
testUpdatePromptAppearsOnFormSubmission
#endif
- (void)MAYBE_testUpdatePromptAppearsOnFormSubmission {
// Load the page the first time an store credentials.
[self loadLoginPage];
[PasswordManagerAppInterface storeCredentialWithUsername:@"Eguser"
password:@"OldPass"];
int credentialsCount = [PasswordManagerAppInterface storedCredentialsCount];
GREYAssertEqual(1, credentialsCount, @"Wrong number of initial credentials.");
// Load the page again and have a new password value to save.
[self loadLoginPage];
// Simulate user interacting with fields.
[[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewMatcher()]
performAction:chrome_test_util::TapWebElementWithId(kFormUsername)];
[[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewMatcher()]
performAction:chrome_test_util::TapWebElementWithId(kFormPassword)];
[[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewMatcher()]
performAction:chrome_test_util::TapWebElementWithId("submit_button")];
// Wait until the update password prompt becomes visible.
[ChromeEarlGrey
waitForUIElementToAppearWithMatcher:
PasswordInfobar(IDS_IOS_PASSWORD_MANAGER_UPDATE_PASSWORD)];
[[EarlGrey
selectElementWithMatcher:PasswordInfobarButton(
IDS_IOS_PASSWORD_MANAGER_UPDATE_BUTTON)]
performAction:grey_tap()];
// Wait until the update password infobar disappears.
[ChromeEarlGrey
waitForUIElementToDisappearWithMatcher:
PasswordInfobar(IDS_IOS_PASSWORD_MANAGER_UPDATE_PASSWORD)];
credentialsCount = [PasswordManagerAppInterface storedCredentialsCount];
GREYAssertEqual(1, credentialsCount, @"Wrong number of final credentials.");
}
// Tests password generation flow.
// TODO(crbug.com/1221635) This fails on iPhone 14.5+
- (void)DISABLED_testPasswordGeneration {
#if TARGET_IPHONE_SIMULATOR
// TODO(crbug.com/1194134): Reenable this test.
if ([ChromeEarlGrey isIPadIdiom]) {
EARL_GREY_TEST_SKIPPED(@"Skipped for iPad (test is flaky)");
}
#endif
[SigninEarlGreyUI signinWithFakeIdentity:[FakeChromeIdentity fakeIdentity1]];
[ChromeEarlGrey waitForSyncInitialized:YES syncTimeout:10.0];
[ChromeEarlGrey loadURL:self.testServer->GetURL("/simple_signup_form.html")];
[ChromeEarlGrey waitForWebStateContainingText:"Signup form."];
// Verify that the target field is empty.
NSString* emptyFieldCondition =
[NSString stringWithFormat:@"document.getElementById('%s').value === ''",
kFormPassword];
[ChromeEarlGrey waitForJavaScriptCondition:emptyFieldCondition];
// Bring up the keyboard.
[[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewMatcher()]
performAction:TapWebElementWithId(kFormPassword)];
// Wait for the accessory icon to appear.
WaitForKeyboardToAppear();
// Tap on a 'Suggest Password...' chip.
[[EarlGrey selectElementWithMatcher:SuggestPasswordChip()]
performAction:grey_tap()];
// Confirm by tapping on the 'Use Suggested Password' button.
[[EarlGrey selectElementWithMatcher:UseSuggestedPasswordMatcher()]
performAction:grey_tap()];
// Verify that the target field is not empty.
NSString* filledFieldCondition =
[NSString stringWithFormat:@"document.getElementById('%s').value !== ''",
kFormPassword];
[ChromeEarlGrey waitForJavaScriptCondition:filledFieldCondition];
}
@end