1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181
|
// Copyright 2022 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_TEST_INTERACTION_INTERACTIVE_BROWSER_TEST_INTERNAL_H_
#define CHROME_TEST_INTERACTION_INTERACTIVE_BROWSER_TEST_INTERNAL_H_
#include <compare>
#include <memory>
#include <utility>
#include <vector>
#include "base/values.h"
#include "chrome/test/interaction/interaction_test_util_browser.h"
#include "chrome/test/interaction/tracked_element_webcontents.h"
#include "chrome/test/interaction/webcontents_interaction_test_util.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/interaction/element_identifier.h"
#include "ui/base/interaction/element_tracker.h"
#include "ui/base/interaction/interaction_sequence.h"
#include "ui/base/interaction/interactive_test_definitions.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/views/interaction/interactive_views_test_internal.h"
class DevToolsAgentCoverageObserver;
class InteractiveBrowserTestApi;
namespace internal {
// Class that provides functionality needed by InteractiveBrowserTestApi but
// which should not be directly visible to tests inheriting from the API class.
class InteractiveBrowserTestPrivate
: public views::test::internal::InteractiveViewsTestPrivate {
public:
explicit InteractiveBrowserTestPrivate(
std::unique_ptr<InteractionTestUtilBrowser> test_util);
~InteractiveBrowserTestPrivate() override;
// views::test::internal::InteractiveViewsTestPrivate:
void DoTestSetUp() override;
void DoTestTearDown() override;
// Starts code coverage if the proper configuration is present.
void MaybeStartWebUICodeCoverage();
void AddInstrumentedWebContents(
std::unique_ptr<WebContentsInteractionTestUtil>
instrumented_web_contents);
bool IsInstrumentedWebContents(ui::ElementIdentifier element_id) const;
// Removes WebContents instrumentation; can allow for re-instrumentation using
// the same ID later. Returns whether `to_remove` was found and removed.
bool UninstrumentWebContents(ui::ElementIdentifier to_remove);
static std::string DeepQueryToString(
const WebContentsInteractionTestUtil::DeepQuery& deep_query);
protected:
// views::test::InteractiveViewsTestPrivate:
gfx::NativeWindow GetNativeWindowFromElement(
ui::TrackedElement* el) const override;
gfx::NativeWindow GetNativeWindowFromContext(
ui::ElementContext context) const override;
std::string DebugDescribeContext(ui::ElementContext context) const override;
DebugTreeNode DebugDumpElement(const ui::TrackedElement* el) const override;
private:
friend InteractiveBrowserTestApi;
// Optional WebUI code coverage tool.
std::unique_ptr<DevToolsAgentCoverageObserver> coverage_observer_;
// Stores instrumented WebContents and WebUI.
std::vector<std::unique_ptr<WebContentsInteractionTestUtil>>
instrumented_web_contents_;
};
// This class wraps a `base::Value` in a wrapper that allows copying when
// necessary via the `Clone()` method. This is so that Value objects can be
// used with gtest and gmock matchers, much of the logic of which requires copy
// operations in order to work.
class MatchableValue {
public:
MatchableValue() noexcept;
MatchableValue(const base::Value& value) noexcept; // NOLINT
MatchableValue(base::Value&& value) noexcept; // NOLINT
MatchableValue(const MatchableValue& value) noexcept;
MatchableValue(MatchableValue&&) noexcept;
MatchableValue& operator=(const base::Value& value) noexcept;
MatchableValue& operator=(base::Value&& value) noexcept;
MatchableValue& operator=(const MatchableValue& value) noexcept;
MatchableValue& operator=(MatchableValue&&) noexcept;
~MatchableValue();
template <typename T>
MatchableValue(T value) noexcept // NOLINT
: MatchableValue(base::Value(value)) {}
// These enable implicit comparison between MatchableValue objects and types
// that a base::Value can be constructed from. This is also required for a lot
// of gtest and gmock logic to work properly.
bool operator==(const MatchableValue& other) const;
bool operator<(const MatchableValue& other) const;
bool operator>(const MatchableValue& other) const;
bool operator<=(const MatchableValue& other) const;
bool operator>=(const MatchableValue& other) const;
operator std::string() const; // NOLINT
const base::Value& value() const { return value_; }
private:
base::Value value_;
};
// Matcher that determines whether a particular value is truthy.
//
// Uses an `internal::MatchableValue` because much of the gtest infrastructure
// expects a value that can be copied, and `base::Value` cannot.
class IsTruthyMatcher
: public testing::MatcherInterface<const internal::MatchableValue&> {
public:
IsTruthyMatcher() = default;
IsTruthyMatcher(const IsTruthyMatcher&) = default;
IsTruthyMatcher& operator=(const IsTruthyMatcher&) = default;
~IsTruthyMatcher() override = default;
using is_gtest_matcher = void;
bool MatchAndExplain(const internal::MatchableValue& x,
testing::MatchResultListener* listener) const override;
void DescribeTo(std::ostream* os) const override;
void DescribeNegationTo(std::ostream* os) const override;
};
extern std::ostream& operator<<(std::ostream& out, const MatchableValue& value);
// Helper class that converts am input into a matcher that can match a
// `base::Value`.
//
// The default implementation wraps a literal value or something that unwraps to
// a literal value to be matched.
template <typename M>
struct MakeValueMatcherHelper {
static auto MakeValueMatcher(M m) {
return testing::Matcher<base::Value>(testing::Eq(m));
}
};
// This specialization handles things that can be directly cast/moved into a
// `testing::Matcher`, which is required since "matcher" is very duck-typed.
template <typename M>
requires requires(M&& m) {
testing::Matcher<MatchableValue>(std::forward<M>(m));
}
struct MakeValueMatcherHelper<M> {
static auto MakeValueMatcher(M&& m) {
return testing::Matcher<MatchableValue>(std::forward<M>(m));
}
};
// Wraps `m` in a `testing::Matcher` that will match a `base::Value`.
// Does not work for all possible inputs, but will work for most.
template <typename M>
auto MakeValueMatcher(M&& m) {
return MakeValueMatcherHelper<M>::MakeValueMatcher(
ui::test::internal::UnwrapArgument(std::forward<M>(m)));
}
// Wraps `m` in a `testing::Matcher` that will match a `base::Value`.
// Does not work for all possible inputs, but will work for most.
template <typename M>
auto MakeConstValueMatcher(const M& m) {
return MakeValueMatcherHelper<M>::MakeValueMatcher(
ui::test::internal::UnwrapArgument(m));
}
} // namespace internal
#endif // CHROME_TEST_INTERACTION_INTERACTIVE_BROWSER_TEST_INTERNAL_H_
|