… | |
… | |
27 | |
27 | |
28 | # this is an example of an action sequence |
28 | # this is an example of an action sequence |
29 | $wd->actions |
29 | $wd->actions |
30 | ->move ($wd->find_element (...), 40, 5) |
30 | ->move ($wd->find_element (...), 40, 5) |
31 | ->click |
31 | ->click |
32 | ->pause # to separate the click from the keypress |
|
|
33 | ->type ("some text") |
32 | ->type ("some text") |
34 | ->key ("{Enter}") |
33 | ->key ("{Enter}") |
35 | ->perform; |
34 | ->perform; |
36 | |
35 | |
37 | =head1 DESCRIPTION |
36 | =head1 DESCRIPTION |
… | |
… | |
933 | id => "myfatfinger", |
932 | id => "myfatfinger", |
934 | type => "pointer", |
933 | type => "pointer", |
935 | pointerType => "touch", |
934 | pointerType => "touch", |
936 | actions => [ |
935 | actions => [ |
937 | { type => "pointerMove", duration => 100, origin => $input, x => 40, y => 5 }, |
936 | { type => "pointerMove", duration => 100, origin => $input, x => 40, y => 5 }, |
938 | { type => "pointerDown", button => 1 }, |
937 | { type => "pointerDown", button => 0 }, |
939 | { type => "pause", duration => 40 }, |
938 | { type => "pause", duration => 40 }, |
940 | { type => "pointerUp", button => 1 }, |
939 | { type => "pointerUp", button => 0 }, |
941 | ], |
940 | ], |
942 | }, |
941 | }, |
943 | { |
942 | { |
944 | id => "mykeyboard", |
943 | id => "mykeyboard", |
945 | type => "key", |
944 | type => "key", |
… | |
… | |
963 | ], |
962 | ], |
964 | }, |
963 | }, |
965 | ]); |
964 | ]); |
966 | |
965 | |
967 | And here is essentially the same (except for fewer pauses) example as |
966 | And here is essentially the same (except for fewer pauses) example as |
968 | above, using the much simpler C<AnyEvent::WebDriver::Actions> API. Note |
967 | above, using the much simpler C<AnyEvent::WebDriver::Actions> API: |
969 | that the pointer up and key down event happen concurrently in this |
|
|
970 | example: |
|
|
971 | |
968 | |
972 | $wd->navigate_to ("https://duckduckgo.com/html"); |
969 | $wd->navigate_to ("https://duckduckgo.com/html"); |
973 | my $input = $wd->find_element ("css selector", 'input[type="text"]'); |
970 | my $input = $wd->find_element ("css selector", 'input[type="text"]'); |
974 | $wd->actions |
971 | $wd->actions |
975 | ->move ($input, 40, 5, "touch1") |
972 | ->move ($input, 40, 5, "touch1") |
976 | ->click |
973 | ->click |
977 | ->pause # to separate the click from the keypress |
|
|
978 | ->key ("a") |
974 | ->key ("a") |
979 | ->key ("b") |
975 | ->key ("b") |
980 | ->pause (2000) # so you can watch leisurely |
976 | ->pause (2000) # so you can watch leisurely |
981 | ->key ("{Enter}") |
977 | ->key ("{Enter}") |
982 | ->pause (5000) # so you can see the result |
978 | ->pause (5000) # so you can see the result |
… | |
… | |
1078 | Action lists can be quite complicated. Or at least it took a while for |
1074 | Action lists can be quite complicated. Or at least it took a while for |
1079 | me to twist my head around them. Basically, an action list consists of a |
1075 | me to twist my head around them. Basically, an action list consists of a |
1080 | number of sources representing devices (such as a finger, a mouse, a pen |
1076 | number of sources representing devices (such as a finger, a mouse, a pen |
1081 | or a keyboard) and a list of actions for each source. |
1077 | or a keyboard) and a list of actions for each source. |
1082 | |
1078 | |
1083 | An action can be a key press, a pointer move or a pause (time |
1079 | An action can be a key press, a pointer move or a pause (time delay). |
1084 | delay). Actions from different sources can happen "at the same time", |
|
|
1085 | while actions from a single source are executed in order. |
|
|
1086 | |
1080 | |
1087 | While you can provide an action list manually, it is (hopefully) less |
1081 | While you can provide these action lists manually, it is (hopefully) less |
1088 | cumbersome to use the API described in this section to create them. |
1082 | cumbersome to use the API described in this section to create them. |
1089 | |
1083 | |
1090 | The basic process of creating and performing actions is to create a new |
1084 | The basic process of creating and performing actions is to create a new |
1091 | action list, adding action sources, followed by adding actions. Finally |
1085 | action list, adding action sources, followed by adding actions. Finally |
1092 | you would C<perform> those actions on the WebDriver. |
1086 | you would C<perform> those actions on the WebDriver. |
1093 | |
1087 | |
1094 | Virtual time progresses as long as you add actions to the same event |
|
|
1095 | source. Adding events to different sources are considered to happen |
|
|
1096 | concurrently. If you want to force time to progress, you can do this using |
|
|
1097 | a call to C<< ->pause (0) >>. |
|
|
1098 | |
|
|
1099 | Most methods here are designed to chain, i.e. they return the web actions |
1088 | Most methods here are designed to chain, i.e. they return the web actions |
1100 | object, to simplify multiple calls. |
1089 | object, to simplify multiple calls. |
1101 | |
1090 | |
|
|
1091 | Also, while actions from different sources can happen "at the same time" |
|
|
1092 | in the WebDriver protocol, this class ensures that actions will execute in |
|
|
1093 | the order specified. |
|
|
1094 | |
1102 | For example, to simulate a mouse click to an input element, followed by |
1095 | For example, to simulate a mouse click to an input element, followed by |
1103 | entering some text and pressing enter, you can use this: |
1096 | entering some text and pressing enter, you can use this: |
1104 | |
1097 | |
1105 | $wd->actions |
1098 | $wd->actions |
1106 | ->click (1, 100) |
1099 | ->click (0, 100) |
1107 | ->pause # to separate the click from keypressed |
|
|
1108 | ->type ("some text") |
1100 | ->type ("some text") |
1109 | ->key ("{Enter}") |
1101 | ->key ("{Enter}") |
1110 | ->perform; |
1102 | ->perform; |
1111 | |
1103 | |
1112 | By default, keyboard and mouse input sources are provided. You can create |
1104 | By default, keyboard and mouse input sources are provided. You can create |
… | |
… | |
1114 | be more verbosely written like this: |
1106 | be more verbosely written like this: |
1115 | |
1107 | |
1116 | $wd->actions |
1108 | $wd->actions |
1117 | ->source ("mouse", "pointer", pointerType => "mouse") |
1109 | ->source ("mouse", "pointer", pointerType => "mouse") |
1118 | ->source ("kbd", "key") |
1110 | ->source ("kbd", "key") |
1119 | ->click (1, 100, "mouse") |
1111 | ->click (0, 100, "mouse") |
1120 | ->pause |
|
|
1121 | ->type ("some text", "kbd") |
1112 | ->type ("some text", "kbd") |
1122 | ->key ("{Enter}", "kbd") |
1113 | ->key ("{Enter}", "kbd") |
1123 | ->perform; |
1114 | ->perform; |
1124 | |
1115 | |
1125 | When you specify the event source explicitly it will switch the current |
1116 | When you specify the event source explicitly it will switch the current |
… | |
… | |
1227 | my $source = $self->{source}{$source} ||= _default_source $source; |
1218 | my $source = $self->{source}{$source} ||= _default_source $source; |
1228 | |
1219 | |
1229 | my $al = $source->{actions}; |
1220 | my $al = $source->{actions}; |
1230 | |
1221 | |
1231 | push @$al, { type => "pause" } |
1222 | push @$al, { type => "pause" } |
1232 | while @$al < $self->{tick} - 1; |
1223 | while @$al < $self->{tick}; # -1 == allow concurrent actions |
1233 | |
1224 | |
1234 | $kv{type} = $type; |
1225 | $kv{type} = $type; |
1235 | |
1226 | |
1236 | push @{ $source->{actions} }, \%kv; |
1227 | push @{ $source->{actions} }, \%kv; |
1237 | |
1228 | |
… | |
… | |
1289 | |
1280 | |
1290 | =item $al = $al->pointer_down ($button, $source) |
1281 | =item $al = $al->pointer_down ($button, $source) |
1291 | |
1282 | |
1292 | =item $al = $al->pointer_up ($button, $source) |
1283 | =item $al = $al->pointer_up ($button, $source) |
1293 | |
1284 | |
1294 | Press or release the given button. C<$button> defaults to C<1>. |
1285 | Press or release the given button. C<$button> defaults to C<0>. |
1295 | |
1286 | |
1296 | =item $al = $al->click ($button, $source) |
1287 | =item $al = $al->click ($button, $source) |
1297 | |
1288 | |
1298 | Convenience function that creates a button press and release action |
1289 | Convenience function that creates a button press and release action |
1299 | without any delay between them. C<$button> defaults to C<1>. |
1290 | without any delay between them. C<$button> defaults to C<0>. |
1300 | |
1291 | |
1301 | =item $al = $al->doubleclick ($button, $source) |
1292 | =item $al = $al->doubleclick ($button, $source) |
1302 | |
1293 | |
1303 | Convenience function that creates two button press and release action |
1294 | Convenience function that creates two button press and release action |
1304 | pairs in a row, with no unnecessary delay between them. C<$button> |
1295 | pairs in a row, with no unnecessary delay between them. C<$button> |
1305 | defaults to C<1>. |
1296 | defaults to C<0>. |
1306 | |
1297 | |
1307 | =cut |
1298 | =cut |
1308 | |
1299 | |
1309 | sub pointer_down { |
1300 | sub pointer_down { |
1310 | my ($self, $button, $source) = @_; |
1301 | my ($self, $button, $source) = @_; |
1311 | |
1302 | |
1312 | $self->_add ($source, ptr => pointerDown => button => ($button // 1)*1) |
1303 | $self->_add ($source, ptr => pointerDown => button => ($button // 0)*1) |
1313 | } |
1304 | } |
1314 | |
1305 | |
1315 | sub pointer_up { |
1306 | sub pointer_up { |
1316 | my ($self, $button, $source) = @_; |
1307 | my ($self, $button, $source) = @_; |
1317 | |
1308 | |
1318 | $self->_add ($source, ptr => pointerUp => button => ($button // 1)*1) |
1309 | $self->_add ($source, ptr => pointerUp => button => ($button // 0)*1) |
1319 | } |
1310 | } |
1320 | |
1311 | |
1321 | sub click { |
1312 | sub click { |
1322 | my ($self, $button, $source) = @_; |
1313 | my ($self, $button, $source) = @_; |
1323 | |
1314 | |
… | |
… | |
1394 | "as-is" if possible. |
1385 | "as-is" if possible. |
1395 | |
1386 | |
1396 | =cut |
1387 | =cut |
1397 | |
1388 | |
1398 | our %SPECIAL_KEY = ( |
1389 | our %SPECIAL_KEY = ( |
|
|
1390 | # "NULL" => \xE000, |
1399 | "Unidentified" => 0xE000, |
1391 | "Unidentified" => 0xE000, |
1400 | "Cancel" => 0xE001, |
1392 | "Cancel" => 0xE001, |
1401 | "Help" => 0xE002, |
1393 | "Help" => 0xE002, |
1402 | "Backspace" => 0xE003, |
1394 | "Backspace" => 0xE003, |
1403 | "Tab" => 0xE004, |
1395 | "Tab" => 0xE004, |