chromium/ios/chrome/browser/ui/settings/password/password_checkup/password_checkup_view_controller_unittest.mm

// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#import "ios/chrome/browser/ui/settings/password/password_checkup/password_checkup_view_controller.h"

#import "base/test/bind.h"
#import "base/test/scoped_feature_list.h"
#import "components/affiliations/core/browser/fake_affiliation_service.h"
#import "components/keyed_service/core/service_access_type.h"
#import "components/password_manager/core/browser/password_form.h"
#import "components/password_manager/core/browser/password_manager_test_utils.h"
#import "components/password_manager/core/browser/password_store/test_password_store.h"
#import "components/password_manager/core/browser/ui/credential_ui_entry.h"
#import "ios/chrome/browser/affiliations/model/ios_chrome_affiliation_service_factory.h"
#import "ios/chrome/browser/passwords/model/ios_chrome_password_check_manager_factory.h"
#import "ios/chrome/browser/passwords/model/ios_chrome_profile_password_store_factory.h"
#import "ios/chrome/browser/passwords/model/password_checkup_utils.h"
#import "ios/chrome/browser/shared/model/browser/test/test_browser.h"
#import "ios/chrome/browser/shared/model/profile/test/test_profile_ios.h"
#import "ios/chrome/browser/shared/ui/symbols/symbols.h"
#import "ios/chrome/browser/shared/ui/table_view/cells/table_view_text_item.h"
#import "ios/chrome/browser/shared/ui/table_view/legacy_chrome_table_view_controller_test.h"
#import "ios/chrome/browser/shared/ui/table_view/table_view_utils.h"
#import "ios/chrome/browser/ui/settings/cells/settings_check_item.h"
#import "ios/chrome/browser/ui/settings/password/password_checkup/password_checkup_commands.h"
#import "ios/chrome/browser/ui/settings/password/password_checkup/password_checkup_constants.h"
#import "ios/chrome/browser/ui/settings/password/password_checkup/password_checkup_mediator+Testing.h"
#import "ios/chrome/browser/ui/settings/password/password_checkup/password_checkup_mediator.h"
#import "ios/chrome/common/ui/colors/semantic_color_names.h"
#import "ios/chrome/grit/ios_strings.h"
#import "ios/web/public/test/web_task_environment.h"
#import "testing/gtest_mac.h"
#import "third_party/ocmock/OCMock/OCMock.h"
#import "third_party/ocmock/gtest_support.h"
#import "ui/base/l10n/l10n_util.h"

using password_manager::CredentialUIEntry;
using password_manager::InsecureType;
using password_manager::PasswordForm;
using password_manager::TestPasswordStore;
using password_manager::WarningType;

