blob: af351ee14723948025e8cdc607fdbeb1f6f25364 [file] [log] [blame]
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/autofill_assistant/browser/actions/use_address_action.h"
#include <utility>
#include "base/guid.h"
#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/gmock_callback_support.h"
#include "base/test/mock_callback.h"
#include "build/build_config.h"
#include "components/autofill/core/browser/autofill_test_utils.h"
#include "components/autofill/core/browser/data_model/autofill_profile.h"
#include "components/autofill_assistant/browser/actions/action_test_utils.h"
#include "components/autofill_assistant/browser/actions/mock_action_delegate.h"
#include "components/autofill_assistant/browser/mock_personal_data_manager.h"
#include "components/autofill_assistant/browser/string_conversions_util.h"
#include "components/autofill_assistant/browser/user_model.h"
#include "components/autofill_assistant/browser/web/mock_web_controller.h"
#include "testing/gmock/include/gmock/gmock.h"
namespace autofill_assistant {
namespace {
const char kAddressName[] = "billing";
const char kFakeSelector[] = "#selector";
const char kFirstName[] = "FirstName";
const char kLastName[] = "LastName";
const char kEmail[] = "foobar@gmail.com";
const char kPhoneNumber[] = "+41791234567";
const char kModelIdentifier[] = "identifier";
using ::base::test::RunOnceCallback;
using ::testing::_;
using ::testing::Eq;
using ::testing::Expectation;
using ::testing::InSequence;
using ::testing::Invoke;
using ::testing::NotNull;
using ::testing::Pointee;
using ::testing::Return;
using ::testing::SaveArgPointee;
class UseAddressActionTest : public testing::Test {
public:
void SetUp() override {
autofill::test::SetProfileInfo(&profile_, kFirstName, "", kLastName, kEmail,
"", "", "", "", "", "", "", kPhoneNumber);
// Store copies of |profile_| in |user_data_| and |user_model_|.
user_data_.selected_addresses_[kAddressName] =
std::make_unique<autofill::AutofillProfile>(profile_);
auto profiles = std::make_unique<
std::vector<std::unique_ptr<autofill::AutofillProfile>>>();
profiles->emplace_back(
std::make_unique<autofill::AutofillProfile>(profile_));
user_model_.SetAutofillProfiles(std::move(profiles));
ValueProto profile_value;
profile_value.mutable_profiles()->add_values()->set_guid(profile_.guid());
user_model_.SetValue(kModelIdentifier, profile_value);
ON_CALL(mock_action_delegate_, GetWebController)
.WillByDefault(Return(&mock_web_controller_));
ON_CALL(mock_action_delegate_, GetUserData)
.WillByDefault(Return(&user_data_));
ON_CALL(mock_action_delegate_, GetUserModel)
.WillByDefault(Return(&user_model_));
ON_CALL(mock_action_delegate_, GetPersonalDataManager)
.WillByDefault(Return(&mock_personal_data_manager_));
ON_CALL(mock_action_delegate_, RunElementChecks)
.WillByDefault(Invoke([this](BatchElementChecker* checker) {
checker->Run(&mock_web_controller_);
}));
ON_CALL(mock_action_delegate_, OnShortWaitForElement(_, _))
.WillByDefault(RunOnceCallback<1>(OkClientStatus(),
base::TimeDelta::FromSeconds(0)));
test_util::MockFindAnyElement(mock_web_controller_);
}
protected:
ActionProto CreateUseAddressAction() {
ActionProto action;
UseAddressProto* use_address = action.mutable_use_address();
use_address->set_name(kAddressName);
*use_address->mutable_form_field_element() = ToSelectorProto(kFakeSelector);
return action;
}
RequiredFieldProto* AddRequiredField(ActionProto* action,
std::string value_expression,
std::string selector) {
auto* required_field = action->mutable_use_address()->add_required_fields();
required_field->set_value_expression(value_expression);
*required_field->mutable_element() = ToSelectorProto(selector);
return required_field;
}
ProcessedActionStatusProto ProcessAction(const ActionProto& action_proto) {
UseAddressAction action(&mock_action_delegate_, action_proto);
ProcessedActionProto capture;
EXPECT_CALL(callback_, Run(_)).WillOnce(SaveArgPointee<0>(&capture));
action.ProcessAction(callback_.Get());
return capture.status();
}
base::MockCallback<Action::ProcessActionCallback> callback_;
MockPersonalDataManager mock_personal_data_manager_;
MockActionDelegate mock_action_delegate_;
MockWebController mock_web_controller_;
UserData user_data_;
UserModel user_model_;
autofill::AutofillProfile profile_ = {base::GenerateGUID(),
autofill::test::kEmptyOrigin};
};
#if !defined(OS_ANDROID)
#define MAYBE_FillManually FillManually
#else
#define MAYBE_FillManually DISABLED_FillManually
#endif
TEST_F(UseAddressActionTest, MAYBE_FillManually) {
InSequence seq;
ActionProto action_proto = CreateUseAddressAction();
EXPECT_EQ(ProcessedActionStatusProto::MANUAL_FALLBACK,
ProcessAction(action_proto));
}
TEST_F(UseAddressActionTest, InvalidActionNoSelectorSet) {
ActionProto action;
action.mutable_use_address();
EXPECT_EQ(ProcessedActionStatusProto::INVALID_ACTION, ProcessAction(action));
}
TEST_F(UseAddressActionTest, InvalidActionNameSetButEmpty) {
ActionProto action;
UseAddressProto* use_address = action.mutable_use_address();
*use_address->mutable_form_field_element() = ToSelectorProto(kFakeSelector);
use_address->set_name("");
EXPECT_EQ(ProcessedActionStatusProto::INVALID_ACTION, ProcessAction(action));
}
TEST_F(UseAddressActionTest, InvalidActionSkipAutofillWithoutRequiredFields) {
ActionProto action;
UseAddressProto* use_address = action.mutable_use_address();
use_address->set_name(kAddressName);
use_address->set_skip_autofill(true);
EXPECT_EQ(ProcessedActionStatusProto::INVALID_ACTION, ProcessAction(action));
}
TEST_F(UseAddressActionTest, PreconditionFailedNoProfileForName) {
ActionProto action;
UseAddressProto* use_address = action.mutable_use_address();
*use_address->mutable_form_field_element() = ToSelectorProto(kFakeSelector);
use_address->set_name("invalid");
EXPECT_EQ(ProcessedActionStatusProto::PRECONDITION_FAILED,
ProcessAction(action));
}
TEST_F(UseAddressActionTest, ResolveProfileByNameSucceeds) {
ON_CALL(mock_action_delegate_,
OnShortWaitForElement(Selector({kFakeSelector}), _))
.WillByDefault(RunOnceCallback<1>(OkClientStatus(),
base::TimeDelta::FromSeconds(0)));
ON_CALL(mock_web_controller_, GetFieldValue(_, _))
.WillByDefault(RunOnceCallback<1>(OkClientStatus(), "not empty"));
ActionProto action;
UseAddressProto* use_address = action.mutable_use_address();
*use_address->mutable_form_field_element() = ToSelectorProto(kFakeSelector);
use_address->set_name(kAddressName);
EXPECT_CALL(mock_action_delegate_,
FillAddressForm(Pointee(Eq(profile_)), _, _))
.WillOnce(RunOnceCallback<2>(OkClientStatus()));
EXPECT_EQ(ProcessedActionStatusProto::ACTION_APPLIED, ProcessAction(action));
}
TEST_F(UseAddressActionTest, InvalidActionModelIdentifierSetButEmpty) {
ActionProto action;
UseAddressProto* use_address = action.mutable_use_address();
*use_address->mutable_form_field_element() = ToSelectorProto(kFakeSelector);
use_address->set_model_identifier("");
EXPECT_EQ(ProcessedActionStatusProto::INVALID_ACTION, ProcessAction(action));
}
TEST_F(UseAddressActionTest, PreconditionFailedNoProfileForModelIdentifier) {
ActionProto action;
UseAddressProto* use_address = action.mutable_use_address();
*use_address->mutable_form_field_element() = ToSelectorProto(kFakeSelector);
use_address->set_model_identifier("invalid");
EXPECT_EQ(ProcessedActionStatusProto::PRECONDITION_FAILED,
ProcessAction(action));
}
TEST_F(UseAddressActionTest, ResolveProfileByModelIdentifierSucceeds) {
ON_CALL(mock_action_delegate_,
OnShortWaitForElement(Selector({kFakeSelector}), _))
.WillByDefault(RunOnceCallback<1>(OkClientStatus(),
base::TimeDelta::FromSeconds(0)));
ON_CALL(mock_web_controller_, GetFieldValue(_, _))
.WillByDefault(RunOnceCallback<1>(OkClientStatus(), "not empty"));
ActionProto action;
UseAddressProto* use_address = action.mutable_use_address();
*use_address->mutable_form_field_element() = ToSelectorProto(kFakeSelector);
use_address->set_model_identifier(kModelIdentifier);
EXPECT_CALL(mock_action_delegate_,
FillAddressForm(Pointee(Eq(profile_)), _, _))
.WillOnce(RunOnceCallback<2>(OkClientStatus()));
EXPECT_EQ(ProcessedActionStatusProto::ACTION_APPLIED, ProcessAction(action));
}
TEST_F(UseAddressActionTest, PreconditionFailedPopulatesUnexpectedErrorInfo) {
InSequence seq;
ActionProto action_proto = CreateUseAddressAction();
user_data_.selected_addresses_[kAddressName] = nullptr;
user_data_.selected_addresses_["one_more"] = nullptr;
UseAddressAction action(&mock_action_delegate_, action_proto);
ProcessedActionProto processed_action;
EXPECT_CALL(callback_, Run(_)).WillOnce(SaveArgPointee<0>(&processed_action));
action.ProcessAction(callback_.Get());
EXPECT_EQ(ProcessedActionStatusProto::PRECONDITION_FAILED,
processed_action.status());
const auto& error_info =
processed_action.status_details().autofill_error_info();
EXPECT_EQ(base::JoinString({kAddressName, "one_more"}, ","),
error_info.client_memory_address_key_names());
EXPECT_EQ(kAddressName, error_info.address_key_requested());
EXPECT_TRUE(error_info.address_pointee_was_null());
}
TEST_F(UseAddressActionTest, ShortWaitForElementVisible) {
EXPECT_CALL(mock_action_delegate_,
OnShortWaitForElement(Selector({kFakeSelector}), _))
.WillOnce(RunOnceCallback<1>(OkClientStatus(),
base::TimeDelta::FromSeconds(0)));
ActionProto action_proto = CreateUseAddressAction();
// Autofill succeeds.
EXPECT_CALL(mock_action_delegate_, FillAddressForm(NotNull(), _, _))
.WillOnce(RunOnceCallback<2>(OkClientStatus()));
// Validation succeeds.
ON_CALL(mock_web_controller_, GetFieldValue(_, _))
.WillByDefault(RunOnceCallback<1>(OkClientStatus(), "not empty"));
EXPECT_EQ(ProcessedActionStatusProto::ACTION_APPLIED,
ProcessAction(action_proto));
}
TEST_F(UseAddressActionTest, ValidationSucceeds) {
InSequence seq;
ActionProto action_proto = CreateUseAddressAction();
AddRequiredField(&action_proto,
base::StrCat({"${",
base::NumberToString(static_cast<int>(
autofill::ServerFieldType::NAME_FIRST)),
"}"}),
"#first_name");
AddRequiredField(&action_proto,
base::StrCat({"${",
base::NumberToString(static_cast<int>(
autofill::ServerFieldType::NAME_LAST)),
"}"}),
"#last_name");
AddRequiredField(&action_proto,
base::StrCat({"${",
base::NumberToString(static_cast<int>(
autofill::ServerFieldType::EMAIL_ADDRESS)),
"}"}),
"#email");
// Autofill succeeds.
EXPECT_CALL(mock_action_delegate_,
FillAddressForm(NotNull(), Eq(Selector({kFakeSelector})), _))
.WillOnce(RunOnceCallback<2>(OkClientStatus()));
// Validation succeeds.
ON_CALL(mock_web_controller_, GetFieldValue(_, _))
.WillByDefault(RunOnceCallback<1>(OkClientStatus(), "not empty"));
EXPECT_EQ(ProcessedActionStatusProto::ACTION_APPLIED,
ProcessAction(action_proto));
}
TEST_F(UseAddressActionTest, FallbackFails) {
ON_CALL(mock_web_controller_, GetElementTag(_, _))
.WillByDefault(RunOnceCallback<1>(OkClientStatus(), "INPUT"));
ActionProto action_proto = CreateUseAddressAction();
AddRequiredField(&action_proto,
base::StrCat({"${",
base::NumberToString(static_cast<int>(
autofill::ServerFieldType::NAME_FIRST)),
"}"}),
"#first_name");
AddRequiredField(&action_proto,
base::StrCat({"${",
base::NumberToString(static_cast<int>(
autofill::ServerFieldType::NAME_LAST)),
"}"}),
"#last_name");
AddRequiredField(&action_proto,
base::StrCat({"${",
base::NumberToString(static_cast<int>(
autofill::ServerFieldType::EMAIL_ADDRESS)),
"}"}),
"#email");
Selector email_selector({"#email"});
Selector first_name_selector({"#first_name"});
Selector last_name_selector({"#last_name"});
// Autofill succeeds.
EXPECT_CALL(mock_action_delegate_,
FillAddressForm(NotNull(), Eq(Selector({kFakeSelector})), _))
.WillOnce(RunOnceCallback<2>(OkClientStatus()));
// Validation fails when getting FIRST_NAME.
EXPECT_CALL(mock_web_controller_,
GetFieldValue(EqualsElement(test_util::MockFindElement(
mock_web_controller_, email_selector)),
_))
.WillOnce(RunOnceCallback<1>(OkClientStatus(), "not empty"));
EXPECT_CALL(mock_web_controller_,
GetFieldValue(EqualsElement(test_util::MockFindElement(
mock_web_controller_, first_name_selector)),
_))
.WillOnce(RunOnceCallback<1>(OkClientStatus(), ""));
EXPECT_CALL(mock_web_controller_,
GetFieldValue(EqualsElement(test_util::MockFindElement(
mock_web_controller_, last_name_selector)),
_))
.WillOnce(RunOnceCallback<1>(OkClientStatus(), "not empty"));
// Fallback fails.
EXPECT_CALL(
mock_web_controller_,
SetValueAttribute(kFirstName,
EqualsElement(test_util::MockFindElement(
mock_action_delegate_, first_name_selector)),
_))
.WillOnce(RunOnceCallback<2>(ClientStatus(OTHER_ACTION_STATUS)));
ProcessedActionProto processed_action;
EXPECT_CALL(callback_, Run(_)).WillOnce(SaveArgPointee<0>(&processed_action));
UseAddressAction action(&mock_action_delegate_, action_proto);
action.ProcessAction(callback_.Get());
EXPECT_EQ(processed_action.status(),
ProcessedActionStatusProto::AUTOFILL_INCOMPLETE);
EXPECT_TRUE(processed_action.has_status_details());
EXPECT_EQ(processed_action.status_details()
.autofill_error_info()
.autofill_field_error_size(),
1);
EXPECT_EQ(OTHER_ACTION_STATUS, processed_action.status_details()
.autofill_error_info()
.autofill_field_error(0)
.status());
}
TEST_F(UseAddressActionTest, FillAddressWithFallback) {
InSequence sequence;
ON_CALL(mock_web_controller_, GetElementTag(_, _))
.WillByDefault(RunOnceCallback<1>(OkClientStatus(), "INPUT"));
ActionProto action_proto = CreateUseAddressAction();
AddRequiredField(&action_proto,
base::StrCat({"${",
base::NumberToString(static_cast<int>(
autofill::ServerFieldType::NAME_FIRST)),
"}"}),
"#first_name");
AddRequiredField(&action_proto,
base::StrCat({"${",
base::NumberToString(static_cast<int>(
autofill::ServerFieldType::NAME_LAST)),
"}"}),
"#last_name");
AddRequiredField(&action_proto,
base::StrCat({"${",
base::NumberToString(static_cast<int>(
autofill::ServerFieldType::EMAIL_ADDRESS)),
"}"}),
"#email");
Selector first_name_selector({"#first_name"});
Selector last_name_selector({"#last_name"});
Selector email_selector({"#email"});
// Autofill succeeds.
EXPECT_CALL(mock_action_delegate_,
FillAddressForm(NotNull(), Eq(Selector({kFakeSelector})), _))
.WillOnce(RunOnceCallback<2>(OkClientStatus()));
// First validation fails with an empty value, called once for each field.
EXPECT_CALL(mock_web_controller_, GetFieldValue(_, _))
.Times(3)
.WillRepeatedly(RunOnceCallback<1>(OkClientStatus(), std::string()));
// Expect fields to be filled
EXPECT_CALL(
mock_web_controller_,
SetValueAttribute(kFirstName,
EqualsElement(test_util::MockFindElement(
mock_action_delegate_, first_name_selector)),
_))
.WillOnce(RunOnceCallback<2>(OkClientStatus()));
EXPECT_CALL(mock_web_controller_,
SetValueAttribute(kLastName,
EqualsElement(test_util::MockFindElement(
mock_action_delegate_, last_name_selector)),
_))
.WillOnce(RunOnceCallback<2>(OkClientStatus()));
EXPECT_CALL(mock_web_controller_,
SetValueAttribute(kEmail,
EqualsElement(test_util::MockFindElement(
mock_action_delegate_, email_selector)),
_))
.WillOnce(RunOnceCallback<2>(OkClientStatus()));
// Second validation succeeds.
EXPECT_CALL(mock_web_controller_, GetFieldValue(_, _))
.Times(3)
.WillRepeatedly(RunOnceCallback<1>(OkClientStatus(), "not empty"));
EXPECT_EQ(ProcessedActionStatusProto::ACTION_APPLIED,
ProcessAction(action_proto));
}
TEST_F(UseAddressActionTest, AutofillFailureWithoutRequiredFieldsIsFatal) {
ActionProto action_proto = CreateUseAddressAction();
EXPECT_CALL(mock_action_delegate_,
FillAddressForm(NotNull(), Eq(Selector({kFakeSelector})), _))
.WillOnce(RunOnceCallback<2>(ClientStatus(OTHER_ACTION_STATUS)));
ProcessedActionProto processed_action;
EXPECT_CALL(callback_, Run(_)).WillOnce(SaveArgPointee<0>(&processed_action));
UseAddressAction action(&mock_action_delegate_, action_proto);
action.ProcessAction(callback_.Get());
EXPECT_EQ(processed_action.status(),
ProcessedActionStatusProto::OTHER_ACTION_STATUS);
EXPECT_EQ(processed_action.has_status_details(), false);
}
TEST_F(UseAddressActionTest,
AutofillFailureWithRequiredFieldsLaunchesFallback) {
InSequence sequence;
ON_CALL(mock_web_controller_, GetElementTag(_, _))
.WillByDefault(RunOnceCallback<1>(OkClientStatus(), "INPUT"));
ActionProto action_proto = CreateUseAddressAction();
AddRequiredField(&action_proto,
base::StrCat({"${",
base::NumberToString(static_cast<int>(
autofill::ServerFieldType::NAME_FIRST)),
"}"}),
"#first_name");
Selector first_name_selector({"#first_name"});
EXPECT_CALL(mock_action_delegate_,
FillAddressForm(NotNull(), Eq(Selector({kFakeSelector})), _))
.WillOnce(RunOnceCallback<2>(ClientStatus(OTHER_ACTION_STATUS)));
// First validation fails.
EXPECT_CALL(mock_web_controller_,
GetFieldValue(EqualsElement(test_util::MockFindElement(
mock_web_controller_, first_name_selector)),
_))
.WillOnce(RunOnceCallback<1>(OkClientStatus(), ""));
// Fill first name.
EXPECT_CALL(
mock_web_controller_,
SetValueAttribute(kFirstName,
EqualsElement(test_util::MockFindElement(
mock_action_delegate_, first_name_selector)),
_))
.WillOnce(RunOnceCallback<2>(OkClientStatus()));
// Second validation succeeds.
EXPECT_CALL(mock_web_controller_,
GetFieldValue(EqualsElement(test_util::MockFindElement(
mock_web_controller_, first_name_selector)),
_))
.WillOnce(RunOnceCallback<1>(OkClientStatus(), "not empty"));
ProcessedActionProto processed_action;
EXPECT_CALL(callback_, Run(_)).WillOnce(SaveArgPointee<0>(&processed_action));
UseAddressAction action(&mock_action_delegate_, action_proto);
action.ProcessAction(callback_.Get());
EXPECT_EQ(processed_action.status(), OTHER_ACTION_STATUS);
EXPECT_EQ(processed_action.status_details()
.autofill_error_info()
.autofill_error_status(),
OTHER_ACTION_STATUS);
}
TEST_F(UseAddressActionTest, FallbackForPhoneSucceeds) {
InSequence sequence;
ON_CALL(mock_web_controller_, GetElementTag(_, _))
.WillByDefault(RunOnceCallback<1>(OkClientStatus(), "INPUT"));
ActionProto action_proto = CreateUseAddressAction();
AddRequiredField(&action_proto, "(+${12}) (${11}) ${10}", "#phone_number");
Selector phone_number_selector({"#phone_number"});
// Autofill succeeds.
EXPECT_CALL(mock_action_delegate_,
FillAddressForm(NotNull(), Eq(Selector({kFakeSelector})), _))
.WillOnce(RunOnceCallback<2>(OkClientStatus()));
// Validation fails when getting phone number.
EXPECT_CALL(mock_web_controller_,
GetFieldValue(EqualsElement(test_util::MockFindElement(
mock_web_controller_, phone_number_selector)),
_))
.WillOnce(RunOnceCallback<1>(OkClientStatus(), ""));
// Fallback succeeds.
EXPECT_CALL(
mock_web_controller_,
SetValueAttribute("(+41) (79) 1234567",
EqualsElement(test_util::MockFindElement(
mock_action_delegate_, phone_number_selector)),
_))
.WillOnce(RunOnceCallback<2>(OkClientStatus()));
// Second validation succeeds.
EXPECT_CALL(mock_web_controller_,
GetFieldValue(EqualsElement(test_util::MockFindElement(
mock_web_controller_, phone_number_selector)),
_))
.WillRepeatedly(RunOnceCallback<1>(OkClientStatus(), "not empty"));
EXPECT_EQ(ProcessedActionStatusProto::ACTION_APPLIED,
ProcessAction(action_proto));
}
TEST_F(UseAddressActionTest, ForcedFallbackWithKeystrokes) {
InSequence sequence;
ON_CALL(mock_web_controller_, GetElementTag(_, _))
.WillByDefault(RunOnceCallback<1>(OkClientStatus(), "INPUT"));
ActionProto action_proto = CreateUseAddressAction();
auto* name_required = AddRequiredField(
&action_proto,
base::StrCat({"${",
base::NumberToString(static_cast<int>(
autofill::ServerFieldType::NAME_FIRST)),
"}"}),
"#first_name");
name_required->set_forced(true);
name_required->set_fill_strategy(SIMULATE_KEY_PRESSES);
name_required->set_delay_in_millisecond(1000);
Selector first_name_selector({"#first_name"});
// Autofill succeeds.
EXPECT_CALL(mock_action_delegate_,
FillAddressForm(NotNull(), Eq(Selector({kFakeSelector})), _))
.WillOnce(RunOnceCallback<2>(OkClientStatus()));
// Do not check required field.
EXPECT_CALL(mock_web_controller_, GetFieldValue(_, _)).Times(0);
// But we still want the first name filled, with simulated keypresses.
auto expected_element =
test_util::MockFindElement(mock_action_delegate_, first_name_selector);
EXPECT_CALL(mock_web_controller_,
SetValueAttribute("", EqualsElement(expected_element), _))
.WillOnce(RunOnceCallback<2>(OkClientStatus()));
EXPECT_CALL(mock_action_delegate_,
WaitUntilDocumentIsInReadyState(
_, DOCUMENT_INTERACTIVE, EqualsElement(expected_element), _))
.WillOnce(RunOnceCallback<3>(OkClientStatus(),
base::TimeDelta::FromSeconds(0)));
EXPECT_CALL(mock_web_controller_,
ScrollIntoView(true, EqualsElement(expected_element), _))
.WillOnce(RunOnceCallback<2>(OkClientStatus()));
EXPECT_CALL(mock_web_controller_, WaitUntilElementIsStable(_, _, _, _))
.WillOnce(RunOnceCallback<3>(OkClientStatus(),
base::TimeDelta::FromSeconds(0)));
EXPECT_CALL(
mock_web_controller_,
ClickOrTapElement(ClickType::CLICK, EqualsElement(expected_element), _))
.WillOnce(RunOnceCallback<2>(OkClientStatus()));
EXPECT_CALL(mock_web_controller_,
SendKeyboardInput(UTF8ToUnicode(kFirstName), 1000,
EqualsElement(expected_element), _))
.WillOnce(RunOnceCallback<3>(OkClientStatus()));
// The field is only checked afterwards and is not empty.
EXPECT_CALL(mock_web_controller_,
GetFieldValue(EqualsElement(test_util::MockFindElement(
mock_web_controller_, first_name_selector)),
_))
.WillOnce(RunOnceCallback<1>(OkClientStatus(), "not empty"));
EXPECT_EQ(ProcessedActionStatusProto::ACTION_APPLIED,
ProcessAction(action_proto));
}
TEST_F(UseAddressActionTest, SkippingAutofill) {
InSequence sequence;
ON_CALL(mock_web_controller_, GetElementTag(_, _))
.WillByDefault(RunOnceCallback<1>(OkClientStatus(), "INPUT"));
ActionProto action_proto;
action_proto.mutable_use_address()->set_name(kAddressName);
AddRequiredField(&action_proto,
base::StrCat({"${",
base::NumberToString(static_cast<int>(
autofill::ServerFieldType::NAME_FIRST)),
"}"}),
"#first_name");
action_proto.mutable_use_address()->set_skip_autofill(true);
Selector first_name_selector({"#first_name"});
EXPECT_CALL(mock_action_delegate_, OnShortWaitForElement(_, _)).Times(0);
EXPECT_CALL(mock_action_delegate_, FillAddressForm(_, _, _)).Times(0);
// First validation fails.
EXPECT_CALL(mock_web_controller_,
GetFieldValue(EqualsElement(test_util::MockFindElement(
mock_web_controller_, first_name_selector)),
_))
.WillOnce(RunOnceCallback<1>(OkClientStatus(), ""));
// Fill first name.
EXPECT_CALL(
mock_web_controller_,
SetValueAttribute(kFirstName,
EqualsElement(test_util::MockFindElement(
mock_action_delegate_, first_name_selector)),
_))
.WillOnce(RunOnceCallback<2>(OkClientStatus()));
// Second validation succeeds.
EXPECT_CALL(mock_web_controller_,
GetFieldValue(EqualsElement(test_util::MockFindElement(
mock_web_controller_, first_name_selector)),
_))
.WillOnce(RunOnceCallback<1>(OkClientStatus(), "not empty"));
ProcessedActionProto processed_action;
EXPECT_CALL(callback_, Run(_)).WillOnce(SaveArgPointee<0>(&processed_action));
UseAddressAction action(&mock_action_delegate_, action_proto);
action.ProcessAction(callback_.Get());
EXPECT_EQ(processed_action.status(),
ProcessedActionStatusProto::ACTION_APPLIED);
}
} // namespace
} // namespace autofill_assistant