… | |
… | |
490 | |
490 | |
491 | =back |
491 | =back |
492 | |
492 | |
493 | =head3 ELEMENT RETRIEVAL |
493 | =head3 ELEMENT RETRIEVAL |
494 | |
494 | |
|
|
495 | To reduce typing and memory strain, the element finding functions accept |
|
|
496 | some shorter and hopefully easier to remember aliases for the standard |
|
|
497 | locator strategy values, as follows: |
|
|
498 | |
|
|
499 | Alias Locator Strategy |
|
|
500 | css css selector |
|
|
501 | link link text |
|
|
502 | substr partial link text |
|
|
503 | tag tag name |
|
|
504 | |
495 | =over |
505 | =over |
496 | |
506 | |
497 | =cut |
507 | =cut |
498 | |
508 | |
|
|
509 | our %USING = ( |
|
|
510 | css => "css selector", |
|
|
511 | link => "link text", |
|
|
512 | substr => "partial link text", |
|
|
513 | tag => "tag name", |
|
|
514 | ); |
|
|
515 | |
|
|
516 | sub _using($) { |
|
|
517 | using => $USING{$_[0]} // "$_[0]" |
|
|
518 | } |
|
|
519 | |
499 | =item $element = $wd->find_element ($location_strategy, $selector) |
520 | =item $element = $wd->find_element ($locator_strategy, $selector) |
500 | |
521 | |
501 | Finds the first element specified by the given selector and returns its |
522 | Finds the first element specified by the given selector and returns its |
502 | element object. Raises an error when no element was found. |
523 | element object. Raises an error when no element was found. |
503 | |
524 | |
504 | $element = $wd->find_element ("css selector" => "body a"); |
525 | $element = $wd->find_element ("css selector" => "body a"); |
… | |
… | |
506 | $element = $wd->find_element ("partial link text" => "orn"); |
527 | $element = $wd->find_element ("partial link text" => "orn"); |
507 | $element = $wd->find_element ("tag name" => "input"); |
528 | $element = $wd->find_element ("tag name" => "input"); |
508 | $element = $wd->find_element ("xpath" => '//input[@type="text"]'); |
529 | $element = $wd->find_element ("xpath" => '//input[@type="text"]'); |
509 | => e.g. { "element-6066-11e4-a52e-4f735466cecf" => "decddca8-5986-4e1d-8c93-efe952505a5f" } |
530 | => e.g. { "element-6066-11e4-a52e-4f735466cecf" => "decddca8-5986-4e1d-8c93-efe952505a5f" } |
510 | |
531 | |
511 | =item $elements = $wd->find_elements ($location_strategy, $selector) |
532 | =item $elements = $wd->find_elements ($locator_strategy, $selector) |
512 | |
533 | |
513 | As above, but returns an arrayref of all found element objects. |
534 | As above, but returns an arrayref of all found element objects. |
514 | |
535 | |
515 | =item $element = $wd->find_element_from_element ($element, $location_strategy, $selector) |
536 | =item $element = $wd->find_element_from_element ($element, $locator_strategy, $selector) |
516 | |
537 | |
517 | Like C<find_element>, but looks only inside the specified C<$element>. |
538 | Like C<find_element>, but looks only inside the specified C<$element>. |
518 | |
539 | |
519 | =item $elements = $wd->find_elements_from_element ($element, $location_strategy, $selector) |
540 | =item $elements = $wd->find_elements_from_element ($element, $locator_strategy, $selector) |
520 | |
541 | |
521 | Like C<find_elements>, but looks only inside the specified C<$element>. |
542 | Like C<find_elements>, but looks only inside the specified C<$element>. |
522 | |
543 | |
523 | my $head = $wd->find_element ("tag name" => "head"); |
544 | my $head = $wd->find_element ("tag name" => "head"); |
524 | my $links = $wd->find_elements_from_element ($head, "tag name", "link"); |
545 | my $links = $wd->find_elements_from_element ($head, "tag name", "link"); |
… | |
… | |
528 | Returns the active element. |
549 | Returns the active element. |
529 | |
550 | |
530 | =cut |
551 | =cut |
531 | |
552 | |
532 | sub find_element_ { |
553 | sub find_element_ { |
533 | $_[0]->post_ (element => { using => "$_[1]", value => "$_[2]" }, $_[3]); |
554 | $_[0]->post_ (element => { _using $_[1], value => "$_[2]" }, $_[3]); |
534 | } |
555 | } |
535 | |
556 | |
536 | sub find_elements_ { |
557 | sub find_elements_ { |
537 | $_[0]->post_ (elements => { using => "$_[1]", value => "$_[2]" }, $_[3]); |
558 | $_[0]->post_ (elements => { _using $_[1], value => "$_[2]" }, $_[3]); |
538 | } |
559 | } |
539 | |
560 | |
540 | sub find_element_from_element_ { |
561 | sub find_element_from_element_ { |
541 | $_[0]->post_ ("element/$_[1]/element" => { using => "$_[2]", value => "$_[3]" }, $_[4]); |
562 | $_[0]->post_ ("element/$_[1]/element" => { _using $_[2], value => "$_[3]" }, $_[4]); |
542 | } |
563 | } |
543 | |
564 | |
544 | sub find_elements_from_element_ { |
565 | sub find_elements_from_element_ { |
545 | $_[0]->post_ ("element/$_[1]/elements" => { using => "$_[2]", value => "$_[3]" }, $_[4]); |
566 | $_[0]->post_ ("element/$_[1]/elements" => { _using $_[2], value => "$_[3]" }, $_[4]); |
546 | } |
567 | } |
547 | |
568 | |
548 | sub get_active_element_ { |
569 | sub get_active_element_ { |
549 | $_[0]->get_ ("element/active" => $_[1]); |
570 | $_[0]->get_ ("element/active" => $_[1]); |
550 | } |
571 | } |
… | |
… | |
946 | entering some text and pressing enter, you can use this: |
967 | entering some text and pressing enter, you can use this: |
947 | |
968 | |
948 | $wd->actions |
969 | $wd->actions |
949 | ->click (1, 100) |
970 | ->click (1, 100) |
950 | ->type ("some text") |
971 | ->type ("some text") |
951 | ->key ("Enter") |
972 | ->key ("{Enter}") |
952 | ->perform; |
973 | ->perform; |
953 | |
974 | |
954 | By default, keyboard and mouse input sources are provided. You can create |
975 | By default, keyboard and mouse input sources are provided. You can create |
955 | your own sources and use them when adding events. The above example could |
976 | your own sources and use them when adding events. The above example could |
956 | be more verbosely written like this: |
977 | be more verbosely written like this: |
957 | |
978 | |
958 | $wd->actions |
979 | $wd->actions |
959 | ->click (1, 100, "mouse") |
980 | ->click (1, 100, "mouse") |
960 | ->type ("some text") |
981 | ->type ("some text") |
961 | ->key ("Enter") |
982 | ->key ("{Enter}") |
962 | ->perform; |
983 | ->perform; |
963 | |
|
|
964 | |
|
|
965 | |
|
|
966 | #TODO verboser example |
|
|
967 | |
984 | |
968 | When you specify the event source expliticly it will switch the current |
985 | When you specify the event source expliticly it will switch the current |
969 | "focus" for this class of device (all keyboards are in one class, all |
986 | "focus" for this class of device (all keyboards are in one class, all |
970 | pointer-like devices such as mice/fingers/pens are in one class), so you |
987 | pointer-like devices such as mice/fingers/pens are in one class), so you |
971 | don't have to specify the source for subsequent actions. |
988 | don't have to specify the source for subsequent actions. |
… | |
… | |
981 | package AnyEvent::WebDriver::Actions; |
998 | package AnyEvent::WebDriver::Actions; |
982 | |
999 | |
983 | =item $al = new AnyEvent::WebDriver::Actions |
1000 | =item $al = new AnyEvent::WebDriver::Actions |
984 | |
1001 | |
985 | Create a new empty action list object. More often you would use the C<< |
1002 | Create a new empty action list object. More often you would use the C<< |
986 | $sel->action_list >> method to create one that is already associated with |
1003 | $wd->action_list >> method to create one that is already associated with |
987 | a given web driver. |
1004 | a given web driver. |
988 | |
1005 | |
989 | =cut |
1006 | =cut |
990 | |
1007 | |
991 | sub new { |
1008 | sub new { |
… | |
… | |
1014 | |
1031 | |
1015 | $al->source (fatfinger => "pointer", pointerType => "touch"); |
1032 | $al->source (fatfinger => "pointer", pointerType => "touch"); |
1016 | |
1033 | |
1017 | =cut |
1034 | =cut |
1018 | |
1035 | |
1019 | sub _default_source { |
1036 | sub _default_source($) { |
1020 | my ($source) = @_; |
1037 | my ($source) = @_; |
1021 | |
1038 | |
1022 | $source eq "keyboard" ? { actions => [], id => $source, type => "key" } |
1039 | $source eq "keyboard" ? { actions => [], id => $source, type => "key" } |
1023 | : $source eq "mouse" ? { actions => [], id => $source, type => "pointer", pointerType => "mouse" } |
1040 | : $source eq "mouse" ? { actions => [], id => $source, type => "pointer", pointerType => "mouse" } |
1024 | : $source eq "touch" ? { actions => [], id => $source, type => "pointer", pointerType => "touch" } |
1041 | : $source eq "touch" ? { actions => [], id => $source, type => "pointer", pointerType => "touch" } |
… | |
… | |
1191 | |
1208 | |
1192 | =item $al = $al->keyUp ($key, $source) |
1209 | =item $al = $al->keyUp ($key, $source) |
1193 | |
1210 | |
1194 | Press or release the given key. |
1211 | Press or release the given key. |
1195 | |
1212 | |
|
|
1213 | =item $al = $al->key ($key, $source) |
|
|
1214 | |
|
|
1215 | Peess and release the given key, without unnecessary delay. |
|
|
1216 | |
|
|
1217 | A special syntax, C<{keyname}> can be used for special keys - all the special key names from |
|
|
1218 | L<section 17.4.2|https://www.w3.org/TR/webdriver1/#keyboard-actions> of the WebDriver recommendation |
|
|
1219 | can be used. |
|
|
1220 | |
|
|
1221 | Example: press and release "a". |
|
|
1222 | |
|
|
1223 | $al->key ("a"); |
|
|
1224 | |
|
|
1225 | Example: press and release the "Enter" key: |
|
|
1226 | |
|
|
1227 | $al->key ("\x{e007}"); |
|
|
1228 | |
|
|
1229 | Example: press and release the "enter" key using the special key name syntax: |
|
|
1230 | |
|
|
1231 | $al->key ("{Enter}"); |
|
|
1232 | |
|
|
1233 | =item $al = $al->type ($string, $source) |
|
|
1234 | |
|
|
1235 | Convenience method to simulate a series of key press and release events |
|
|
1236 | for the keys in C<$string>. There is no syntax for special keys, |
|
|
1237 | everything will be typed "as-is" if possible. |
|
|
1238 | |
1196 | =cut |
1239 | =cut |
|
|
1240 | |
|
|
1241 | our %SPECIAL_KEY = ( |
|
|
1242 | "Unidentified" => 0xE000, |
|
|
1243 | "Cancel" => 0xE001, |
|
|
1244 | "Help" => 0xE002, |
|
|
1245 | "Backspace" => 0xE003, |
|
|
1246 | "Tab" => 0xE004, |
|
|
1247 | "Clear" => 0xE005, |
|
|
1248 | "Return" => 0xE006, |
|
|
1249 | "Enter" => 0xE007, |
|
|
1250 | "Shift" => 0xE008, |
|
|
1251 | "Control" => 0xE009, |
|
|
1252 | "Alt" => 0xE00A, |
|
|
1253 | "Pause" => 0xE00B, |
|
|
1254 | "Escape" => 0xE00C, |
|
|
1255 | " " => 0xE00D, |
|
|
1256 | "PageUp" => 0xE00E, |
|
|
1257 | "PageDown" => 0xE00F, |
|
|
1258 | "End" => 0xE010, |
|
|
1259 | "Home" => 0xE011, |
|
|
1260 | "ArrowLeft" => 0xE012, |
|
|
1261 | "ArrowUp" => 0xE013, |
|
|
1262 | "ArrowRight" => 0xE014, |
|
|
1263 | "ArrowDown" => 0xE015, |
|
|
1264 | "Insert" => 0xE016, |
|
|
1265 | "Delete" => 0xE017, |
|
|
1266 | ";" => 0xE018, |
|
|
1267 | "=" => 0xE019, |
|
|
1268 | "0" => 0xE01A, |
|
|
1269 | "1" => 0xE01B, |
|
|
1270 | "2" => 0xE01C, |
|
|
1271 | "3" => 0xE01D, |
|
|
1272 | "4" => 0xE01E, |
|
|
1273 | "5" => 0xE01F, |
|
|
1274 | "6" => 0xE020, |
|
|
1275 | "7" => 0xE021, |
|
|
1276 | "8" => 0xE022, |
|
|
1277 | "9" => 0xE023, |
|
|
1278 | "*" => 0xE024, |
|
|
1279 | "+" => 0xE025, |
|
|
1280 | "," => 0xE026, |
|
|
1281 | "-" => 0xE027, |
|
|
1282 | "." => 0xE028, |
|
|
1283 | "/" => 0xE029, |
|
|
1284 | "F1" => 0xE031, |
|
|
1285 | "F2" => 0xE032, |
|
|
1286 | "F3" => 0xE033, |
|
|
1287 | "F4" => 0xE034, |
|
|
1288 | "F5" => 0xE035, |
|
|
1289 | "F6" => 0xE036, |
|
|
1290 | "F7" => 0xE037, |
|
|
1291 | "F8" => 0xE038, |
|
|
1292 | "F9" => 0xE039, |
|
|
1293 | "F10" => 0xE03A, |
|
|
1294 | "F11" => 0xE03B, |
|
|
1295 | "F12" => 0xE03C, |
|
|
1296 | "Meta" => 0xE03D, |
|
|
1297 | "ZenkakuHankaku" => 0xE040, |
|
|
1298 | "Shift" => 0xE050, |
|
|
1299 | "Control" => 0xE051, |
|
|
1300 | "Alt" => 0xE052, |
|
|
1301 | "Meta" => 0xE053, |
|
|
1302 | "PageUp" => 0xE054, |
|
|
1303 | "PageDown" => 0xE055, |
|
|
1304 | "End" => 0xE056, |
|
|
1305 | "Home" => 0xE057, |
|
|
1306 | "ArrowLeft" => 0xE058, |
|
|
1307 | "ArrowUp" => 0xE059, |
|
|
1308 | "ArrowRight" => 0xE05A, |
|
|
1309 | "ArrowDown" => 0xE05B, |
|
|
1310 | "Insert" => 0xE05C, |
|
|
1311 | "Delete" => 0xE05D, |
|
|
1312 | ); |
|
|
1313 | |
|
|
1314 | sub _kv($) { |
|
|
1315 | $_[0] =~ /^\{(.*)\}$/s |
|
|
1316 | ? (exists $SPECIAL_KEY{$1} |
|
|
1317 | ? chr $SPECIAL_KEY{$1} |
|
|
1318 | : Carp::croak "AnyEvent::WebDriver::Actions: special key '$1' not known") |
|
|
1319 | : $_[0] |
|
|
1320 | } |
1197 | |
1321 | |
1198 | sub key_down { |
1322 | sub key_down { |
1199 | my ($self, $key, $source) = @_; |
1323 | my ($self, $key, $source) = @_; |
1200 | |
1324 | |
1201 | $self->_add ($source, kbd => keyDown => value => $key) |
1325 | $self->_add ($source, kbd => keyDown => value => _kv $key) |
1202 | } |
1326 | } |
1203 | |
1327 | |
1204 | sub key_up { |
1328 | sub key_up { |
1205 | my ($self, $key, $source) = @_; |
1329 | my ($self, $key, $source) = @_; |
1206 | |
1330 | |
1207 | $self->_add ($source, kbd => keyUp => value => $key) |
1331 | $self->_add ($source, kbd => keyUp => value => _kv $key) |
1208 | } |
1332 | } |
1209 | |
1333 | |
1210 | sub key { |
1334 | sub key { |
1211 | my ($self, $key, $source) = @_; |
1335 | my ($self, $key, $source) = @_; |
1212 | |
1336 | |
1213 | $self |
1337 | $self |
1214 | ->key_down ($key, $source) |
1338 | ->key_down ($key, $source) |
1215 | ->key_up ($key) |
1339 | ->key_up ($key) |
|
|
1340 | } |
|
|
1341 | |
|
|
1342 | sub type { |
|
|
1343 | my ($self, $string, $source) = @_; |
|
|
1344 | |
|
|
1345 | $self->key ($_, $source) |
|
|
1346 | for $string =~ /(\X)/g; |
|
|
1347 | |
|
|
1348 | $self |
1216 | } |
1349 | } |
1217 | |
1350 | |
1218 | =item $al->perform ($wd) |
1351 | =item $al->perform ($wd) |
1219 | |
1352 | |
1220 | Finaluses and compiles the list, if not done yet, and calls C<< |
1353 | Finaluses and compiles the list, if not done yet, and calls C<< |