// Test fixture for testing PasswordCheckupViewController class.
class PasswordCheckupViewControllerTest
    : public LegacyChromeTableViewControllerTest {
 protected:
  PasswordCheckupViewControllerTest() = default;

  void SetUp() override {
    LegacyChromeTableViewControllerTest::SetUp();
    TestChromeBrowserState::Builder builder;
    builder.AddTestingFactory(
        IOSChromeProfilePasswordStoreFactory::GetInstance(),
        base::BindRepeating(
            &password_manager::BuildPasswordStore<web::BrowserState,
                                                  TestPasswordStore>));
    builder.AddTestingFactory(
        IOSChromeAffiliationServiceFactory::GetInstance(),
        base::BindRepeating(base::BindLambdaForTesting([](web::BrowserState*) {
          return std::unique_ptr<KeyedService>(
              std::make_unique<affiliations::FakeAffiliationService>());
        })));
    browser_state_ = std::move(builder).Build();
    browser_ = std::make_unique<TestBrowser>(browser_state_.get());

    CreateController();

    PasswordCheckupViewController* view_controller =
        GetPasswordCheckupViewController();

    mediator_ = [[PasswordCheckupMediator alloc]
        initWithPasswordCheckManager:IOSChromePasswordCheckManagerFactory::
                                         GetForBrowserState(
                                             browser_state_.get())];
    view_controller.delegate = mediator_;
    mediator_.consumer = view_controller;

    handler_ = OCMStrictProtocolMock(@protocol(PasswordCheckupCommands));
    view_controller.handler = handler_;

    // Add a saved password since Password Checkup is not available when the
    // user doesn't have any saved passwords.
    AddSavedForm();
  }

  TestPasswordStore& GetTestStore() {
    return *static_cast<TestPasswordStore*>(
        IOSChromeProfilePasswordStoreFactory::GetForBrowserState(
            browser_->GetBrowserState(), ServiceAccessType::EXPLICIT_ACCESS)
            .get());
  }

  LegacyChromeTableViewController* InstantiateController() override {
    return [[PasswordCheckupViewController alloc]
        initWithStyle:ChromeTableViewStyle()];
  }

  PasswordCheckupViewController* GetPasswordCheckupViewController() {
    return static_cast<PasswordCheckupViewController*>(controller());
  }

  // Changes the PasswordCheckupHomepageState.
  void ChangePasswordCheckupHomepageState(PasswordCheckupHomepageState state) {
    PasswordCheckupViewController* view_controller =
        GetPasswordCheckupViewController();

    password_manager::InsecurePasswordCounts counts = {};
    for (const auto& signon_realm_forms : GetTestStore().stored_passwords()) {
      for (const PasswordForm& form : signon_realm_forms.second) {
        CredentialUIEntry credential = CredentialUIEntry(form);
        if (credential.IsMuted()) {
          counts.dismissed_count++;
        } else if (IsCompromised(credential)) {
          counts.compromised_count++;
        }
        if (credential.IsReused()) {
          counts.reused_count++;
        }
        if (credential.IsWeak()) {
          counts.weak_count++;
        }
      }
    }

    [view_controller setPasswordCheckupHomepageState:state
                              insecurePasswordCounts:counts
                  formattedElapsedTimeSinceLastCheck:
                      [mediator_ formattedElapsedTimeSinceLastCheck]];
  }

  // Adds a form to the test password store.
  void AddPasswordForm(std::unique_ptr<password_manager::PasswordForm> form) {
    GetTestStore().AddLogin(*form);
    RunUntilIdle();
  }

  // Creates and adds a saved password form.
  void AddSavedForm(std::string url = "http://www.example1.com/") {
    auto form = std::make_unique<password_manager::PasswordForm>();
    form->url = GURL(url);
    form->username_element = u"Email";
    form->username_value = u"[email protected]";
    form->password_element = u"Passwd";
    form->password_value = u"test";
    form->signon_realm = url;
    form->scheme = password_manager::PasswordForm::Scheme::kHtml;
    form->in_store = password_manager::PasswordForm::Store::kProfileStore;
    AddPasswordForm(std::move(form));
  }

  // Creates and adds a saved insecure password form.
  void AddSavedInsecureForm(InsecureType insecure_type,
                            bool is_muted = false,
                            std::string url = "http://www.example2.com/") {
    auto form = std::make_unique<password_manager::PasswordForm>();
    form->url = GURL(url);
    form->username_element = u"Email";
    form->username_value = u"[email protected]";
    form->password_element = u"Passwd";
    form->password_value = u"test";
    form->signon_realm = url;
    form->scheme = password_manager::PasswordForm::Scheme::kHtml;
    form->in_store = password_manager::PasswordForm::Store::kProfileStore;
    form->password_issues = {
        {insecure_type,
         password_manager::InsecurityMetadata(
             base::Time::Now(), password_manager::IsMuted(is_muted),
             password_manager::TriggerBackendNotification(false))}};
    AddPasswordForm(std::move(form));
  }

  // Checks if the header image of the table view is as expected.
  void CheckHeaderImage(NSString* image_name) {
    UIImageView* headerImageView =
        (UIImageView*)GetPasswordCheckupViewController()
            .tableView.tableHeaderView;
    EXPECT_NSEQ([UIImage imageNamed:image_name], headerImageView.image);
  }

  // Checks if the item at the given index of the insecure types section is as
  // expected.
  void CheckItemFromInsecureTypesSection(
      int index,
      NSString* text,
      NSString* detail_text,
      bool indicator_hidden,
      bool trailing_icon_hidden,
      NSString* trailing_icon_name,
      NSString* trailing_icon_color_name,
      UITableViewCellAccessoryType accessory_type) {
    SettingsCheckItem* cell =
        static_cast<SettingsCheckItem*>(GetTableViewItem(0, index));
    EXPECT_NSEQ(text, cell.text);
    EXPECT_NSEQ(detail_text, cell.detailText);
    EXPECT_TRUE(cell.enabled);
    EXPECT_TRUE(cell.indicatorHidden == indicator_hidden);
    EXPECT_TRUE(cell.infoButtonHidden);
    if (trailing_icon_hidden) {
      EXPECT_TRUE(nil == cell.trailingImage);
    } else {
      EXPECT_NSEQ(DefaultSymbolTemplateWithPointSize(trailing_icon_name, 22),
                  cell.trailingImage);
      EXPECT_TRUE([cell.trailingImageTintColor
          isEqual:[UIColor colorNamed:trailing_icon_color_name]]);
    }
    EXPECT_TRUE(accessory_type == cell.accessoryType);
  }

  // Checks if the timestamp item is as expected.
  void CheckPasswordCheckupTimestampItem(NSString* text,
                                         int detail_text_id,
                                         int affiliated_group_count,
                                         bool indicator_hidden) {
    SettingsCheckItem* cell =
        static_cast<SettingsCheckItem*>(GetTableViewItem(1, 0));
    EXPECT_NSEQ(text, cell.text);
    EXPECT_NSEQ(
        l10n_util::GetPluralNSStringF(detail_text_id, affiliated_group_count),
        cell.detailText);
    EXPECT_TRUE(cell.enabled);
    EXPECT_TRUE(cell.indicatorHidden == indicator_hidden);
    EXPECT_TRUE(cell.infoButtonHidden);
  }

  // Checks if the check passwords button item is as expected.
  void CheckCheckPasswordsButtonItem(NSString* text_color_name,
                                     bool is_enabled) {
    TableViewTextItem* cell =
        static_cast<TableViewTextItem*>(GetTableViewItem(1, 1));
    EXPECT_NSEQ(l10n_util::GetNSString(
                    IDS_IOS_PASSWORD_CHECKUP_HOMEPAGE_CHECK_AGAIN_BUTTON),
                cell.text);
    EXPECT_TRUE([cell.textColor isEqual:[UIColor colorNamed:text_color_name]]);
    EXPECT_TRUE(cell.enabled == is_enabled);
  }

  // Initializes the strings for the items in the insecure types section as if
  // all saved passwords were safe.
  void InitializeStringsForInsecureTypeSection() {
    compromised_text_ = l10n_util::GetPluralNSStringF(
        IDS_IOS_PASSWORD_CHECKUP_HOMEPAGE_COMPROMISED_PASSWORDS_TITLE, 0);
    compromised_detail_text_ = l10n_util::GetNSString(
        IDS_IOS_PASSWORD_CHECKUP_HOMEPAGE_NO_COMPROMISED_PASSWORDS_SUBTITLE);
    reused_text_ = l10n_util::GetNSString(
        IDS_IOS_PASSWORD_CHECKUP_HOMEPAGE_NO_REUSED_PASSWORDS_TITLE);
    reused_detail_text_ = l10n_util::GetNSString(
        IDS_IOS_PASSWORD_CHECKUP_HOMEPAGE_NO_REUSED_PASSWORDS_SUBTITLE);
    weak_text_ = l10n_util::GetNSString(
        IDS_IOS_PASSWORD_CHECKUP_HOMEPAGE_NO_WEAK_PASSWORDS_TITLE);
    weak_detail_text_ = l10n_util::GetNSString(
        IDS_IOS_PASSWORD_CHECKUP_HOMEPAGE_NO_WEAK_PASSWORDS_SUBTITLE);
  }

  // Simulates a tap on an item in the tableView.
  void SimulateTap(int index, int section) {
    [controller() tableView:controller().tableView
        didSelectRowAtIndexPath:[NSIndexPath indexPathForItem:index
                                                    inSection:section]];
  }

  void RunUntilIdle() { task_environment_.RunUntilIdle(); }

  web::WebTaskEnvironment task_environment_;
  std::unique_ptr<TestChromeBrowserState> browser_state_;
  std::unique_ptr<TestBrowser> browser_;
  PasswordCheckupMediator* mediator_;
  base::test::ScopedFeatureList feature_list;
  id<PasswordCheckupCommands> handler_;
  // Strings for the insecure types section.
  NSString* compromised_text_;
  NSString* compromised_detail_text_;
  NSString* reused_text_;
  NSString* reused_detail_text_;
  NSString* weak_text_;
  NSString* weak_detail_text_;
};

