Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: chrome/test/chromedriver/element_util.cc

Issue 12764021: [chromedriver] Support clicking an element in sub frames. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix compile error. Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/test/chromedriver/element_util.h ('k') | chrome/test/chromedriver/run_py_tests.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/test/chromedriver/element_util.h" 5 #include "chrome/test/chromedriver/element_util.h"
6 6
7 #include "base/string_util.h" 7 #include "base/string_util.h"
8 #include "base/stringprintf.h"
9 #include "base/strings/string_number_conversions.h"
8 #include "base/threading/platform_thread.h" 10 #include "base/threading/platform_thread.h"
9 #include "base/time.h" 11 #include "base/time.h"
10 #include "base/values.h" 12 #include "base/values.h"
11 #include "chrome/test/chromedriver/basic_types.h" 13 #include "chrome/test/chromedriver/basic_types.h"
12 #include "chrome/test/chromedriver/js.h" 14 #include "chrome/test/chromedriver/js.h"
13 #include "chrome/test/chromedriver/session.h" 15 #include "chrome/test/chromedriver/session.h"
14 #include "chrome/test/chromedriver/status.h" 16 #include "chrome/test/chromedriver/status.h"
15 #include "chrome/test/chromedriver/web_view.h" 17 #include "chrome/test/chromedriver/web_view.h"
16 #include "third_party/webdriver/atoms.h" 18 #include "third_party/webdriver/atoms.h"
17 19
18 namespace { 20 namespace {
19 21
20 const char kElementKey[] = "ELEMENT"; 22 const char kElementKey[] = "ELEMENT";
21 23
22 bool ParseFromValue(base::Value* value, WebPoint* point) { 24 bool ParseFromValue(base::Value* value, WebPoint* point) {
23 base::DictionaryValue* dict_value; 25 base::DictionaryValue* dict_value;
24 if (!value->GetAsDictionary(&dict_value)) 26 if (!value->GetAsDictionary(&dict_value))
25 return false; 27 return false;
26 double x, y; 28 double x, y;
27 if (!dict_value->GetDouble("x", &x) || 29 if (!dict_value->GetDouble("x", &x) ||
28 !dict_value->GetDouble("y", &y)) 30 !dict_value->GetDouble("y", &y))
29 return false; 31 return false;
30 point->x = static_cast<int>(x); 32 point->x = static_cast<int>(x);
31 point->y = static_cast<int>(y); 33 point->y = static_cast<int>(y);
32 return true; 34 return true;
33 } 35 }
34 36
35 base::Value* CreateValueFrom(const WebPoint* point) { 37 base::Value* CreateValueFrom(const WebPoint& point) {
36 base::DictionaryValue* dict = new base::DictionaryValue(); 38 base::DictionaryValue* dict = new base::DictionaryValue();
37 dict->SetInteger("x", point->x); 39 dict->SetInteger("x", point.x);
38 dict->SetInteger("y", point->y); 40 dict->SetInteger("y", point.y);
39 return dict; 41 return dict;
40 } 42 }
41 43
42 bool ParseFromValue(base::Value* value, WebSize* size) { 44 bool ParseFromValue(base::Value* value, WebSize* size) {
43 base::DictionaryValue* dict_value; 45 base::DictionaryValue* dict_value;
44 if (!value->GetAsDictionary(&dict_value)) 46 if (!value->GetAsDictionary(&dict_value))
45 return false; 47 return false;
46 double width, height; 48 double width, height;
47 if (!dict_value->GetDouble("width", &width) || 49 if (!dict_value->GetDouble("width", &width) ||
48 !dict_value->GetDouble("height", &height)) 50 !dict_value->GetDouble("height", &height))
49 return false; 51 return false;
50 size->width = static_cast<int>(width); 52 size->width = static_cast<int>(width);
51 size->height = static_cast<int>(height); 53 size->height = static_cast<int>(height);
52 return true; 54 return true;
53 } 55 }
54 56
55 base::Value* CreateValueFrom(const WebSize* size) { 57 base::Value* CreateValueFrom(const WebSize& size) {
56 base::DictionaryValue* dict = new base::DictionaryValue(); 58 base::DictionaryValue* dict = new base::DictionaryValue();
57 dict->SetInteger("width", size->width); 59 dict->SetInteger("width", size.width);
58 dict->SetInteger("height", size->height); 60 dict->SetInteger("height", size.height);
59 return dict; 61 return dict;
60 } 62 }
61 63
62 bool ParseFromValue(base::Value* value, WebRect* rect) { 64 bool ParseFromValue(base::Value* value, WebRect* rect) {
63 base::DictionaryValue* dict_value; 65 base::DictionaryValue* dict_value;
64 if (!value->GetAsDictionary(&dict_value)) 66 if (!value->GetAsDictionary(&dict_value))
65 return false; 67 return false;
66 double x, y, width, height; 68 double x, y, width, height;
67 if (!dict_value->GetDouble("left", &x) || 69 if (!dict_value->GetDouble("left", &x) ||
68 !dict_value->GetDouble("top", &y) || 70 !dict_value->GetDouble("top", &y) ||
69 !dict_value->GetDouble("width", &width) || 71 !dict_value->GetDouble("width", &width) ||
70 !dict_value->GetDouble("height", &height)) 72 !dict_value->GetDouble("height", &height))
71 return false; 73 return false;
72 rect->origin.x = static_cast<int>(x); 74 rect->origin.x = static_cast<int>(x);
73 rect->origin.y = static_cast<int>(y); 75 rect->origin.y = static_cast<int>(y);
74 rect->size.width = static_cast<int>(width); 76 rect->size.width = static_cast<int>(width);
75 rect->size.height = static_cast<int>(height); 77 rect->size.height = static_cast<int>(height);
76 return true; 78 return true;
77 } 79 }
78 80
79 base::Value* CreateValueFrom(const WebRect* rect) { 81 base::Value* CreateValueFrom(const WebRect& rect) {
80 base::DictionaryValue* dict = new base::DictionaryValue(); 82 base::DictionaryValue* dict = new base::DictionaryValue();
81 dict->SetInteger("left", rect->origin.x); 83 dict->SetInteger("left", rect.X());
82 dict->SetInteger("top", rect->origin.y); 84 dict->SetInteger("top", rect.Y());
83 dict->SetInteger("width", rect->size.width); 85 dict->SetInteger("width", rect.Width());
84 dict->SetInteger("height", rect->size.height); 86 dict->SetInteger("height", rect.Height());
85 return dict; 87 return dict;
86 } 88 }
87 89
88 Status CallAtomsJs( 90 Status CallAtomsJs(
89 Session* session, 91 const std::string& frame,
90 WebView* web_view, 92 WebView* web_view,
91 const char* const* atom_function, 93 const char* const* atom_function,
92 const base::ListValue& args, 94 const base::ListValue& args,
93 scoped_ptr<base::Value>* result) { 95 scoped_ptr<base::Value>* result) {
94 return web_view->CallFunction( 96 return web_view->CallFunction(
95 session->frame, webdriver::atoms::asString(atom_function), 97 frame, webdriver::atoms::asString(atom_function), args, result);
96 args, result); 98 }
99
100 Status VerifyElementClickable(
101 const std::string& frame,
102 WebView* web_view,
103 const std::string& element_id,
104 const WebPoint& location) {
105 base::ListValue args;
106 args.Append(CreateElement(element_id));
107 args.Append(CreateValueFrom(location));
108 scoped_ptr<base::Value> result;
109 Status status = CallAtomsJs(
110 frame, web_view, webdriver::atoms::IS_ELEMENT_CLICKABLE,
111 args, &result);
112 if (status.IsError())
113 return status;
114 base::DictionaryValue* dict;
115 bool is_clickable;
116 if (!result->GetAsDictionary(&dict) ||
117 !dict->GetBoolean("clickable", &is_clickable))
118 return Status(kUnknownError, "fail to parse value of IS_ELEMENT_CLICKABLE");
119
120 if (!is_clickable) {
121 std::string message;
122 if (!dict->GetString("message", &message))
123 message = "element is not clickable";
124 return Status(kUnknownError, message);
125 }
126 return Status(kOk);
127 }
128
129 Status ScrollElementRegionIntoViewHelper(
130 const std::string& frame,
131 WebView* web_view,
132 const std::string& element_id,
133 const WebRect& region,
134 bool center,
135 bool verify_clickable,
136 WebPoint* location) {
137 WebPoint tmp_location = *location;
138 base::ListValue args;
139 args.Append(CreateElement(element_id));
140 args.AppendBoolean(center);
141 args.Append(CreateValueFrom(region));
142 scoped_ptr<base::Value> result;
143 Status status = web_view->CallFunction(
144 frame, webdriver::atoms::asString(webdriver::atoms::GET_LOCATION_IN_VIEW),
145 args, &result);
146 if (status.IsError())
147 return status;
148 if (!ParseFromValue(result.get(), &tmp_location))
149 return Status(kUnknownError, "fail to parse value of GET_LOCATION_IN_VIEW");
150 if (verify_clickable) {
151 WebPoint middle = tmp_location;
152 middle.Offset(region.Width() / 2, region.Height() / 2);
153 status = VerifyElementClickable(frame, web_view, element_id, middle);
154 if (status.IsError())
155 return status;
156 }
157 *location = tmp_location;
158 return Status(kOk);
159 }
160
161 Status GetElementEffectiveStyle(
162 const std::string& frame,
163 WebView* web_view,
164 const std::string& element_id,
165 const std::string& property,
166 std::string* value) {
167 base::ListValue args;
168 args.Append(CreateElement(element_id));
169 args.AppendString(property);
170 scoped_ptr<base::Value> result;
171 Status status = web_view->CallFunction(
172 frame, webdriver::atoms::asString(webdriver::atoms::GET_EFFECTIVE_STYLE),
173 args, &result);
174 if (status.IsError())
175 return status;
176 if (!result->GetAsString(value))
177 return Status(kUnknownError, "fail to parse value of GET_EFFECTIVE_STYLE");
178 return Status(kOk);
179 }
180
181 Status GetElementBorder(
182 const std::string& frame,
183 WebView* web_view,
184 const std::string& element_id,
185 int* border_left,
186 int* border_top) {
187 std::string border_left_str;
188 Status status = GetElementEffectiveStyle(
189 frame, web_view, element_id, "border-left-width", &border_left_str);
190 if (status.IsError())
191 return status;
192 std::string border_top_str;
193 status = GetElementEffectiveStyle(
194 frame, web_view, element_id, "border-top-width", &border_top_str);
195 if (status.IsError())
196 return status;
197 int border_left_tmp = -1;
198 int border_top_tmp = -1;
199 base::StringToInt(border_left_str, &border_left_tmp);
200 base::StringToInt(border_top_str, &border_top_tmp);
201 if (border_left_tmp == -1 || border_top_tmp == -1)
202 return Status(kUnknownError, "fail to get border width of element");
203 *border_left = border_left_tmp;
204 *border_top = border_top_tmp;
205 return Status(kOk);
97 } 206 }
98 207
99 } // namespace 208 } // namespace
100 209
101 base::DictionaryValue* CreateElement(const std::string& element_id) { 210 base::DictionaryValue* CreateElement(const std::string& element_id) {
102 base::DictionaryValue* element = new base::DictionaryValue(); 211 base::DictionaryValue* element = new base::DictionaryValue();
103 element->SetString(kElementKey, element_id); 212 element->SetString(kElementKey, element_id);
104 return element; 213 return element;
105 } 214 }
106 215
(...skipping 21 matching lines...) Expand all
128 locator->SetString(strategy, target); 237 locator->SetString(strategy, target);
129 base::ListValue arguments; 238 base::ListValue arguments;
130 arguments.Append(locator.release()); 239 arguments.Append(locator.release());
131 if (root_element_id) 240 if (root_element_id)
132 arguments.Append(CreateElement(*root_element_id)); 241 arguments.Append(CreateElement(*root_element_id));
133 242
134 base::Time start_time = base::Time::Now(); 243 base::Time start_time = base::Time::Now();
135 while (true) { 244 while (true) {
136 scoped_ptr<base::Value> temp; 245 scoped_ptr<base::Value> temp;
137 Status status = web_view->CallFunction( 246 Status status = web_view->CallFunction(
138 session->frame, script, arguments, &temp); 247 session->GetCurrentFrameId(), script, arguments, &temp);
139 if (status.IsError()) 248 if (status.IsError())
140 return status; 249 return status;
141 250
142 if (!temp->IsType(base::Value::TYPE_NULL)) { 251 if (!temp->IsType(base::Value::TYPE_NULL)) {
143 if (only_one) { 252 if (only_one) {
144 value->reset(temp.release()); 253 value->reset(temp.release());
145 return Status(kOk); 254 return Status(kOk);
146 } else { 255 } else {
147 base::ListValue* result; 256 base::ListValue* result;
148 if (!temp->GetAsList(&result)) 257 if (!temp->GetAsList(&result))
(...skipping 24 matching lines...) Expand all
173 Status GetElementAttribute( 282 Status GetElementAttribute(
174 Session* session, 283 Session* session,
175 WebView* web_view, 284 WebView* web_view,
176 const std::string& element_id, 285 const std::string& element_id,
177 const std::string& attribute_name, 286 const std::string& attribute_name,
178 scoped_ptr<base::Value>* value) { 287 scoped_ptr<base::Value>* value) {
179 base::ListValue args; 288 base::ListValue args;
180 args.Append(CreateElement(element_id)); 289 args.Append(CreateElement(element_id));
181 args.AppendString(attribute_name); 290 args.AppendString(attribute_name);
182 return CallAtomsJs( 291 return CallAtomsJs(
183 session, web_view, webdriver::atoms::GET_ATTRIBUTE, args, value); 292 session->GetCurrentFrameId(), web_view, webdriver::atoms::GET_ATTRIBUTE,
293 args, value);
184 } 294 }
185 295
186 Status IsElementAttributeEqualToIgnoreCase( 296 Status IsElementAttributeEqualToIgnoreCase(
187 Session* session, 297 Session* session,
188 WebView* web_view, 298 WebView* web_view,
189 const std::string& element_id, 299 const std::string& element_id,
190 const std::string& attribute_name, 300 const std::string& attribute_name,
191 const std::string& attribute_value, 301 const std::string& attribute_value,
192 bool* is_equal) { 302 bool* is_equal) {
193 scoped_ptr<base::Value> result; 303 scoped_ptr<base::Value> result;
194 Status status = GetElementAttribute( 304 Status status = GetElementAttribute(
195 session, web_view, element_id, attribute_name, &result); 305 session, web_view, element_id, attribute_name, &result);
196 if (status.IsError()) 306 if (status.IsError())
197 return status; 307 return status;
198 std::string actual_value; 308 std::string actual_value;
199 if (result->GetAsString(&actual_value)) 309 if (result->GetAsString(&actual_value))
200 *is_equal = LowerCaseEqualsASCII(actual_value, attribute_value.c_str()); 310 *is_equal = LowerCaseEqualsASCII(actual_value, attribute_value.c_str());
201 else 311 else
202 *is_equal = false; 312 *is_equal = false;
203 return status; 313 return status;
204 } 314 }
205 315
206 Status GetElementClickableLocation( 316 Status GetElementClickableLocation(
207 Session* session, 317 Session* session,
208 WebView* web_view, 318 WebView* web_view,
209 const std::string& element_id, 319 const std::string& element_id,
210 WebPoint* location, 320 WebPoint* location) {
211 bool* is_clickable) {
212 bool is_displayed = false; 321 bool is_displayed = false;
213 Status status = IsElementDisplayed( 322 Status status = IsElementDisplayed(
214 session, web_view, element_id, true, &is_displayed); 323 session, web_view, element_id, true, &is_displayed);
215 if (status.IsError()) 324 if (status.IsError())
216 return status; 325 return status;
217 if (!is_displayed) 326 if (!is_displayed)
218 return Status(kElementNotVisible); 327 return Status(kElementNotVisible);
219 328
220 WebRect rect; 329 WebRect rect;
221 status = GetElementRegion(session, web_view, element_id, &rect); 330 status = GetElementRegion(session, web_view, element_id, &rect);
222 if (status.IsError()) 331 if (status.IsError())
223 return status; 332 return status;
224 333
225 status = ScrollElementRegionIntoView( 334 status = ScrollElementRegionIntoView(
226 session, web_view, element_id, rect, true, location); 335 session, web_view, element_id, rect,
336 true /* center */, true /* verify_clickable */, location);
227 if (status.IsError()) 337 if (status.IsError())
228 return status; 338 return status;
229 location->offset(rect.width() / 2, rect.height() / 2); 339 location->Offset(rect.Width() / 2, rect.Height() / 2);
230 if (is_clickable) {
231 return IsElementClickable(
232 session, web_view, element_id, location, is_clickable);
233 }
234 return Status(kOk); 340 return Status(kOk);
235 } 341 }
236 342
237 Status GetElementRegion( 343 Status GetElementRegion(
238 Session* session, 344 Session* session,
239 WebView* web_view, 345 WebView* web_view,
240 const std::string& element_id, 346 const std::string& element_id,
241 WebRect* rect) { 347 WebRect* rect) {
242 base::ListValue args; 348 base::ListValue args;
243 args.Append(CreateElement(element_id)); 349 args.Append(CreateElement(element_id));
244 scoped_ptr<base::Value> result; 350 scoped_ptr<base::Value> result;
245 Status status = web_view->CallFunction( 351 Status status = web_view->CallFunction(
246 session->frame, kGetElementRegionScript, args, &result); 352 session->GetCurrentFrameId(), kGetElementRegionScript, args, &result);
247 if (status.IsError()) 353 if (status.IsError())
248 return status; 354 return status;
249 if (!ParseFromValue(result.get(), rect)) { 355 if (!ParseFromValue(result.get(), rect)) {
250 return Status(kUnknownError, 356 return Status(kUnknownError,
251 "fail to parse value of getElementRegion"); 357 "fail to parse value of getElementRegion");
252 } 358 }
253 return Status(kOk); 359 return Status(kOk);
254 } 360 }
255 361
256 Status GetElementTagName( 362 Status GetElementTagName(
257 Session* session, 363 Session* session,
258 WebView* web_view, 364 WebView* web_view,
259 const std::string& element_id, 365 const std::string& element_id,
260 std::string* name) { 366 std::string* name) {
261 base::ListValue args; 367 base::ListValue args;
262 args.Append(CreateElement(element_id)); 368 args.Append(CreateElement(element_id));
263 scoped_ptr<base::Value> result; 369 scoped_ptr<base::Value> result;
264 Status status = web_view->CallFunction( 370 Status status = web_view->CallFunction(
265 session->frame, "function(elem) { return elem.tagName.toLowerCase(); }", 371 session->GetCurrentFrameId(),
372 "function(elem) { return elem.tagName.toLowerCase(); }",
266 args, &result); 373 args, &result);
267 if (status.IsError()) 374 if (status.IsError())
268 return status; 375 return status;
269 if (!result->GetAsString(name)) 376 if (!result->GetAsString(name))
270 return Status(kUnknownError, "fail to get element tag name"); 377 return Status(kUnknownError, "fail to get element tag name");
271 return Status(kOk); 378 return Status(kOk);
272 } 379 }
273 380
274 Status GetElementSize( 381 Status GetElementSize(
275 Session* session, 382 Session* session,
276 WebView* web_view, 383 WebView* web_view,
277 const std::string& element_id, 384 const std::string& element_id,
278 WebSize* size) { 385 WebSize* size) {
279 base::ListValue args; 386 base::ListValue args;
280 args.Append(CreateElement(element_id)); 387 args.Append(CreateElement(element_id));
281 scoped_ptr<base::Value> result; 388 scoped_ptr<base::Value> result;
282 Status status = CallAtomsJs( 389 Status status = CallAtomsJs(
283 session, web_view, webdriver::atoms::GET_SIZE, args, &result); 390 session->GetCurrentFrameId(), web_view, webdriver::atoms::GET_SIZE,
391 args, &result);
284 if (status.IsError()) 392 if (status.IsError())
285 return status; 393 return status;
286 if (!ParseFromValue(result.get(), size)) 394 if (!ParseFromValue(result.get(), size))
287 return Status(kUnknownError, "fail to parse value of GET_SIZE"); 395 return Status(kUnknownError, "fail to parse value of GET_SIZE");
288 return Status(kOk); 396 return Status(kOk);
289 } 397 }
290 398
291 Status IsElementClickable(
292 Session* session,
293 WebView* web_view,
294 const std::string& element_id,
295 WebPoint* location,
296 bool* is_clickable) {
297 base::ListValue args;
298 args.Append(CreateElement(element_id));
299 args.Append(CreateValueFrom(location));
300 scoped_ptr<base::Value> result;
301 Status status = CallAtomsJs(
302 session, web_view, webdriver::atoms::IS_ELEMENT_CLICKABLE, args, &result);
303 if (status.IsError())
304 return status;
305 base::DictionaryValue* dict;
306 if (!result->GetAsDictionary(&dict) ||
307 !dict->GetBoolean("clickable", is_clickable))
308 return Status(kUnknownError, "fail to parse value of IS_ELEMENT_CLICKABLE");
309
310 if (!*is_clickable) {
311 std::string message;
312 if (!dict->GetString("message", &message))
313 message = "element is not clickable";
314 return Status(kOk, message);
315 }
316 return Status(kOk);
317 }
318
319 Status IsElementDisplayed( 399 Status IsElementDisplayed(
320 Session* session, 400 Session* session,
321 WebView* web_view, 401 WebView* web_view,
322 const std::string& element_id, 402 const std::string& element_id,
323 bool ignore_opacity, 403 bool ignore_opacity,
324 bool* is_displayed) { 404 bool* is_displayed) {
325 base::ListValue args; 405 base::ListValue args;
326 args.Append(CreateElement(element_id)); 406 args.Append(CreateElement(element_id));
327 args.AppendBoolean(ignore_opacity); 407 args.AppendBoolean(ignore_opacity);
328 scoped_ptr<base::Value> result; 408 scoped_ptr<base::Value> result;
329 Status status = CallAtomsJs( 409 Status status = CallAtomsJs(
330 session, web_view, webdriver::atoms::IS_DISPLAYED, args, &result); 410 session->GetCurrentFrameId(), web_view, webdriver::atoms::IS_DISPLAYED,
411 args, &result);
331 if (status.IsError()) 412 if (status.IsError())
332 return status; 413 return status;
333 if (!result->GetAsBoolean(is_displayed)) 414 if (!result->GetAsBoolean(is_displayed))
334 return Status(kUnknownError, "IS_DISPLAYED should return a boolean value"); 415 return Status(kUnknownError, "IS_DISPLAYED should return a boolean value");
335 return Status(kOk); 416 return Status(kOk);
336 } 417 }
337 418
338 Status IsElementEnabled( 419 Status IsElementEnabled(
339 Session* session, 420 Session* session,
340 WebView* web_view, 421 WebView* web_view,
341 const std::string& element_id, 422 const std::string& element_id,
342 bool* is_enabled) { 423 bool* is_enabled) {
343 base::ListValue args; 424 base::ListValue args;
344 args.Append(CreateElement(element_id)); 425 args.Append(CreateElement(element_id));
345 scoped_ptr<base::Value> result; 426 scoped_ptr<base::Value> result;
346 Status status = CallAtomsJs( 427 Status status = CallAtomsJs(
347 session, web_view, webdriver::atoms::IS_ENABLED, args, &result); 428 session->GetCurrentFrameId(), web_view, webdriver::atoms::IS_ENABLED,
429 args, &result);
348 if (status.IsError()) 430 if (status.IsError())
349 return status; 431 return status;
350 if (!result->GetAsBoolean(is_enabled)) 432 if (!result->GetAsBoolean(is_enabled))
351 return Status(kUnknownError, "IS_ENABLED should return a boolean value"); 433 return Status(kUnknownError, "IS_ENABLED should return a boolean value");
352 return Status(kOk); 434 return Status(kOk);
353 } 435 }
354 436
355 Status IsOptionElementSelected( 437 Status IsOptionElementSelected(
356 Session* session, 438 Session* session,
357 WebView* web_view, 439 WebView* web_view,
358 const std::string& element_id, 440 const std::string& element_id,
359 bool* is_selected) { 441 bool* is_selected) {
360 base::ListValue args; 442 base::ListValue args;
361 args.Append(CreateElement(element_id)); 443 args.Append(CreateElement(element_id));
362 scoped_ptr<base::Value> result; 444 scoped_ptr<base::Value> result;
363 Status status = CallAtomsJs( 445 Status status = CallAtomsJs(
364 session, web_view, webdriver::atoms::IS_SELECTED, args, &result); 446 session->GetCurrentFrameId(), web_view, webdriver::atoms::IS_SELECTED,
447 args, &result);
365 if (status.IsError()) 448 if (status.IsError())
366 return status; 449 return status;
367 if (!result->GetAsBoolean(is_selected)) 450 if (!result->GetAsBoolean(is_selected))
368 return Status(kUnknownError, "IS_SELECTED should return a boolean value"); 451 return Status(kUnknownError, "IS_SELECTED should return a boolean value");
369 return Status(kOk); 452 return Status(kOk);
370 } 453 }
371 454
372 Status IsOptionElementTogglable( 455 Status IsOptionElementTogglable(
373 Session* session, 456 Session* session,
374 WebView* web_view, 457 WebView* web_view,
375 const std::string& element_id, 458 const std::string& element_id,
376 bool* is_togglable) { 459 bool* is_togglable) {
377 base::ListValue args; 460 base::ListValue args;
378 args.Append(CreateElement(element_id)); 461 args.Append(CreateElement(element_id));
379 scoped_ptr<base::Value> result; 462 scoped_ptr<base::Value> result;
380 Status status = web_view->CallFunction( 463 Status status = web_view->CallFunction(
381 session->frame, kIsOptionElementToggleableScript, args, &result); 464 session->GetCurrentFrameId(), kIsOptionElementToggleableScript,
465 args, &result);
382 if (status.IsError()) 466 if (status.IsError())
383 return status; 467 return status;
384 if (!result->GetAsBoolean(is_togglable)) 468 if (!result->GetAsBoolean(is_togglable))
385 return Status(kUnknownError, "fail check if option togglable or not"); 469 return Status(kUnknownError, "fail check if option togglable or not");
386 return Status(kOk); 470 return Status(kOk);
387 } 471 }
388 472
389 Status SetOptionElementSelected( 473 Status SetOptionElementSelected(
390 Session* session, 474 Session* session,
391 WebView* web_view, 475 WebView* web_view,
392 const std::string& element_id, 476 const std::string& element_id,
393 bool selected) { 477 bool selected) {
394 // TODO(171034): need to fix throwing error if an alert is triggered. 478 // TODO(171034): need to fix throwing error if an alert is triggered.
395 base::ListValue args; 479 base::ListValue args;
396 args.Append(CreateElement(element_id)); 480 args.Append(CreateElement(element_id));
397 args.AppendBoolean(selected); 481 args.AppendBoolean(selected);
398 scoped_ptr<base::Value> result; 482 scoped_ptr<base::Value> result;
399 return CallAtomsJs( 483 return CallAtomsJs(
400 session, web_view, webdriver::atoms::CLICK, args, &result); 484 session->GetCurrentFrameId(), web_view, webdriver::atoms::CLICK,
485 args, &result);
401 } 486 }
402 487
403 Status ToggleOptionElement( 488 Status ToggleOptionElement(
404 Session* session, 489 Session* session,
405 WebView* web_view, 490 WebView* web_view,
406 const std::string& element_id) { 491 const std::string& element_id) {
407 bool is_selected; 492 bool is_selected;
408 Status status = IsOptionElementSelected( 493 Status status = IsOptionElementSelected(
409 session, web_view, element_id, &is_selected); 494 session, web_view, element_id, &is_selected);
410 if (status.IsError()) 495 if (status.IsError())
411 return status; 496 return status;
412 return SetOptionElementSelected(session, web_view, element_id, !is_selected); 497 return SetOptionElementSelected(session, web_view, element_id, !is_selected);
413 } 498 }
414 499
415 Status ScrollElementIntoView( 500 Status ScrollElementIntoView(
416 Session* session, 501 Session* session,
417 WebView* web_view, 502 WebView* web_view,
418 const std::string& id, 503 const std::string& id,
419 WebPoint* location) { 504 WebPoint* location) {
420 WebSize size; 505 WebSize size;
421 Status status = GetElementSize(session, web_view, id, &size); 506 Status status = GetElementSize(session, web_view, id, &size);
422 if (status.IsError()) 507 if (status.IsError())
423 return status; 508 return status;
424 return ScrollElementRegionIntoView( 509 return ScrollElementRegionIntoView(
425 session, web_view, id, WebRect(WebPoint(0, 0), size), false, location); 510 session, web_view, id, WebRect(WebPoint(0, 0), size),
511 false /* center */, false /* verify_clickable */, location);
426 } 512 }
427 513
428 Status ScrollElementRegionIntoView( 514 Status ScrollElementRegionIntoView(
429 Session* session, 515 Session* session,
430 WebView* web_view, 516 WebView* web_view,
431 const std::string& element_id, 517 const std::string& element_id,
432 const WebRect& region, 518 const WebRect& region,
433 bool center, 519 bool center,
520 bool verify_clickable,
434 WebPoint* location) { 521 WebPoint* location) {
435 WebPoint region_offset = region.origin; 522 WebPoint region_offset = region.origin;
436 base::ListValue args; 523 WebSize region_size = region.size;
437 args.Append(CreateElement(element_id)); 524 Status status = ScrollElementRegionIntoViewHelper(
438 args.AppendBoolean(center); 525 session->GetCurrentFrameId(), web_view, element_id, region,
439 args.Append(CreateValueFrom(&region)); 526 center, verify_clickable, &region_offset);
440 scoped_ptr<base::Value> result;
441
442 // TODO(chrisgao): Nested frame. See http://crbug.com/170998.
443 Status status = CallAtomsJs(
444 session, web_view, webdriver::atoms::GET_LOCATION_IN_VIEW, args, &result);
445 if (status.IsError()) 527 if (status.IsError())
446 return status; 528 return status;
447 if (!ParseFromValue(result.get(), &region_offset)) 529 const char* kFindSubFrameScript =
448 return Status(kUnknownError, "fail to parse value of GET_LOCATION_IN_VIEW"); 530 "function(xpath) {"
531 " return document.evaluate(xpath, document, null,"
532 " XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;"
533 "}";
534 for (std::list<FrameInfo>::reverse_iterator rit = session->frames.rbegin();
535 rit != session->frames.rend(); ++rit) {
536 base::ListValue args;
537 args.AppendString(
538 base::StringPrintf("//*[@cd_frame_id_ = '%s']",
539 rit->chromedriver_frame_id.c_str()));
540 scoped_ptr<base::Value> result;
541 status = web_view->CallFunction(
542 rit->parent_frame_id, kFindSubFrameScript, args, &result);
543 if (status.IsError())
544 return status;
545 const base::DictionaryValue* element_dict;
546 if (!result->GetAsDictionary(&element_dict))
547 return Status(kUnknownError, "no element reference returned by script");
548 std::string frame_element_id;
549 if (!element_dict->GetString(kElementKey, &frame_element_id))
550 return Status(kUnknownError, "fail to locate a sub frame");
551
552 // Modify |region_offset| by the frame's border.
553 int border_left = -1;
554 int border_top = -1;
555 status = GetElementBorder(
556 rit->parent_frame_id, web_view, frame_element_id,
557 &border_left, &border_top);
558 if (status.IsError())
559 return status;
560 region_offset.Offset(border_left, border_top);
561
562 status = ScrollElementRegionIntoViewHelper(
563 rit->parent_frame_id, web_view, frame_element_id,
564 WebRect(region_offset, region_size),
565 center, verify_clickable, &region_offset);
566 if (status.IsError())
567 return status;
568 }
449 *location = region_offset; 569 *location = region_offset;
450 return Status(kOk); 570 return Status(kOk);
451 } 571 }
OLDNEW
« no previous file with comments | « chrome/test/chromedriver/element_util.h ('k') | chrome/test/chromedriver/run_py_tests.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698