chromium/chrome/test/interaction/interactive_browser_test.cc

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

#include "chrome/test/interaction/interactive_browser_test.h"

#include <ostream>
#include <sstream>
#include <string>
#include <utility>
#include <variant>

#include "base/check.h"
#include "base/functional/bind.h"
#include "base/functional/overloaded.h"
#include "base/strings/strcat.h"
#include "base/strings/stringprintf.h"
#include "base/task/single_thread_task_runner.h"
#include "base/test/bind.h"
#include "base/values.h"
#include "build/build_config.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/browser_navigator.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/interaction/interaction_test_util_browser.h"
#include "chrome/test/interaction/interactive_browser_test_internal.h"
#include "chrome/test/interaction/tracked_element_webcontents.h"
#include "chrome/test/interaction/webcontents_interaction_test_util.h"
#include "content/public/browser/visibility.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/update_user_activation_state_interceptor.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/mojom/frame/user_activation_notification_type.mojom-shared.h"
#include "third_party/blink/public/mojom/frame/user_activation_update_types.mojom-shared.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/interaction_test_util.h"
#include "ui/base/interaction/interactive_test_internal.h"
#include "ui/views/controls/webview/webview.h"
#include "ui/views/interaction/interaction_test_util_views.h"
#include "ui/views/interaction/interactive_views_test.h"
#include "ui/views/views_delegate.h"

namespace {

// Since we enforce a 1:1 correspondence between ElementIdentifiers and
// WebContents defaulting to ContextMode::kAny prevents accidentally missing the
// correct context, which is a common mistake that causes tests to mysteriously
// time out looking in the wrong place.
constexpr ui::InteractionSequence::ContextMode kDefaultWebContentsContextMode =;

// Matcher that determines whether a particular value is truthy.
class IsTruthyMatcher : public testing::MatcherInterface<const base::Value&> {};

}  // namespace

InteractiveBrowserTestApi::InteractiveBrowserTestApi()
    :{}

InteractiveBrowserTestApi::InteractiveBrowserTestApi(
    std::unique_ptr<internal::InteractiveBrowserTestPrivate> private_test_impl)
    :{}

InteractiveBrowserTestApi::~InteractiveBrowserTestApi() = default;

// static
WebContentsInteractionTestUtil*
InteractiveBrowserTestApi::AsInstrumentedWebContents(ui::TrackedElement* el) {}

void InteractiveBrowserTestApi::EnableWebUICodeCoverage() {}

InteractiveBrowserTestApi::MultiStep InteractiveBrowserTestApi::Screenshot(
    ElementSpecifier element,
    const std::string& screenshot_name,
    const std::string& baseline_cl) {}

InteractiveBrowserTestApi::MultiStep
InteractiveBrowserTestApi::ScreenshotSurface(
    ElementSpecifier element_in_surface,
    const std::string& screenshot_name,
    const std::string& baseline_cl) {}

InteractiveBrowserTestApi::MultiStep InteractiveBrowserTestApi::InstrumentTab(
    ui::ElementIdentifier id,
    std::optional<int> tab_index,
    BrowserSpecifier in_browser,
    bool wait_for_ready) {}

ui::InteractionSequence::StepBuilder
InteractiveBrowserTestApi::InstrumentNextTab(ui::ElementIdentifier id,
                                             BrowserSpecifier in_browser) {}

InteractiveBrowserTestApi::MultiStep
InteractiveBrowserTestApi::AddInstrumentedTab(ui::ElementIdentifier id,
                                              GURL url,
                                              std::optional<int> at_index,
                                              BrowserSpecifier in_browser) {}

InteractiveBrowserTestApi::MultiStep
InteractiveBrowserTestApi::InstrumentNonTabWebView(ui::ElementIdentifier id,
                                                   ElementSpecifier web_view,
                                                   bool wait_for_ready) {}

InteractiveBrowserTestApi::MultiStep
InteractiveBrowserTestApi::InstrumentNonTabWebView(
    ui::ElementIdentifier id,
    AbsoluteViewSpecifier web_view,
    bool wait_for_ready) {}

// static
ui::InteractionSequence::StepBuilder
InteractiveBrowserTestApi::WaitForWebContentsReady(
    ui::ElementIdentifier webcontents_id,
    std::optional<GURL> expected_url) {}

