Enable PPAPI tests for non-SFI mode.
[chromium-blink-merge.git] / chrome / test / chromedriver / commands_unittest.cc
blob44571863054bbd1a38e1ca25808019295033843a
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.
5 #include <string>
7 #include "base/bind.h"
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/message_loop/message_loop.h"
13 #include "base/run_loop.h"
14 #include "base/synchronization/lock.h"
15 #include "base/threading/thread.h"
16 #include "base/values.h"
17 #include "chrome/test/chromedriver/chrome/status.h"
18 #include "chrome/test/chromedriver/chrome/stub_chrome.h"
19 #include "chrome/test/chromedriver/chrome/stub_web_view.h"
20 #include "chrome/test/chromedriver/chrome/web_view.h"
21 #include "chrome/test/chromedriver/commands.h"
22 #include "chrome/test/chromedriver/element_commands.h"
23 #include "chrome/test/chromedriver/session.h"
24 #include "chrome/test/chromedriver/session_commands.h"
25 #include "chrome/test/chromedriver/window_commands.h"
26 #include "testing/gtest/include/gtest/gtest.h"
27 #include "third_party/webdriver/atoms.h"
29 namespace {
31 void OnGetStatus(const Status& status,
32 scoped_ptr<base::Value> value,
33 const std::string& session_id) {
34 ASSERT_EQ(kOk, status.code());
35 base::DictionaryValue* dict;
36 ASSERT_TRUE(value->GetAsDictionary(&dict));
37 base::Value* unused;
38 ASSERT_TRUE(dict->Get("os.name", &unused));
39 ASSERT_TRUE(dict->Get("os.version", &unused));
40 ASSERT_TRUE(dict->Get("os.arch", &unused));
41 ASSERT_TRUE(dict->Get("build.version", &unused));
44 } // namespace
46 TEST(CommandsTest, GetStatus) {
47 base::DictionaryValue params;
48 ExecuteGetStatus(params, std::string(), base::Bind(&OnGetStatus));
51 namespace {
53 void ExecuteStubQuit(
54 int* count,
55 const base::DictionaryValue& params,
56 const std::string& session_id,
57 const CommandCallback& callback) {
58 if (*count == 0) {
59 EXPECT_STREQ("id", session_id.c_str());
60 } else {
61 EXPECT_STREQ("id2", session_id.c_str());
63 (*count)++;
64 callback.Run(Status(kOk), scoped_ptr<base::Value>(), session_id);
67 void OnQuitAll(const Status& status,
68 scoped_ptr<base::Value> value,
69 const std::string& session_id) {
70 ASSERT_EQ(kOk, status.code());
71 ASSERT_FALSE(value.get());
74 } // namespace
76 TEST(CommandsTest, QuitAll) {
77 SessionThreadMap map;
78 Session session("id");
79 Session session2("id2");
80 map[session.id] = make_linked_ptr(new base::Thread("1"));
81 map[session2.id] = make_linked_ptr(new base::Thread("2"));
83 int count = 0;
84 Command cmd = base::Bind(&ExecuteStubQuit, &count);
85 base::DictionaryValue params;
86 base::MessageLoop loop;
87 ExecuteQuitAll(cmd, &map, params, std::string(), base::Bind(&OnQuitAll));
88 ASSERT_EQ(2, count);
91 namespace {
93 Status ExecuteSimpleCommand(
94 const std::string& expected_id,
95 base::DictionaryValue* expected_params,
96 base::Value* value,
97 Session* session,
98 const base::DictionaryValue& params,
99 scoped_ptr<base::Value>* return_value) {
100 EXPECT_EQ(expected_id, session->id);
101 EXPECT_TRUE(expected_params->Equals(&params));
102 return_value->reset(value->DeepCopy());
103 session->quit = true;
104 return Status(kOk);
107 void OnSimpleCommand(base::RunLoop* run_loop,
108 const std::string& expected_session_id,
109 base::Value* expected_value,
110 const Status& status,
111 scoped_ptr<base::Value> value,
112 const std::string& session_id) {
113 ASSERT_EQ(kOk, status.code());
114 ASSERT_TRUE(expected_value->Equals(value.get()));
115 ASSERT_EQ(expected_session_id, session_id);
116 run_loop->Quit();
119 } // namespace
121 TEST(CommandsTest, ExecuteSessionCommand) {
122 SessionThreadMap map;
123 linked_ptr<base::Thread> thread(new base::Thread("1"));
124 ASSERT_TRUE(thread->Start());
125 std::string id("id");
126 thread->message_loop()->PostTask(
127 FROM_HERE,
128 base::Bind(&internal::CreateSessionOnSessionThreadForTesting, id));
129 map[id] = thread;
131 base::DictionaryValue params;
132 params.SetInteger("param", 5);
133 base::FundamentalValue expected_value(6);
134 SessionCommand cmd = base::Bind(
135 &ExecuteSimpleCommand, id, &params, &expected_value);
137 base::MessageLoop loop;
138 base::RunLoop run_loop;
139 ExecuteSessionCommand(
140 &map,
141 "cmd",
142 cmd,
143 false,
144 params,
146 base::Bind(&OnSimpleCommand, &run_loop, id, &expected_value));
147 run_loop.Run();
150 namespace {
152 Status ShouldNotBeCalled(
153 Session* session,
154 const base::DictionaryValue& params,
155 scoped_ptr<base::Value>* value) {
156 EXPECT_TRUE(false);
157 return Status(kOk);
160 void OnNoSuchSession(const Status& status,
161 scoped_ptr<base::Value> value,
162 const std::string& session_id) {
163 EXPECT_EQ(kNoSuchSession, status.code());
164 EXPECT_FALSE(value.get());
167 void OnNoSuchSessionIsOk(const Status& status,
168 scoped_ptr<base::Value> value,
169 const std::string& session_id) {
170 EXPECT_EQ(kOk, status.code());
171 EXPECT_FALSE(value.get());
174 } // namespace
176 TEST(CommandsTest, ExecuteSessionCommandOnNoSuchSession) {
177 SessionThreadMap map;
178 base::DictionaryValue params;
179 ExecuteSessionCommand(&map,
180 "cmd",
181 base::Bind(&ShouldNotBeCalled),
182 false,
183 params,
184 "session",
185 base::Bind(&OnNoSuchSession));
188 TEST(CommandsTest, ExecuteSessionCommandOnNoSuchSessionWhenItExpectsOk) {
189 SessionThreadMap map;
190 base::DictionaryValue params;
191 ExecuteSessionCommand(&map,
192 "cmd",
193 base::Bind(&ShouldNotBeCalled),
194 true,
195 params,
196 "session",
197 base::Bind(&OnNoSuchSessionIsOk));
200 namespace {
202 void OnNoSuchSessionAndQuit(base::RunLoop* run_loop,
203 const Status& status,
204 scoped_ptr<base::Value> value,
205 const std::string& session_id) {
206 run_loop->Quit();
207 EXPECT_EQ(kNoSuchSession, status.code());
208 EXPECT_FALSE(value.get());
211 } // namespace
213 TEST(CommandsTest, ExecuteSessionCommandOnJustDeletedSession) {
214 SessionThreadMap map;
215 linked_ptr<base::Thread> thread(new base::Thread("1"));
216 ASSERT_TRUE(thread->Start());
217 std::string id("id");
218 map[id] = thread;
220 base::MessageLoop loop;
221 base::RunLoop run_loop;
222 ExecuteSessionCommand(&map,
223 "cmd",
224 base::Bind(&ShouldNotBeCalled),
225 false,
226 base::DictionaryValue(),
227 "session",
228 base::Bind(&OnNoSuchSessionAndQuit, &run_loop));
229 run_loop.Run();
232 namespace {
234 enum TestScenario {
235 kElementExistsQueryOnce = 0,
236 kElementExistsQueryTwice,
237 kElementNotExistsQueryOnce,
238 kElementExistsTimeout
241 class FindElementWebView : public StubWebView {
242 public:
243 FindElementWebView(bool only_one, TestScenario scenario)
244 : StubWebView("1"), only_one_(only_one), scenario_(scenario),
245 current_count_(0) {
246 switch (scenario_) {
247 case kElementExistsQueryOnce:
248 case kElementExistsQueryTwice:
249 case kElementExistsTimeout: {
250 if (only_one_) {
251 base::DictionaryValue element;
252 element.SetString("ELEMENT", "1");
253 result_.reset(element.DeepCopy());
254 } else {
255 base::DictionaryValue element1;
256 element1.SetString("ELEMENT", "1");
257 base::DictionaryValue element2;
258 element2.SetString("ELEMENT", "2");
259 base::ListValue list;
260 list.Append(element1.DeepCopy());
261 list.Append(element2.DeepCopy());
262 result_.reset(list.DeepCopy());
264 break;
266 case kElementNotExistsQueryOnce: {
267 if (only_one_)
268 result_.reset(base::Value::CreateNullValue());
269 else
270 result_.reset(new base::ListValue());
271 break;
275 virtual ~FindElementWebView() {}
277 void Verify(const std::string& expected_frame,
278 const base::ListValue* expected_args,
279 const base::Value* actrual_result) {
280 EXPECT_EQ(expected_frame, frame_);
281 std::string function;
282 if (only_one_)
283 function = webdriver::atoms::asString(webdriver::atoms::FIND_ELEMENT);
284 else
285 function = webdriver::atoms::asString(webdriver::atoms::FIND_ELEMENTS);
286 EXPECT_EQ(function, function_);
287 ASSERT_TRUE(args_.get());
288 EXPECT_TRUE(expected_args->Equals(args_.get()));
289 ASSERT_TRUE(actrual_result);
290 EXPECT_TRUE(result_->Equals(actrual_result));
293 // Overridden from WebView:
294 virtual Status CallFunction(const std::string& frame,
295 const std::string& function,
296 const base::ListValue& args,
297 scoped_ptr<base::Value>* result) OVERRIDE {
298 ++current_count_;
299 if (scenario_ == kElementExistsTimeout ||
300 (scenario_ == kElementExistsQueryTwice && current_count_ == 1)) {
301 // Always return empty result when testing timeout.
302 if (only_one_)
303 result->reset(base::Value::CreateNullValue());
304 else
305 result->reset(new base::ListValue());
306 } else {
307 switch (scenario_) {
308 case kElementExistsQueryOnce:
309 case kElementNotExistsQueryOnce: {
310 EXPECT_EQ(1, current_count_);
311 break;
313 case kElementExistsQueryTwice: {
314 EXPECT_EQ(2, current_count_);
315 break;
317 default: {
318 break;
322 result->reset(result_->DeepCopy());
323 frame_ = frame;
324 function_ = function;
325 args_.reset(args.DeepCopy());
327 return Status(kOk);
330 private:
331 bool only_one_;
332 TestScenario scenario_;
333 int current_count_;
334 std::string frame_;
335 std::string function_;
336 scoped_ptr<base::ListValue> args_;
337 scoped_ptr<base::Value> result_;
340 } // namespace
342 TEST(CommandsTest, SuccessfulFindElement) {
343 FindElementWebView web_view(true, kElementExistsQueryTwice);
344 Session session("id");
345 session.implicit_wait = base::TimeDelta::FromSeconds(1);
346 session.SwitchToSubFrame("frame_id1", std::string());
347 base::DictionaryValue params;
348 params.SetString("using", "id");
349 params.SetString("value", "a");
350 scoped_ptr<base::Value> result;
351 ASSERT_EQ(kOk,
352 ExecuteFindElement(1, &session, &web_view, params, &result).code());
353 base::DictionaryValue param;
354 param.SetString("id", "a");
355 base::ListValue expected_args;
356 expected_args.Append(param.DeepCopy());
357 web_view.Verify("frame_id1", &expected_args, result.get());
360 TEST(CommandsTest, FailedFindElement) {
361 FindElementWebView web_view(true, kElementNotExistsQueryOnce);
362 Session session("id");
363 base::DictionaryValue params;
364 params.SetString("using", "id");
365 params.SetString("value", "a");
366 scoped_ptr<base::Value> result;
367 ASSERT_EQ(kNoSuchElement,
368 ExecuteFindElement(1, &session, &web_view, params, &result).code());
371 TEST(CommandsTest, SuccessfulFindElements) {
372 FindElementWebView web_view(false, kElementExistsQueryTwice);
373 Session session("id");
374 session.implicit_wait = base::TimeDelta::FromSeconds(1);
375 session.SwitchToSubFrame("frame_id2", std::string());
376 base::DictionaryValue params;
377 params.SetString("using", "name");
378 params.SetString("value", "b");
379 scoped_ptr<base::Value> result;
380 ASSERT_EQ(
381 kOk,
382 ExecuteFindElements(1, &session, &web_view, params, &result).code());
383 base::DictionaryValue param;
384 param.SetString("name", "b");
385 base::ListValue expected_args;
386 expected_args.Append(param.DeepCopy());
387 web_view.Verify("frame_id2", &expected_args, result.get());
390 TEST(CommandsTest, FailedFindElements) {
391 Session session("id");
392 FindElementWebView web_view(false, kElementNotExistsQueryOnce);
393 base::DictionaryValue params;
394 params.SetString("using", "id");
395 params.SetString("value", "a");
396 scoped_ptr<base::Value> result;
397 ASSERT_EQ(
398 kOk,
399 ExecuteFindElements(1, &session, &web_view, params, &result).code());
400 base::ListValue* list;
401 ASSERT_TRUE(result->GetAsList(&list));
402 ASSERT_EQ(0U, list->GetSize());
405 TEST(CommandsTest, SuccessfulFindChildElement) {
406 FindElementWebView web_view(true, kElementExistsQueryTwice);
407 Session session("id");
408 session.implicit_wait = base::TimeDelta::FromSeconds(1);
409 session.SwitchToSubFrame("frame_id3", std::string());
410 base::DictionaryValue params;
411 params.SetString("using", "tag name");
412 params.SetString("value", "div");
413 std::string element_id = "1";
414 scoped_ptr<base::Value> result;
415 ASSERT_EQ(
416 kOk,
417 ExecuteFindChildElement(
418 1, &session, &web_view, element_id, params, &result).code());
419 base::DictionaryValue locator_param;
420 locator_param.SetString("tag name", "div");
421 base::DictionaryValue root_element_param;
422 root_element_param.SetString("ELEMENT", element_id);
423 base::ListValue expected_args;
424 expected_args.Append(locator_param.DeepCopy());
425 expected_args.Append(root_element_param.DeepCopy());
426 web_view.Verify("frame_id3", &expected_args, result.get());
429 TEST(CommandsTest, FailedFindChildElement) {
430 Session session("id");
431 FindElementWebView web_view(true, kElementNotExistsQueryOnce);
432 base::DictionaryValue params;
433 params.SetString("using", "id");
434 params.SetString("value", "a");
435 std::string element_id = "1";
436 scoped_ptr<base::Value> result;
437 ASSERT_EQ(
438 kNoSuchElement,
439 ExecuteFindChildElement(
440 1, &session, &web_view, element_id, params, &result).code());
443 TEST(CommandsTest, SuccessfulFindChildElements) {
444 FindElementWebView web_view(false, kElementExistsQueryTwice);
445 Session session("id");
446 session.implicit_wait = base::TimeDelta::FromSeconds(1);
447 session.SwitchToSubFrame("frame_id4", std::string());
448 base::DictionaryValue params;
449 params.SetString("using", "class name");
450 params.SetString("value", "c");
451 std::string element_id = "1";
452 scoped_ptr<base::Value> result;
453 ASSERT_EQ(
454 kOk,
455 ExecuteFindChildElements(
456 1, &session, &web_view, element_id, params, &result).code());
457 base::DictionaryValue locator_param;
458 locator_param.SetString("class name", "c");
459 base::DictionaryValue root_element_param;
460 root_element_param.SetString("ELEMENT", element_id);
461 base::ListValue expected_args;
462 expected_args.Append(locator_param.DeepCopy());
463 expected_args.Append(root_element_param.DeepCopy());
464 web_view.Verify("frame_id4", &expected_args, result.get());
467 TEST(CommandsTest, FailedFindChildElements) {
468 Session session("id");
469 FindElementWebView web_view(false, kElementNotExistsQueryOnce);
470 base::DictionaryValue params;
471 params.SetString("using", "id");
472 params.SetString("value", "a");
473 std::string element_id = "1";
474 scoped_ptr<base::Value> result;
475 ASSERT_EQ(
476 kOk,
477 ExecuteFindChildElements(
478 1, &session, &web_view, element_id, params, &result).code());
479 base::ListValue* list;
480 ASSERT_TRUE(result->GetAsList(&list));
481 ASSERT_EQ(0U, list->GetSize());
484 TEST(CommandsTest, TimeoutInFindElement) {
485 Session session("id");
486 FindElementWebView web_view(true, kElementExistsTimeout);
487 session.implicit_wait = base::TimeDelta::FromMilliseconds(2);
488 base::DictionaryValue params;
489 params.SetString("using", "id");
490 params.SetString("value", "a");
491 params.SetString("id", "1");
492 scoped_ptr<base::Value> result;
493 ASSERT_EQ(kNoSuchElement,
494 ExecuteFindElement(1, &session, &web_view, params, &result).code());
497 namespace {
499 class ErrorCallFunctionWebView : public StubWebView {
500 public:
501 explicit ErrorCallFunctionWebView(StatusCode code)
502 : StubWebView("1"), code_(code) {}
503 virtual ~ErrorCallFunctionWebView() {}
505 // Overridden from WebView:
506 virtual Status CallFunction(const std::string& frame,
507 const std::string& function,
508 const base::ListValue& args,
509 scoped_ptr<base::Value>* result) OVERRIDE {
510 return Status(code_);
513 private:
514 StatusCode code_;
517 } // namespace
519 TEST(CommandsTest, ErrorFindElement) {
520 Session session("id");
521 ErrorCallFunctionWebView web_view(kUnknownError);
522 base::DictionaryValue params;
523 params.SetString("using", "id");
524 params.SetString("value", "a");
525 scoped_ptr<base::Value> value;
526 ASSERT_EQ(kUnknownError,
527 ExecuteFindElement(1, &session, &web_view, params, &value).code());
528 ASSERT_EQ(kUnknownError,
529 ExecuteFindElements(1, &session, &web_view, params, &value).code());
532 TEST(CommandsTest, ErrorFindChildElement) {
533 Session session("id");
534 ErrorCallFunctionWebView web_view(kStaleElementReference);
535 base::DictionaryValue params;
536 params.SetString("using", "id");
537 params.SetString("value", "a");
538 std::string element_id = "1";
539 scoped_ptr<base::Value> result;
540 ASSERT_EQ(
541 kStaleElementReference,
542 ExecuteFindChildElement(
543 1, &session, &web_view, element_id, params, &result).code());
544 ASSERT_EQ(
545 kStaleElementReference,
546 ExecuteFindChildElements(
547 1, &session, &web_view, element_id, params, &result).code());