// Tests the running state of the Password Checkup homepage.
TEST_F(PasswordCheckupViewControllerTest, PasswordCheckupHomepageStateRunning) {
  ChangePasswordCheckupHomepageState(PasswordCheckupHomepageStateRunning);

  CheckHeaderImage(password_manager::kPasswordCheckupHeaderImageLoading);

  InitializeStringsForInsecureTypeSection();
  CheckItemFromInsecureTypesSection(
      /*index=*/0, /*text=*/compromised_text_,
      /*detail_text=*/compromised_detail_text_,
      /*indicator_hidden=*/NO,
      /*trailing_icon_hidden=*/YES,
      /*trailing_icon_name=*/@"",
      /*trailing_icon_color_name=*/@"",
      /*accessory_type=*/UITableViewCellAccessoryNone);
  CheckItemFromInsecureTypesSection(
      /*index=*/1, /*text=*/reused_text_,
      /*detail_text=*/reused_detail_text_,
      /*indicator_hidden=*/NO,
      /*trailing_icon_hidden=*/YES,
      /*trailing_icon_name=*/@"",
      /*trailing_icon_color_name=*/@"",
      /*accessory_type=*/UITableViewCellAccessoryNone);
  CheckItemFromInsecureTypesSection(
      /*index=*/2, /*text=*/weak_text_,
      /*detail_text=*/weak_detail_text_,
      /*indicator_hidden=*/NO,
      /*trailing_icon_hidden=*/YES,
      /*trailing_icon_name=*/@"",
      /*trailing_icon_color_name=*/@"",
      /*accessory_type=*/UITableViewCellAccessoryNone);

  CheckPasswordCheckupTimestampItem(
      /*text=*/l10n_util::GetNSString(IDS_IOS_PASSWORD_CHECKUP_ONGOING),
      /*detail_text_id=*/
      IDS_IOS_PASSWORD_CHECKUP_SITES_AND_APPS_COUNT,
      /*affiliated_group_count=*/1, /*indicator_hidden=*/false);
  CheckCheckPasswordsButtonItem(/*text_color_name=*/kTextSecondaryColor,
                                /*is_enabled=*/false);

  [GetPasswordCheckupViewController() settingsWillBeDismissed];
}

