chromium/ios/chrome/browser/ui/settings/autofill/autofill_credit_card_table_view_controller_unittest.mm

// Copyright 2018 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/autofill/autofill_credit_card_table_view_controller.h"

#import "base/apple/foundation_util.h"
#import "base/strings/utf_string_conversions.h"
#import "base/test/ios/wait_util.h"
#import "base/test/scoped_feature_list.h"
#import "base/uuid.h"
#import "components/autofill/core/browser/address_data_manager.h"
#import "components/autofill/core/browser/data_model/credit_card.h"
#import "components/autofill/core/browser/geo/alternative_state_name_map_updater.h"
#import "components/autofill/core/browser/payments_data_manager.h"
#import "components/autofill/core/browser/personal_data_manager.h"
#import "components/autofill/core/browser/personal_data_manager_test_utils.h"
#import "components/autofill/core/common/autofill_features.h"
#import "components/autofill/core/common/autofill_payments_features.h"
#import "components/strings/grit/components_strings.h"
#import "ios/chrome/browser/autofill/model/personal_data_manager_factory.h"
#import "ios/chrome/browser/shared/model/application_context/application_context.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/table_view/legacy_chrome_table_view_controller_test.h"
#import "ios/chrome/browser/webdata_services/model/web_data_service_factory.h"
#import "ios/chrome/common/ui/reauthentication/reauthentication_module.h"
#import "ios/chrome/test/ios_chrome_scoped_testing_local_state.h"
#import "ios/web/public/test/web_task_environment.h"
#import "testing/gtest/include/gtest/gtest.h"
#import "ui/base/l10n/l10n_util.h"

