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

Unified Diff: ios/chrome/browser/ui/settings/passwords_settings_egtest.mm

Issue 2846253002: Add EGTests for passwords settings on iOS (Closed)
Patch Set: Comments Created 3 years, 8 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « ios/chrome/browser/ui/settings/password_details_collection_view_controller_for_testing.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ios/chrome/browser/ui/settings/passwords_settings_egtest.mm
diff --git a/ios/chrome/browser/ui/settings/passwords_settings_egtest.mm b/ios/chrome/browser/ui/settings/passwords_settings_egtest.mm
new file mode 100644
index 0000000000000000000000000000000000000000..e5b7c06b231f5f08f93b023d7182a26135132a81
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/passwords_settings_egtest.mm
@@ -0,0 +1,307 @@
+// Copyright 2017 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/callback.h"
+#include "base/mac/foundation_util.h"
+#include "base/memory/ref_counted.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/time/time.h"
+#include "components/autofill/core/common/password_form.h"
+#include "components/keyed_service/core/service_access_type.h"
+#include "components/password_manager/core/browser/password_store.h"
+#include "components/password_manager/core/common/password_manager_pref_names.h"
+#include "components/prefs/pref_service.h"
+#include "ios/chrome/browser/browser_state/chrome_browser_state.h"
+#include "ios/chrome/browser/passwords/ios_chrome_password_store_factory.h"
+#import "ios/chrome/browser/ui/settings/password_details_collection_view_controller_for_testing.h"
+#import "ios/chrome/browser/ui/settings/reauthentication_module.h"
+#import "ios/chrome/browser/ui/settings/settings_navigation_controller.h"
+#include "ios/chrome/browser/ui/tools_menu/tools_menu_constants.h"
+#import "ios/chrome/browser/ui/util/top_view_controller.h"
+#include "ios/chrome/grit/ios_strings.h"
+#import "ios/chrome/test/app/chrome_test_util.h"
+#include "ios/chrome/test/earl_grey/accessibility_util.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"
+#include "ui/base/l10n/l10n_util.h"
+#include "url/gurl.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+// This test complements
+// password_details_collection_view_controller_unittest.mm. Very simple
+// integration tests and features which are not currently unittestable should
+// go here, the rest into the unittest.
+// This test only uses the new UI which allows viewing passwords.
+// TODO(crbug.com/159166): Remove the above sentence once the new UI is the
+// default one.
+
+using autofill::PasswordForm;
+using chrome_test_util::ButtonWithAccessibilityLabel;
+using chrome_test_util::ButtonWithAccessibilityLabelId;
+using chrome_test_util::NavigationBarDoneButton;
+
+namespace {
+
+// Matcher for the Settings button in the tools menu.
+id<GREYMatcher> SettingsButton() {
+ return grey_accessibilityID(kToolsMenuSettingsId);
+}
+
+// Matcher for the Save Passwords cell on the main Settings screen.
+id<GREYMatcher> PasswordsButton() {
+ return ButtonWithAccessibilityLabelId(IDS_IOS_SAVE_PASSWORDS);
+}
+
+// Matcher for a password entry for |username|.
+id<GREYMatcher> Entry(NSString* username) {
+ return ButtonWithAccessibilityLabel(username);
+}
+
+// Matcher for the Edit button in Save Passwords view.
+id<GREYMatcher> EditButton() {
+ return ButtonWithAccessibilityLabelId(IDS_IOS_NAVIGATION_BAR_EDIT_BUTTON);
+}
+
+// Matcher for the Copy password button in Password Details view.
+id<GREYMatcher> CopyPasswordButton() {
+ return ButtonWithAccessibilityLabelId(IDS_IOS_SETTINGS_PASSWORD_COPY_BUTTON);
+}
+
+} // namespace
+
+@interface MockReauthenticationModule : NSObject<ReauthenticationProtocol>
+
+@property(nonatomic, assign) BOOL shouldSucceed;
+
+@end
+
+@implementation MockReauthenticationModule
+
+@synthesize shouldSucceed = _shouldSucceed;
+
+- (BOOL)canAttemptReauth {
+ return YES;
+}
+
+- (void)attemptReauthWithLocalizedReason:(NSString*)localizedReason
+ handler:(void (^)(BOOL success))
+ showCopyPasswordsHandler {
+ showCopyPasswordsHandler(_shouldSucceed);
+}
+
+@end
+
+// Various tests for the Save Passwords section of the settings.
+@interface PasswordsSettingsTestCase : ChromeTestCase
+@end
+
+@implementation PasswordsSettingsTestCase
+
+// Return pref for saving passwords back to the passed value and restores the
+// experimental flag for viewing passwords.
+- (void)passwordsTearDown:(BOOL)defaultPasswordManagementSetting
+ :(NSString*)oldExperiment {
+ ios::ChromeBrowserState* browserState =
+ chrome_test_util::GetOriginalBrowserState();
+ PrefService* preferences = browserState->GetPrefs();
+ preferences->SetBoolean(
+ password_manager::prefs::kPasswordManagerSavingEnabled,
+ defaultPasswordManagementSetting);
+
+ NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
+ [defaults setObject:oldExperiment forKey:@"EnableViewCopyPasswords"];
+}
+
+// Sets the preference to allow saving passwords and activates the flag to use
+// the new UI for viewing passwords in settings. Also, ensures that original
+// state is restored after the test ends.
+- (void)scopedEnablePasswordManagementAndViewingUI {
+ // Retrieve the original preference state.
+ ios::ChromeBrowserState* browserState =
+ chrome_test_util::GetOriginalBrowserState();
+ PrefService* preferences = browserState->GetPrefs();
+ bool defaultPasswordManagerSavingPref = preferences->GetBoolean(
+ password_manager::prefs::kPasswordManagerSavingEnabled);
+
+ // Retrieve the experiment setting.
+ NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
+ NSString* oldSetting = [defaults stringForKey:@"EnableViewCopyPasswords"];
+
+ // Ensure restoring that on tear-down.
+ __weak PasswordsSettingsTestCase* weakSelf = self;
+ [self setTearDownHandler:^{
+ [weakSelf passwordsTearDown:defaultPasswordManagerSavingPref:oldSetting];
+ }];
+
+ // Enable saving.
+ preferences->SetBoolean(
+ password_manager::prefs::kPasswordManagerSavingEnabled, true);
+
+ // Enable viewing passwords in settings.
+ [defaults setObject:@"Enabled" forKey:@"EnableViewCopyPasswords"];
+}
+
+- (scoped_refptr<password_manager::PasswordStore>)passwordStore {
+ // ServiceAccessType governs behaviour in Incognito: only modifications with
+ // EXPLICIT_ACCESS, which correspond to user's explicit gesture, succeed.
+ // This test does not deal with Incognito, so the value of the argument is
+ // irrelevant.
+ return IOSChromePasswordStoreFactory::GetForBrowserState(
+ chrome_test_util::GetOriginalBrowserState(),
+ ServiceAccessType::EXPLICIT_ACCESS);
+}
+
+// Saves an example form in the store.
+- (void)saveExamplePasswordForm {
+ PasswordForm example;
+ example.username_value = base::ASCIIToUTF16("user");
+ example.password_value = base::ASCIIToUTF16("password");
+ example.origin = GURL("https://example.com");
+ example.signon_realm = example.origin.spec();
+
+ [self passwordStore]->AddLogin(example);
+ // Allow the PasswordStore to process this on the DB thread.
+ [[GREYUIThreadExecutor sharedInstance] drainUntilIdle];
+}
+
+// Removes all credentials stored.
+- (void)clearPasswordStore {
+ [self passwordStore]->RemoveLoginsCreatedBetween(base::Time(), base::Time(),
+ base::Closure());
+ // Allow the PasswordStore to process this on the DB thread.
+ [[GREYUIThreadExecutor sharedInstance] drainUntilIdle];
+}
+
+// Opens the passwords page from the NTP. It requires no menus to be open.
+- (void)openPasswordSettings {
+ // Open settings and verify data in the view controller.
+ [ChromeEarlGreyUI openToolsMenu];
+ [[EarlGrey selectElementWithMatcher:SettingsButton()]
+ performAction:grey_tap()];
+ [[EarlGrey selectElementWithMatcher:PasswordsButton()]
+ performAction:grey_tap()];
+
+ // Wait for UI components to finish loading.
+ [[GREYUIThreadExecutor sharedInstance] drainUntilIdle];
+}
+
+// Tap back arrow, to get one level higher in settings.
+- (void)tapBackArrow {
+ [[EarlGrey
+ selectElementWithMatcher:grey_allOf(
+ grey_accessibilityID(@"ic_arrow_back"),
+ grey_accessibilityTrait(
+ UIAccessibilityTraitButton),
+ nil)] performAction:grey_tap()];
+
+ // Wait for UI components to finish loading.
+ [[GREYUIThreadExecutor sharedInstance] drainUntilIdle];
+}
+
+// Tap Edit in any settings view.
+- (void)tapEdit {
+ [[EarlGrey selectElementWithMatcher:EditButton()] performAction:grey_tap()];
+
+ // Wait for UI components to finish loading.
+ [[GREYUIThreadExecutor sharedInstance] drainUntilIdle];
+}
+
+// Tap Done in any settings view.
+- (void)tapDone {
+ [[EarlGrey selectElementWithMatcher:NavigationBarDoneButton()]
+ performAction:grey_tap()];
+
+ // Wait for UI components to finish loading.
+ [[GREYUIThreadExecutor sharedInstance] drainUntilIdle];
+}
+
+// Verifies the UI elements are accessible on the Passwords page.
+// TODO(crbug.com/159166): This differs from testAccessibilityOnPasswords in
+// settings_egtest.mm in that here this tests the new UI (for viewing
+// passwords), where in settings_egtest.mm the default (old) UI is tested.
+// Once the new is the default, just remove the test in settings_egtest.mm.
+- (void)testAccessibilityOnPasswords {
+ [self scopedEnablePasswordManagementAndViewingUI];
+
+ // Saving a form is needed for using the "password details" view.
+ [self saveExamplePasswordForm];
+
+ [self openPasswordSettings];
+ chrome_test_util::VerifyAccessibilityForCurrentScreen();
+
+ [self tapEdit];
+ chrome_test_util::VerifyAccessibilityForCurrentScreen();
+ [self tapDone];
+
+ // Inspect "password details" view.
+ [[EarlGrey selectElementWithMatcher:Entry(@"https://example.com, user")]
+ performAction:grey_tap()];
+ chrome_test_util::VerifyAccessibilityForCurrentScreen();
+ [self tapBackArrow];
+
+ [self tapBackArrow];
+ [self tapDone];
+ [self clearPasswordStore];
+}
+
+// Checks that attempts to copy a password provide appropriate feedback,
+// both when reauthentication succeeds and when it fails.
+- (void)testCopyPasswordToast {
+ [self scopedEnablePasswordManagementAndViewingUI];
+
+ // Saving a form is needed for using the "password details" view.
+ [self saveExamplePasswordForm];
+
+ [self openPasswordSettings];
+
+ [[EarlGrey selectElementWithMatcher:Entry(@"https://example.com, user")]
+ performAction:grey_tap()];
+
+ // Get the PasswordDetailsCollectionViewController and replace the
+ // reauthentication module with a fake one to avoid being blocked with a
+ // reauth prompt.
+ MockReauthenticationModule* mock_reauthentication_module =
+ [[MockReauthenticationModule alloc] init];
+ SettingsNavigationController* settings_navigation_controller =
+ base::mac::ObjCCastStrict<SettingsNavigationController>(
+ top_view_controller::TopPresentedViewController());
+ PasswordDetailsCollectionViewController*
+ password_details_collection_view_controller =
+ base::mac::ObjCCastStrict<PasswordDetailsCollectionViewController>(
+ settings_navigation_controller.topViewController);
+ [password_details_collection_view_controller
+ setReauthenticationModule:mock_reauthentication_module];
+
+ // Check the snackbar in case of successful reauthentication.
+ mock_reauthentication_module.shouldSucceed = YES;
+ [[EarlGrey selectElementWithMatcher:CopyPasswordButton()]
+ performAction:grey_tap()];
+ [[GREYUIThreadExecutor sharedInstance] drainUntilIdle];
+ NSString* snackbarLabel =
+ l10n_util::GetNSString(IDS_IOS_SETTINGS_PASSWORD_WAS_COPIED_MESSAGE);
+ [[EarlGrey selectElementWithMatcher:grey_accessibilityLabel(snackbarLabel)]
+ assertWithMatcher:grey_notNil()];
+
+ // Check the snackbar in case of failed reauthentication.
+ mock_reauthentication_module.shouldSucceed = NO;
+ [[EarlGrey selectElementWithMatcher:CopyPasswordButton()]
+ performAction:grey_tap()];
+ [[GREYUIThreadExecutor sharedInstance] drainUntilIdle];
+ snackbarLabel =
+ l10n_util::GetNSString(IDS_IOS_SETTINGS_PASSWORD_WAS_NOT_COPIED_MESSAGE);
+ [[EarlGrey selectElementWithMatcher:grey_accessibilityLabel(snackbarLabel)]
+ assertWithMatcher:grey_notNil()];
+
+ [self tapBackArrow];
+ [self tapBackArrow];
+ [self tapDone];
+ [self clearPasswordStore];
+}
+
+@end
« no previous file with comments | « ios/chrome/browser/ui/settings/password_details_collection_view_controller_for_testing.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698