// Tests the "done" state of the Password Checkup homepage with no insecure
// passwords.
TEST_F(PasswordCheckupViewControllerTest, PasswordCheckupHomepageStateSafe) {
  ChangePasswordCheckupHomepageState(PasswordCheckupHomepageStateDone);

  CheckHeaderImage(password_manager::kPasswordCheckupHeaderImageGreen);

  InitializeStringsForInsecureTypeSection();
  CheckItemFromInsecureTypesSection(
      /*index=*/0, /*text=*/compromised_text_,
      /*detail_text=*/compromised_detail_text_,
      /*indicator_hidden=*/YES,
      /*trailing_icon_hidden=*/NO,
      /*trailing_icon_name=*/kCheckmarkCircleFillSymbol,
      /*trailing_icon_color_name=*/kGreen500Color,
      /*accessory_type=*/UITableViewCellAccessoryNone);
  CheckItemFromInsecureTypesSection(
      /*index=*/1, /*text=*/reused_text_,
      /*detail_text=*/reused_detail_text_,
      /*indicator_hidden=*/YES,
      /*trailing_icon_hidden=*/NO,
      /*trailing_icon_name=*/kCheckmarkCircleFillSymbol,
      /*trailing_icon_color_name=*/kGreen500Color,
      /*accessory_type=*/UITableViewCellAccessoryNone);
  CheckItemFromInsecureTypesSection(
      /*index=*/2, /*text=*/weak_text_,
      /*detail_text=*/weak_detail_text_,
      /*indicator_hidden=*/YES,
      /*trailing_icon_hidden=*/NO,
      /*trailing_icon_name=*/kCheckmarkCircleFillSymbol,
      /*trailing_icon_color_name=*/kGreen500Color,
      /*accessory_type=*/UITableViewCellAccessoryNone);

  CheckPasswordCheckupTimestampItem(
      /*text=*/[mediator_ formattedElapsedTimeSinceLastCheck],
      /*detail_text_id=*/IDS_IOS_PASSWORD_CHECKUP_SITES_AND_APPS_COUNT,
      /*affiliated_group_count=*/1, /*indicator_hidden=*/true);
  CheckCheckPasswordsButtonItem(/*text_color_name=*/kBlueColor,
                                /*is_enabled=*/true);

  [GetPasswordCheckupViewController() settingsWillBeDismissed];
}

// Tests the "done" state of the Password Checkup homepage with compromised
// passwords.
TEST_F(PasswordCheckupViewControllerTest,
       PasswordCheckupHomepageStateWithCompromisedPasswords) {
  AddSavedInsecureForm(InsecureType::kLeaked);
  ChangePasswordCheckupHomepageState(PasswordCheckupHomepageStateDone);

  CheckHeaderImage(password_manager::kPasswordCheckupHeaderImageRed);

  InitializeStringsForInsecureTypeSection();
  compromised_text_ = l10n_util::GetPluralNSStringF(
      IDS_IOS_PASSWORD_CHECKUP_HOMEPAGE_COMPROMISED_PASSWORDS_TITLE, 1);
  compromised_detail_text_ = l10n_util::GetNSString(
      IDS_IOS_PASSWORD_CHECKUP_HOMEPAGE_COMPROMISED_PASSWORDS_SUBTITLE);
  CheckItemFromInsecureTypesSection(
      /*index=*/0, /*text=*/compromised_text_,
      /*detail_text=*/compromised_detail_text_,
      /*indicator_hidden=*/YES,
      /*trailing_icon_hidden=*/NO,
      /*trailing_icon_name=*/kErrorCircleFillSymbol,
      /*trailing_icon_color_name=*/kRed500Color,
      /*accessory_type=*/UITableViewCellAccessoryDisclosureIndicator);
  CheckItemFromInsecureTypesSection(
      /*index=*/1, /*text=*/reused_text_,
      /*detail_text=*/reused_detail_text_,
      /*indicator_hidden=*/YES,
      /*trailing_icon_hidden=*/NO,
      /*trailing_icon_name=*/kCheckmarkCircleFillSymbol,
      /*trailing_icon_color_name=*/kGreen500Color,
      /*accessory_type=*/UITableViewCellAccessoryNone);
  CheckItemFromInsecureTypesSection(
      /*index=*/2, /*text=*/weak_text_,
      /*detail_text=*/weak_detail_text_,
      /*indicator_hidden=*/YES,
      /*trailing_icon_hidden=*/NO,
      /*trailing_icon_name=*/kCheckmarkCircleFillSymbol,
      /*trailing_icon_color_name=*/kGreen500Color,
      /*accessory_type=*/UITableViewCellAccessoryNone);

  CheckPasswordCheckupTimestampItem(
      /*text=*/[mediator_ formattedElapsedTimeSinceLastCheck],
      /*detail_text_id=*/IDS_IOS_PASSWORD_CHECKUP_SITES_AND_APPS_COUNT,
      /*affiliated_group_count=*/2, /*indicator_hidden=*/true);
  CheckCheckPasswordsButtonItem(/*text_color_name=*/kBlueColor,
                                /*is_enabled=*/true);

  [GetPasswordCheckupViewController() settingsWillBeDismissed];
}

// Tests the "done" state of the Password Checkup homepage with muted
// compromised passwords.
TEST_F(PasswordCheckupViewControllerTest,
       PasswordCheckupHomepageStateWithMutedCompromisedPasswords) {
  AddSavedInsecureForm(InsecureType::kLeaked, /*is_muted=*/true);
  ChangePasswordCheckupHomepageState(PasswordCheckupHomepageStateDone);

  CheckHeaderImage(password_manager::kPasswordCheckupHeaderImageYellow);

  InitializeStringsForInsecureTypeSection();
  compromised_detail_text_ = l10n_util::GetPluralNSStringF(
      IDS_IOS_PASSWORD_CHECKUP_HOMEPAGE_DISMISSED_WARNINGS_SUBTITLE, 1);
  CheckItemFromInsecureTypesSection(
      /*index=*/0, /*text=*/compromised_text_,
      /*detail_text=*/compromised_detail_text_,
      /*indicator_hidden=*/YES,
      /*trailing_icon_hidden=*/NO,
      /*trailing_icon_name=*/kErrorCircleFillSymbol,
      /*trailing_icon_color_name=*/kYellow500Color,
      /*accessory_type=*/UITableViewCellAccessoryDisclosureIndicator);
  CheckItemFromInsecureTypesSection(
      /*index=*/1, /*text=*/reused_text_,
      /*detail_text=*/reused_detail_text_,
      /*indicator_hidden=*/YES,
      /*trailing_icon_hidden=*/NO,
      /*trailing_icon_name=*/kCheckmarkCircleFillSymbol,
      /*trailing_icon_color_name=*/kGreen500Color,
      /*accessory_type=*/UITableViewCellAccessoryNone);
  CheckItemFromInsecureTypesSection(
      /*index=*/2, /*text=*/weak_text_,
      /*detail_text=*/weak_detail_text_,
      /*indicator_hidden=*/YES,
      /*trailing_icon_hidden=*/NO,
      /*trailing_icon_name=*/kCheckmarkCircleFillSymbol,
      /*trailing_icon_color_name=*/kGreen500Color,
      /*accessory_type=*/UITableViewCellAccessoryNone);

  CheckPasswordCheckupTimestampItem(
      /*text=*/[mediator_ formattedElapsedTimeSinceLastCheck],
      /*detail_text_id=*/IDS_IOS_PASSWORD_CHECKUP_SITES_AND_APPS_COUNT,
      /*affiliated_group_count=*/2, /*indicator_hidden=*/true);
  CheckCheckPasswordsButtonItem(/*text_color_name=*/kBlueColor,
                                /*is_enabled=*/true);

  [GetPasswordCheckupViewController() settingsWillBeDismissed];
}

