1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include <string> 6 7#include "base/compiler_specific.h" 8#include "base/json/json_reader.h" 9#include "base/values.h" 10#include "chrome/test/chromedriver/chrome/navigation_tracker.h" 11#include "chrome/test/chromedriver/chrome/status.h" 12#include "chrome/test/chromedriver/chrome/stub_devtools_client.h" 13#include "testing/gtest/include/gtest/gtest.h" 14 15namespace { 16 17void AssertPendingState(NavigationTracker* tracker, 18 const std::string& frame_id, 19 bool expected_is_pending) { 20 bool is_pending = !expected_is_pending; 21 ASSERT_EQ(kOk, tracker->IsPendingNavigation(frame_id, &is_pending).code()); 22 ASSERT_EQ(expected_is_pending, is_pending); 23} 24 25} // namespace 26 27TEST(NavigationTracker, FrameLoadStartStop) { 28 StubDevToolsClient client; 29 NavigationTracker tracker(&client); 30 31 base::DictionaryValue params; 32 ASSERT_EQ( 33 kOk, tracker.OnEvent(&client, "Page.frameStartedLoading", params).code()); 34 ASSERT_NO_FATAL_FAILURE(AssertPendingState(&tracker, "f", true)); 35 ASSERT_EQ( 36 kOk, tracker.OnEvent(&client, "Page.frameStoppedLoading", params).code()); 37 ASSERT_NO_FATAL_FAILURE(AssertPendingState(&tracker, "f", false)); 38} 39 40TEST(NavigationTracker, NavigationScheduledThenLoaded) { 41 StubDevToolsClient client; 42 NavigationTracker tracker(&client, NavigationTracker::kNotLoading); 43 base::DictionaryValue params; 44 params.SetString("frameId", "f"); 45 base::DictionaryValue params_scheduled; 46 params_scheduled.SetInteger("delay", 0); 47 params_scheduled.SetString("frameId", "f"); 48 49 ASSERT_EQ( 50 kOk, 51 tracker.OnEvent( 52 &client, "Page.frameScheduledNavigation", params_scheduled).code()); 53 ASSERT_NO_FATAL_FAILURE(AssertPendingState(&tracker, "f", true)); 54 ASSERT_EQ( 55 kOk, tracker.OnEvent(&client, "Page.frameStartedLoading", params).code()); 56 ASSERT_NO_FATAL_FAILURE(AssertPendingState(&tracker, "f", true)); 57 ASSERT_EQ( 58 kOk, 59 tracker.OnEvent(&client, "Page.frameClearedScheduledNavigation", params) 60 .code()); 61 ASSERT_NO_FATAL_FAILURE(AssertPendingState(&tracker, "f", true)); 62 ASSERT_EQ( 63 kOk, tracker.OnEvent(&client, "Page.frameStoppedLoading", params).code()); 64 ASSERT_NO_FATAL_FAILURE(AssertPendingState(&tracker, "f", false)); 65} 66 67TEST(NavigationTracker, NavigationScheduledForOtherFrame) { 68 StubDevToolsClient client; 69 NavigationTracker tracker(&client, NavigationTracker::kNotLoading); 70 base::DictionaryValue params_scheduled; 71 params_scheduled.SetInteger("delay", 0); 72 params_scheduled.SetString("frameId", "other"); 73 74 ASSERT_EQ( 75 kOk, 76 tracker.OnEvent( 77 &client, "Page.frameScheduledNavigation", params_scheduled).code()); 78 ASSERT_NO_FATAL_FAILURE(AssertPendingState(&tracker, "f", false)); 79} 80 81TEST(NavigationTracker, NavigationScheduledThenCancelled) { 82 StubDevToolsClient client; 83 NavigationTracker tracker(&client, NavigationTracker::kNotLoading); 84 base::DictionaryValue params; 85 params.SetString("frameId", "f"); 86 base::DictionaryValue params_scheduled; 87 params_scheduled.SetInteger("delay", 0); 88 params_scheduled.SetString("frameId", "f"); 89 90 ASSERT_EQ( 91 kOk, 92 tracker.OnEvent( 93 &client, "Page.frameScheduledNavigation", params_scheduled).code()); 94 ASSERT_NO_FATAL_FAILURE(AssertPendingState(&tracker, "f", true)); 95 ASSERT_EQ( 96 kOk, 97 tracker.OnEvent(&client, "Page.frameClearedScheduledNavigation", params) 98 .code()); 99 ASSERT_NO_FATAL_FAILURE(AssertPendingState(&tracker, "f", false)); 100} 101 102TEST(NavigationTracker, NavigationScheduledTooFarAway) { 103 StubDevToolsClient client; 104 NavigationTracker tracker(&client, NavigationTracker::kNotLoading); 105 106 base::DictionaryValue params_scheduled; 107 params_scheduled.SetInteger("delay", 10); 108 params_scheduled.SetString("frameId", "f"); 109 ASSERT_EQ( 110 kOk, 111 tracker.OnEvent( 112 &client, "Page.frameScheduledNavigation", params_scheduled).code()); 113 ASSERT_NO_FATAL_FAILURE(AssertPendingState(&tracker, "f", false)); 114} 115 116TEST(NavigationTracker, DiscardScheduledNavigationsOnMainFrameCommit) { 117 StubDevToolsClient client; 118 NavigationTracker tracker(&client, NavigationTracker::kNotLoading); 119 120 base::DictionaryValue params_scheduled; 121 params_scheduled.SetString("frameId", "subframe"); 122 params_scheduled.SetInteger("delay", 0); 123 ASSERT_EQ( 124 kOk, 125 tracker.OnEvent( 126 &client, "Page.frameScheduledNavigation", params_scheduled).code()); 127 ASSERT_NO_FATAL_FAILURE(AssertPendingState(&tracker, "subframe", true)); 128 129 base::DictionaryValue params_navigated; 130 params_navigated.SetString("frame.parentId", "something"); 131 ASSERT_EQ( 132 kOk, 133 tracker.OnEvent(&client, "Page.frameNavigated", params_navigated).code()); 134 ASSERT_NO_FATAL_FAILURE(AssertPendingState(&tracker, "subframe", true)); 135 params_navigated.Clear(); 136 ASSERT_EQ( 137 kOk, 138 tracker.OnEvent(&client, "Page.frameNavigated", params_navigated).code()); 139 ASSERT_NO_FATAL_FAILURE(AssertPendingState(&tracker, "subframe", false)); 140} 141 142namespace { 143 144class FailToEvalScriptDevToolsClient : public StubDevToolsClient { 145 public: 146 virtual ~FailToEvalScriptDevToolsClient() {} 147 148 virtual Status SendCommandAndGetResult( 149 const std::string& method, 150 const base::DictionaryValue& params, 151 scoped_ptr<base::DictionaryValue>* result) OVERRIDE { 152 EXPECT_STREQ("Runtime.evaluate", method.c_str()); 153 return Status(kUnknownError, "failed to eval script"); 154 } 155}; 156 157} // namespace 158 159TEST(NavigationTracker, UnknownStateFailsToDetermineState) { 160 FailToEvalScriptDevToolsClient client; 161 NavigationTracker tracker(&client); 162 bool is_pending; 163 ASSERT_EQ(kUnknownError, 164 tracker.IsPendingNavigation("f", &is_pending).code()); 165} 166 167namespace { 168 169class DeterminingLoadStateDevToolsClient : public StubDevToolsClient { 170 public: 171 DeterminingLoadStateDevToolsClient( 172 bool is_loading, 173 const std::string& send_event_first, 174 base::DictionaryValue* send_event_first_params) 175 : is_loading_(is_loading), 176 send_event_first_(send_event_first), 177 send_event_first_params_(send_event_first_params) {} 178 179 virtual ~DeterminingLoadStateDevToolsClient() {} 180 181 virtual Status SendCommandAndGetResult( 182 const std::string& method, 183 const base::DictionaryValue& params, 184 scoped_ptr<base::DictionaryValue>* result) OVERRIDE { 185 if (send_event_first_.length()) { 186 Status status = listeners_.front() 187 ->OnEvent(this, send_event_first_, *send_event_first_params_); 188 if (status.IsError()) 189 return status; 190 } 191 192 base::DictionaryValue result_dict; 193 result_dict.SetBoolean("result.value", is_loading_); 194 result->reset(result_dict.DeepCopy()); 195 return Status(kOk); 196 } 197 198 private: 199 bool is_loading_; 200 std::string send_event_first_; 201 base::DictionaryValue* send_event_first_params_; 202}; 203 204} // namespace 205 206TEST(NavigationTracker, UnknownStateForcesStart) { 207 base::DictionaryValue params; 208 DeterminingLoadStateDevToolsClient client(true, std::string(), ¶ms); 209 NavigationTracker tracker(&client); 210 ASSERT_NO_FATAL_FAILURE(AssertPendingState(&tracker, "f", true)); 211} 212 213TEST(NavigationTracker, UnknownStateForcesStartReceivesStop) { 214 base::DictionaryValue params; 215 DeterminingLoadStateDevToolsClient client( 216 true, "Page.frameStoppedLoading", ¶ms); 217 NavigationTracker tracker(&client); 218 ASSERT_NO_FATAL_FAILURE(AssertPendingState(&tracker, "f", false)); 219} 220