// static
ui::InteractionSequence::StepBuilder
InteractiveBrowserTestApi::WaitForWebContentsNavigation(
    ui::ElementIdentifier webcontents_id,
    std::optional<GURL> expected_url) {}

// There is a bug that causes WebContents::CompletedFirstVisuallyNonEmptyPaint()
// to occasionally fail to ever become true. This mostly manifests when running
// Lacros tests on Linux, and sometimes on Mac builders. In order to prevent
// tests from hanging when trying to ensure a non-empty paint, then, a
// workaround is required.
//
// See b/332895669 and b/334747109 for more information.

namespace {

// Warning message so people aren't surprised when something else in their test
// flakes after this step due to the bug.
constexpr char kPaintWorkaroundWarning[] =;

// CheckJsResult() can handle promises, so queue a promise that only succeeds
// after the contents have been rendered.
constexpr char kPaintWorkaroundFunction[] =;

// Event sent on a delay to bypass the "was this WebContents painted?" check on
// platforms where the check is flaky; see comments above.
DEFINE_LOCAL_CUSTOM_ELEMENT_EVENT_TYPE();

void MaybePostPaintWorkaroundEvent(ui::TrackedElement* el) {}

}  // namespace

// static
ui::InteractionSequence::StepBuilder
InteractiveBrowserTestApi::WaitForWebContentsPainted(
    ui::ElementIdentifier webcontents_id) {}

// static
InteractiveBrowserTestApi::MultiStep
InteractiveBrowserTestApi::NavigateWebContents(
    ui::ElementIdentifier webcontents_id,
    GURL target_url) {}

InteractiveBrowserTestApi::StepBuilder
InteractiveBrowserTestApi::FocusWebContents(
    ui::ElementIdentifier webcontents_id) {}

// static
InteractiveBrowserTestApi::MultiStep
InteractiveBrowserTestApi::WaitForStateChange(
    ui::ElementIdentifier webcontents_id,
    const StateChange& state_change,
    bool expect_timeout) {}

// static
ui::InteractionSequence::StepBuilder InteractiveBrowserTestApi::EnsurePresent(
    ui::ElementIdentifier webcontents_id,
    const DeepQuery& where) {}

// static
ui::InteractionSequence::StepBuilder
InteractiveBrowserTestApi::EnsureNotPresent(
    ui::ElementIdentifier webcontents_id,
    const DeepQuery& where) {}

// static
ui::InteractionSequence::StepBuilder InteractiveBrowserTestApi::ExecuteJs(
    ui::ElementIdentifier webcontents_id,
    const std::string& function,
    ExecuteJsMode mode) {}

// static
ui::InteractionSequence::StepBuilder InteractiveBrowserTestApi::ExecuteJsAt(
    ui::ElementIdentifier webcontents_id,
    const DeepQuery& where,
    const std::string& function,
    ExecuteJsMode mode) {}

// static
ui::InteractionSequence::StepBuilder InteractiveBrowserTestApi::CheckJsResult(
    ui::ElementIdentifier webcontents_id,
    const std::string& function) {}

// static
ui::InteractionSequence::StepBuilder InteractiveBrowserTestApi::CheckJsResultAt(
    ui::ElementIdentifier webcontents_id,
    const DeepQuery& where,
    const std::string& function) {}

InteractiveBrowserTestApi::MultiStep InteractiveBrowserTestApi::MoveMouseTo(
    ui::ElementIdentifier web_contents,
    const DeepQuery& where) {}

InteractiveBrowserTestApi::MultiStep InteractiveBrowserTestApi::DragMouseTo(
    ui::ElementIdentifier web_contents,
    const DeepQuery& where,
    bool release) {}

ui::InteractionSequence::StepBuilder InteractiveBrowserTestApi::ScrollIntoView(
    ui::ElementIdentifier web_contents,
    const DeepQuery& where) {}

// static
InteractiveBrowserTestApi::RelativePositionCallback
InteractiveBrowserTestApi::DeepQueryToRelativePosition(const DeepQuery& query) {}

// static
InteractiveBrowserTestApi::MultiStep
InteractiveBrowserTestApi::MaybeWaitForPaint(ElementSpecifier element,
                                             const std::string& desc) {}

Browser* InteractiveBrowserTestApi::GetBrowserFor(
    ui::ElementContext current_context,
    BrowserSpecifier spec) {}