chromium/chrome/browser/ui/autofill/autofill_suggestion_controller_test_base.h

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

#ifndef CHROME_BROWSER_UI_AUTOFILL_AUTOFILL_SUGGESTION_CONTROLLER_TEST_BASE_H_
#define CHROME_BROWSER_UI_AUTOFILL_AUTOFILL_SUGGESTION_CONTROLLER_TEST_BASE_H_

#include <concepts>
#include <memory>
#include <optional>
#include <utility>

#include "base/functional/callback.h"
#include "base/memory/weak_ptr.h"
#include "chrome/browser/autofill/personal_data_manager_factory.h"
#include "chrome/browser/ui/autofill/autofill_popup_view.h"
#include "chrome/browser/ui/autofill/mock_autofill_popup_view.h"
#include "chrome/test/base/chrome_render_view_host_test_harness.h"
#include "components/autofill/content/browser/content_autofill_driver.h"
#include "components/autofill/content/browser/test_autofill_client_injector.h"
#include "components/autofill/content/browser/test_autofill_driver_injector.h"
#include "components/autofill/content/browser/test_autofill_manager_injector.h"
#include "components/autofill/content/browser/test_content_autofill_client.h"
#include "components/autofill/core/browser/autofill_external_delegate.h"
#include "components/autofill/core/browser/browser_autofill_manager.h"
#include "components/autofill/core/browser/ui/autofill_suggestion_delegate.h"
#include "components/autofill/core/browser/ui/suggestion_button_action.h"
#include "components/autofill/core/common/autofill_test_utils.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

#if BUILDFLAG(IS_ANDROID)
#include "chrome/browser/autofill/mock_manual_filling_view.h"
#include "chrome/browser/keyboard_accessory/android/manual_filling_controller_impl.h"
#include "chrome/browser/keyboard_accessory/test_utils/android/mock_address_accessory_controller.h"
#include "chrome/browser/keyboard_accessory/test_utils/android/mock_password_accessory_controller.h"
#include "chrome/browser/keyboard_accessory/test_utils/android/mock_payment_method_accessory_controller.h"
#include "chrome/browser/ui/autofill/autofill_keyboard_accessory_controller_impl.h"
#else
#include "chrome/browser/ui/autofill/autofill_popup_controller_impl.h"
#endif  // BUILDFLAG(IS_ANDROID)

namespace autofill {

class AutofillExternalDelegateForPopupTest;
class AutofillSuggestionControllerForTest;

// A `BrowserAutofillManager` with a modified `AutofillExternalDelegate` that
// allows verifying interactions with the popup.
class BrowserAutofillManagerForPopupTest : public BrowserAutofillManager {};

// This text fixture is intended for unit tests of the Autofill popup
// controller, which controls the Autofill popup on Desktop and the Keyboard
// Accessory on Clank. It has two template parameters that allow customizing the
// test fixture's behavior:
// - The class of the `AutofillSuggestionController` to test. The use of this
//   parameter is to be able to test different implementations of the
//   `AutofillSuggestionController` interface.
// - The class of the `AutofillDriver` to inject, used, e.g., in a11y-specific
//   tests.
//
// The main reason for the complexity of the test fixture is that there is
// little value in testing an `AutofillSuggestionController` just by itself:
// Most of its behavior depends on interactions with the `WebContents`, the
// `AutofillClient`, or the `AutofillPopupView`. This test fixture sets these up
// in a way that allows for controller testing.
//
// Once setup, the test fixture should allow writing suggestion controller unit
// tests (on both Desktop and Android) that closely mirror the production setup.
// Example for Desktop:
//
// using SampleTest = AutofillSuggestionControllerTestBase<
//     TestAutofillPopupControllerAutofillClient<>>;
//
// TEST_F(SampleTest, AcceptSuggestionWorksAfter500Ms) {
//   ShowSuggestions(manager(), {SuggestionType::kAddressEntry});
//   EXPECT_CALL(manager().external_delegate(), DidAcceptSuggestion);
//   task_environment()->FastForwardBy(base::Milliseconds(500));
//   client().popup_controller(manager()).AcceptSuggestion(/*index=*/0);
// }
//
// The same test can be run on for the Keyboard Accessory on Android by simply
// changing the test fixture template parameter:
//
// using SampleTest = AutofillSuggestionControllerTestBase<
//     TestAutofillKeyboardAccessoryControllerAutofillClient<>>;
template <typename Client, typename Driver = ContentAutofillDriver>
  requires(std::derived_from<Client, ContentAutofillClient> &&
           std::derived_from<Driver, ContentAutofillDriver>)
class AutofillSuggestionControllerTestBase
    : public ChromeRenderViewHostTestHarness {};

// Below are test versions of `AutofillClient`, `BrowserAutofillManager`,
// `AutofillExternalDelegate` and `AutofillSuggestionController` that are used in the
// fixture above.

class AutofillExternalDelegateForPopupTest : public AutofillExternalDelegate {};

AutofillSuggestionControllerForTestBase;
#endif

class AutofillSuggestionControllerForTest
    : public AutofillSuggestionControllerForTestBase {};

}  // namespace autofill

#endif  // CHROME_BROWSER_UI_AUTOFILL_AUTOFILL_SUGGESTION_CONTROLLER_TEST_BASE_H_