chromium/chrome/browser/ui/android/autofill/autofill_save_iban_delegate_unittest.cc

// 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.

#include "chrome/browser/ui/android/autofill/autofill_save_iban_delegate.h"

#include <memory>
#include <string>
#include <string_view>

#include "base/test/mock_callback.h"
#include "chrome/test/base/chrome_render_view_host_test_harness.h"
#include "components/autofill/core/browser/autofill_client.h"
#include "components/browser_ui/device_lock/android/test_device_lock_bridge.h"
#include "content/public/browser/web_contents.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/android/window_android.h"

namespace autofill {
namespace {

const std::u16string kUserProvidedNickname = u"My doctor's IBAN";

}  // namespace

using SaveIbanOfferUserDecision =
    payments::PaymentsAutofillClient::SaveIbanOfferUserDecision;
using LocalCallbackArgs = std::pair<SaveIbanOfferUserDecision, std::u16string>;

class AutofillSaveIbanDelegateTest : public ChromeRenderViewHostTestHarness {
 protected:
  void SetUp() override {
    ChromeRenderViewHostTestHarness::SetUp();

    delegate_ = std::make_unique<AutofillSaveIbanDelegate>(MakeLocalCallback(),
                                                           web_contents());
    std::unique_ptr<TestDeviceLockBridge> bridge =
        std::make_unique<TestDeviceLockBridge>();
    test_bridge_ = bridge.get();
    delegate_->SetDeviceLockBridgeForTesting(std::move(bridge));

    // Create a scoped window so that
    // WebContents::GetNativeView()->GetWindowAndroid() does not return null.
    window_ = ui::WindowAndroid::CreateForTesting();
    window_.get()->get()->AddChild(web_contents()->GetNativeView());
  }

  void LocalCallback(SaveIbanOfferUserDecision decision,
                     std::u16string_view nickname);

  payments::PaymentsAutofillClient::SaveIbanPromptCallback MakeLocalCallback();

  std::optional<LocalCallbackArgs> local_offer_decision_;

  std::unique_ptr<AutofillSaveIbanDelegate> delegate_;
  raw_ptr<TestDeviceLockBridge> test_bridge_;
  std::unique_ptr<ui::WindowAndroid::ScopedWindowAndroidForTesting> window_;
};

void AutofillSaveIbanDelegateTest::LocalCallback(
    SaveIbanOfferUserDecision decision,
    std::u16string_view nickname) {
  local_offer_decision_.emplace(decision, nickname);
}

payments::PaymentsAutofillClient::SaveIbanPromptCallback
AutofillSaveIbanDelegateTest::MakeLocalCallback() {
  return base::BindOnce(
      &AutofillSaveIbanDelegateTest::LocalCallback,
      base::Unretained(this));  // Test function does not outlive test fixture.
}

// Matches the SaveIbanPromptCallback arguments to a LocalCallbackArgs.
testing::Matcher<LocalCallbackArgs> EqualToLocalCallbackArgs(
    SaveIbanOfferUserDecision decision,
    std::u16string user_provided_nickname) {
  return testing::AllOf(
      testing::Field(&LocalCallbackArgs::first, decision),
      testing::Field(&LocalCallbackArgs::second, user_provided_nickname));
}

TEST_F(AutofillSaveIbanDelegateTest,
       OnUiAcceptedWithCallbackArgumentRunsCallback) {
  auto delegate = AutofillSaveIbanDelegate(MakeLocalCallback(), web_contents());

  base::MockOnceClosure mock_finish_gathering_consent_callback;
  EXPECT_CALL(mock_finish_gathering_consent_callback, Run).Times(1);
  delegate.OnUiAccepted(mock_finish_gathering_consent_callback.Get());
}

TEST_F(AutofillSaveIbanDelegateTest, OnUiAcceptedRunsLocalCallback) {
  auto delegate = AutofillSaveIbanDelegate(MakeLocalCallback(), web_contents());

  base::MockOnceClosure mock_finish_gathering_consent_callback;
  delegate.OnUiAccepted(mock_finish_gathering_consent_callback.Get(),
                        kUserProvidedNickname);

  EXPECT_THAT(local_offer_decision_,
              testing::Optional(EqualToLocalCallbackArgs(
                  SaveIbanOfferUserDecision::kAccepted,
                  /*user_provided_nickname=*/kUserProvidedNickname)));
}

TEST_F(AutofillSaveIbanDelegateTest, OnUiCanceledRunsLocalCallback) {
  auto delegate = AutofillSaveIbanDelegate(MakeLocalCallback(), web_contents());

  delegate.OnUiCanceled();

  EXPECT_THAT(local_offer_decision_, testing::Optional(EqualToLocalCallbackArgs(
                                         SaveIbanOfferUserDecision::kDeclined,
                                         /*user_provided_nickname=*/u"")));
}

TEST_F(AutofillSaveIbanDelegateTest, OnUiIgnoredRunsLocalCallback) {
  auto delegate = AutofillSaveIbanDelegate(MakeLocalCallback(), web_contents());

  delegate.OnUiIgnored();

  EXPECT_THAT(local_offer_decision_, testing::Optional(EqualToLocalCallbackArgs(
                                         SaveIbanOfferUserDecision::kIgnored,
                                         /*user_provided_nickname=*/u"")));
}

// Tests that IBAN is saved if device lock requirements are met (example: device
// lock is set).
TEST_F(AutofillSaveIbanDelegateTest, DeviceLockRequirementsMet) {
  base::MockOnceClosure mock_finish_gathering_consent_callback;
  delegate_->OnUiAccepted(mock_finish_gathering_consent_callback.Get(),
                          kUserProvidedNickname);

  // Verify that device lock requirements check was started but that IBAN is not
  // saved yet.
  EXPECT_TRUE(test_bridge_->did_start_checking_device_lock_requirements());
  EXPECT_FALSE(local_offer_decision_.has_value());

  test_bridge_->SimulateFinishedCheckingDeviceLockRequirements(
      /*are_device_lock_requirements_met=*/true);
  EXPECT_THAT(local_offer_decision_,
              testing::Optional(EqualToLocalCallbackArgs(
                  SaveIbanOfferUserDecision::kAccepted,
                  /*user_provided_nickname=*/kUserProvidedNickname)));
}

// Tests that IBAN is not saved if device lock UI is shown but device lock is
// not set.
TEST_F(AutofillSaveIbanDelegateTest, DeviceLockRequirementsNotMet) {
  base::MockOnceClosure mock_finish_gathering_consent_callback;
  delegate_->OnUiAccepted(mock_finish_gathering_consent_callback.Get(), u"");

  // Verify that device lock requirements check was started but that IBAN is not
  // saved yet.
  EXPECT_TRUE(test_bridge_->did_start_checking_device_lock_requirements());
  EXPECT_FALSE(local_offer_decision_.has_value());

  test_bridge_->SimulateFinishedCheckingDeviceLockRequirements(
      /*are_device_lock_requirements_met=*/false);
  EXPECT_THAT(local_offer_decision_, testing::Optional(EqualToLocalCallbackArgs(
                                         SaveIbanOfferUserDecision::kDeclined,
                                         /*user_provided_nickname=*/u"")));
}

}  // namespace autofill