chromium/ui/base/interaction/state_observer.h

// 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_