// Tests the "done" state of the Password Checkup homepage with reused
// passwords.
TEST_F(PasswordCheckupViewControllerTest,
       PasswordCheckupHomepageStateWithReusedPasswords) {
  AddSavedInsecureForm(InsecureType::kReused);
  ChangePasswordCheckupHomepageState(PasswordCheckupHomepageStateDone);

  CheckHeaderImage(password_manager::kPasswordCheckupHeaderImageYellow);

  InitializeStringsForInsecureTypeSection();
  reused_text_ = l10n_util::GetNSStringF(
      IDS_IOS_PASSWORD_CHECKUP_HOMEPAGE_REUSED_PASSWORDS_TITLE,
      base::NumberToString16(1));
  reused_detail_text_ = l10n_util::GetNSString(
      IDS_IOS_PASSWORD_CHECKUP_HOMEPAGE_REUSED_PASSWORDS_SUBTITLE);
  CheckItemFromInsecureTypesSection(
      /*index=*/0, /*text=*/compromised_text_,
      /*detail_text=*/compromised_detail_text_,
      /*indicator_hidden=*/YES,
      /*trailing_icon_hidden=*/NO,
      /*trailing_icon_name=*/kCheckmarkCircleFillSymbol,
      /*trailing_icon_color_name=*/kGreen500Color,
      /*accessory_type=*/UITableViewCellAccessoryNone);
  CheckItemFromInsecureTypesSection(
      /*index=*/1, /*text=*/reused_text_,
      /*detail_text=*/reused_detail_text_,
      /*indicator_hidden=*/YES,
      /*trailing_icon_hidden=*/NO,
      /*trailing_icon_name=*/kErrorCircleFillSymbol,
      /*trailing_icon_color_name=*/kYellow500Color,
      /*accessory_type=*/UITableViewCellAccessoryDisclosureIndicator);
  CheckItemFromInsecureTypesSection(
      /*index=*/2, /*text=*/weak_text_,
      /*detail_text=*/weak_detail_text_,
      /*indicator_hidden=*/YES,
      /*trailing_icon_hidden=*/NO,
      /*trailing_icon_name=*/kCheckmarkCircleFillSymbol,
      /*trailing_icon_color_name=*/kGreen500Color,
      /*accessory_type=*/UITableViewCellAccessoryNone);

  CheckPasswordCheckupTimestampItem(
      /*text=*/[mediator_ formattedElapsedTimeSinceLastCheck],
      /*text_id=*/IDS_IOS_PASSWORD_CHECKUP_SITES_AND_APPS_COUNT,
      /*affiliated_group_count=*/2, /*indicator_hidden=*/true);
  CheckCheckPasswordsButtonItem(/*text_color_name=*/kBlueColor,
                                /*is_enabled=*/true);

  [GetPasswordCheckupViewController() settingsWillBeDismissed];
}

