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.
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 "chrome/test/chromedriver/chrome/version.h"
14 #include "testing/gtest/include/gtest/gtest.h"
18 void AssertPendingState(NavigationTracker* tracker,
19 const std::string& frame_id,
20 bool expected_is_pending) {
21 bool is_pending = !expected_is_pending;
22 ASSERT_EQ(kOk, tracker->IsPendingNavigation(frame_id, &is_pending).code());
23 ASSERT_EQ(expected_is_pending, is_pending);
26 void AssertTrackerExpectsSingleStopEvent(BrowserInfo* browser_info) {
27 StubDevToolsClient client;
28 NavigationTracker tracker(&client, browser_info);
29 base::DictionaryValue params;
30 params.SetString("frameId", "f");
32 // pending_frames_set_.size() == 0
34 kOk, tracker.OnEvent(&client, "Page.frameStartedLoading", params).code());
35 // pending_frames_set_.size() == 1
36 ASSERT_NO_FATAL_FAILURE(AssertPendingState(&tracker, "f", true));
38 kOk, tracker.OnEvent(&client, "Page.frameStartedLoading", params).code());
39 // pending_frames_set_.size() == 2
40 ASSERT_NO_FATAL_FAILURE(AssertPendingState(&tracker, "f", true));
42 kOk, tracker.OnEvent(&client, "Page.frameStoppedLoading", params).code());
43 // pending_frames_set_.size() == 0
44 ASSERT_NO_FATAL_FAILURE(AssertPendingState(&tracker, "f", false));
47 void AssertTrackerExpectsMultipleStopEvents(BrowserInfo* browser_info) {
48 StubDevToolsClient client;
49 NavigationTracker tracker(&client, browser_info);
50 base::DictionaryValue params;
52 // pending_frames_set_.size() == 0
53 params.SetString("frameId", "1");
55 kOk, tracker.OnEvent(&client, "Page.frameStartedLoading", params).code());
56 // pending_frames_set_.size() == 1
57 ASSERT_NO_FATAL_FAILURE(AssertPendingState(&tracker, "1", true));
58 params.SetString("frameId", "2");
60 kOk, tracker.OnEvent(&client, "Page.frameStartedLoading", params).code());
61 // pending_frames_set_.size() == 2
62 ASSERT_NO_FATAL_FAILURE(AssertPendingState(&tracker, "2", true));
63 params.SetString("frameId", "2");
65 kOk, tracker.OnEvent(&client, "Page.frameStoppedLoading", params).code());
66 // pending_frames_set_.size() == 1
67 ASSERT_NO_FATAL_FAILURE(AssertPendingState(&tracker, "2", true));
68 params.SetString("frameId", "1");
70 kOk, tracker.OnEvent(&client, "Page.frameStoppedLoading", params).code());
71 // pending_frames_set_.size() == 0
72 ASSERT_NO_FATAL_FAILURE(AssertPendingState(&tracker, "1", false));
73 params.SetString("frameId", "3");
75 kOk, tracker.OnEvent(&client, "Page.frameStoppedLoading", params).code());
76 // pending_frames_set_.size() == 0
77 ASSERT_NO_FATAL_FAILURE(AssertPendingState(&tracker, "3", false));
79 kOk, tracker.OnEvent(&client, "Page.frameStartedLoading", params).code());
80 // pending_frames_set_.size() == 1
81 ASSERT_NO_FATAL_FAILURE(AssertPendingState(&tracker, "3", true));
86 TEST(NavigationTracker, FrameLoadStartStop) {
87 StubDevToolsClient client;
88 BrowserInfo browser_info;
89 NavigationTracker tracker(&client, &browser_info);
91 base::DictionaryValue params;
92 params.SetString("frameId", "f");
95 kOk, tracker.OnEvent(&client, "Page.frameStartedLoading", params).code());
96 ASSERT_NO_FATAL_FAILURE(AssertPendingState(&tracker, "f", true));
98 kOk, tracker.OnEvent(&client, "Page.frameStoppedLoading", params).code());
99 ASSERT_NO_FATAL_FAILURE(AssertPendingState(&tracker, "f", false));
102 // When a frame fails to load due to (for example) a DNS resolution error, we
103 // can sometimes see two Page.frameStartedLoading events with only a single
104 // Page.frameStoppedLoading event.
105 TEST(NavigationTracker, FrameLoadStartStartStop) {
106 StubDevToolsClient client;
107 BrowserInfo browser_info;
108 NavigationTracker tracker(&client, &browser_info);
110 base::DictionaryValue params;
111 params.SetString("frameId", "f");
114 kOk, tracker.OnEvent(&client, "Page.frameStartedLoading", params).code());
115 ASSERT_NO_FATAL_FAILURE(AssertPendingState(&tracker, "f", true));
117 kOk, tracker.OnEvent(&client, "Page.frameStartedLoading", params).code());
118 ASSERT_NO_FATAL_FAILURE(AssertPendingState(&tracker, "f", true));
120 kOk, tracker.OnEvent(&client, "Page.frameStoppedLoading", params).code());
121 ASSERT_NO_FATAL_FAILURE(AssertPendingState(&tracker, "f", false));
124 // NavigationTracker::OnEvent handles the Page.frameStoppedLoading event
125 // differently, depending on the browser and blink version. See the comment in
126 // NavigationTracker::OnEvent for details.
128 TEST(NavigationTracker, MultipleFramesLoadOldDevtools) {
129 BrowserInfo kOldChromeWithNewBlink("chrome", std::string(), 1916, 170248);
130 AssertTrackerExpectsSingleStopEvent(&kOldChromeWithNewBlink);
132 BrowserInfo kWebViewWithOldBlink("webview", std::string(), 9999, 170247);
133 AssertTrackerExpectsSingleStopEvent(&kWebViewWithOldBlink);
136 TEST(NavigationTracker, MultipleFramesLoad) {
137 BrowserInfo kNewChromeWithNewBlink("chrome", std::string(), 1917, 170248);
138 AssertTrackerExpectsMultipleStopEvents(&kNewChromeWithNewBlink);
140 BrowserInfo kWebViewWithNewBlink("webview", std::string(), 9999, 170248);
141 AssertTrackerExpectsMultipleStopEvents(&kWebViewWithNewBlink);
144 TEST(NavigationTracker, NavigationScheduledThenLoaded) {
145 StubDevToolsClient client;
146 BrowserInfo browser_info;
147 NavigationTracker tracker(
148 &client, NavigationTracker::kNotLoading, &browser_info);
149 base::DictionaryValue params;
150 params.SetString("frameId", "f");
151 base::DictionaryValue params_scheduled;
152 params_scheduled.SetInteger("delay", 0);
153 params_scheduled.SetString("frameId", "f");
158 &client, "Page.frameScheduledNavigation", params_scheduled).code());
159 ASSERT_NO_FATAL_FAILURE(AssertPendingState(&tracker, "f", true));
161 kOk, tracker.OnEvent(&client, "Page.frameStartedLoading", params).code());
162 ASSERT_NO_FATAL_FAILURE(AssertPendingState(&tracker, "f", true));
165 tracker.OnEvent(&client, "Page.frameClearedScheduledNavigation", params)
167 ASSERT_NO_FATAL_FAILURE(AssertPendingState(&tracker, "f", true));
169 kOk, tracker.OnEvent(&client, "Page.frameStoppedLoading", params).code());
170 ASSERT_NO_FATAL_FAILURE(AssertPendingState(&tracker, "f", false));
173 TEST(NavigationTracker, NavigationScheduledForOtherFrame) {
174 StubDevToolsClient client;
175 BrowserInfo browser_info;
176 NavigationTracker tracker(
177 &client, NavigationTracker::kNotLoading, &browser_info);
178 base::DictionaryValue params_scheduled;
179 params_scheduled.SetInteger("delay", 0);
180 params_scheduled.SetString("frameId", "other");
185 &client, "Page.frameScheduledNavigation", params_scheduled).code());
186 ASSERT_NO_FATAL_FAILURE(AssertPendingState(&tracker, "f", false));
189 TEST(NavigationTracker, NavigationScheduledThenCancelled) {
190 StubDevToolsClient client;
191 BrowserInfo browser_info;
192 NavigationTracker tracker(
193 &client, NavigationTracker::kNotLoading, &browser_info);
194 base::DictionaryValue params;
195 params.SetString("frameId", "f");
196 base::DictionaryValue params_scheduled;
197 params_scheduled.SetInteger("delay", 0);
198 params_scheduled.SetString("frameId", "f");
203 &client, "Page.frameScheduledNavigation", params_scheduled).code());
204 ASSERT_NO_FATAL_FAILURE(AssertPendingState(&tracker, "f", true));
207 tracker.OnEvent(&client, "Page.frameClearedScheduledNavigation", params)
209 ASSERT_NO_FATAL_FAILURE(AssertPendingState(&tracker, "f", false));
212 TEST(NavigationTracker, NavigationScheduledTooFarAway) {
213 StubDevToolsClient client;
214 BrowserInfo browser_info;
215 NavigationTracker tracker(
216 &client, NavigationTracker::kNotLoading, &browser_info);
218 base::DictionaryValue params_scheduled;
219 params_scheduled.SetInteger("delay", 10);
220 params_scheduled.SetString("frameId", "f");
224 &client, "Page.frameScheduledNavigation", params_scheduled).code());
225 ASSERT_NO_FATAL_FAILURE(AssertPendingState(&tracker, "f", false));
228 TEST(NavigationTracker, DiscardScheduledNavigationsOnMainFrameCommit) {
229 StubDevToolsClient client;
230 BrowserInfo browser_info;
231 NavigationTracker tracker(
232 &client, NavigationTracker::kNotLoading, &browser_info);
234 base::DictionaryValue params_scheduled;
235 params_scheduled.SetString("frameId", "subframe");
236 params_scheduled.SetInteger("delay", 0);
240 &client, "Page.frameScheduledNavigation", params_scheduled).code());
241 ASSERT_NO_FATAL_FAILURE(AssertPendingState(&tracker, "subframe", true));
243 base::DictionaryValue params_navigated;
244 params_navigated.SetString("frame.parentId", "something");
247 tracker.OnEvent(&client, "Page.frameNavigated", params_navigated).code());
248 ASSERT_NO_FATAL_FAILURE(AssertPendingState(&tracker, "subframe", true));
249 params_navigated.Clear();
252 tracker.OnEvent(&client, "Page.frameNavigated", params_navigated).code());
253 ASSERT_NO_FATAL_FAILURE(AssertPendingState(&tracker, "subframe", false));
258 class FailToEvalScriptDevToolsClient : public StubDevToolsClient {
260 virtual ~FailToEvalScriptDevToolsClient() {}
262 virtual Status SendCommandAndGetResult(
263 const std::string& method,
264 const base::DictionaryValue& params,
265 scoped_ptr<base::DictionaryValue>* result) OVERRIDE {
266 EXPECT_STREQ("Runtime.evaluate", method.c_str());
267 return Status(kUnknownError, "failed to eval script");
273 TEST(NavigationTracker, UnknownStateFailsToDetermineState) {
274 FailToEvalScriptDevToolsClient client;
275 BrowserInfo browser_info;
276 NavigationTracker tracker(&client, &browser_info);
278 ASSERT_EQ(kUnknownError,
279 tracker.IsPendingNavigation("f", &is_pending).code());
284 class DeterminingLoadStateDevToolsClient : public StubDevToolsClient {
286 DeterminingLoadStateDevToolsClient(
288 const std::string& send_event_first,
289 base::DictionaryValue* send_event_first_params)
290 : is_loading_(is_loading),
291 send_event_first_(send_event_first),
292 send_event_first_params_(send_event_first_params) {}
294 virtual ~DeterminingLoadStateDevToolsClient() {}
296 virtual Status SendCommandAndGetResult(
297 const std::string& method,
298 const base::DictionaryValue& params,
299 scoped_ptr<base::DictionaryValue>* result) OVERRIDE {
300 if (send_event_first_.length()) {
301 Status status = listeners_.front()
302 ->OnEvent(this, send_event_first_, *send_event_first_params_);
303 if (status.IsError())
307 base::DictionaryValue result_dict;
308 result_dict.SetBoolean("result.value", is_loading_);
309 result->reset(result_dict.DeepCopy());
315 std::string send_event_first_;
316 base::DictionaryValue* send_event_first_params_;
321 TEST(NavigationTracker, UnknownStateForcesStart) {
322 base::DictionaryValue params;
323 DeterminingLoadStateDevToolsClient client(true, std::string(), ¶ms);
324 BrowserInfo browser_info;
325 NavigationTracker tracker(&client, &browser_info);
326 ASSERT_NO_FATAL_FAILURE(AssertPendingState(&tracker, "f", true));
329 TEST(NavigationTracker, UnknownStateForcesStartReceivesStop) {
330 base::DictionaryValue params;
331 params.SetString("frameId", "f");
332 DeterminingLoadStateDevToolsClient client(
333 true, "Page.frameStoppedLoading", ¶ms);
334 BrowserInfo browser_info;
335 NavigationTracker tracker(&client, &browser_info);
336 ASSERT_NO_FATAL_FAILURE(AssertPendingState(&tracker, "f", false));
339 TEST(NavigationTracker, OnSuccessfulNavigate) {
340 base::DictionaryValue params;
341 params.SetString("frameId", "f");
342 DeterminingLoadStateDevToolsClient client(
343 true, "Page.frameStoppedLoading", ¶ms);
344 BrowserInfo browser_info;
345 NavigationTracker tracker(
346 &client, NavigationTracker::kNotLoading, &browser_info);
347 tracker.OnCommandSuccess(&client, "Page.navigate");
348 ASSERT_NO_FATAL_FAILURE(AssertPendingState(&tracker, "f", false));
351 TEST(NavigationTracker, OnSuccessfulNavigateStillWaiting) {
352 base::DictionaryValue params;
353 params.SetString("frameId", "f");
354 DeterminingLoadStateDevToolsClient client(true, std::string(), ¶ms);
355 BrowserInfo browser_info;
356 NavigationTracker tracker(
357 &client, NavigationTracker::kNotLoading, &browser_info);
358 tracker.OnCommandSuccess(&client, "Page.navigate");
359 ASSERT_NO_FATAL_FAILURE(AssertPendingState(&tracker, "f", true));