Commit bd7b15d0 authored by Viktor Semeniuk's avatar Viktor Semeniuk Committed by Commit Bot

Reland "[iOS][Password Check] Rewriting Passwords test with new details screen"

This is a reland of 7b693e30

Fixed failing tests:
testStoredEntriesAlwaysShown
testCancelDeletionInDetailView
testSearchPasswords

Original change's description:
> [iOS][Password Check] Rewriting Passwords test with new details screen
>
> This change rewrites Passwords tests with new Password Details screen.
> Obsolete tests are deleted. Fixed flakiness for
> testSearchAndDeleteAllPasswords.
>
> Bug: 1075494, 1129441
> Change-Id: Id6d44a2f77c20edb1788f1d3dcaa04e9e645cdb5
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2418853
> Commit-Queue: Viktor Semeniuk <vsemeniuk@google.com>
> Reviewed-by: Gauthier Ambard <gambard@chromium.org>
> Reviewed-by: Eugene But <eugenebut@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#811668}

Bug: 1075494
Bug: 1129441
Change-Id: Ibfe28ea3ee68f9fb69fcb50085da9c1c558f86d2
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2438380
Commit-Queue: Viktor Semeniuk <vsemeniuk@google.com>
Reviewed-by: default avatarGauthier Ambard <gambard@chromium.org>
Reviewed-by: default avatarEugene But <eugenebut@chromium.org>
Cr-Commit-Position: refs/heads/master@{#813660}
parent c252b4af
......@@ -268,6 +268,9 @@ BOOL WaitForJavaScriptCondition(NSString* java_script_condition) {
// Verify keyboard is shown without the password controller.
GREYAssertTrue([ChromeEarlGrey isKeyboardShownWithError:nil],
@"Keyboard Should be Shown");
[[EarlGrey
selectElementWithMatcher:chrome_test_util::NavigationBarCancelButton()]
performAction:grey_tap()];
[[EarlGrey selectElementWithMatcher:ManualFallbackPasswordTableViewMatcher()]
assertWithMatcher:grey_notVisible()];
}
......
......@@ -233,6 +233,7 @@ source_set("eg2_tests") {
":password_constants",
"//base:base",
"//base/test:test_support",
"//components/password_manager/core/common",
"//components/strings:components_strings_grit",
"//ios/chrome/app/strings:ios_strings_grit",
"//ios/chrome/browser/ui/settings:settings_root_constants",
......
......@@ -9,4 +9,4 @@
#endif
NSString* const kPasswordDetailsViewControllerId =
@"kPasswordDetailsViewControllerId";
@"PasswordDetailsTableViewId";
......@@ -210,6 +210,8 @@ typedef NS_ENUM(NSInteger, ReauthenticationReason) {
item.identifyingIcon = [[UIImage imageNamed:image]
imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
item.identifyingIconEnabled = YES;
item.identifyingIconAccessibilityLabel =
l10n_util::GetNSString(IDS_IOS_SETTINGS_PASSWORD_SHOW_BUTTON);
}
return item;
}
......
......@@ -8,7 +8,9 @@
#include "base/callback.h"
#include "base/ios/ios_util.h"
#include "base/test/scoped_feature_list.h"
#include "base/time/time.h"
#include "components/password_manager/core/common/password_manager_features.h"
#include "components/strings/grit/components_strings.h"
#include "ios/chrome/browser/ui/settings/password/passwords_settings_app_interface.h"
#import "ios/chrome/browser/ui/settings/password/passwords_table_view_constants.h"
......@@ -46,6 +48,7 @@ GREY_STUB_CLASS_IN_APP_MAIN_QUEUE(PasswordSettingsAppInterface);
// go here, the rest into the unittest.
using chrome_test_util::ButtonWithAccessibilityLabel;
using chrome_test_util::ButtonWithAccessibilityLabelId;
using chrome_test_util::NavigationBarDoneButton;
using chrome_test_util::SettingsDoneButton;
using chrome_test_util::SettingsMenuBackButton;
......@@ -58,6 +61,11 @@ namespace {
// it too high could result in scrolling way past the searched element.
constexpr int kScrollAmount = 150;
NSString* GetTextFieldForID(int category_id) {
return [NSString
stringWithFormat:@"%@_textField", l10n_util::GetNSString(category_id)];
}
// Returns the GREYElementInteraction* for the item on the password list with
// the given |matcher|. It scrolls in |direction| if necessary to ensure that
// the matched item is interactable.
......@@ -84,20 +92,10 @@ GREYElementInteraction* GetInteractionForPasswordDetailItem(
id<GREYMatcher> matcher) {
return [[EarlGrey
selectElementWithMatcher:grey_allOf(matcher, grey_interactable(), nil)]
usingSearchAction:grey_scrollInDirection(kGREYDirectionDown,
kScrollAmount)
usingSearchAction:grey_scrollToContentEdge(kGREYContentEdgeTop)
onElementWithMatcher:grey_accessibilityID(kPasswordDetailsTableViewId)];
}
// Returns the GREYElementInteraction* for the item on the deletion alert
// identified with the given |matcher|.
GREYElementInteraction* GetInteractionForPasswordDetailDeletionAlert(
id<GREYMatcher> matcher) {
return [[EarlGrey
selectElementWithMatcher:grey_allOf(matcher, grey_interactable(), nil)]
inRoot:grey_accessibilityID(kPasswordDetailsDeletionAlertViewId)];
}
// Returns the GREYElementInteraction* for the item on the deletion alert
// identified with the given |matcher|.
GREYElementInteraction* GetInteractionForPasswordsExportConfirmAlert(
......@@ -120,34 +118,6 @@ id<GREYMatcher> SearchTextField() {
return grey_accessibilityID(kPasswordsSearchBarId);
}
id<GREYMatcher> SiteHeader() {
return grey_allOf(
grey_accessibilityLabel(
l10n_util::GetNSString(IDS_IOS_SHOW_PASSWORD_VIEW_SITE)),
grey_accessibilityTrait(UIAccessibilityTraitHeader), nullptr);
}
id<GREYMatcher> UsernameHeader() {
return grey_allOf(
grey_accessibilityLabel(
l10n_util::GetNSString(IDS_IOS_SHOW_PASSWORD_VIEW_USERNAME)),
grey_accessibilityTrait(UIAccessibilityTraitHeader), nullptr);
}
id<GREYMatcher> PasswordHeader() {
return grey_allOf(
grey_accessibilityLabel(
l10n_util::GetNSString(IDS_IOS_SHOW_PASSWORD_VIEW_PASSWORD)),
grey_accessibilityTrait(UIAccessibilityTraitHeader), nullptr);
}
id<GREYMatcher> FederationHeader() {
return grey_allOf(
grey_accessibilityLabel(
l10n_util::GetNSString(IDS_IOS_SHOW_PASSWORD_VIEW_FEDERATION)),
grey_accessibilityTrait(UIAccessibilityTraitHeader), nullptr);
}
GREYLayoutConstraint* Below() {
return [GREYLayoutConstraint
layoutConstraintWithAttribute:kGREYLayoutAttributeTop
......@@ -158,39 +128,24 @@ GREYLayoutConstraint* Below() {
}
// Matcher for the Copy site button in Password Details view.
id<GREYMatcher> CopySiteButton() {
id<GREYMatcher> PasswordDetailWebsite() {
return grey_allOf(
ButtonWithAccessibilityLabel(
[NSString stringWithFormat:@"%@: %@",
l10n_util::GetNSString(
IDS_IOS_SHOW_PASSWORD_VIEW_SITE),
l10n_util::GetNSString(
IDS_IOS_SETTINGS_SITE_COPY_BUTTON)]),
grey_interactable(), nullptr);
grey_accessibilityID(GetTextFieldForID(IDS_IOS_SHOW_PASSWORD_VIEW_SITE)),
grey_kindOfClassName(@"UITextField"), nil);
}
// Matcher for the Copy username button in Password Details view.
id<GREYMatcher> CopyUsernameButton() {
return grey_allOf(
ButtonWithAccessibilityLabel([NSString
stringWithFormat:@"%@: %@",
l10n_util::GetNSString(
IDS_IOS_SHOW_PASSWORD_VIEW_USERNAME),
l10n_util::GetNSString(
IDS_IOS_SETTINGS_USERNAME_COPY_BUTTON)]),
grey_interactable(), nullptr);
id<GREYMatcher> PasswordDetailUsername() {
return grey_allOf(grey_accessibilityID(
GetTextFieldForID(IDS_IOS_SHOW_PASSWORD_VIEW_USERNAME)),
grey_kindOfClassName(@"UITextField"), nil);
}
// Matcher for the Copy password button in Password Details view.
id<GREYMatcher> CopyPasswordButton() {
return grey_allOf(
ButtonWithAccessibilityLabel([NSString
stringWithFormat:@"%@: %@",
l10n_util::GetNSString(
IDS_IOS_SHOW_PASSWORD_VIEW_PASSWORD),
l10n_util::GetNSString(
IDS_IOS_SETTINGS_PASSWORD_COPY_BUTTON)]),
grey_interactable(), nullptr);
id<GREYMatcher> PasswordDetailPassword() {
return grey_allOf(grey_accessibilityID(
GetTextFieldForID(IDS_IOS_SHOW_PASSWORD_VIEW_PASSWORD)),
grey_kindOfClassName(@"UITextField"), nil);
}
// Matcher for the Show password button in Password Details view.
......@@ -202,8 +157,16 @@ id<GREYMatcher> ShowPasswordButton() {
// Matcher for the Delete button in Password Details view.
id<GREYMatcher> DeleteButton() {
return grey_allOf(
ButtonWithAccessibilityLabelId(IDS_IOS_SETTINGS_TOOLBAR_DELETE),
grey_not(grey_accessibilityTrait(UIAccessibilityTraitNotEnabled)),
nullptr);
}
// Matcher for the Delete button in Confirmation Alert for password deletion.
id<GREYMatcher> DeleteConfirmationButton() {
return grey_allOf(ButtonWithAccessibilityLabel(l10n_util::GetNSString(
IDS_IOS_SETTINGS_PASSWORD_DELETE_BUTTON)),
IDS_IOS_CONFIRM_PASSWORD_DELETION)),
grey_interactable(), nullptr);
}
......@@ -300,10 +263,24 @@ void TapEdit() {
performAction:grey_tap()];
}
void CopyPasswordDetailWithID(int detail_id) {
[GetInteractionForPasswordDetailItem(grey_allOf(
grey_accessibilityID(GetTextFieldForID(detail_id)),
grey_kindOfClassName(@"UITextField"), nil)) performAction:grey_tap()];
// Tap the context menu item for copying.
[[EarlGrey selectElementWithMatcher:PopUpMenuItemWithLabel(
IDS_IOS_SETTINGS_SITE_COPY_MENU_ITEM)]
performAction:grey_tap()];
}
} // namespace
// Various tests for the Save Passwords section of the settings.
@interface PasswordsSettingsTestCase : ChromeTestCase
@interface PasswordsSettingsTestCase : ChromeTestCase {
base::test::ScopedFeatureList _featureList;
}
@end
@implementation PasswordsSettingsTestCase
......@@ -319,6 +296,18 @@ void TapEdit() {
[super tearDown];
}
- (AppLaunchConfiguration)appConfigurationForTestCase {
AppLaunchConfiguration config;
// Password Check Feature is enabled for all tests. This is done because it
// is inefficient to use ensureAppLaunchedWithConfiguration for each test.
// This should be removed once test config is modified.
// TODO(crbug.com/1075494): Remove this once feature is launched.
config.features_enabled.push_back(password_manager::features::kPasswordCheck);
return config;
}
// Verifies the UI elements are accessible on the Passwords page.
- (void)testAccessibilityOnPasswords {
// Saving a form is needed for using the "password details" view.
......@@ -356,13 +345,12 @@ void TapEdit() {
[GetInteractionForPasswordEntry(@"example.com, concrete username")
performAction:grey_tap()];
// Check the snackbar in case of successful reauthentication.
[PasswordSettingsAppInterface setUpMockReauthenticationModule];
[PasswordSettingsAppInterface mockReauthenticationModuleExpectedResult:
ReauthenticationResult::kSuccess];
// Check the snackbar in case of successful reauthentication.
[GetInteractionForPasswordDetailItem(CopyPasswordButton())
performAction:grey_tap()];
CopyPasswordDetailWithID(IDS_IOS_SHOW_PASSWORD_VIEW_PASSWORD);
NSString* snackbarLabel =
l10n_util::GetNSString(IDS_IOS_SETTINGS_PASSWORD_WAS_COPIED_MESSAGE);
......@@ -373,8 +361,8 @@ void TapEdit() {
// Check the snackbar in case of failed reauthentication.
[PasswordSettingsAppInterface mockReauthenticationModuleExpectedResult:
ReauthenticationResult::kFailure];
[GetInteractionForPasswordDetailItem(CopyPasswordButton())
performAction:grey_tap()];
CopyPasswordDetailWithID(IDS_IOS_SHOW_PASSWORD_VIEW_PASSWORD);
snackbarLabel =
l10n_util::GetNSString(IDS_IOS_SETTINGS_PASSWORD_WAS_NOT_COPIED_MESSAGE);
......@@ -392,7 +380,7 @@ void TapEdit() {
// Checks that an attempt to show a password provides an appropriate feedback
// when reauthentication succeeds.
- (void)testShowPasswordToastAuthSucceeded {
- (void)testShowPasswordAuthSucceeded {
// Saving a form is needed for using the "password details" view.
SaveExamplePasswordForm();
......@@ -405,14 +393,12 @@ void TapEdit() {
[PasswordSettingsAppInterface mockReauthenticationModuleExpectedResult:
ReauthenticationResult::kSuccess];
// Check the snackbar in case of successful reauthentication.
[GetInteractionForPasswordDetailItem(ShowPasswordButton())
performAction:grey_tap()];
// Check that the password is displayed.
[[EarlGrey
selectElementWithMatcher:grey_accessibilityLabel(@"concrete password")]
assertWithMatcher:grey_sufficientlyVisible()];
// Ensure that password is shown.
[GetInteractionForPasswordDetailItem(grey_textFieldValue(
@"concrete password")) assertWithMatcher:grey_notNil()];
[[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()]
performAction:grey_tap()];
......@@ -442,8 +428,7 @@ void TapEdit() {
performAction:grey_tap()];
// Check that the password is not displayed.
[[EarlGrey
selectElementWithMatcher:grey_accessibilityLabel(@"concrete password")]
[[EarlGrey selectElementWithMatcher:grey_textFieldValue(@"concrete password")]
assertWithMatcher:grey_nil()];
// Note that there is supposed to be no message (cf. the case of the copy
......@@ -468,8 +453,7 @@ void TapEdit() {
[GetInteractionForPasswordEntry(@"example.com, concrete username")
performAction:grey_tap()];
[GetInteractionForPasswordDetailItem(CopyUsernameButton())
performAction:grey_tap()];
CopyPasswordDetailWithID(IDS_IOS_SHOW_PASSWORD_VIEW_USERNAME);
NSString* snackbarLabel =
l10n_util::GetNSString(IDS_IOS_SETTINGS_USERNAME_WAS_COPIED_MESSAGE);
// The tap checks the existence of the snackbar and also closes it.
......@@ -494,8 +478,8 @@ void TapEdit() {
[GetInteractionForPasswordEntry(@"example.com, concrete username")
performAction:grey_tap()];
[GetInteractionForPasswordDetailItem(CopySiteButton())
performAction:grey_tap()];
CopyPasswordDetailWithID(IDS_IOS_SHOW_PASSWORD_VIEW_SITE);
NSString* snackbarLabel =
l10n_util::GetNSString(IDS_IOS_SETTINGS_SITE_WAS_COPIED_MESSAGE);
// The tap checks the existence of the snackbar and also closes it.
......@@ -521,11 +505,16 @@ void TapEdit() {
[GetInteractionForPasswordEntry(@"example.com, concrete username")
performAction:grey_tap()];
[GetInteractionForPasswordDetailItem(DeleteButton())
[PasswordSettingsAppInterface setUpMockReauthenticationModule];
[PasswordSettingsAppInterface mockReauthenticationModuleExpectedResult:
ReauthenticationResult::kSuccess];
[[EarlGrey selectElementWithMatcher:NavigationBarEditButton()]
performAction:grey_tap()];
[GetInteractionForPasswordDetailDeletionAlert(ButtonWithAccessibilityLabel(
l10n_util::GetNSString(IDS_IOS_CONFIRM_PASSWORD_DELETION)))
[[EarlGrey selectElementWithMatcher:DeleteButton()] performAction:grey_tap()];
[[EarlGrey selectElementWithMatcher:DeleteConfirmationButton()]
performAction:grey_tap()];
// Wait until the alert and the detail view are dismissed.
......@@ -576,11 +565,16 @@ void TapEdit() {
[GetInteractionForPasswordEntry(@"example.com, concrete username")
performAction:grey_tap()];
[GetInteractionForPasswordDetailItem(DeleteButton())
[PasswordSettingsAppInterface setUpMockReauthenticationModule];
[PasswordSettingsAppInterface mockReauthenticationModuleExpectedResult:
ReauthenticationResult::kSuccess];
[[EarlGrey selectElementWithMatcher:NavigationBarEditButton()]
performAction:grey_tap()];
[GetInteractionForPasswordDetailDeletionAlert(ButtonWithAccessibilityLabel(
l10n_util::GetNSString(IDS_IOS_CONFIRM_PASSWORD_DELETION)))
[[EarlGrey selectElementWithMatcher:DeleteButton()] performAction:grey_tap()];
[[EarlGrey selectElementWithMatcher:DeleteConfirmationButton()]
performAction:grey_tap()];
// Wait until the alert and the detail view are dismissed.
......@@ -623,11 +617,12 @@ void TapEdit() {
[GetInteractionForPasswordEntry(@"blocked.com") performAction:grey_tap()];
[GetInteractionForPasswordDetailItem(DeleteButton())
[[EarlGrey selectElementWithMatcher:NavigationBarEditButton()]
performAction:grey_tap()];
[GetInteractionForPasswordDetailDeletionAlert(ButtonWithAccessibilityLabel(
l10n_util::GetNSString(IDS_IOS_CONFIRM_PASSWORD_DELETION)))
[[EarlGrey selectElementWithMatcher:DeleteButton()] performAction:grey_tap()];
[[EarlGrey selectElementWithMatcher:DeleteConfirmationButton()]
performAction:grey_tap()];
// Wait until the alert and the detail view are dismissed.
......@@ -671,11 +666,17 @@ void TapEdit() {
[GetInteractionForPasswordEntry(@"example.com, concrete username")
performAction:grey_tap()];
[GetInteractionForPasswordDetailItem(DeleteButton())
[PasswordSettingsAppInterface setUpMockReauthenticationModule];
[PasswordSettingsAppInterface mockReauthenticationModuleExpectedResult:
ReauthenticationResult::kSuccess];
[[EarlGrey selectElementWithMatcher:NavigationBarEditButton()]
performAction:grey_tap()];
[[EarlGrey selectElementWithMatcher:DeleteButton()] performAction:grey_tap()];
// Tap the alert's Cancel button to cancel.
if (base::ios::IsRunningOnOrLater(13, 2, 0) && [ChromeEarlGrey isIPadIdiom]) {
if ([ChromeEarlGrey isIPadIdiom]) {
[[EarlGrey selectElementWithMatcher:grey_accessibilityID(
kPasswordDetailsTableViewId)]
performAction:grey_tap()];
......@@ -689,10 +690,10 @@ void TapEdit() {
performAction:grey_tap()];
}
// Check that the current view is still the detail view, by locating the Copy
// button.
[[EarlGrey selectElementWithMatcher:CopyPasswordButton()]
assertWithMatcher:grey_sufficientlyVisible()];
// Check that the current view is still the detail view.
[[EarlGrey selectElementWithMatcher:grey_accessibilityID(
kPasswordDetailsTableViewId)]
assertWithMatcher:grey_notNil()];
// Verify that the deletion did not happen.
GREYAssertEqual(1u, [PasswordSettingsAppInterface passwordStoreResultsCount],
......@@ -732,7 +733,7 @@ void TapEdit() {
// Check that the current view is not the detail view, by failing to locate
// the Copy button.
[[EarlGrey selectElementWithMatcher:CopyPasswordButton()]
[[EarlGrey selectElementWithMatcher:PasswordDetailPassword()]
assertWithMatcher:grey_nil()];
[[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()]
......@@ -741,77 +742,6 @@ void TapEdit() {
performAction:grey_tap()];
}
// Checks that attempts to copy the site via the context menu item provide an
// appropriate feedback.
- (void)testCopySiteMenuItem {
// Saving a form is needed for using the "password details" view.
SaveExamplePasswordForm();
OpenPasswordSettings();
[GetInteractionForPasswordEntry(@"example.com, concrete username")
performAction:grey_tap()];
// Tap the site cell to display the context menu.
[GetInteractionForPasswordDetailItem(grey_accessibilityLabel(
@"https://example.com/")) performAction:grey_tap()];
// Tap the context menu item for copying.
[[EarlGrey selectElementWithMatcher:PopUpMenuItemWithLabel(
IDS_IOS_SETTINGS_SITE_COPY_MENU_ITEM)]
performAction:grey_tap()];
// Check the snackbar.
NSString* snackbarLabel =
l10n_util::GetNSString(IDS_IOS_SETTINGS_SITE_WAS_COPIED_MESSAGE);
// The tap checks the existence of the snackbar and also closes it.
[[EarlGrey selectElementWithMatcher:grey_accessibilityLabel(snackbarLabel)]
performAction:grey_tap()];
[[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()]
performAction:grey_tap()];
[[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()]
performAction:grey_tap()];
[[EarlGrey selectElementWithMatcher:SettingsDoneButton()]
performAction:grey_tap()];
}
// Checks that attempts to copy the username via the context menu item provide
// an appropriate feedback.
- (void)testCopyUsernameMenuItem {
// Saving a form is needed for using the "password details" view.
SaveExamplePasswordForm();
OpenPasswordSettings();
[GetInteractionForPasswordEntry(@"example.com, concrete username")
performAction:grey_tap()];
// Tap the username cell to display the context menu.
[GetInteractionForPasswordDetailItem(
grey_accessibilityLabel(@"concrete username")) performAction:grey_tap()];
// Tap the context menu item for copying.
[[EarlGrey
selectElementWithMatcher:PopUpMenuItemWithLabel(
IDS_IOS_SETTINGS_USERNAME_COPY_MENU_ITEM)]
performAction:grey_tap()];
// Check the snackbar.
NSString* snackbarLabel =
l10n_util::GetNSString(IDS_IOS_SETTINGS_USERNAME_WAS_COPIED_MESSAGE);
// The tap checks the existence of the snackbar and also closes it.
[[EarlGrey selectElementWithMatcher:grey_accessibilityLabel(snackbarLabel)]
performAction:grey_tap()];
[[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()]
performAction:grey_tap()];
[[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()]
performAction:grey_tap()];
[[EarlGrey selectElementWithMatcher:SettingsDoneButton()]
performAction:grey_tap()];
}
// Checks that attempts to copy the password via the context menu item provide
// an appropriate feedback.
- (void)testCopyPasswordMenuItem {
......@@ -860,62 +790,6 @@ void TapEdit() {
performAction:grey_tap()];
}
// Checks that attempts to show and hide the password via the context menu item
// provide an appropriate feedback.
- (void)testShowHidePasswordMenuItem {
if (![ChromeEarlGrey isIPadIdiom]) {
// TODO(crbug.com/1109644): Enable the test on iPhone once the bug is fixed.
EARL_GREY_TEST_DISABLED(@"Disabled for iPhone.");
}
// Saving a form is needed for using the "password details" view.
SaveExamplePasswordForm();
OpenPasswordSettings();
[GetInteractionForPasswordEntry(@"example.com, concrete username")
performAction:grey_tap()];
// Tap the password cell to display the context menu.
[GetInteractionForPasswordDetailItem(grey_text(kMaskedPassword))
performAction:grey_tap()];
// Make sure to capture the reauthentication module in a variable until the
// end of the test, otherwise it might get deleted too soon and break the
// functionality of copying and viewing passwords.
[PasswordSettingsAppInterface setUpMockReauthenticationModule];
[PasswordSettingsAppInterface mockReauthenticationModuleExpectedResult:
ReauthenticationResult::kSuccess];
// Tap the context menu item for showing.
[[EarlGrey
selectElementWithMatcher:PopUpMenuItemWithLabel(
IDS_IOS_SETTINGS_PASSWORD_SHOW_MENU_ITEM)]
performAction:grey_tap()];
// Tap the password cell to display the context menu again, and to check that
// the password was unmasked.
[GetInteractionForPasswordDetailItem(
grey_accessibilityLabel(@"concrete password")) performAction:grey_tap()];
// Tap the context menu item for hiding.
[[EarlGrey
selectElementWithMatcher:PopUpMenuItemWithLabel(
IDS_IOS_SETTINGS_PASSWORD_HIDE_MENU_ITEM)]
performAction:grey_tap()];
// Check that the password is masked again.
[GetInteractionForPasswordDetailItem(grey_text(kMaskedPassword))
performAction:grey_tap()];
[[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()]
performAction:grey_tap()];
[[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()]
performAction:grey_tap()];
[[EarlGrey selectElementWithMatcher:SettingsDoneButton()]
performAction:grey_tap()];
}
// Checks that federated credentials have no password but show the federation.
- (void)testFederated {
GREYAssert([PasswordSettingsAppInterface
......@@ -929,24 +803,26 @@ void TapEdit() {
[GetInteractionForPasswordEntry(@"example.com, federated username")
performAction:grey_tap()];
// Check that the Site, Username, Federation and Delete Saved Password
// sections are there.
[GetInteractionForPasswordDetailItem(SiteHeader())
assertWithMatcher:grey_notNil()];
[GetInteractionForPasswordDetailItem(UsernameHeader())
assertWithMatcher:grey_notNil()];
// For federation check both the section header and content.
[GetInteractionForPasswordDetailItem(FederationHeader())
assertWithMatcher:grey_notNil()];
[GetInteractionForPasswordDetailItem(grey_text(@"famous.provider.net"))
assertWithMatcher:grey_notNil()];
[GetInteractionForPasswordDetailItem(DeleteButton())
assertWithMatcher:grey_notNil()];
// Check that the Site and Username are present and correct.
[[EarlGrey selectElementWithMatcher:PasswordDetailWebsite()]
assertWithMatcher:grey_textFieldValue(@"https://example.com/")];
[[EarlGrey selectElementWithMatcher:PasswordDetailUsername()]
assertWithMatcher:grey_textFieldValue(@"federated username")];
// Check that the password is not present.
[GetInteractionForPasswordDetailItem(PasswordHeader())
[[EarlGrey selectElementWithMatcher:PasswordDetailPassword()]
assertWithMatcher:grey_nil()];
// Check that editing doesn't require reauth.
[PasswordSettingsAppInterface setUpMockReauthenticationModule];
[PasswordSettingsAppInterface mockReauthenticationModuleExpectedResult:
ReauthenticationResult::kFailure];
[[EarlGrey selectElementWithMatcher:NavigationBarEditButton()]
performAction:grey_tap()];
// Ensure delete button is present after entering editing mode.
[[EarlGrey selectElementWithMatcher:DeleteButton()]
assertWithMatcher:grey_notNil()];
[[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()]
performAction:grey_tap()];
[[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()]
......@@ -965,44 +841,17 @@ void TapEdit() {
[GetInteractionForPasswordEntry(@"example.com, concrete username")
performAction:grey_tap()];
[GetInteractionForPasswordDetailItem(SiteHeader())
assertWithMatcher:grey_notNil()];
id<GREYMatcher> siteCell = grey_accessibilityLabel(@"https://example.com/");
[GetInteractionForPasswordDetailItem(siteCell)
assertWithMatcher:grey_layout(@[ Below() ], SiteHeader())];
[GetInteractionForPasswordDetailItem(CopySiteButton())
assertWithMatcher:grey_layout(@[ Below() ], siteCell)];
[GetInteractionForPasswordDetailItem(UsernameHeader())
assertWithMatcher:grey_layout(@[ Below() ], CopySiteButton())];
id<GREYMatcher> usernameCell = grey_accessibilityLabel(@"concrete username");
[GetInteractionForPasswordDetailItem(usernameCell)
assertWithMatcher:grey_layout(@[ Below() ], UsernameHeader())];
[GetInteractionForPasswordDetailItem(CopyUsernameButton())
assertWithMatcher:grey_layout(@[ Below() ], usernameCell)];
id<GREYMatcher> passwordHeader =
grey_allOf(PasswordHeader(),
grey_kindOfClassName(@"UITableViewHeaderFooterView"), nil);
[GetInteractionForPasswordDetailItem(passwordHeader)
assertWithMatcher:grey_layout(@[ Below() ], CopyUsernameButton())];
id<GREYMatcher> passwordCell = grey_accessibilityLabel(
l10n_util::GetNSString(IDS_IOS_SETTINGS_PASSWORD_HIDDEN_LABEL));
[GetInteractionForPasswordDetailItem(passwordCell)
assertWithMatcher:grey_layout(@[ Below() ], passwordHeader)];
[GetInteractionForPasswordDetailItem(CopyPasswordButton())
assertWithMatcher:grey_layout(@[ Below() ], passwordCell)];
[GetInteractionForPasswordDetailItem(ShowPasswordButton())
assertWithMatcher:grey_layout(@[ Below() ], CopyPasswordButton())];
[GetInteractionForPasswordDetailItem(DeleteButton())
assertWithMatcher:grey_layout(@[ Below() ], ShowPasswordButton())];
[[EarlGrey selectElementWithMatcher:PasswordDetailWebsite()]
assertWithMatcher:grey_textFieldValue(@"https://example.com/")];
[[EarlGrey selectElementWithMatcher:PasswordDetailUsername()]
assertWithMatcher:grey_textFieldValue(@"concrete username")];
[[EarlGrey selectElementWithMatcher:PasswordDetailPassword()]
assertWithMatcher:grey_textFieldValue(kMaskedPassword)];
// Check that the federation block is not present. Match directly to also
// catch the case where the block would be present but not currently visible
// due to the scrolling state.
[[EarlGrey selectElementWithMatcher:FederationHeader()]
assertWithMatcher:grey_nil()];
[GetInteractionForPasswordDetailItem(PasswordDetailPassword())
assertWithMatcher:grey_layout(@[ Below() ], PasswordDetailUsername())];
[GetInteractionForPasswordDetailItem(PasswordDetailUsername())
assertWithMatcher:grey_layout(@[ Below() ], PasswordDetailWebsite())];
[[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()]
performAction:grey_tap()];
......@@ -1023,25 +872,11 @@ void TapEdit() {
[GetInteractionForPasswordEntry(@"example.com") performAction:grey_tap()];
[GetInteractionForPasswordDetailItem(SiteHeader())
assertWithMatcher:grey_notNil()];
id<GREYMatcher> siteCell = grey_accessibilityLabel(@"https://example.com/");
[GetInteractionForPasswordDetailItem(siteCell)
assertWithMatcher:grey_layout(@[ Below() ], SiteHeader())];
[GetInteractionForPasswordDetailItem(CopySiteButton())
assertWithMatcher:grey_layout(@[ Below() ], siteCell)];
[GetInteractionForPasswordDetailItem(DeleteButton())
assertWithMatcher:grey_layout(@[ Below() ], CopySiteButton())];
// Check that the other blocks are not present. Match directly to also catch
// the case where those blocks would be present but not currently visible due
// to the scrolling state.
[[EarlGrey selectElementWithMatcher:UsernameHeader()]
assertWithMatcher:grey_nil()];
[[EarlGrey selectElementWithMatcher:PasswordHeader()]
[[EarlGrey selectElementWithMatcher:PasswordDetailWebsite()]
assertWithMatcher:grey_textFieldValue(@"https://example.com/")];
[[EarlGrey selectElementWithMatcher:PasswordDetailUsername()]
assertWithMatcher:grey_nil()];
[[EarlGrey selectElementWithMatcher:FederationHeader()]
[[EarlGrey selectElementWithMatcher:PasswordDetailPassword()]
assertWithMatcher:grey_nil()];
[[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()]
......@@ -1066,37 +901,16 @@ void TapEdit() {
[GetInteractionForPasswordEntry(@"example.com, federated username")
performAction:grey_tap()];
[GetInteractionForPasswordDetailItem(SiteHeader())
assertWithMatcher:grey_notNil()];
id<GREYMatcher> siteCell = grey_accessibilityLabel(@"https://example.com/");
[GetInteractionForPasswordDetailItem(siteCell)
assertWithMatcher:grey_layout(@[ Below() ], SiteHeader())];
[GetInteractionForPasswordDetailItem(CopySiteButton())
assertWithMatcher:grey_layout(@[ Below() ], siteCell)];
[GetInteractionForPasswordDetailItem(UsernameHeader())
assertWithMatcher:grey_layout(@[ Below() ], CopySiteButton())];
id<GREYMatcher> usernameCell = grey_accessibilityLabel(@"federated username");
[GetInteractionForPasswordDetailItem(usernameCell)
assertWithMatcher:grey_layout(@[ Below() ], UsernameHeader())];
[GetInteractionForPasswordDetailItem(CopyUsernameButton())
assertWithMatcher:grey_layout(@[ Below() ], usernameCell)];
[GetInteractionForPasswordDetailItem(FederationHeader())
assertWithMatcher:grey_layout(@[ Below() ], CopyUsernameButton())];
id<GREYMatcher> federationCell = grey_text(@"famous.provider.net");
[GetInteractionForPasswordDetailItem(federationCell)
assertWithMatcher:grey_layout(@[ Below() ], FederationHeader())];
[GetInteractionForPasswordDetailItem(DeleteButton())
assertWithMatcher:grey_layout(@[ Below() ], federationCell)];
// Check that the password is not present. Match directly to also catch the
// case where the password header would be present but not currently visible
// due to the scrolling state.
[[EarlGrey selectElementWithMatcher:PasswordHeader()]
[[EarlGrey selectElementWithMatcher:PasswordDetailWebsite()]
assertWithMatcher:grey_textFieldValue(@"https://example.com/")];
[[EarlGrey selectElementWithMatcher:PasswordDetailUsername()]
assertWithMatcher:grey_textFieldValue(@"federated username")];
[[EarlGrey selectElementWithMatcher:PasswordDetailPassword()]
assertWithMatcher:grey_nil()];
[GetInteractionForPasswordDetailItem(PasswordDetailUsername())
assertWithMatcher:grey_layout(@[ Below() ], PasswordDetailWebsite())];
[[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()]
performAction:grey_tap()];
[[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()]
......@@ -1110,15 +924,13 @@ void TapEdit() {
- (void)testStoredEntriesAlwaysShown {
SaveExamplePasswordForm();
GREYAssert([PasswordSettingsAppInterface
saveExampleBlockedOrigin:@"https://blocked.com"],
@"Stored form was not found in the PasswordStore results.");
OpenPasswordSettings();
// Toggle the "Save Passwords" control off and back on and check that stored
// items are still present.
constexpr BOOL kExpectedState[] = {YES, NO};
BOOL isSwitchEnabled =
[PasswordSettingsAppInterface isCredentialsServiceEnabled];
BOOL kExpectedState[] = {isSwitchEnabled, !isSwitchEnabled};
for (BOOL expected_state : kExpectedState) {
// Toggle the switch. It is located near the top, so if not interactable,
// try scrolling up.
......@@ -1136,8 +948,6 @@ void TapEdit() {
// Check the stored items. Scroll down if needed.
[GetInteractionForPasswordEntry(@"example.com, concrete username")
assertWithMatcher:grey_notNil()];
[GetInteractionForPasswordEntry(@"blocked.com")
assertWithMatcher:grey_notNil()];
}
[[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()]
......@@ -1214,8 +1024,7 @@ void TapEdit() {
[PasswordSettingsAppInterface setUpMockReauthenticationModule];
[PasswordSettingsAppInterface mockReauthenticationModuleCanAttempt:NO];
[GetInteractionForPasswordDetailItem(CopyPasswordButton())
performAction:grey_tap()];
CopyPasswordDetailWithID(IDS_IOS_SHOW_PASSWORD_VIEW_PASSWORD);
NSString* title =
l10n_util::GetNSString(IDS_IOS_SETTINGS_SET_UP_SCREENLOCK_TITLE);
......@@ -1223,6 +1032,10 @@ void TapEdit() {
assertWithMatcher:grey_sufficientlyVisible()];
[[EarlGrey selectElementWithMatcher:chrome_test_util::OKButton()]
performAction:grey_tap()];
[[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()]
performAction:grey_tap()];
[[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()]
performAction:grey_tap()];
[[EarlGrey selectElementWithMatcher:SettingsDoneButton()]
performAction:grey_tap()];
}
......@@ -1303,12 +1116,12 @@ void TapEdit() {
assertWithMatcher:grey_notNil()];
// Aim at an entry almost at the end of the list.
constexpr int kRemoteIndex = kPasswordsCount - 2;
constexpr int kRemoteIndex = kPasswordsCount - 4;
// The scrolling in GetInteractionForPasswordEntry has too fine steps to
// reach the desired part of the list quickly. The following gives it a head
// start of almost the desired position, counting 30 points per entry and
// aiming 3 entries before |kRemoteIndex|.
constexpr int kJump = (kRemoteIndex - 3) * 30;
// start of the desired position, counting 30 points per entry and
// aiming at |kRemoteIndex|.
constexpr int kJump = kRemoteIndex * 30 + 150;
[[EarlGrey
selectElementWithMatcher:grey_accessibilityID(kPasswordsTableViewId)]
performAction:grey_scrollInDirection(kGREYDirectionDown, kJump)];
......@@ -1317,10 +1130,10 @@ void TapEdit() {
kRemoteIndex, kRemoteIndex]) performAction:grey_tap()];
// Check that the detail view loaded correctly by verifying the site content.
id<GREYMatcher> siteCell = grey_accessibilityLabel([NSString
stringWithFormat:@"https://www%02d.example.com/", kRemoteIndex]);
[GetInteractionForPasswordDetailItem(siteCell)
assertWithMatcher:grey_notNil()];
[[EarlGrey selectElementWithMatcher:PasswordDetailWebsite()]
assertWithMatcher:grey_textFieldValue([NSString
stringWithFormat:@"https://www%02d.example.com/",
kRemoteIndex])];
[[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()]
performAction:grey_tap()];
......@@ -1469,15 +1282,17 @@ void TapEdit() {
assertWithMatcher:grey_nil()];
[GetInteractionForPasswordEntry(@"exclude2.com")
assertWithMatcher:grey_notNil()];
[[EarlGrey
selectElementWithMatcher:ButtonWithAccessibilityLabelId(IDS_CANCEL)]
performAction:grey_tap()];
[[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()]
performAction:grey_tap()];
[[EarlGrey selectElementWithMatcher:SettingsDoneButton()]
performAction:grey_tap()];
}
// Test search and delete all passwords and blocked items.
- (void)testSearchAndDeleteAllPasswords {
// TODO(crbug.com/1129441): This is failing regularly downstream on iOS14.
if (@available(iOS 14, *)) {
EARL_GREY_TEST_DISABLED(@"Test disabled on iOS14.");
}
SaveExamplePasswordForms();
SaveExampleBlockedForms();
......@@ -1489,6 +1304,10 @@ void TapEdit() {
// [[EarlGrey selectElementWithMatcher:SearchTextField()]
// performAction:grey_typeText(@"u\n")];
[[EarlGrey
selectElementWithMatcher:grey_accessibilityID(kPasswordsTableViewId)]
performAction:grey_scrollToContentEdge(kGREYContentEdgeBottom)];
TapEdit();
// Select all.
......@@ -1496,6 +1315,7 @@ void TapEdit() {
performAction:grey_tap()];
[GetInteractionForPasswordEntry(@"example12.com, user2")
performAction:grey_tap()];
[GetInteractionForPasswordEntry(@"exclude1.com") performAction:grey_tap()];
[GetInteractionForPasswordEntry(@"exclude2.com") performAction:grey_tap()];
......
......@@ -43,6 +43,7 @@ source_set("test_support") {
"//components/keyed_service/core",
"//components/metrics",
"//components/metrics:demographics_test_support",
"//components/password_manager/core/common",
"//components/prefs",
"//components/signin/public/base",
"//components/sync:test_support_nigori",
......@@ -70,6 +71,7 @@ source_set("test_support") {
"//ios/chrome/browser/signin",
"//ios/chrome/browser/sync",
"//ios/chrome/browser/tabs",
"//ios/chrome/browser/ui:feature_flags",
"//ios/chrome/browser/ui/authentication/cells",
"//ios/chrome/browser/ui/browser_view",
"//ios/chrome/browser/ui/commands",
......@@ -81,6 +83,7 @@ source_set("test_support") {
"//ios/chrome/browser/ui/settings/password",
"//ios/chrome/browser/ui/settings/password:password_ui",
"//ios/chrome/browser/ui/settings/password:test_support",
"//ios/chrome/browser/ui/settings/password/password_details:password_details_ui",
"//ios/chrome/browser/ui/tab_grid",
"//ios/chrome/browser/ui/tabs",
"//ios/chrome/browser/ui/util",
......
......@@ -6,8 +6,10 @@
#include "base/mac/foundation_util.h"
#import "ios/chrome/browser/ui/settings/password/legacy_password_details_table_view_controller+testing.h"
#import "ios/chrome/browser/ui/settings/password/password_details/password_details_table_view_controller.h"
#import "ios/chrome/browser/ui/settings/password/passwords_table_view_controller.h"
#import "ios/chrome/browser/ui/settings/settings_navigation_controller.h"
#include "ios/chrome/browser/ui/ui_feature_flags.h"
#import "ios/chrome/browser/ui/util/top_view_controller.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
......@@ -53,12 +55,11 @@ MockReauthenticationModule* SetUpAndReturnMockReauthenticationModule() {
SettingsNavigationController* settings_navigation_controller =
base::mac::ObjCCastStrict<SettingsNavigationController>(
top_view_controller::TopPresentedViewController());
LegacyPasswordDetailsTableViewController*
password_details_table_view_controller =
base::mac::ObjCCastStrict<LegacyPasswordDetailsTableViewController>(
settings_navigation_controller.topViewController);
[password_details_table_view_controller
setReauthenticationModule:mock_reauthentication_module];
PasswordDetailsTableViewController* password_details_table_view_controller =
base::mac::ObjCCastStrict<PasswordDetailsTableViewController>(
settings_navigation_controller.topViewController);
password_details_table_view_controller.reauthModule =
mock_reauthentication_module;
return mock_reauthentication_module;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment