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

Side by Side 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, 7 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 unified diff | 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 »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2017 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/callback.h"
6 #include "base/mac/foundation_util.h"
7 #include "base/memory/ref_counted.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "base/time/time.h"
10 #include "components/autofill/core/common/password_form.h"
11 #include "components/keyed_service/core/service_access_type.h"
12 #include "components/password_manager/core/browser/password_store.h"
13 #include "components/password_manager/core/common/password_manager_pref_names.h"
14 #include "components/prefs/pref_service.h"
15 #include "ios/chrome/browser/browser_state/chrome_browser_state.h"
16 #include "ios/chrome/browser/passwords/ios_chrome_password_store_factory.h"
17 #import "ios/chrome/browser/ui/settings/password_details_collection_view_control ler_for_testing.h"
18 #import "ios/chrome/browser/ui/settings/reauthentication_module.h"
19 #import "ios/chrome/browser/ui/settings/settings_navigation_controller.h"
20 #include "ios/chrome/browser/ui/tools_menu/tools_menu_constants.h"
21 #import "ios/chrome/browser/ui/util/top_view_controller.h"
22 #include "ios/chrome/grit/ios_strings.h"
23 #import "ios/chrome/test/app/chrome_test_util.h"
24 #include "ios/chrome/test/earl_grey/accessibility_util.h"
25 #import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
26 #import "ios/chrome/test/earl_grey/chrome_earl_grey_ui.h"
27 #import "ios/chrome/test/earl_grey/chrome_matchers.h"
28 #import "ios/chrome/test/earl_grey/chrome_test_case.h"
29 #include "ui/base/l10n/l10n_util.h"
30 #include "url/gurl.h"
31
32 #if !defined(__has_feature) || !__has_feature(objc_arc)
33 #error "This file requires ARC support."
34 #endif
35
36 // This test complements
37 // password_details_collection_view_controller_unittest.mm. Very simple
38 // integration tests and features which are not currently unittestable should
39 // go here, the rest into the unittest.
40 // This test only uses the new UI which allows viewing passwords.
41 // TODO(crbug.com/159166): Remove the above sentence once the new UI is the
42 // default one.
43
44 using autofill::PasswordForm;
45 using chrome_test_util::ButtonWithAccessibilityLabel;
46 using chrome_test_util::ButtonWithAccessibilityLabelId;
47 using chrome_test_util::NavigationBarDoneButton;
48
49 namespace {
50
51 // Matcher for the Settings button in the tools menu.
52 id<GREYMatcher> SettingsButton() {
53 return grey_accessibilityID(kToolsMenuSettingsId);
54 }
55
56 // Matcher for the Save Passwords cell on the main Settings screen.
57 id<GREYMatcher> PasswordsButton() {
58 return ButtonWithAccessibilityLabelId(IDS_IOS_SAVE_PASSWORDS);
59 }
60
61 // Matcher for a password entry for |username|.
62 id<GREYMatcher> Entry(NSString* username) {
63 return ButtonWithAccessibilityLabel(username);
64 }
65
66 // Matcher for the Edit button in Save Passwords view.
67 id<GREYMatcher> EditButton() {
68 return ButtonWithAccessibilityLabelId(IDS_IOS_NAVIGATION_BAR_EDIT_BUTTON);
69 }
70
71 // Matcher for the Copy password button in Password Details view.
72 id<GREYMatcher> CopyPasswordButton() {
73 return ButtonWithAccessibilityLabelId(IDS_IOS_SETTINGS_PASSWORD_COPY_BUTTON);
74 }
75
76 } // namespace
77
78 @interface MockReauthenticationModule : NSObject<ReauthenticationProtocol>
79
80 @property(nonatomic, assign) BOOL shouldSucceed;
81
82 @end
83
84 @implementation MockReauthenticationModule
85
86 @synthesize shouldSucceed = _shouldSucceed;
87
88 - (BOOL)canAttemptReauth {
89 return YES;
90 }
91
92 - (void)attemptReauthWithLocalizedReason:(NSString*)localizedReason
93 handler:(void (^)(BOOL success))
94 showCopyPasswordsHandler {
95 showCopyPasswordsHandler(_shouldSucceed);
96 }
97
98 @end
99
100 // Various tests for the Save Passwords section of the settings.
101 @interface PasswordsSettingsTestCase : ChromeTestCase
102 @end
103
104 @implementation PasswordsSettingsTestCase
105
106 // Return pref for saving passwords back to the passed value and restores the
107 // experimental flag for viewing passwords.
108 - (void)passwordsTearDown:(BOOL)defaultPasswordManagementSetting
109 :(NSString*)oldExperiment {
110 ios::ChromeBrowserState* browserState =
111 chrome_test_util::GetOriginalBrowserState();
112 PrefService* preferences = browserState->GetPrefs();
113 preferences->SetBoolean(
114 password_manager::prefs::kPasswordManagerSavingEnabled,
115 defaultPasswordManagementSetting);
116
117 NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
118 [defaults setObject:oldExperiment forKey:@"EnableViewCopyPasswords"];
119 }
120
121 // Sets the preference to allow saving passwords and activates the flag to use
122 // the new UI for viewing passwords in settings. Also, ensures that original
123 // state is restored after the test ends.
124 - (void)scopedEnablePasswordManagementAndViewingUI {
125 // Retrieve the original preference state.
126 ios::ChromeBrowserState* browserState =
127 chrome_test_util::GetOriginalBrowserState();
128 PrefService* preferences = browserState->GetPrefs();
129 bool defaultPasswordManagerSavingPref = preferences->GetBoolean(
130 password_manager::prefs::kPasswordManagerSavingEnabled);
131
132 // Retrieve the experiment setting.
133 NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
134 NSString* oldSetting = [defaults stringForKey:@"EnableViewCopyPasswords"];
135
136 // Ensure restoring that on tear-down.
137 __weak PasswordsSettingsTestCase* weakSelf = self;
138 [self setTearDownHandler:^{
139 [weakSelf passwordsTearDown:defaultPasswordManagerSavingPref:oldSetting];
140 }];
141
142 // Enable saving.
143 preferences->SetBoolean(
144 password_manager::prefs::kPasswordManagerSavingEnabled, true);
145
146 // Enable viewing passwords in settings.
147 [defaults setObject:@"Enabled" forKey:@"EnableViewCopyPasswords"];
148 }
149
150 - (scoped_refptr<password_manager::PasswordStore>)passwordStore {
151 // ServiceAccessType governs behaviour in Incognito: only modifications with
152 // EXPLICIT_ACCESS, which correspond to user's explicit gesture, succeed.
153 // This test does not deal with Incognito, so the value of the argument is
154 // irrelevant.
155 return IOSChromePasswordStoreFactory::GetForBrowserState(
156 chrome_test_util::GetOriginalBrowserState(),
157 ServiceAccessType::EXPLICIT_ACCESS);
158 }
159
160 // Saves an example form in the store.
161 - (void)saveExamplePasswordForm {
162 PasswordForm example;
163 example.username_value = base::ASCIIToUTF16("user");
164 example.password_value = base::ASCIIToUTF16("password");
165 example.origin = GURL("https://example.com");
166 example.signon_realm = example.origin.spec();
167
168 [self passwordStore]->AddLogin(example);
169 // Allow the PasswordStore to process this on the DB thread.
170 [[GREYUIThreadExecutor sharedInstance] drainUntilIdle];
171 }
172
173 // Removes all credentials stored.
174 - (void)clearPasswordStore {
175 [self passwordStore]->RemoveLoginsCreatedBetween(base::Time(), base::Time(),
176 base::Closure());
177 // Allow the PasswordStore to process this on the DB thread.
178 [[GREYUIThreadExecutor sharedInstance] drainUntilIdle];
179 }
180
181 // Opens the passwords page from the NTP. It requires no menus to be open.
182 - (void)openPasswordSettings {
183 // Open settings and verify data in the view controller.
184 [ChromeEarlGreyUI openToolsMenu];
185 [[EarlGrey selectElementWithMatcher:SettingsButton()]
186 performAction:grey_tap()];
187 [[EarlGrey selectElementWithMatcher:PasswordsButton()]
188 performAction:grey_tap()];
189
190 // Wait for UI components to finish loading.
191 [[GREYUIThreadExecutor sharedInstance] drainUntilIdle];
192 }
193
194 // Tap back arrow, to get one level higher in settings.
195 - (void)tapBackArrow {
196 [[EarlGrey
197 selectElementWithMatcher:grey_allOf(
198 grey_accessibilityID(@"ic_arrow_back"),
199 grey_accessibilityTrait(
200 UIAccessibilityTraitButton),
201 nil)] performAction:grey_tap()];
202
203 // Wait for UI components to finish loading.
204 [[GREYUIThreadExecutor sharedInstance] drainUntilIdle];
205 }
206
207 // Tap Edit in any settings view.
208 - (void)tapEdit {
209 [[EarlGrey selectElementWithMatcher:EditButton()] performAction:grey_tap()];
210
211 // Wait for UI components to finish loading.
212 [[GREYUIThreadExecutor sharedInstance] drainUntilIdle];
213 }
214
215 // Tap Done in any settings view.
216 - (void)tapDone {
217 [[EarlGrey selectElementWithMatcher:NavigationBarDoneButton()]
218 performAction:grey_tap()];
219
220 // Wait for UI components to finish loading.
221 [[GREYUIThreadExecutor sharedInstance] drainUntilIdle];
222 }
223
224 // Verifies the UI elements are accessible on the Passwords page.
225 // TODO(crbug.com/159166): This differs from testAccessibilityOnPasswords in
226 // settings_egtest.mm in that here this tests the new UI (for viewing
227 // passwords), where in settings_egtest.mm the default (old) UI is tested.
228 // Once the new is the default, just remove the test in settings_egtest.mm.
229 - (void)testAccessibilityOnPasswords {
230 [self scopedEnablePasswordManagementAndViewingUI];
231
232 // Saving a form is needed for using the "password details" view.
233 [self saveExamplePasswordForm];
234
235 [self openPasswordSettings];
236 chrome_test_util::VerifyAccessibilityForCurrentScreen();
237
238 [self tapEdit];
239 chrome_test_util::VerifyAccessibilityForCurrentScreen();
240 [self tapDone];
241
242 // Inspect "password details" view.
243 [[EarlGrey selectElementWithMatcher:Entry(@"https://example.com, user")]
244 performAction:grey_tap()];
245 chrome_test_util::VerifyAccessibilityForCurrentScreen();
246 [self tapBackArrow];
247
248 [self tapBackArrow];
249 [self tapDone];
250 [self clearPasswordStore];
251 }
252
253 // Checks that attempts to copy a password provide appropriate feedback,
254 // both when reauthentication succeeds and when it fails.
255 - (void)testCopyPasswordToast {
256 [self scopedEnablePasswordManagementAndViewingUI];
257
258 // Saving a form is needed for using the "password details" view.
259 [self saveExamplePasswordForm];
260
261 [self openPasswordSettings];
262
263 [[EarlGrey selectElementWithMatcher:Entry(@"https://example.com, user")]
264 performAction:grey_tap()];
265
266 // Get the PasswordDetailsCollectionViewController and replace the
267 // reauthentication module with a fake one to avoid being blocked with a
268 // reauth prompt.
269 MockReauthenticationModule* mock_reauthentication_module =
270 [[MockReauthenticationModule alloc] init];
271 SettingsNavigationController* settings_navigation_controller =
272 base::mac::ObjCCastStrict<SettingsNavigationController>(
273 top_view_controller::TopPresentedViewController());
274 PasswordDetailsCollectionViewController*
275 password_details_collection_view_controller =
276 base::mac::ObjCCastStrict<PasswordDetailsCollectionViewController>(
277 settings_navigation_controller.topViewController);
278 [password_details_collection_view_controller
279 setReauthenticationModule:mock_reauthentication_module];
280
281 // Check the snackbar in case of successful reauthentication.
282 mock_reauthentication_module.shouldSucceed = YES;
283 [[EarlGrey selectElementWithMatcher:CopyPasswordButton()]
284 performAction:grey_tap()];
285 [[GREYUIThreadExecutor sharedInstance] drainUntilIdle];
286 NSString* snackbarLabel =
287 l10n_util::GetNSString(IDS_IOS_SETTINGS_PASSWORD_WAS_COPIED_MESSAGE);
288 [[EarlGrey selectElementWithMatcher:grey_accessibilityLabel(snackbarLabel)]
289 assertWithMatcher:grey_notNil()];
290
291 // Check the snackbar in case of failed reauthentication.
292 mock_reauthentication_module.shouldSucceed = NO;
293 [[EarlGrey selectElementWithMatcher:CopyPasswordButton()]
294 performAction:grey_tap()];
295 [[GREYUIThreadExecutor sharedInstance] drainUntilIdle];
296 snackbarLabel =
297 l10n_util::GetNSString(IDS_IOS_SETTINGS_PASSWORD_WAS_NOT_COPIED_MESSAGE);
298 [[EarlGrey selectElementWithMatcher:grey_accessibilityLabel(snackbarLabel)]
299 assertWithMatcher:grey_notNil()];
300
301 [self tapBackArrow];
302 [self tapBackArrow];
303 [self tapDone];
304 [self clearPasswordStore];
305 }
306
307 @end
OLDNEW
« 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