// Copyright 2023 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_STATE_OBSERVER_H_ #define UI_BASE_INTERACTION_STATE_OBSERVER_H_ #include <algorithm> #include <ostream> #include <utility> #include "base/functional/callback.h" #include "base/memory/raw_ptr.h" #include "base/scoped_observation.h" #include "ui/base/interaction/element_identifier.h" namespace ui::test { // Base class for all state change observers. Observes some state of the system, // which we can then wait on. // // Used with `InteractiveTestApi::ObserveState()` and `WaitForState()`. // // Value type `T` must be default-constructible and copy-assignable. template <typename T> class StateObserver { … }; // State observer that uses a `ScopedObservation<T, Source, Observer>` to watch // for state changes using an observer pattern. // // You will still need to override the specific observer methods to detect: // - The actual state change // - call `OnStateObserverStateChanged()` // - The "source destroyed" message (optional) // - call `OnObservationStateObserverSourceDestroyed()` // // If the initial state may vary, you can also override // `GetStateObserverInitialState()`. Use `source()` to extract the relevant // information. // // An example can be found in chrome/test/interaction/README.md. template <typename T, typename Source, typename Observer> class ObservationStateObserver : public StateObserver<T>, public Observer { … }; // Uniquely identifies a state associated with `ObserverType`. // // Use the DECLARE/DEFINE macros below to create unique identifiers, similarly // to how ElementIdentifier, etc. work. template <typename ObserverType> class StateIdentifier final { … }; template <typename T> extern void PrintTo(StateIdentifier<T> state_identifier, std::ostream* os) { … } template <typename T> extern std::ostream& operator<<(std::ostream& os, StateIdentifier<T> state_identifier) { … } } // namespace ui::test // The following macros create a state identifier value for use in tests. // // The associated type of observer should be specified along with the unique // identifier name: // ``` // DECLARE_STATE_IDENTIFIER_VALUE(MyObserverType, kMyState); // ``` // // `DECLARE_STATE_IDENTIFIER_VALUE()` and `DEFINE_STATE_IDENTIFIER_VALUE()` are // for use in .h and .cc files, respectively, as with declaring // `ElementIdentifier`s. // // To declare a `StateIdentifier` local to a .cc file or method body, use // DEFINE_LOCAL_STATE_IDENTIFIER_VALUE() instead. This will create a file- and // line-mangled name that will not suffer name collisions with other // identifiers. #define DECLARE_STATE_IDENTIFIER_VALUE(ObserverType, Name) … #define DEFINE_STATE_IDENTIFIER_VALUE(ObserverType, Name) … #define DEFINE_LOCAL_STATE_IDENTIFIER_VALUE(ObserverType, Name) … #endif // UI_BASE_INTERACTION_STATE_OBSERVER_H_