// Tests the "done" state of the Password Checkup homepage with weak passwords.
TEST_F(PasswordCheckupViewControllerTest,
       PasswordCheckupHomepageStateWithWeakPasswords) {
  AddSavedInsecureForm(InsecureType::kWeak);
  ChangePasswordCheckupHomepageState(PasswordCheckupHomepageStateDone);

  CheckHeaderImage(password_manager::kPasswordCheckupHeaderImageYellow);

  InitializeStringsForInsecureTypeSection();
  weak_text_ = l10n_util::GetPluralNSStringF(
      IDS_IOS_PASSWORD_CHECKUP_HOMEPAGE_WEAK_PASSWORDS_TITLE, 1);
  weak_detail_text_ = l10n_util::GetNSString(
      IDS_IOS_PASSWORD_CHECKUP_HOMEPAGE_WEAK_PASSWORDS_SUBTITLE);
  CheckItemFromInsecureTypesSection(
      /*index=*/0, /*text=*/compromised_text_,
      /*detail_text=*/compromised_detail_text_,
      /*indicator_hidden=*/YES,
      /*trailing_icon_hidden=*/NO,
      /*trailing_icon_name=*/kCheckmarkCircleFillSymbol,
      /*trailing_icon_color_name=*/kGreen500Color,
      /*accessory_type=*/UITableViewCellAccessoryNone);
  CheckItemFromInsecureTypesSection(
      /*index=*/1, /*text=*/reused_text_,
      /*detail_text=*/reused_detail_text_,
      /*indicator_hidden=*/YES,
      /*trailing_icon_hidden=*/NO,
      /*trailing_icon_name=*/kCheckmarkCircleFillSymbol,
      /*trailing_icon_color_name=*/kGreen500Color,
      /*accessory_type=*/UITableViewCellAccessoryNone);
  CheckItemFromInsecureTypesSection(
      /*index=*/2, /*text=*/weak_text_,
      /*detail_text=*/weak_detail_text_,
      /*indicator_hidden=*/YES,
      /*trailing_icon_hidden=*/NO,
      /*trailing_icon_name=*/kErrorCircleFillSymbol,
      /*trailing_icon_color_name=*/kYellow500Color,
      /*accessory_type=*/UITableViewCellAccessoryDisclosureIndicator);

  CheckPasswordCheckupTimestampItem(
      /*text=*/[mediator_ formattedElapsedTimeSinceLastCheck],
      /*detail_text_id=*/IDS_IOS_PASSWORD_CHECKUP_SITES_AND_APPS_COUNT,
      /*affiliated_group_count=*/2, /*indicator_hidden=*/true);
  CheckCheckPasswordsButtonItem(/*text_color_name=*/kBlueColor,
                                /*is_enabled=*/true);

  [GetPasswordCheckupViewController() settingsWillBeDismissed];
}

// Verifies that tapping on the compromised passwords cell tells the handler to
// show compromised issues.
TEST_F(PasswordCheckupViewControllerTest,
       TestTapCompromisedPasswordsNotifiesHandler) {
  AddSavedInsecureForm(InsecureType::kLeaked);
  ChangePasswordCheckupHomepageState(PasswordCheckupHomepageStateDone);

  OCMExpect([handler_ showPasswordIssuesWithWarningType:
                          WarningType::kCompromisedPasswordsWarning]);

  SimulateTap(/*index=*/0, /*section=*/0);

  EXPECT_OCMOCK_VERIFY((id)handler_);
}

// Verifies that tapping on the reused passwords cell tells the handler to show
// reused issues.
TEST_F(PasswordCheckupViewControllerTest,
       TestTapReusedPasswordsNotifiesHandler) {
  AddSavedInsecureForm(InsecureType::kReused);
  ChangePasswordCheckupHomepageState(PasswordCheckupHomepageStateDone);

  OCMExpect([handler_
      showPasswordIssuesWithWarningType:WarningType::kReusedPasswordsWarning]);

  SimulateTap(/*index=*/1, /*section=*/0);

  EXPECT_OCMOCK_VERIFY((id)handler_);
}

// Verifies that tapping on the weak passwords cell tells the handler to
// show weak issues.
TEST_F(PasswordCheckupViewControllerTest, TestTapWeakPasswordsNotifiesHandler) {
  AddSavedInsecureForm(InsecureType::kWeak);
  ChangePasswordCheckupHomepageState(PasswordCheckupHomepageStateDone);

  OCMExpect([handler_
      showPasswordIssuesWithWarningType:WarningType::kWeakPasswordsWarning]);

  SimulateTap(/*index=*/2, /*section=*/0);

  EXPECT_OCMOCK_VERIFY((id)handler_);
}

// Verifies that deleting all saved passwords through Password Checkup triggers
// a dismissal in the handler.
TEST_F(PasswordCheckupViewControllerTest, TestDismissAfterPasswordsGone) {
  OCMExpect([handler_ dismissAfterAllPasswordsGone]);

  ChangePasswordCheckupHomepageState(PasswordCheckupHomepageStateDisabled);

  EXPECT_OCMOCK_VERIFY((id)handler_);
}