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.
8 #include "base/callback.h"
9 #include "base/compiler_specific.h"
10 #include "base/files/file_path.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/synchronization/lock.h"
13 #include "base/values.h"
14 #include "chrome/test/chromedriver/chrome/status.h"
15 #include "chrome/test/chromedriver/chrome/stub_chrome.h"
16 #include "chrome/test/chromedriver/chrome/stub_web_view.h"
17 #include "chrome/test/chromedriver/chrome/web_view.h"
18 #include "chrome/test/chromedriver/command_executor_impl.h"
19 #include "chrome/test/chromedriver/commands.h"
20 #include "chrome/test/chromedriver/element_commands.h"
21 #include "chrome/test/chromedriver/fake_session_accessor.h"
22 #include "chrome/test/chromedriver/session_commands.h"
23 #include "chrome/test/chromedriver/window_commands.h"
24 #include "testing/gtest/include/gtest/gtest.h"
25 #include "third_party/webdriver/atoms.h"
27 TEST(CommandsTest
, GetStatus
) {
28 base::DictionaryValue params
;
29 scoped_ptr
<base::Value
> value
;
30 std::string session_id
;
32 kOk
, ExecuteGetStatus(params
, std::string(), &value
, &session_id
).code());
33 base::DictionaryValue
* dict
;
34 ASSERT_TRUE(value
->GetAsDictionary(&dict
));
36 ASSERT_TRUE(dict
->Get("os.name", &unused
));
37 ASSERT_TRUE(dict
->Get("os.version", &unused
));
38 ASSERT_TRUE(dict
->Get("os.arch", &unused
));
39 ASSERT_TRUE(dict
->Get("build.version", &unused
));
44 Status
ExecuteStubQuit(
46 const base::DictionaryValue
& params
,
47 const std::string
& session_id
,
48 scoped_ptr
<base::Value
>* value
,
49 std::string
* out_session_id
) {
51 EXPECT_STREQ("id", session_id
.c_str());
53 EXPECT_STREQ("id2", session_id
.c_str());
61 TEST(CommandsTest
, QuitAll
) {
63 Session
session("id");
64 Session
session2("id2");
66 scoped_refptr
<SessionAccessor
>(new FakeSessionAccessor(&session
)));
68 scoped_refptr
<SessionAccessor
>(new FakeSessionAccessor(&session2
)));
71 Command cmd
= base::Bind(&ExecuteStubQuit
, &count
);
72 base::DictionaryValue params
;
73 scoped_ptr
<base::Value
> value
;
74 std::string session_id
;
76 ExecuteQuitAll(cmd
, &map
, params
, std::string(), &value
, &session_id
);
77 ASSERT_EQ(kOk
, status
.code());
78 ASSERT_FALSE(value
.get());
82 TEST(CommandsTest
, Quit
) {
84 Session
session("id", scoped_ptr
<Chrome
>(new StubChrome()));
85 ASSERT_TRUE(session
.thread
.Start());
86 scoped_refptr
<FakeSessionAccessor
> session_accessor(
87 new FakeSessionAccessor(&session
));
88 map
.Set(session
.id
, session_accessor
);
89 base::DictionaryValue params
;
90 scoped_ptr
<base::Value
> value
;
91 std::string out_session_id
;
93 ExecuteSessionCommand(&map
, base::Bind(ExecuteQuit
, &map
), params
,
94 session
.id
, &value
, &out_session_id
).code());
95 ASSERT_FALSE(map
.Has(session
.id
));
96 ASSERT_TRUE(session_accessor
->IsSessionDeleted());
97 ASSERT_FALSE(value
.get());
102 class FailsToQuitChrome
: public StubChrome
{
104 FailsToQuitChrome() {}
105 virtual ~FailsToQuitChrome() {}
107 // Overridden from Chrome:
108 virtual Status
Quit() OVERRIDE
{
109 return Status(kUnknownError
);
115 TEST(CommandsTest
, QuitFails
) {
117 Session
session("id", scoped_ptr
<Chrome
>(new FailsToQuitChrome()));
118 ASSERT_TRUE(session
.thread
.Start());
119 scoped_refptr
<FakeSessionAccessor
> session_accessor(
120 new FakeSessionAccessor(&session
));
121 map
.Set(session
.id
, session_accessor
);
122 base::DictionaryValue params
;
123 scoped_ptr
<base::Value
> value
;
124 std::string out_session_id
;
125 ASSERT_EQ(kUnknownError
,
126 ExecuteSessionCommand(&map
, base::Bind(ExecuteQuit
, &map
), params
,
127 session
.id
, &value
, &out_session_id
).code());
128 ASSERT_FALSE(map
.Has(session
.id
));
129 ASSERT_TRUE(session_accessor
->IsSessionDeleted());
130 ASSERT_FALSE(value
.get());
136 kElementExistsQueryOnce
= 0,
137 kElementExistsQueryTwice
,
138 kElementNotExistsQueryOnce
,
139 kElementExistsTimeout
142 class FindElementWebView
: public StubWebView
{
144 FindElementWebView(bool only_one
, TestScenario scenario
)
145 : StubWebView("1"), only_one_(only_one
), scenario_(scenario
),
148 case kElementExistsQueryOnce
:
149 case kElementExistsQueryTwice
:
150 case kElementExistsTimeout
: {
152 base::DictionaryValue element
;
153 element
.SetString("ELEMENT", "1");
154 result_
.reset(element
.DeepCopy());
156 base::DictionaryValue element1
;
157 element1
.SetString("ELEMENT", "1");
158 base::DictionaryValue element2
;
159 element2
.SetString("ELEMENT", "2");
160 base::ListValue list
;
161 list
.Append(element1
.DeepCopy());
162 list
.Append(element2
.DeepCopy());
163 result_
.reset(list
.DeepCopy());
167 case kElementNotExistsQueryOnce
: {
169 result_
.reset(base::Value::CreateNullValue());
171 result_
.reset(new base::ListValue());
176 virtual ~FindElementWebView() {}
178 void Verify(const std::string
& expected_frame
,
179 const base::ListValue
* expected_args
,
180 const base::Value
* actrual_result
) {
181 EXPECT_EQ(expected_frame
, frame_
);
182 std::string function
;
184 function
= webdriver::atoms::asString(webdriver::atoms::FIND_ELEMENT
);
186 function
= webdriver::atoms::asString(webdriver::atoms::FIND_ELEMENTS
);
187 EXPECT_EQ(function
, function_
);
188 ASSERT_TRUE(args_
.get());
189 EXPECT_TRUE(expected_args
->Equals(args_
.get()));
190 ASSERT_TRUE(actrual_result
);
191 EXPECT_TRUE(result_
->Equals(actrual_result
));
194 // Overridden from WebView:
195 virtual Status
CallFunction(const std::string
& frame
,
196 const std::string
& function
,
197 const base::ListValue
& args
,
198 scoped_ptr
<base::Value
>* result
) OVERRIDE
{
200 if (scenario_
== kElementExistsTimeout
||
201 (scenario_
== kElementExistsQueryTwice
&& current_count_
== 1)) {
202 // Always return empty result when testing timeout.
204 result
->reset(base::Value::CreateNullValue());
206 result
->reset(new base::ListValue());
209 case kElementExistsQueryOnce
:
210 case kElementNotExistsQueryOnce
: {
211 EXPECT_EQ(1, current_count_
);
214 case kElementExistsQueryTwice
: {
215 EXPECT_EQ(2, current_count_
);
223 result
->reset(result_
->DeepCopy());
225 function_
= function
;
226 args_
.reset(args
.DeepCopy());
233 TestScenario scenario_
;
236 std::string function_
;
237 scoped_ptr
<base::ListValue
> args_
;
238 scoped_ptr
<base::Value
> result_
;
243 TEST(CommandsTest
, SuccessfulFindElement
) {
244 FindElementWebView
web_view(true, kElementExistsQueryTwice
);
245 Session
session("id");
246 session
.implicit_wait
= 1000;
247 session
.SwitchToSubFrame("frame_id1", std::string());
248 base::DictionaryValue params
;
249 params
.SetString("using", "id");
250 params
.SetString("value", "a");
251 scoped_ptr
<base::Value
> result
;
253 ExecuteFindElement(1, &session
, &web_view
, params
, &result
).code());
254 base::DictionaryValue param
;
255 param
.SetString("id", "a");
256 base::ListValue expected_args
;
257 expected_args
.Append(param
.DeepCopy());
258 web_view
.Verify("frame_id1", &expected_args
, result
.get());
261 TEST(CommandsTest
, FailedFindElement
) {
262 FindElementWebView
web_view(true, kElementNotExistsQueryOnce
);
263 Session
session("id");
264 base::DictionaryValue params
;
265 params
.SetString("using", "id");
266 params
.SetString("value", "a");
267 scoped_ptr
<base::Value
> result
;
268 ASSERT_EQ(kNoSuchElement
,
269 ExecuteFindElement(1, &session
, &web_view
, params
, &result
).code());
272 TEST(CommandsTest
, SuccessfulFindElements
) {
273 FindElementWebView
web_view(false, kElementExistsQueryTwice
);
274 Session
session("id");
275 session
.implicit_wait
= 1000;
276 session
.SwitchToSubFrame("frame_id2", std::string());
277 base::DictionaryValue params
;
278 params
.SetString("using", "name");
279 params
.SetString("value", "b");
280 scoped_ptr
<base::Value
> result
;
283 ExecuteFindElements(1, &session
, &web_view
, params
, &result
).code());
284 base::DictionaryValue param
;
285 param
.SetString("name", "b");
286 base::ListValue expected_args
;
287 expected_args
.Append(param
.DeepCopy());
288 web_view
.Verify("frame_id2", &expected_args
, result
.get());
291 TEST(CommandsTest
, FailedFindElements
) {
292 Session
session("id");
293 FindElementWebView
web_view(false, kElementNotExistsQueryOnce
);
294 base::DictionaryValue params
;
295 params
.SetString("using", "id");
296 params
.SetString("value", "a");
297 scoped_ptr
<base::Value
> result
;
300 ExecuteFindElements(1, &session
, &web_view
, params
, &result
).code());
301 base::ListValue
* list
;
302 ASSERT_TRUE(result
->GetAsList(&list
));
303 ASSERT_EQ(0U, list
->GetSize());
306 TEST(CommandsTest
, SuccessfulFindChildElement
) {
307 FindElementWebView
web_view(true, kElementExistsQueryTwice
);
308 Session
session("id");
309 session
.implicit_wait
= 1000;
310 session
.SwitchToSubFrame("frame_id3", std::string());
311 base::DictionaryValue params
;
312 params
.SetString("using", "tag name");
313 params
.SetString("value", "div");
314 std::string element_id
= "1";
315 scoped_ptr
<base::Value
> result
;
318 ExecuteFindChildElement(
319 1, &session
, &web_view
, element_id
, params
, &result
).code());
320 base::DictionaryValue locator_param
;
321 locator_param
.SetString("tag name", "div");
322 base::DictionaryValue root_element_param
;
323 root_element_param
.SetString("ELEMENT", element_id
);
324 base::ListValue expected_args
;
325 expected_args
.Append(locator_param
.DeepCopy());
326 expected_args
.Append(root_element_param
.DeepCopy());
327 web_view
.Verify("frame_id3", &expected_args
, result
.get());
330 TEST(CommandsTest
, FailedFindChildElement
) {
331 Session
session("id");
332 FindElementWebView
web_view(true, kElementNotExistsQueryOnce
);
333 base::DictionaryValue params
;
334 params
.SetString("using", "id");
335 params
.SetString("value", "a");
336 std::string element_id
= "1";
337 scoped_ptr
<base::Value
> result
;
340 ExecuteFindChildElement(
341 1, &session
, &web_view
, element_id
, params
, &result
).code());
344 TEST(CommandsTest
, SuccessfulFindChildElements
) {
345 FindElementWebView
web_view(false, kElementExistsQueryTwice
);
346 Session
session("id");
347 session
.implicit_wait
= 1000;
348 session
.SwitchToSubFrame("frame_id4", std::string());
349 base::DictionaryValue params
;
350 params
.SetString("using", "class name");
351 params
.SetString("value", "c");
352 std::string element_id
= "1";
353 scoped_ptr
<base::Value
> result
;
356 ExecuteFindChildElements(
357 1, &session
, &web_view
, element_id
, params
, &result
).code());
358 base::DictionaryValue locator_param
;
359 locator_param
.SetString("class name", "c");
360 base::DictionaryValue root_element_param
;
361 root_element_param
.SetString("ELEMENT", element_id
);
362 base::ListValue expected_args
;
363 expected_args
.Append(locator_param
.DeepCopy());
364 expected_args
.Append(root_element_param
.DeepCopy());
365 web_view
.Verify("frame_id4", &expected_args
, result
.get());
368 TEST(CommandsTest
, FailedFindChildElements
) {
369 Session
session("id");
370 FindElementWebView
web_view(false, kElementNotExistsQueryOnce
);
371 base::DictionaryValue params
;
372 params
.SetString("using", "id");
373 params
.SetString("value", "a");
374 std::string element_id
= "1";
375 scoped_ptr
<base::Value
> result
;
378 ExecuteFindChildElements(
379 1, &session
, &web_view
, element_id
, params
, &result
).code());
380 base::ListValue
* list
;
381 ASSERT_TRUE(result
->GetAsList(&list
));
382 ASSERT_EQ(0U, list
->GetSize());
385 TEST(CommandsTest
, TimeoutInFindElement
) {
386 Session
session("id");
387 FindElementWebView
web_view(true, kElementExistsTimeout
);
388 session
.implicit_wait
= 2;
389 base::DictionaryValue params
;
390 params
.SetString("using", "id");
391 params
.SetString("value", "a");
392 params
.SetString("id", "1");
393 scoped_ptr
<base::Value
> result
;
394 ASSERT_EQ(kNoSuchElement
,
395 ExecuteFindElement(1, &session
, &web_view
, params
, &result
).code());
400 class ErrorCallFunctionWebView
: public StubWebView
{
402 explicit ErrorCallFunctionWebView(StatusCode code
)
403 : StubWebView("1"), code_(code
) {}
404 virtual ~ErrorCallFunctionWebView() {}
406 // Overridden from WebView:
407 virtual Status
CallFunction(const std::string
& frame
,
408 const std::string
& function
,
409 const base::ListValue
& args
,
410 scoped_ptr
<base::Value
>* result
) OVERRIDE
{
411 return Status(code_
);
420 TEST(CommandsTest
, ErrorFindElement
) {
421 Session
session("id");
422 ErrorCallFunctionWebView
web_view(kUnknownError
);
423 base::DictionaryValue params
;
424 params
.SetString("using", "id");
425 params
.SetString("value", "a");
426 scoped_ptr
<base::Value
> value
;
427 ASSERT_EQ(kUnknownError
,
428 ExecuteFindElement(1, &session
, &web_view
, params
, &value
).code());
429 ASSERT_EQ(kUnknownError
,
430 ExecuteFindElements(1, &session
, &web_view
, params
, &value
).code());
433 TEST(CommandsTest
, ErrorFindChildElement
) {
434 Session
session("id");
435 ErrorCallFunctionWebView
web_view(kStaleElementReference
);
436 base::DictionaryValue params
;
437 params
.SetString("using", "id");
438 params
.SetString("value", "a");
439 std::string element_id
= "1";
440 scoped_ptr
<base::Value
> result
;
442 kStaleElementReference
,
443 ExecuteFindChildElement(
444 1, &session
, &web_view
, element_id
, params
, &result
).code());
446 kStaleElementReference
,
447 ExecuteFindChildElements(
448 1, &session
, &web_view
, element_id
, params
, &result
).code());