1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117

fuchsia_web / common / test / test_navigation_listener.h [blame]

// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef FUCHSIA_WEB_COMMON_TEST_TEST_NAVIGATION_LISTENER_H_
#define FUCHSIA_WEB_COMMON_TEST_TEST_NAVIGATION_LISTENER_H_

#include <fuchsia/web/cpp/fidl.h>

#include <string>
#include <string_view>
#include <vector>

#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"

class GURL;

// Observes navigation events and enables test code to block until a desired
// navigational state is observed.
// When run with -v1, information about navigation state transitions and
// unmet test expectations are logged.
class TestNavigationListener final
    : public fuchsia::web::NavigationEventListener {
 public:
  using BeforeAckCallback =
      base::RepeatingCallback<void(const fuchsia::web::NavigationState& change,
                                   OnNavigationStateChangedCallback)>;

  TestNavigationListener();
  ~TestNavigationListener() override;

  TestNavigationListener(const TestNavigationListener&) = delete;
  TestNavigationListener& operator=(const TestNavigationListener&) = delete;

  // Spins a RunLoop until the navigation state of the page matches the fields
  // of |expected_state| that have been set.
  void RunUntilNavigationStateMatches(
      const fuchsia::web::NavigationState& expected_state);

  // Calls RunUntilNavigationStateMatches with a NavigationState that has
  // the main document loaded and the normal page type.
  void RunUntilLoaded();

  // Calls RunUntilNavigationStateMatches with a NavigationState that has
  // |expected_url|, the normal page type, and the main document loaded.
  void RunUntilUrlEquals(const GURL& expected_url);

  // Calls RunUntilNavigationStateMatches with a NavigationState that has
  // |expected_title| and the normal page type.
  void RunUntilTitleEquals(std::string_view expected_title);

  // Calls RunUntilNavigationStateMatches with a NavigationState that has
  // |expected_url|, |expected_title|, and the normal page type.
  void RunUntilUrlAndTitleEquals(const GURL& expected_url,
                                 std::string_view expected_title);

  // Calls RunUntilNavigationStateMatches with a NavigationState that has
  // the error page type, |expected_title|, and the main document loaded.
  void RunUntilErrorPageIsLoadedAndTitleEquals(std::string_view expected_title);

  // Calls RunUntilNavigationStateMatches with a NavigationState that has
  // all the expected fields and the normal page type.
  void RunUntilUrlTitleBackForwardEquals(const GURL& expected_url,
                                         std::string_view expected_title,
                                         bool expected_can_go_back,
                                         bool expected_can_go_forward);

  // Returns the title.
  std::string title() { return current_state_.title(); }

  // Returns the current navigation state.
  fuchsia::web::NavigationState* current_state() { return ¤t_state_; }

  // Returns the last received changes.
  fuchsia::web::NavigationState* last_changes() { return &last_changes_; }

  // Register a callback which intercepts the execution of the event
  // acknowledgement callback. |before_ack| takes ownership of the
  // acknowledgement callback and the responsibility for executing it.
  // The default behavior can be restored by providing an unbound callback for
  // |before_ack|.
  void SetBeforeAckHook(BeforeAckCallback before_ack);

 private:
  struct FailureReason {
    const char* field_name;
    std::string expected;
  };

  // fuchsia::web::NavigationEventListener implementation.
  void OnNavigationStateChanged(
      fuchsia::web::NavigationState change,
      OnNavigationStateChangedCallback callback) override;

  // Compare the current state with all fields of |expected_state_| that have
  // been set. Any expectation mismatches will be recorded in |failure_reasons|,
  // if set.
  bool AllFieldsMatch(std::vector<FailureReason>* failure_reasons);

  void QuitLoopIfAllFieldsMatch(
      base::RepeatingClosure quit_run_loop_closure,
      BeforeAckCallback before_ack_callback,
      const fuchsia::web::NavigationState& change,
      fuchsia::web::NavigationEventListener::OnNavigationStateChangedCallback
          ack_callback);

  fuchsia::web::NavigationState current_state_;
  fuchsia::web::NavigationState last_changes_;

  // Set for the duration of a call to RunUntilNavigationStateMatches().
  raw_ptr<const fuchsia::web::NavigationState> expected_state_ = nullptr;

  BeforeAckCallback before_ack_;
};

#endif  // FUCHSIA_WEB_COMMON_TEST_TEST_NAVIGATION_LISTENER_H_