chromium/ui/base/interaction/interactive_test_internal.h

// 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 UI_BASE_INTERACTION_INTERACTIVE_TEST_INTERNAL_H_
#define UI_BASE_INTERACTION_INTERACTIVE_TEST_INTERNAL_H_

#include <concepts>
#include <functional>
#include <memory>
#include <string>
#include <string_view>
#include <tuple>
#include <type_traits>
#include <variant>

#include "base/callback_list.h"
#include "base/containers/contains.h"
#include "base/functional/callback_helpers.h"
#include "base/gtest_prod_util.h"
#include "base/logging.h"
#include "base/no_destructor.h"
#include "base/strings/strcat.h"
#include "base/test/bind.h"
#include "base/test/rectify_callback.h"
#include "base/types/is_instantiation.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/interaction/element_identifier.h"
#include "ui/base/interaction/element_test_util.h"
#include "ui/base/interaction/element_tracker.h"
#include "ui/base/interaction/framework_specific_implementation.h"
#include "ui/base/interaction/interaction_sequence.h"
#include "ui/base/interaction/interaction_test_util.h"
#include "ui/base/interaction/state_observer.h"

namespace ui::test {

class InteractiveTestApi;
class InteractiveTestTest;

namespace internal {

// Element that is present during interactive tests that actions can bounce
// events off of.
DECLARE_ELEMENT_IDENTIFIER_VALUE();
DECLARE_CUSTOM_ELEMENT_EVENT_TYPE();

extern const char kInteractiveTestFailedMessagePrefix[];
extern const char kNoCheckDescriptionSpecified[];

class StateObserverElement;

// Class that implements functionality for InteractiveTest* that should be
// hidden from tests that inherit the API.
class InteractiveTestPrivate {};

// Specifies an element either by ID or by name.
ElementSpecifier;

class StateObserverElement : public TestElementBase {};

// Implements an element that is shown when an observed state matches a desired
// value or pattern, and hidden when it does not.
template <typename T>
class StateObserverElementT : public StateObserverElement {};

// Applies `matcher` to `value` and returns the result; on failure a useful
// error message is printed using `test_name`, `value`, and `matcher`.
//
// Steps which use this method will fail if it returns false, printing out the
// details of the step in the usual way.
template <typename T, typename V = std::decay_t<T>>
bool MatchAndExplain(std::string_view test_name,
                     const testing::Matcher<V>& matcher,
                     const T& value) {}

template <typename Observer, typename V>
bool InteractiveTestPrivate::AddStateObserver(
    ElementIdentifier id,
    ElementContext context,
    std::unique_ptr<Observer> state_observer) {}

// Similar to `std::invocable<T, Args...>`, but does not put constraints on the
// parameters passed to the invocation method.
IsCallable;

// Applies if `T` has bound state (such as a lambda expression with captures).
HasState;

// Helper for matching a function pointer.
IsFunctionPointerValue;

IsFunctionPointerValue;

// Applies if `T` is a function pointer (but not a pointer to an instance
// member function).
IsFunctionPointer;

// Optionally converts `function` to something that is compatible with a
// base::OnceCallback.
template <typename F>
auto MaybeBind(F&& function) {}

// Helper struct that captures information about what signature a function-like
// object would have if it were bound.
template <typename F>
struct MaybeBindTypeHelper {};

// DoNothing always has a void return type but no defined signature.
template <>
struct MaybeBindTypeHelper<decltype(base::DoNothing())> {};

// Optionally converts `function` to something that is compatible with a
// base::RepeatingCallback, or returns it as-is if it's already a callback.
template <typename F>
base::RepeatingCallback<typename MaybeBindTypeHelper<F>::Signature>
MaybeBindRepeating(F&& function) {}

template <typename T>
struct ArgsExtractor;

ArgsExtractor<R (Args...)>;

ReturnTypeOf;

NthArgumentOf;

// Requires that `F` resolves to some kind of callable object with call
// signature `S`.
HasSignature;

// Helper for `HasCompatibleSignature`; see recursive implementation below.
HasCompatibleSignatureValue;

// Requires that `F` resolves to some kind of callable object whose signature
// can be rectified to `S`; see `base::RectifyCallback` for more information.
// (Basically, `F` can omit arguments from the left of `S`; these arguments
// will be ignored.)
HasCompatibleSignature;

// This is the leaf state for the recursive compatibility computation; see
// below.
HasCompatibleSignatureValue;

// Implementation for `HasCompatibleSignature`.
//
// This removes arguments one by one from the left of the target signature `S`
// to see if `F` has that signature. The recursion stops when one matches, or
// when the arg list is empty (in which case the leaf state is hit, above).
HasCompatibleSignatureValue;

// Checks that `T` is a reference wrapper around any type.
IsReferenceWrapper;

// Helper to determine the type used to match a value. The default is to just
// use the decayed value type.
template <typename T>
struct MatcherTypeHelper {};

// Specialization for string types used in Chrome. For any representation of a
// string using character type, the type used for matching is the corresponding
// `std::basic_string`.
//
// Add to this template if different character formats become supported (e.g.
// char8_t, char32_t, wchar_t, etc.)
MatcherTypeHelper<C *>;

// Gets the appropriate matchable type for `T`. This affects string-like types
// (e.g. `const char*`) as the corresponding `Matcher` should match a
// `std::string` or `std::u16string`.
MatcherTypeFor;

// Determines if `T` is a valid type to be used in a matcher. This precludes
// string-like types (const char*, constexpr char16_t[], etc.) in favor of
// `std::string` and `std::u16string`.
IsValidMatcherType;

IsGtestMatcher;

HasMatchAndExplain;

IsMatcher;

// Accepts any function-like object that is compatible with
// `InteractionSequence::StepCallback`.
IsStepCallback;

// Accepts any function-like object that can be used with `Check()` and
// `CheckResult()`.
IsCheckCallback;

// Converts an ElementSpecifier to an element ID or name and sets it onto
// `builder`.
void SpecifyElement(ui::InteractionSequence::StepBuilder& builder,
                    ElementSpecifier element);

std::string DescribeElement(ElementSpecifier spec);

InteractionSequence::Builder BuildSubsequence(
    InteractiveTestPrivate::MultiStep steps);

// Takes an argument expected to be a literal value and retrieves the literal
// value by either calling the object (if it's callable), unwrapping it (if it's
// a `std::reference_wrapper`) or just returning it otherwise.
//
// This allows e.g. passing deferred or computed values to the `Log()` verb.
template <typename Arg>
auto UnwrapArgument(Arg arg) {}

}  // namespace internal

}  // namespace ui::test

#endif  // UI_BASE_INTERACTION_INTERACTIVE_TEST_INTERNAL_H_