Perl のモジュール Selenium::Remote::Driver で「ある要素の上でクリックする」という動作をさせたい場合は mouse_move_to_location を使って以下のようにマウスを移動させてからクリックすれば良いはずなのだが、
$driver->mouse_move_to_location(element => $driver->find_element('myElem', 'id'), xoffset => 80, yoffset => 10);
$driver->click('RIGHT');
この xoffset 、yoffset がなぜか有効にならなかった( Selenium::Remote::Driver 0.17, Selenium Standalone Server 2.39.0, Firefox 12.0 )。オフセットが指定されていない場合や有効にならない場合、mouse_move_to_location は指定された要素の中央にマウスポジションを移動する。
JavaScript を挟んで要素の位置調整をする
目的としては下図のように「テキストエリアに入力したテキストをマウスで選んで反転した所で右クリックするとメニューが出る」というシーンを自動でスクリーンショットに取りたかったので、要素(テキストエリア)の中心にメニューが出てしまうのでは期待に反する。ということで、クリックで表示されたメニューパネルを、スクリーンショットを取る前に JavaScript で動かす事にした。
要素の位置移動のサンプルコード
$driver->mouse_move_to_location(element => $driver->find_element('myParentElem', 'id'));
$driver->click('RIGHT');
# myParentElem の中央で右クリックされた事になる。
#(このとき、マウスの位置に myTargetElem 要素が現れるようにWebアプリが組んである。)
#現れた要素の位置変更
my $script = qq{
var callback = arguments[arguments.length-1];
var panel = document.getElementById("myTargetElem");
#位置はテストしながら決める。
#panel の CSS position 属性に何が指定されているかによって位置の指定の仕方を考慮する。
panel.style.left = panel.offsetLeft-70 + "px";
panel.style.top = panel.offsetTop-30 + "px";
callback(panel);
};
my $callback = q{return arguments[0];};
$driver->execute_async_script($script, $callback);
#おまけ:要素の移動先と、移動前のマウスの位置が期待に反して重なってしまう場合の対応(適当な位置にマウスを移動)。
$driver->mouse_move_to_location(element => $driver->find_element(qq{//h1[1]}, 'xpath'));
#ここでスクリーンショット