#include "chrome/browser/autofill/glic/actor_filling_observer.h"
#include "base/test/gmock_expected_support.h"
#include "base/test/task_environment.h"
#include "base/test/test_future.h"
#include "base/time/time.h"
#include "components/autofill/core/browser/data_model/payments/credit_card.h"
#include "components/autofill/core/browser/foundations/autofill_manager.h"
#include "components/autofill/core/browser/foundations/with_test_autofill_client_driver_manager.h"
#include "components/autofill/core/browser/payments/credit_card_access_manager_test_api.h"
#include "components/autofill/core/common/autofill_test_utils.h"
#include "components/autofill/core/common/unique_ids.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace autofill {
namespace {
using ::base::test::ErrorIs;
using ::base::test::HasValue;
using test::MakeFieldGlobalId;
using test::MakeFormGlobalId;
class ActorFillingObserverTest : public ::testing::Test,
public WithTestAutofillClientDriverManager<> {
public:
ActorFillingObserverTest() {
InitAutofillClient();
CreateAutofillDriver();
}
protected:
using Future =
base::test::TestFuture<base::expected<void, ActorFormFillingError>>;
const AutofillProfile* AddProfile() {
AutofillProfile profile = test::GetFullProfile();
adm().AddProfile(profile);
return adm().GetProfileByGUID(profile.guid());
}
AddressDataManager& adm() {
return autofill_client().GetPersonalDataManager().address_data_manager();
}
CreditCardAccessManager& credit_card_access_manager(size_t index = 0) {
return *autofill_manager(index).GetCreditCardAccessManager();
}
void FastForwardBy(base::TimeDelta delta) {
task_environment_.FastForwardBy(delta);
}
private:
base::test::TaskEnvironment task_environment_{
base::test::TaskEnvironment::TimeSource::MOCK_TIME};
test::AutofillUnitTestEnvironment autofill_unit_test_environment_;
};
TEST_F(ActorFillingObserverTest, EmptyInput) {
Future future;
ActorFillingObserver observer(autofill_client(), {},
future.GetCallback());
EXPECT_THAT(future.Get(), HasValue());
}
TEST_F(ActorFillingObserverTest, Destruction) {
Future future;
std::optional<ActorFillingObserver> observer;
observer.emplace(autofill_client(),
base::span_from_ref(MakeFieldGlobalId()),
future.GetCallback());
observer.reset();
EXPECT_THAT(future.Get(), ErrorIs(ActorFormFillingError::kNoForm));
}
TEST_F(ActorFillingObserverTest, SingleFieldFill) {
std::vector<FieldGlobalId> field_ids = {MakeFieldGlobalId()};
Future future;
ActorFillingObserver observer(autofill_client(), field_ids,
future.GetCallback());
autofill_manager().NotifyObservers(
&AutofillManager::Observer::OnFillOrPreviewForm, MakeFormGlobalId(),
mojom::ActionPersistence::kFill, field_ids, AddProfile());
EXPECT_THAT(future.Get(), HasValue());
}
TEST_F(ActorFillingObserverTest, SingleFieldPreview) {
std::vector<FieldGlobalId> field_ids = {MakeFieldGlobalId()};
Future future;
std::optional<ActorFillingObserver> observer;
observer.emplace(autofill_client(), field_ids, future.GetCallback());
autofill_manager().NotifyObservers(
&AutofillManager::Observer::OnFillOrPreviewForm, MakeFormGlobalId(),
mojom::ActionPersistence::kPreview, field_ids, AddProfile());
observer.reset();
EXPECT_THAT(future.Get(), ErrorIs(ActorFormFillingError::kNoForm));
}
TEST_F(ActorFillingObserverTest, MultiFieldFill) {
std::vector<FieldGlobalId> field_ids = {MakeFieldGlobalId(),
MakeFieldGlobalId()};
Future future;
ActorFillingObserver observer(autofill_client(), field_ids,
future.GetCallback());
autofill_manager().NotifyObservers(
&AutofillManager::Observer::OnFillOrPreviewForm, MakeFormGlobalId(),
mojom::ActionPersistence::kFill, std::vector({field_ids[0]}),
AddProfile());
autofill_manager().NotifyObservers(
&AutofillManager::Observer::OnFillOrPreviewForm, MakeFormGlobalId(),
mojom::ActionPersistence::kFill, std::vector({field_ids[1]}),
AddProfile());
EXPECT_THAT(future.Get(), HasValue());
}
TEST_F(ActorFillingObserverTest, IncompleteMultiFieldFill) {
std::vector<FieldGlobalId> field_ids = {MakeFieldGlobalId(),
MakeFieldGlobalId()};
Future future;
std::optional<ActorFillingObserver> observer;
observer.emplace(autofill_client(), field_ids, future.GetCallback());
autofill_manager().NotifyObservers(
&AutofillManager::Observer::OnFillOrPreviewForm, MakeFormGlobalId(),
mojom::ActionPersistence::kFill, std::vector({field_ids[0]}),
AddProfile());
observer.reset();
EXPECT_THAT(future.Get(), ErrorIs(ActorFormFillingError::kNoForm));
}
TEST_F(ActorFillingObserverTest, FillingTimeout) {
Future future;
ActorFillingObserver observer(
autofill_client(),
base::span_from_ref(MakeFieldGlobalId()),
future.GetCallback());
ASSERT_GT(ActorFillingObserver::GetFillingTimeout(), base::Milliseconds(1));
EXPECT_FALSE(future.IsReady());
FastForwardBy(ActorFillingObserver::GetFillingTimeout() -
base::Milliseconds(1));
EXPECT_FALSE(future.IsReady());
FastForwardBy(base::Milliseconds(1));
EXPECT_TRUE(future.IsReady());
EXPECT_THAT(future.Get(), ErrorIs(ActorFormFillingError::kNoForm));
}
TEST_F(ActorFillingObserverTest, FillingTimeoutWithCreditCardFetch) {
CreateAutofillDriver();
using Observer = CreditCardAccessManager::Observer;
Future future;
CreditCard card;
ActorFillingObserver observer(
autofill_client(),
base::span_from_ref(MakeFieldGlobalId()),
future.GetCallback());
ASSERT_GT(ActorFillingObserver::GetFillingTimeout(), base::Milliseconds(1));
FastForwardBy(ActorFillingObserver::GetFillingTimeout() -
base::Milliseconds(1));
EXPECT_FALSE(future.IsReady());
test_api(credit_card_access_manager(1))
.NotifyObservers(&Observer::OnCreditCardFetchStarted, card);
EXPECT_FALSE(future.IsReady());
FastForwardBy(base::Milliseconds(1));
EXPECT_FALSE(future.IsReady());
FastForwardBy(2 * ActorFillingObserver::GetFillingTimeout());
EXPECT_FALSE(future.IsReady());
test_api(credit_card_access_manager(1))
.NotifyObservers(&Observer::OnCreditCardFetchFailed, &card);
FastForwardBy(ActorFillingObserver::GetFillingTimeout() -
base::Milliseconds(1));
EXPECT_FALSE(future.IsReady());
FastForwardBy(base::Milliseconds(1));
EXPECT_TRUE(future.IsReady());
EXPECT_THAT(future.Get(), ErrorIs(ActorFormFillingError::kNoForm));
}
}
}