blob: 3c39e90b3dbc1049072442073bd6258e5f134df9 [file] [log] [blame]
// Copyright 2019 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/collect_user_data_action.h"
#include <utility>
#include "base/guid.h"
#include "base/strings/string16.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/gmock_callback_support.h"
#include "base/test/mock_callback.h"
#include "components/autofill/core/browser/autofill_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/mock_website_login_fetcher.h"
#include "content/public/test/test_renderer_host.h"
#include "content/public/test/web_contents_tester.h"
#include "testing/gmock/include/gmock/gmock.h"
namespace {
const char kFakeUrl[] = "https://www.example.com";
const char kFakeUsername[] = "user@example.com";
const char kFakePassword[] = "example_password";
const char kMemoryLocation[] = "billing";
} // namespace
namespace autofill_assistant {
namespace {
void SetDateTimeProto(DateTimeProto* proto,
int year,
int month,
int day,
int hour,
int minute,
int second) {
proto->mutable_date()->set_year(year);
proto->mutable_date()->set_month(month);
proto->mutable_date()->set_day(day);
proto->mutable_time()->set_hour(hour);
proto->mutable_time()->set_minute(minute);
proto->mutable_time()->set_second(second);
}
MATCHER_P(EqualsProto, message, "") {
std::string expected_serialized, actual_serialized;
message.SerializeToString(&expected_serialized);
arg.SerializeToString(&actual_serialized);
return expected_serialized == actual_serialized;
}
using ::base::test::RunOnceCallback;
using ::testing::_;
using ::testing::Eq;
using ::testing::Invoke;
using ::testing::Property;
using ::testing::Return;
class CollectUserDataActionTest : public content::RenderViewHostTestHarness {
public:
void SetUp() override {
RenderViewHostTestHarness::SetUp();
ON_CALL(mock_action_delegate_, GetClientMemory)
.WillByDefault(Return(&client_memory_));
ON_CALL(mock_action_delegate_, GetPersonalDataManager)
.WillByDefault(Return(&mock_personal_data_manager_));
ON_CALL(mock_action_delegate_, GetWebsiteLoginFetcher)
.WillByDefault(Return(&mock_website_login_fetcher_));
ON_CALL(mock_action_delegate_, CollectUserData(_, _))
.WillByDefault(Invoke([](std::unique_ptr<CollectUserDataOptions>
collect_user_data_options,
std::unique_ptr<UserData> user_data) {
std::move(collect_user_data_options->confirm_callback)
.Run(std::move(user_data));
}));
ON_CALL(mock_website_login_fetcher_, OnGetLoginsForUrl(_, _))
.WillByDefault(
RunOnceCallback<1>(std::vector<WebsiteLoginFetcher::Login>{
WebsiteLoginFetcher::Login(GURL(kFakeUrl), kFakeUsername)}));
ON_CALL(mock_website_login_fetcher_, OnGetPasswordForLogin(_, _))
.WillByDefault(RunOnceCallback<1>(true, kFakePassword));
content::WebContentsTester::For(web_contents())
->SetLastCommittedURL(GURL(kFakeUrl));
ON_CALL(mock_action_delegate_, GetWebContents())
.WillByDefault(Return(web_contents()));
}
protected:
base::MockCallback<Action::ProcessActionCallback> callback_;
MockPersonalDataManager mock_personal_data_manager_;
MockWebsiteLoginFetcher mock_website_login_fetcher_;
MockActionDelegate mock_action_delegate_;
ClientMemory client_memory_;
};
TEST_F(CollectUserDataActionTest, PromptIsShown) {
const char kPrompt[] = "Some message.";
ActionProto action_proto;
action_proto.mutable_collect_user_data()->set_prompt(kPrompt);
CollectUserDataAction action(&mock_action_delegate_, action_proto);
EXPECT_CALL(mock_action_delegate_, SetStatusMessage(kPrompt));
EXPECT_CALL(callback_, Run(_));
action.ProcessAction(callback_.Get());
}
TEST_F(CollectUserDataActionTest, SelectLogin) {
ActionProto action_proto;
auto* login_details =
action_proto.mutable_collect_user_data()->mutable_login_details();
auto* login_option = login_details->add_login_options();
login_option->mutable_password_manager();
login_option->set_payload("payload");
// Action should fetch the logins, but not the passwords.
EXPECT_CALL(mock_website_login_fetcher_, OnGetLoginsForUrl(GURL(kFakeUrl), _))
.Times(1);
EXPECT_CALL(mock_website_login_fetcher_, OnGetPasswordForLogin(_, _))
.Times(0);
ON_CALL(mock_action_delegate_, CollectUserData(_, _))
.WillByDefault(Invoke(
[](std::unique_ptr<CollectUserDataOptions> collect_user_data_options,
std::unique_ptr<UserData> user_data) {
user_data->succeed = true;
user_data->login_choice_identifier.assign(
collect_user_data_options->login_choices[0].identifier);
std::move(collect_user_data_options->confirm_callback)
.Run(std::move(user_data));
}));
EXPECT_CALL(callback_,
Run(Pointee(AllOf(
Property(&ProcessedActionProto::status, ACTION_APPLIED),
Property(&ProcessedActionProto::collect_user_data_result,
Property(&CollectUserDataResultProto::login_payload,
"payload"))))));
CollectUserDataAction action(&mock_action_delegate_, action_proto);
action.ProcessAction(callback_.Get());
}
TEST_F(CollectUserDataActionTest, LoginChoiceAutomaticIfNoOtherOptions) {
ActionProto action_proto;
auto* collect_user_data = action_proto.mutable_collect_user_data();
collect_user_data->set_request_terms_and_conditions(false);
auto* login_details = collect_user_data->mutable_login_details();
auto* login_option = login_details->add_login_options();
login_option->mutable_custom()->set_label("Guest Checkout");
login_option->set_payload("guest");
login_option->set_choose_automatically_if_no_other_options(true);
login_option = login_details->add_login_options();
login_option->mutable_password_manager();
login_option->set_payload("password_manager");
ON_CALL(mock_website_login_fetcher_, OnGetLoginsForUrl(_, _))
.WillByDefault(
RunOnceCallback<1>(std::vector<WebsiteLoginFetcher::Login>{}));
EXPECT_CALL(mock_action_delegate_, CollectUserData(_, _)).Times(0);
EXPECT_CALL(callback_,
Run(Pointee(AllOf(
Property(&ProcessedActionProto::status, ACTION_APPLIED),
Property(&ProcessedActionProto::collect_user_data_result,
Property(&CollectUserDataResultProto::login_payload,
"guest"))))));
CollectUserDataAction action(&mock_action_delegate_, action_proto);
action.ProcessAction(callback_.Get());
}
TEST_F(CollectUserDataActionTest, SelectLoginFailsIfNoOptionAvailable) {
ActionProto action_proto;
auto* collect_user_data = action_proto.mutable_collect_user_data();
auto* login_details = collect_user_data->mutable_login_details();
auto* login_option = login_details->add_login_options();
login_option->mutable_password_manager();
login_option->set_payload("password_manager");
ON_CALL(mock_website_login_fetcher_, OnGetLoginsForUrl(_, _))
.WillByDefault(
RunOnceCallback<1>(std::vector<WebsiteLoginFetcher::Login>{}));
EXPECT_CALL(callback_, Run(Pointee(Property(&ProcessedActionProto::status,
COLLECT_USER_DATA_ERROR))));
CollectUserDataAction action(&mock_action_delegate_, action_proto);
action.ProcessAction(callback_.Get());
}
TEST_F(CollectUserDataActionTest, SelectContactDetails) {
ActionProto action_proto;
auto* collect_user_data_proto = action_proto.mutable_collect_user_data();
collect_user_data_proto->set_request_terms_and_conditions(false);
auto* contact_details_proto =
collect_user_data_proto->mutable_contact_details();
contact_details_proto->set_contact_details_name(kMemoryLocation);
contact_details_proto->set_request_payer_name(true);
contact_details_proto->set_request_payer_email(true);
contact_details_proto->set_request_payer_phone(true);
autofill::AutofillProfile contact_profile;
contact_profile.SetRawInfo(autofill::ServerFieldType::NAME_FULL,
base::UTF8ToUTF16("Marion Mitchell Morrison"));
contact_profile.SetRawInfo(autofill::ServerFieldType::NAME_FIRST,
base::UTF8ToUTF16("Marion"));
contact_profile.SetRawInfo(autofill::ServerFieldType::NAME_MIDDLE,
base::UTF8ToUTF16("Mitchell"));
contact_profile.SetRawInfo(autofill::ServerFieldType::NAME_LAST,
base::UTF8ToUTF16("Morrison"));
contact_profile.SetRawInfo(autofill::ServerFieldType::EMAIL_ADDRESS,
base::UTF8ToUTF16("marion@me.xyz"));
contact_profile.SetRawInfo(autofill::ServerFieldType::PHONE_HOME_WHOLE_NUMBER,
base::UTF8ToUTF16("16505678910"));
ON_CALL(mock_action_delegate_, CollectUserData(_, _))
.WillByDefault(Invoke(
[=](std::unique_ptr<CollectUserDataOptions> collect_user_data_options,
std::unique_ptr<UserData> user_data) {
user_data->succeed = true;
user_data->contact_profile =
std::make_unique<autofill::AutofillProfile>(contact_profile);
std::move(collect_user_data_options->confirm_callback)
.Run(std::move(user_data));
}));
EXPECT_CALL(callback_,
Run(Pointee(AllOf(
Property(&ProcessedActionProto::status, ACTION_APPLIED),
Property(&ProcessedActionProto::collect_user_data_result,
Property(&CollectUserDataResultProto::payer_email,
"marion@me.xyz"))))));
CollectUserDataAction action(&mock_action_delegate_, action_proto);
action.ProcessAction(callback_.Get());
EXPECT_EQ(client_memory_.has_selected_address(kMemoryLocation), true);
auto* profile = client_memory_.selected_address(kMemoryLocation);
EXPECT_EQ(profile->GetRawInfo(autofill::NAME_FULL),
base::UTF8ToUTF16("Marion Mitchell Morrison"));
EXPECT_EQ(profile->GetRawInfo(autofill::PHONE_HOME_WHOLE_NUMBER),
base::UTF8ToUTF16("16505678910"));
EXPECT_EQ(profile->GetRawInfo(autofill::EMAIL_ADDRESS),
base::UTF8ToUTF16("marion@me.xyz"));
}
TEST_F(CollectUserDataActionTest, SelectPaymentMethod) {
ActionProto action_proto;
action_proto.mutable_collect_user_data()->set_request_payment_method(true);
action_proto.mutable_collect_user_data()->set_request_terms_and_conditions(
false);
autofill::AutofillProfile billing_profile(base::GenerateGUID(), kFakeUrl);
autofill::test::SetProfileInfo(&billing_profile, "Marion", "Mitchell",
"Morrison", "marion@me.xyz", "Fox",
"123 Zoo St.", "unit 5", "Hollywood", "CA",
"91601", "US", "16505678910");
ON_CALL(mock_personal_data_manager_, GetProfileByGUID(billing_profile.guid()))
.WillByDefault(Return(&billing_profile));
autofill::CreditCard credit_card(base::GenerateGUID(), kFakeUrl);
autofill::test::SetCreditCardInfo(&credit_card, "Marion Mitchell",
"4111 1111 1111 1111", "01", "2020",
billing_profile.guid());
ON_CALL(mock_action_delegate_, CollectUserData(_, _))
.WillByDefault(Invoke(
[=](std::unique_ptr<CollectUserDataOptions> collect_user_data_options,
std::unique_ptr<UserData> user_data) {
user_data->card =
std::make_unique<autofill::CreditCard>(credit_card);
user_data->succeed = true;
std::move(collect_user_data_options->confirm_callback)
.Run(std::move(user_data));
}));
EXPECT_CALL(
callback_,
Run(Pointee(AllOf(
Property(&ProcessedActionProto::status, ACTION_APPLIED),
Property(&ProcessedActionProto::collect_user_data_result,
Property(&CollectUserDataResultProto::card_issuer_network,
"visa"))))));
CollectUserDataAction action(&mock_action_delegate_, action_proto);
action.ProcessAction(callback_.Get());
EXPECT_EQ(client_memory_.has_selected_card(), true);
EXPECT_THAT(client_memory_.selected_card()->Compare(credit_card), Eq(0));
}
TEST_F(CollectUserDataActionTest, MandatoryPostalCodeWithoutErrorMessageFails) {
ActionProto action_proto;
action_proto.mutable_collect_user_data()->set_request_payment_method(true);
action_proto.mutable_collect_user_data()->set_require_billing_postal_code(
true);
EXPECT_CALL(
callback_,
Run(Pointee(Property(&ProcessedActionProto::status, INVALID_ACTION))));
CollectUserDataAction action(&mock_action_delegate_, action_proto);
action.ProcessAction(callback_.Get());
}
TEST_F(CollectUserDataActionTest, ContactDetailsCanHandleUtf8) {
ActionProto action_proto;
auto* collect_user_data_proto = action_proto.mutable_collect_user_data();
collect_user_data_proto->set_request_terms_and_conditions(false);
auto* contact_details_proto =
collect_user_data_proto->mutable_contact_details();
contact_details_proto->set_contact_details_name(kMemoryLocation);
contact_details_proto->set_request_payer_name(true);
contact_details_proto->set_request_payer_email(true);
// Name = 艾丽森 in UTF-8.
autofill::AutofillProfile contact_profile;
contact_profile.SetRawInfo(
autofill::ServerFieldType::NAME_FULL,
base::UTF8ToUTF16("\xE8\x89\xBE\xE4\xB8\xBD\xE6\xA3\xAE"));
contact_profile.SetRawInfo(
autofill::ServerFieldType::EMAIL_ADDRESS,
base::UTF8ToUTF16("\xE8\x89\xBE\xE4\xB8\xBD\xE6\xA3\xAE@example.com"));
ON_CALL(mock_action_delegate_, CollectUserData(_, _))
.WillByDefault(Invoke(
[=](std::unique_ptr<CollectUserDataOptions> collect_user_data_options,
std::unique_ptr<UserData> user_data) {
user_data->succeed = true;
user_data->contact_profile =
std::make_unique<autofill::AutofillProfile>(contact_profile);
std::move(collect_user_data_options->confirm_callback)
.Run(std::move(user_data));
}));
EXPECT_CALL(
callback_,
Run(Pointee(AllOf(
Property(&ProcessedActionProto::status, ACTION_APPLIED),
Property(
&ProcessedActionProto::collect_user_data_result,
Property(&CollectUserDataResultProto::payer_email,
"\xE8\x89\xBE\xE4\xB8\xBD\xE6\xA3\xAE@example.com"))))));
CollectUserDataAction action(&mock_action_delegate_, action_proto);
action.ProcessAction(callback_.Get());
EXPECT_EQ(client_memory_.has_selected_address(kMemoryLocation), true);
auto* profile = client_memory_.selected_address(kMemoryLocation);
EXPECT_EQ(profile->GetRawInfo(autofill::NAME_FULL),
base::UTF8ToUTF16("\xE8\x89\xBE\xE4\xB8\xBD\xE6\xA3\xAE"));
EXPECT_EQ(
profile->GetRawInfo(autofill::EMAIL_ADDRESS),
base::UTF8ToUTF16("\xE8\x89\xBE\xE4\xB8\xBD\xE6\xA3\xAE@example.com"));
}
TEST_F(CollectUserDataActionTest, UserDataComplete_Contact) {
UserData user_data;
CollectUserDataOptions options;
EXPECT_TRUE(CollectUserDataAction::IsUserDataComplete(
&mock_personal_data_manager_, user_data, options));
user_data.contact_profile = std::make_unique<autofill::AutofillProfile>(
base::GenerateGUID(), kFakeUrl);
options.request_payer_email = true;
EXPECT_FALSE(CollectUserDataAction::IsUserDataComplete(
&mock_personal_data_manager_, user_data, options));
user_data.contact_profile->SetRawInfo(
autofill::ServerFieldType::EMAIL_ADDRESS,
base::UTF8ToUTF16("joedoe@example.com"));
EXPECT_TRUE(CollectUserDataAction::IsUserDataComplete(
&mock_personal_data_manager_, user_data, options));
options.request_payer_name = true;
EXPECT_FALSE(CollectUserDataAction::IsUserDataComplete(
&mock_personal_data_manager_, user_data, options));
user_data.contact_profile->SetRawInfo(autofill::ServerFieldType::NAME_FULL,
base::UTF8ToUTF16("Joe Doe"));
EXPECT_TRUE(CollectUserDataAction::IsUserDataComplete(
&mock_personal_data_manager_, user_data, options));
options.request_payer_phone = true;
EXPECT_FALSE(CollectUserDataAction::IsUserDataComplete(
&mock_personal_data_manager_, user_data, options));
user_data.contact_profile->SetRawInfo(
autofill::ServerFieldType::PHONE_HOME_WHOLE_NUMBER,
base::UTF8ToUTF16("+1 23 456 789 01"));
EXPECT_TRUE(CollectUserDataAction::IsUserDataComplete(
&mock_personal_data_manager_, user_data, options));
}
TEST_F(CollectUserDataActionTest, UserDataComplete_Payment) {
UserData user_data;
CollectUserDataOptions options;
options.request_payment_method = true;
EXPECT_FALSE(CollectUserDataAction::IsUserDataComplete(
&mock_personal_data_manager_, user_data, options));
// Valid credit card, but no billing address.
user_data.card =
std::make_unique<autofill::CreditCard>(base::GenerateGUID(), kFakeUrl);
autofill::test::SetCreditCardInfo(user_data.card.get(), "Marion Mitchell",
"4111 1111 1111 1111", "01", "2020",
/* billing_address_id = */ "");
EXPECT_FALSE(CollectUserDataAction::IsUserDataComplete(
&mock_personal_data_manager_, user_data, options));
// Valid credit card, but invalid billing address.
user_data.card->set_billing_address_id("invalid");
ON_CALL(mock_personal_data_manager_, GetProfileByGUID("invalid"))
.WillByDefault(Return(nullptr));
EXPECT_FALSE(CollectUserDataAction::IsUserDataComplete(
&mock_personal_data_manager_, user_data, options));
// Incomplete billing address.
user_data.billing_address = std::make_unique<autofill::AutofillProfile>(
base::GenerateGUID(), kFakeUrl);
autofill::test::SetProfileInfo(user_data.billing_address.get(), "Marion",
"Mitchell", "Morrison", "marion@me.xyz", "Fox",
"123 Zoo St.", "unit 5", "Hollywood", "CA",
/* zipcode = */ "", "US", "16505678910");
ON_CALL(mock_personal_data_manager_,
GetProfileByGUID(user_data.billing_address->guid()))
.WillByDefault(Return(user_data.billing_address.get()));
user_data.card->set_billing_address_id(user_data.billing_address->guid());
EXPECT_FALSE(CollectUserDataAction::IsUserDataComplete(
&mock_personal_data_manager_, user_data, options));
user_data.billing_address->SetRawInfo(autofill::ADDRESS_HOME_ZIP,
base::UTF8ToUTF16("91601"));
EXPECT_TRUE(CollectUserDataAction::IsUserDataComplete(
&mock_personal_data_manager_, user_data, options));
// Zip code is optional in Argentinian address.
user_data.billing_address->SetRawInfo(autofill::ADDRESS_HOME_ZIP,
base::UTF8ToUTF16(""));
user_data.billing_address->SetRawInfo(autofill::ADDRESS_HOME_COUNTRY,
base::UTF8ToUTF16("AR"));
EXPECT_TRUE(CollectUserDataAction::IsUserDataComplete(
&mock_personal_data_manager_, user_data, options));
options.require_billing_postal_code = true;
EXPECT_FALSE(CollectUserDataAction::IsUserDataComplete(
&mock_personal_data_manager_, user_data, options));
user_data.billing_address->SetRawInfo(autofill::ADDRESS_HOME_ZIP,
base::UTF8ToUTF16("B1675"));
EXPECT_TRUE(CollectUserDataAction::IsUserDataComplete(
&mock_personal_data_manager_, user_data, options));
}
TEST_F(CollectUserDataActionTest, UserDataComplete_Terms) {
UserData user_data;
CollectUserDataOptions options;
options.accept_terms_and_conditions_text.assign("Accept T&C");
EXPECT_FALSE(CollectUserDataAction::IsUserDataComplete(
&mock_personal_data_manager_, user_data, options));
user_data.terms_and_conditions = REQUIRES_REVIEW;
EXPECT_TRUE(CollectUserDataAction::IsUserDataComplete(
&mock_personal_data_manager_, user_data, options));
user_data.terms_and_conditions = ACCEPTED;
EXPECT_TRUE(CollectUserDataAction::IsUserDataComplete(
&mock_personal_data_manager_, user_data, options));
}
TEST_F(CollectUserDataActionTest, UserDataComplete_Login) {
UserData user_data;
CollectUserDataOptions options;
options.request_login_choice = true;
EXPECT_FALSE(CollectUserDataAction::IsUserDataComplete(
&mock_personal_data_manager_, user_data, options));
user_data.login_choice_identifier.assign("1");
EXPECT_TRUE(CollectUserDataAction::IsUserDataComplete(
&mock_personal_data_manager_, user_data, options));
}
TEST_F(CollectUserDataActionTest, UserDataComplete_ShippingAddress) {
UserData user_data;
CollectUserDataOptions options;
options.request_shipping = true;
EXPECT_FALSE(CollectUserDataAction::IsUserDataComplete(
&mock_personal_data_manager_, user_data, options));
// Incomplete address.
user_data.shipping_address = std::make_unique<autofill::AutofillProfile>(
base::GenerateGUID(), kFakeUrl);
autofill::test::SetProfileInfo(user_data.shipping_address.get(), "Marion",
"Mitchell", "Morrison", "marion@me.xyz", "Fox",
"123 Zoo St.", "unit 5", "Hollywood", "CA",
/* zipcode = */ "", "US", "16505678910");
EXPECT_FALSE(CollectUserDataAction::IsUserDataComplete(
&mock_personal_data_manager_, user_data, options));
user_data.shipping_address->SetRawInfo(autofill::ADDRESS_HOME_ZIP,
base::UTF8ToUTF16("91601"));
EXPECT_TRUE(CollectUserDataAction::IsUserDataComplete(
&mock_personal_data_manager_, user_data, options));
}
TEST_F(CollectUserDataActionTest, UserDataComplete_DateTimeRange) {
UserData user_data;
CollectUserDataOptions options;
options.request_date_time_range = true;
EXPECT_FALSE(CollectUserDataAction::IsUserDataComplete(
&mock_personal_data_manager_, user_data, options));
SetDateTimeProto(&user_data.date_time_range_start, 2019, 12, 31, 10, 30, 0);
SetDateTimeProto(&user_data.date_time_range_end, 2019, 1, 28, 16, 0, 0);
// Start date not before end date.
EXPECT_FALSE(CollectUserDataAction::IsUserDataComplete(
&mock_personal_data_manager_, user_data, options));
user_data.date_time_range_end.mutable_date()->set_year(2020);
EXPECT_TRUE(CollectUserDataAction::IsUserDataComplete(
&mock_personal_data_manager_, user_data, options));
}
TEST_F(CollectUserDataActionTest, SelectDateTimeRange) {
ActionProto action_proto;
auto* collect_user_data_proto = action_proto.mutable_collect_user_data();
collect_user_data_proto->set_request_terms_and_conditions(false);
auto* date_time_proto = collect_user_data_proto->mutable_date_time_range();
SetDateTimeProto(date_time_proto->mutable_start(), 2019, 10, 21, 8, 0, 0);
SetDateTimeProto(date_time_proto->mutable_end(), 2019, 11, 5, 16, 0, 0);
SetDateTimeProto(date_time_proto->mutable_min(), 2019, 11, 5, 16, 0, 0);
SetDateTimeProto(date_time_proto->mutable_max(), 2020, 11, 5, 16, 0, 0);
date_time_proto->set_start_label("Pick up");
date_time_proto->set_end_label("Return");
DateTimeProto actual_pickup_time;
DateTimeProto actual_return_time;
SetDateTimeProto(&actual_pickup_time, 2019, 10, 21, 7, 0, 0);
SetDateTimeProto(&actual_return_time, 2019, 10, 25, 19, 0, 0);
ON_CALL(mock_action_delegate_, CollectUserData(_, _))
.WillByDefault(Invoke(
[&](std::unique_ptr<CollectUserDataOptions> collect_user_data_options,
std::unique_ptr<UserData> user_data) {
user_data->succeed = true;
user_data->date_time_range_start = actual_pickup_time;
user_data->date_time_range_end = actual_return_time;
std::move(collect_user_data_options->confirm_callback)
.Run(std::move(user_data));
}));
EXPECT_CALL(
callback_,
Run(Pointee(
AllOf(Property(&ProcessedActionProto::status, ACTION_APPLIED),
Property(&ProcessedActionProto::collect_user_data_result,
Property(&CollectUserDataResultProto::date_time_start,
EqualsProto(actual_pickup_time))),
Property(&ProcessedActionProto::collect_user_data_result,
Property(&CollectUserDataResultProto::date_time_end,
EqualsProto(actual_return_time)))))));
CollectUserDataAction action(&mock_action_delegate_, action_proto);
action.ProcessAction(callback_.Get());
}
TEST_F(CollectUserDataActionTest, StaticSectionValid) {
ActionProto action_proto;
auto* collect_user_data_proto = action_proto.mutable_collect_user_data();
collect_user_data_proto->set_request_terms_and_conditions(false);
ON_CALL(mock_action_delegate_, CollectUserData(_, _))
.WillByDefault(Invoke(
[](std::unique_ptr<CollectUserDataOptions> collect_user_data_options,
std::unique_ptr<UserData> user_data) {
user_data->succeed = true;
std::move(collect_user_data_options->confirm_callback)
.Run(std::move(user_data));
}));
auto* static_section =
collect_user_data_proto->add_additional_prepended_sections();
{
CollectUserDataAction action(&mock_action_delegate_, action_proto);
EXPECT_CALL(
callback_,
Run(Pointee(Property(&ProcessedActionProto::status, INVALID_ACTION))));
action.ProcessAction(callback_.Get());
}
static_section->set_title("Static section");
{
CollectUserDataAction action(&mock_action_delegate_, action_proto);
EXPECT_CALL(
callback_,
Run(Pointee(Property(&ProcessedActionProto::status, INVALID_ACTION))));
action.ProcessAction(callback_.Get());
}
static_section->mutable_static_text_section()->set_text("Lorem ipsum.");
{
CollectUserDataAction action(&mock_action_delegate_, action_proto);
EXPECT_CALL(
callback_,
Run(Pointee(Property(&ProcessedActionProto::status, ACTION_APPLIED))));
action.ProcessAction(callback_.Get());
}
}
TEST_F(CollectUserDataActionTest, TextInputSectionValid) {
ActionProto action_proto;
auto* collect_user_data_proto = action_proto.mutable_collect_user_data();
collect_user_data_proto->set_request_terms_and_conditions(false);
ON_CALL(mock_action_delegate_, CollectUserData(_, _))
.WillByDefault(Invoke(
[](std::unique_ptr<CollectUserDataOptions> collect_user_data_options,
std::unique_ptr<UserData> user_data) {
user_data->succeed = true;
std::move(collect_user_data_options->confirm_callback)
.Run(std::move(user_data));
}));
auto* text_input_section =
collect_user_data_proto->add_additional_prepended_sections();
{
CollectUserDataAction action(&mock_action_delegate_, action_proto);
EXPECT_CALL(
callback_,
Run(Pointee(Property(&ProcessedActionProto::status, INVALID_ACTION))));
action.ProcessAction(callback_.Get());
}
text_input_section->set_title("Text input section");
{
CollectUserDataAction action(&mock_action_delegate_, action_proto);
EXPECT_CALL(
callback_,
Run(Pointee(Property(&ProcessedActionProto::status, INVALID_ACTION))));
action.ProcessAction(callback_.Get());
}
auto* input_field =
text_input_section->mutable_text_input_section()->add_input_fields();
input_field->set_value("12345");
{
CollectUserDataAction action(&mock_action_delegate_, action_proto);
EXPECT_CALL(
callback_,
Run(Pointee(Property(&ProcessedActionProto::status, INVALID_ACTION))));
action.ProcessAction(callback_.Get());
}
input_field->set_input_type(TextInputProto::INPUT_ALPHANUMERIC);
{
CollectUserDataAction action(&mock_action_delegate_, action_proto);
EXPECT_CALL(
callback_,
Run(Pointee(Property(&ProcessedActionProto::status, INVALID_ACTION))));
action.ProcessAction(callback_.Get());
}
input_field->set_client_memory_key("code");
{
CollectUserDataAction action(&mock_action_delegate_, action_proto);
EXPECT_CALL(
callback_,
Run(Pointee(Property(&ProcessedActionProto::status, ACTION_APPLIED))));
action.ProcessAction(callback_.Get());
}
// Duplicate input field fails due to duplicate memory key.
*text_input_section->mutable_text_input_section()->add_input_fields() =
*input_field;
{
CollectUserDataAction action(&mock_action_delegate_, action_proto);
EXPECT_CALL(
callback_,
Run(Pointee(Property(&ProcessedActionProto::status, INVALID_ACTION))));
action.ProcessAction(callback_.Get());
}
text_input_section->mutable_text_input_section()
->mutable_input_fields(1)
->set_client_memory_key("something else");
{
CollectUserDataAction action(&mock_action_delegate_, action_proto);
EXPECT_CALL(
callback_,
Run(Pointee(Property(&ProcessedActionProto::status, ACTION_APPLIED))));
action.ProcessAction(callback_.Get());
}
}
TEST_F(CollectUserDataActionTest, TextInputSectionWritesToClientMemory) {
ActionProto action_proto;
auto* collect_user_data_proto = action_proto.mutable_collect_user_data();
collect_user_data_proto->set_request_terms_and_conditions(false);
ON_CALL(mock_action_delegate_, CollectUserData(_, _))
.WillByDefault(Invoke(
[](std::unique_ptr<CollectUserDataOptions> collect_user_data_options,
std::unique_ptr<UserData> user_data) {
user_data->succeed = true;
user_data->additional_values_to_store["key2"] = "modified";
std::move(collect_user_data_options->confirm_callback)
.Run(std::move(user_data));
}));
auto* text_input_section =
collect_user_data_proto->add_additional_prepended_sections();
text_input_section->set_title("Text input section");
auto* input_field_1 =
text_input_section->mutable_text_input_section()->add_input_fields();
input_field_1->set_value("initial");
input_field_1->set_input_type(TextInputProto::INPUT_ALPHANUMERIC);
input_field_1->set_client_memory_key("key1");
auto* input_field_2 =
text_input_section->mutable_text_input_section()->add_input_fields();
input_field_2->set_value("initial");
input_field_2->set_input_type(TextInputProto::INPUT_ALPHANUMERIC);
input_field_2->set_client_memory_key("key2");
EXPECT_FALSE(client_memory_.has_additional_value("key1"));
EXPECT_FALSE(client_memory_.has_additional_value("key2"));
CollectUserDataAction action(&mock_action_delegate_, action_proto);
EXPECT_CALL(
callback_,
Run(Pointee(Property(&ProcessedActionProto::status, ACTION_APPLIED))));
action.ProcessAction(callback_.Get());
EXPECT_EQ(*client_memory_.additional_value("key1"), "initial");
EXPECT_EQ(*client_memory_.additional_value("key2"), "modified");
}
} // namespace
} // namespace autofill_assistant