blob: b9074528acd7a9f82754d8902e52f16fd1bf5426 [file] [log] [blame]
// Copyright 2012 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_BASE_INTERACTIVE_TEST_UTILS_H_
#define CHROME_TEST_BASE_INTERACTIVE_TEST_UTILS_H_
#include <utility>
#include "base/memory/weak_ptr.h"
#include "base/run_loop.h"
#include "build/build_config.h"
#include "chrome/browser/ui/browser_list_observer.h"
#include "chrome/browser/ui/view_ids.h"
#include "ui/base/test/ui_controls.h"
#include "ui/display/display.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/vector2d.h"
#include "ui/gfx/native_ui_types.h"
#include "ui/views/widget/widget_observer.h"
class BrowserWindowInterface;
namespace display {
class Screen;
} // namespace display
#if defined(TOOLKIT_VIEWS)
namespace views {
class View;
class Widget;
}
#endif
namespace ui_test_utils {
// Use in browser interactive uitests to wait until a browser is set to active.
// To use, create and call WaitForActivation(). Since on some platforms, the
// active browser list kept in |BrowserList| is updated before the actual
// activation (see |BrowserView::Show()| for details), observe the widget
// directly and wait for it to actually get activated.
class BrowserActivationWaiter : public views::WidgetObserver {
public:
explicit BrowserActivationWaiter(const BrowserWindowInterface* browser);
BrowserActivationWaiter(const BrowserActivationWaiter&) = delete;
BrowserActivationWaiter& operator=(const BrowserActivationWaiter&) = delete;
~BrowserActivationWaiter() override;
// Runs a message loop until the widget associated to |browser| supplied to
// the constructor is activated, or returns immediately if |browser| has
// already active. Should only be called once.
void WaitForActivation();
// views::WidgetObserver
void OnWidgetActivationChanged(views::Widget* widget, bool active) override;
private:
bool observed_ = false;
base::RunLoop run_loop_;
};
// Use in browser interactive uitests to wait until a browser is deactivated.
// To use, create and call WaitForDeactivation().
class BrowserDeactivationWaiter : public BrowserListObserver {
public:
explicit BrowserDeactivationWaiter(const Browser* browser);
BrowserDeactivationWaiter(const BrowserDeactivationWaiter&) = delete;
BrowserDeactivationWaiter& operator=(const BrowserDeactivationWaiter&) =
delete;
~BrowserDeactivationWaiter() override;
// Runs a message loop until the |browser_| supplied to the constructor is
// deactivated, or returns immediately if |browser_| has already become
// inactive.
// Should only be called once.
void WaitForDeactivation();
private:
// BrowserListObserver:
void OnBrowserNoLongerActive(Browser* browser) override;
const base::WeakPtr<const Browser> browser_;
bool observed_ = false;
base::RunLoop run_loop_;
};
// Brings the native window for |browser| to the foreground and waits until the
// browser is active.
[[nodiscard]] bool BringBrowserWindowToFront(
const BrowserWindowInterface* browser);
// Returns true if the View is focused.
bool IsViewFocused(const Browser* browser, ViewID vid);
// Simulates a mouse click on a View in the browser.
void ClickOnView(views::View* view);
void ClickOnView(const Browser* browser, ViewID vid);
// Makes focus shift to the given View without clicking it.
void FocusView(const Browser* browser, ViewID vid);
// A collection of utilities that are used from interactive_ui_tests. These are
// separated from ui_test_utils.h to ensure that browser_tests don't use them,
// since they depend on focus which isn't possible for sharded test.
// Hide a native window.
void HideNativeWindow(gfx::NativeWindow window);
// Show and focus a native window. Returns true on success.
[[nodiscard]] bool ShowAndFocusNativeWindow(gfx::NativeWindow window);
// Sends key press and release events to a `browser` or `window`. Waits until at
// least the key release (or key press, depending on `wait_for`) events have
// been dispatched, or the test times out. It's useful to wait for key press
// instead of key release when the target may be deleted in response to key
// press. This may wait for key release even if `wait_for` is `kKeyPress` on
// platforms where it's possible to confirm that key release has been dispatched
// on a deleted target. This uses `ui_controls::SendKeyPress`, see it for
// details. Returns true if the event was successfully dispatched.
[[nodiscard]] bool SendKeyPressSync(
const BrowserWindowInterface* browser,
ui::KeyboardCode key,
bool control,
bool shift,
bool alt,
bool command,
ui_controls::KeyEventType wait_for = ui_controls::kKeyRelease);
[[nodiscard]] bool SendKeyPressToWindowSync(
const gfx::NativeWindow window,
ui::KeyboardCode key,
bool control,
bool shift,
bool alt,
bool command,
ui_controls::KeyEventType wait_for = ui_controls::kKeyRelease);
// Sends a move event blocking until received. Returns true if the event was
// successfully received. This uses ui_controls::SendMouse***NotifyWhenDone,
// see it for details.
[[nodiscard]] bool SendMouseMoveSync(
const gfx::Point& location,
gfx::NativeWindow window_hint = gfx::NativeWindow());
[[nodiscard]] bool SendMouseEventsSync(
ui_controls::MouseButton type,
int button_state,
gfx::NativeWindow window_hint = gfx::NativeWindow());
// A combination of SendMouseMove to the middle of the view followed by
// SendMouseEvents. Only exposed for toolkit-views.
// Alternatives: ClickOnView() and ui::test::EventGenerator.
#if defined(TOOLKIT_VIEWS)
void MoveMouseToCenterAndClick(
views::View* view,
ui_controls::MouseButton button,
int button_state,
base::OnceClosure task,
int accelerator_state = ui_controls::kNoAccelerator);
void MoveMouseToCenterWithOffsetAndClick(
views::View* view,
const gfx::Vector2d& offset,
ui_controls::MouseButton button,
int button_state,
base::OnceClosure task,
int accelerator_state = ui_controls::kNoAccelerator);
// Returns the center of |view| in screen coordinates.
gfx::Point GetCenterInScreenCoordinates(const views::View* view);
// Blocks until the given view is focused (or not focused, depending on
// |focused|). Returns immediately if the state is already correct.
void WaitForViewFocus(Browser* browser, ViewID vid, bool focused);
void WaitForViewFocus(Browser* browser, views::View* view, bool focused);
#endif
#if BUILDFLAG(IS_MAC)
// Clear pressed modifier keys and report true if any key modifiers were down.
bool ClearKeyEventModifiers();
// Ensures that if no key window is set (can happen in apps that are not
// frontmost), we simulate the frontmost window becoming key, which triggers
// any logic that would normally run in this case.
void HandleMissingKeyWindow();
#endif
namespace internal {
// A utility function to send a mouse click event in a closure. It's shared by
// ui_controls_linux.cc and ui_controls_mac.cc
void ClickTask(ui_controls::MouseButton button,
int button_state,
base::OnceClosure followup,
int accelerator_state = ui_controls::kNoAccelerator);
} // namespace internal
// Returns the secondary display from the screen. DCHECKs if there is no such
// display.
display::Display GetSecondaryDisplay(display::Screen* screen);
// Returns the pair of displays -- the first one is the primary display and the
// second one is the other display.
std::pair<display::Display, display::Display> GetDisplays(
display::Screen* screen);
} // namespace ui_test_utils
#endif // CHROME_TEST_BASE_INTERACTIVE_TEST_UTILS_H_