blob: 0be49061b36169f5799f7f65638cbab6d5ae6b4d [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/batch_element_checker.h"
#include <map>
#include <set>
#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/test/gmock_callback_support.h"
#include "base/test/mock_callback.h"
#include "base/test/task_environment.h"
#include "components/autofill_assistant/browser/actions/action_test_utils.h"
#include "components/autofill_assistant/browser/web/element_finder.h"
#include "components/autofill_assistant/browser/web/mock_web_controller.h"
#include "testing/gmock/include/gmock/gmock.h"
using ::base::test::RunOnceCallback;
using ::testing::_;
using ::testing::Contains;
using ::testing::ElementsAre;
using ::testing::Eq;
using ::testing::InSequence;
using ::testing::Key;
using ::testing::Not;
using ::testing::Pair;
namespace autofill_assistant {
namespace {
class BatchElementCheckerTest : public testing::Test {
protected:
BatchElementCheckerTest() : checks_() {}
void SetUp() override { test_util::MockFindAnyElement(mock_web_controller_); }
void OnElementExistenceCheck(const std::string& name,
const ClientStatus& result,
const ElementFinder::Result& ignored_element) {
element_exists_results_[name] = result.ok();
}
BatchElementChecker::ElementCheckCallback ElementExistenceCallback(
const std::string& name) {
return base::BindOnce(&BatchElementCheckerTest::OnElementExistenceCheck,
base::Unretained(this), name);
}
void OnVisibilityRequirementCheck(
const std::string& name,
const ClientStatus& result,
const ElementFinder::Result& ignored_element) {
element_visible_results_[name] = result.ok();
}
BatchElementChecker::ElementCheckCallback VisibilityRequirementCallback(
const std::string& name) {
return base::BindOnce(
&BatchElementCheckerTest::OnVisibilityRequirementCheck,
base::Unretained(this), name);
}
void OnFieldValueCheck(const std::string& name,
const ClientStatus& result,
const std::string& value) {
get_field_value_results_[name] = value;
}
BatchElementChecker::GetFieldValueCallback FieldValueCallback(
const std::string& name) {
return base::BindOnce(&BatchElementCheckerTest::OnFieldValueCheck,
base::Unretained(this), name);
}
void OnDone(const std::string& name) { all_done_.insert(name); }
base::OnceCallback<void()> DoneCallback(const std::string& name) {
return base::BindOnce(&BatchElementCheckerTest::OnDone,
base::Unretained(this), name);
}
void Run(const std::string& callback_name) {
checks_.AddAllDoneCallback(DoneCallback(callback_name));
checks_.Run(&mock_web_controller_);
}
MockWebController mock_web_controller_;
BatchElementChecker checks_;
std::map<std::string, bool> element_exists_results_;
std::map<std::string, bool> element_visible_results_;
std::map<std::string, std::string> get_field_value_results_;
std::set<std::string> all_done_;
};
TEST_F(BatchElementCheckerTest, Empty) {
EXPECT_TRUE(checks_.empty());
checks_.AddElementCheck(Selector({"exists"}),
ElementExistenceCallback("exists"));
EXPECT_FALSE(checks_.empty());
Run("all_done");
EXPECT_THAT(all_done_, Contains("all_done"));
}
TEST_F(BatchElementCheckerTest, OneElementFound) {
Selector expected_selector({"exists"});
test_util::MockFindElement(mock_web_controller_, expected_selector);
checks_.AddElementCheck(expected_selector,
ElementExistenceCallback("exists"));
Run("was_run");
EXPECT_THAT(element_exists_results_, Contains(Pair("exists", true)));
EXPECT_THAT(all_done_, Contains("was_run"));
}
TEST_F(BatchElementCheckerTest, OneElementNotFound) {
Selector expected_notexists_selector({"does_not_exist"});
EXPECT_CALL(mock_web_controller_,
OnFindElement(expected_notexists_selector, _))
.WillOnce(
RunOnceCallback<1>(ClientStatus(ELEMENT_RESOLUTION_FAILED), nullptr));
checks_.AddElementCheck(expected_notexists_selector,
ElementExistenceCallback("does_not_exist"));
Run("was_run");
EXPECT_THAT(element_exists_results_, Contains(Pair("does_not_exist", false)));
EXPECT_THAT(all_done_, Contains("was_run"));
}
TEST_F(BatchElementCheckerTest, OneFieldValueFound) {
Selector expected_selector({"field"});
EXPECT_CALL(mock_web_controller_,
GetFieldValue(EqualsElement(test_util::MockFindElement(
mock_web_controller_, expected_selector)),
_))
.WillOnce(RunOnceCallback<1>(OkClientStatus(), "some value"));
checks_.AddFieldValueCheck(expected_selector, FieldValueCallback("field"));
Run("was_run");
EXPECT_THAT(get_field_value_results_, Contains(Pair("field", "some value")));
EXPECT_THAT(all_done_, Contains("was_run"));
}
TEST_F(BatchElementCheckerTest, OneFieldValueNotFound) {
Selector expected_selector({"field"});
EXPECT_CALL(mock_web_controller_, OnFindElement(expected_selector, _))
.WillOnce(
RunOnceCallback<1>(ClientStatus(ELEMENT_RESOLUTION_FAILED), nullptr));
EXPECT_CALL(mock_web_controller_, GetFieldValue(_, _)).Times(0);
checks_.AddFieldValueCheck(expected_selector, FieldValueCallback("field"));
Run("was_run");
EXPECT_THAT(get_field_value_results_, Contains(Pair("field", "")));
EXPECT_THAT(all_done_, Contains("was_run"));
}
TEST_F(BatchElementCheckerTest, OneFieldValueEmpty) {
Selector expected_selector({"field"});
EXPECT_CALL(mock_web_controller_,
GetFieldValue(EqualsElement(test_util::MockFindElement(
mock_web_controller_, expected_selector)),
_))
.WillOnce(RunOnceCallback<1>(OkClientStatus(), std::string()));
checks_.AddFieldValueCheck(expected_selector, FieldValueCallback("field"));
Run("was_run");
EXPECT_THAT(get_field_value_results_, Contains(Pair("field", std::string())));
EXPECT_THAT(all_done_, Contains("was_run"));
}
TEST_F(BatchElementCheckerTest, MultipleElements) {
Selector expected_selector_1({"1"});
test_util::MockFindElement(mock_web_controller_, expected_selector_1);
Selector expected_selector_2({"2"});
test_util::MockFindElement(mock_web_controller_, expected_selector_2);
Selector expected_selector_3({"3"});
EXPECT_CALL(mock_web_controller_, OnFindElement(expected_selector_3, _))
.WillOnce(
RunOnceCallback<1>(ClientStatus(ELEMENT_RESOLUTION_FAILED), nullptr));
Selector expected_selector_4({"4"});
EXPECT_CALL(mock_web_controller_,
GetFieldValue(EqualsElement(test_util::MockFindElement(
mock_web_controller_, expected_selector_4)),
_))
.WillOnce(RunOnceCallback<1>(OkClientStatus(), "value"));
Selector expected_selector_5({"5"});
EXPECT_CALL(mock_web_controller_,
GetFieldValue(EqualsElement(test_util::MockFindElement(
mock_web_controller_, expected_selector_5)),
_))
.WillOnce(RunOnceCallback<1>(ClientStatus(ELEMENT_RESOLUTION_FAILED),
std::string()));
checks_.AddElementCheck(expected_selector_1, ElementExistenceCallback("1"));
checks_.AddElementCheck(expected_selector_2, ElementExistenceCallback("2"));
checks_.AddElementCheck(expected_selector_3, ElementExistenceCallback("3"));
checks_.AddFieldValueCheck(expected_selector_4, FieldValueCallback("4"));
checks_.AddFieldValueCheck(expected_selector_5, FieldValueCallback("5"));
Run("was_run");
EXPECT_THAT(element_exists_results_, Contains(Pair("1", true)));
EXPECT_THAT(element_exists_results_, Contains(Pair("2", true)));
EXPECT_THAT(element_exists_results_, Contains(Pair("3", false)));
EXPECT_THAT(get_field_value_results_, Contains(Pair("4", "value")));
EXPECT_THAT(get_field_value_results_, Contains(Pair("5", std::string())));
EXPECT_THAT(all_done_, Contains("was_run"));
}
TEST_F(BatchElementCheckerTest, DeduplicateElementExists) {
Selector expected_selector_1({"1"});
test_util::MockFindElement(mock_web_controller_, expected_selector_1);
Selector expected_selector_2({"2"});
test_util::MockFindElement(mock_web_controller_, expected_selector_2);
checks_.AddElementCheck(expected_selector_1,
ElementExistenceCallback("first 1"));
checks_.AddElementCheck(expected_selector_1,
ElementExistenceCallback("second 1"));
checks_.AddElementCheck(expected_selector_2, ElementExistenceCallback("2"));
Run("was_run");
EXPECT_THAT(element_exists_results_, Contains(Pair("first 1", true)));
EXPECT_THAT(element_exists_results_, Contains(Pair("second 1", true)));
EXPECT_THAT(element_exists_results_, Contains(Pair("2", true)));
EXPECT_THAT(all_done_, Contains("was_run"));
}
TEST_F(BatchElementCheckerTest, DeduplicateElementVisible) {
Selector expected_selector_1({"1"});
test_util::MockFindElement(mock_web_controller_, expected_selector_1);
Selector expected_selector_2({"2"});
test_util::MockFindElement(mock_web_controller_, expected_selector_2);
checks_.AddElementCheck(expected_selector_1,
VisibilityRequirementCallback("first 1"));
checks_.AddElementCheck(expected_selector_1,
VisibilityRequirementCallback("second 1"));
checks_.AddElementCheck(expected_selector_2,
VisibilityRequirementCallback("2"));
Run("was_run");
EXPECT_THAT(element_visible_results_, Contains(Pair("first 1", true)));
EXPECT_THAT(element_visible_results_, Contains(Pair("second 1", true)));
EXPECT_THAT(element_visible_results_, Contains(Pair("2", true)));
EXPECT_THAT(all_done_, Contains("was_run"));
}
TEST_F(BatchElementCheckerTest, CallMultipleAllDoneCallbacks) {
Selector expected_selector({"exists"});
test_util::MockFindElement(mock_web_controller_, expected_selector);
checks_.AddElementCheck(expected_selector,
ElementExistenceCallback("exists"));
checks_.AddAllDoneCallback(DoneCallback("1"));
checks_.AddAllDoneCallback(DoneCallback("2"));
checks_.AddAllDoneCallback(DoneCallback("3"));
checks_.Run(&mock_web_controller_);
EXPECT_THAT(all_done_, ElementsAre("1", "2", "3"));
}
// Deduplicate get field
} // namespace
} // namespace autofill_assistant