namespace {

class AutofillCreditCardTableViewControllerTest
    : public LegacyChromeTableViewControllerTest {
 protected:
  AutofillCreditCardTableViewControllerTest() {
    TestChromeBrowserState::Builder test_cbs_builder;
    // Credit card import requires a PersonalDataManager which itself needs the
    // WebDataService; this is not initialized on a TestChromeBrowserState by
    // default.
    test_cbs_builder.AddTestingFactory(
        ios::WebDataServiceFactory::GetInstance(),
        ios::WebDataServiceFactory::GetDefaultFactory());
    chrome_browser_state_ = std::move(test_cbs_builder).Build();
    browser_ = std::make_unique<TestBrowser>(chrome_browser_state_.get());

    // Set circular SyncService dependency to null.
    autofill::PersonalDataManagerFactory::GetForBrowserState(
        chrome_browser_state_.get())
        ->SetSyncServiceForTest(nullptr);
  }

  LegacyChromeTableViewController* InstantiateController() override {
    return [[AutofillCreditCardTableViewController alloc]
        initWithBrowser:browser_.get()];
  }

  void TearDown() override {
    [base::apple::ObjCCastStrict<AutofillCreditCardTableViewController>(
        controller()) settingsWillBeDismissed];
    LegacyChromeTableViewControllerTest::TearDown();
  }

  void AddCreditCard(const std::string& origin,
                     const std::string& card_holder_name,
                     const std::string& card_number) {
    autofill::PersonalDataManager* personal_data_manager =
        autofill::PersonalDataManagerFactory::GetForBrowserState(
            chrome_browser_state_.get());
    autofill::PersonalDataChangedWaiter waiter(*personal_data_manager);

    autofill::CreditCard credit_card(
        base::Uuid::GenerateRandomV4().AsLowercaseString(), origin);
    credit_card.SetRawInfo(autofill::CREDIT_CARD_NAME_FULL,
                           base::ASCIIToUTF16(card_holder_name));
    credit_card.SetRawInfo(autofill::CREDIT_CARD_NUMBER,
                           base::ASCIIToUTF16(card_number));
    personal_data_manager->payments_data_manager()
        .OnAcceptedLocalCreditCardSave(credit_card);
    personal_data_manager->address_data_manager()
        .get_alternative_state_name_map_updater_for_testing()
        ->set_local_state_for_testing(local_state());
    std::move(waiter).Wait();  // Wait for completion of the async operation.
  }

  // Deletes the item at (section, row) and waits util condition returns true or
  // timeout.
  bool DeleteItemAndWait(int section, int row, ConditionBlock condition) {
    AutofillCreditCardTableViewController* view_controller =
        base::apple::ObjCCastStrict<AutofillCreditCardTableViewController>(
            controller());
    [view_controller deleteItems:@[ [NSIndexPath indexPathForRow:row
                                                       inSection:section] ]];
    return base::test::ios::WaitUntilConditionOrTimeout(
        base::test::ios::kWaitForUIElementTimeout, condition);
  }

  // Checks whether device reauth is supported.
  bool CheckCanAttemptReauth() {
    ReauthenticationModule* reauthModule =
        [[ReauthenticationModule alloc] init];
    return [reauthModule canAttemptReauth];
  }

  PrefService* local_state() {
    return GetApplicationContext()->GetLocalState();
  }

  web::WebTaskEnvironment task_environment_;
  IOSChromeScopedTestingLocalState scoped_testing_local_state_;
  std::unique_ptr<TestChromeBrowserState> chrome_browser_state_;
  std::unique_ptr<Browser> browser_;
};

// Default test case of no credit cards.
TEST_F(AutofillCreditCardTableViewControllerTest, TestInitialization) {
  CreateController();
  CheckController();

  // Expect two switch sections (the credit card Autofill switch and the
  // mandatory reauth switch).
  ASSERT_EQ(2, NumberOfSections());
  // Expect each switch section to contain one row.
  EXPECT_EQ(1, NumberOfItemsInSection(0));
  EXPECT_EQ(1, NumberOfItemsInSection(1));
}

// Adding a single credit card results in a credit card section.
TEST_F(AutofillCreditCardTableViewControllerTest, TestOneCreditCard) {
  AddCreditCard("https://www.example.com/", "John Doe", "378282246310005");
  CreateController();
  CheckController();

  // Expect three sections (credit card switch, mandatory reauth switch and
  // credit card section).
  ASSERT_EQ(3, NumberOfSections());
  // Expect credit card section to contain one row (the credit card itself).
  EXPECT_EQ(1, NumberOfItemsInSection(2));
}

// Deleting the only credit card results in item deletion and section deletion.
TEST_F(AutofillCreditCardTableViewControllerTest,
       TestOneCreditCardItemDeleted) {
  AddCreditCard("https://www.example.com/", "John Doe", "378282246310005");
  CreateController();
  CheckController();

  // Expect three sections (credit card Autofill switch, mandatory reauth switch
  // and credit card section).
  ASSERT_EQ(3, NumberOfSections());
  // Expect credit card section to contain one row (the credit card itself).
  EXPECT_EQ(1, NumberOfItemsInSection(2));

  // Delete the credit card item and check that the section is removed.
  EXPECT_TRUE(DeleteItemAndWait(2, 0, ^{
    return NumberOfSections() == 2;
  }));
}

// Tests that when the MandatoryReauth feature is enabled a switch
// appears.
TEST_F(AutofillCreditCardTableViewControllerTest,
       TestMandatoryReauthSwitchExists) {
  autofill::PersonalDataManager* personal_data_manager =
      autofill::PersonalDataManagerFactory::GetForBrowserState(
          chrome_browser_state_.get());
  EXPECT_TRUE(personal_data_manager->payments_data_manager()
                  .IsPaymentMethodsMandatoryReauthEnabled());

  CreateController();
  CheckController();

  // Expect 2 sections, 1 for switches and 1 for mandatory reauth.
  EXPECT_EQ(2, NumberOfSections());

  // Expect Mandatory Reauth section to have 2 items, the switch and the
  // subtitle.
  EXPECT_EQ(1, NumberOfItemsInSection(1));

  // Confirm the text to the side of the switch. Whether the switch is turned on
  // depends on whether the device supports device reauth.
  CheckSwitchCellStateAndText(
      CheckCanAttemptReauth(),
      l10n_util::GetNSString(
          IDS_PAYMENTS_AUTOFILL_ENABLE_MANDATORY_REAUTH_TOGGLE_LABEL),
      1, 0);

  // Confirm the sublabel of the switch.
  CheckSectionFooter(
      l10n_util::GetNSString(
          IDS_PAYMENTS_AUTOFILL_ENABLE_MANDATORY_REAUTH_TOGGLE_SUBLABEL),
      1);
}

}  // namespace