- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / test / chromedriver / commands_unittest.cc
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/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"
28
29 namespace {
30
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));
42 }
43
44 }  // namespace
45
46 TEST(CommandsTest, GetStatus) {
47   base::DictionaryValue params;
48   ExecuteGetStatus(params, std::string(), base::Bind(&OnGetStatus));
49 }
50
51 namespace {
52
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());
62   }
63   (*count)++;
64   callback.Run(Status(kOk), scoped_ptr<base::Value>(), session_id);
65 }
66
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());
72 }
73
74 }  // namespace
75
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"));
82
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);
89 }
90
91 namespace {
92
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);
105 }
106
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();
117 }
118
119 }  // namespace
120
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;
130
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);
136
137   base::MessageLoop loop;
138   base::RunLoop run_loop;
139   ExecuteSessionCommand(
140       &map,
141       "cmd",
142       cmd,
143       false,
144       params,
145       id,
146       base::Bind(&OnSimpleCommand, &run_loop, id, &expected_value));
147   run_loop.Run();
148 }
149
150 namespace {
151
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);
158 }
159
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());
165 }
166
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());
172 }
173
174 }  // namespace
175
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));
186 }
187
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));
198 }
199
200 namespace {
201
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());
209 }
210
211 }  // namespace
212
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;
219
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();
230 }
231
232 namespace {
233
234 enum TestScenario {
235   kElementExistsQueryOnce = 0,
236   kElementExistsQueryTwice,
237   kElementNotExistsQueryOnce,
238   kElementExistsTimeout
239 };
240
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());
263         }
264         break;
265       }
266       case kElementNotExistsQueryOnce: {
267         if (only_one_)
268           result_.reset(base::Value::CreateNullValue());
269         else
270           result_.reset(new base::ListValue());
271         break;
272       }
273     }
274   }
275   virtual ~FindElementWebView() {}
276
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));
291   }
292
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;
312         }
313         case kElementExistsQueryTwice: {
314           EXPECT_EQ(2, current_count_);
315           break;
316         }
317         default: {
318           break;
319         }
320       }
321
322       result->reset(result_->DeepCopy());
323       frame_ = frame;
324       function_ = function;
325       args_.reset(args.DeepCopy());
326     }
327     return Status(kOk);
328   }
329
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_;
338 };
339
340 }  // namespace
341
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());
358 }
359
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());
369 }
370
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());
388 }
389
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());
403 }
404
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());
427 }
428
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());
441 }
442
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());
465 }
466
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());
482 }
483
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());
495 }
496
497 namespace {
498
499 class ErrorCallFunctionWebView : public StubWebView {
500  public:
501   explicit ErrorCallFunctionWebView(StatusCode code)
502       : StubWebView("1"), code_(code) {}
503   virtual ~ErrorCallFunctionWebView() {}
504
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_);
511   }
512
513  private:
514   StatusCode code_;
515 };
516
517 }  // namespace
518
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());
530 }
531
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());
548 }