はじめに
LaravelのDuskで新しいブラウザタブへの切替方法を検索した際にヒットする方法が意図した動作にならない場合があったので、公式が推奨している方法の紹介をしようと思います。
※公式の推奨方法が先に知りたい方はこちらをご覧ください
意図した動作にならない方法
検索してよくヒットする方法が以下です
// クリックして新しいブラウザタブを開く
$browser->click('@new-tab');
// 新しいブラウザタブを取得
$newTab = collect($browser->driver->getWindowHandles())->last();
// 新しいブラウザタブに切替
$browser->driver->switchTo()->window($newTab);
$newTab = collect($browser->driver->getWindowHandles())->last();
上記で新しいブラウザタブを取得しており、これはgetWindowHandlesメソッドで取得したwindowHandlesの最後が必ず新しいブラウザタブになっていることを前提とした実装方法になっていますが、現在表示しているタブが取得される場合もあるのが意図しない動作になります。
Duskのブラウザ操作で利用するphp-webdriverにもその注意書きがあります。
Note: Do not use end($handles) to find the last open window, because getWindowHandles() does not necessarily return window in the order in which they were opened.
公式が推奨する方法
// 新しいタブを開く前に現在のタブ情報を取得
$windowHandlesBefore = $this->driver->getWindowHandles();
// クリックして新しいブラウザタブを開く
$browser->click('@new-tab');
// 新しいタブが追加された状態でタブ情報を取得
$windowHandlesAfter = $this->driver->getWindowHandles();
// 追加前と追加後の差分を比較して、新しいタブだけ取得
$newWindowHandle = array_diff($windowHandlesAfter, $windowHandlesBefore);
// 新しいタブに切替
$driver->switchTo()->window(reset($newWindowHandle));
getWindowHandlesで取得できるタブ情報が順不同の為、新しいタブの追加前と追加後の差分だけを取得することで新しいタブを取得するようにしています。
さいごに
私も意図しない方法で新しいブラウザタブの切替を行なっていたのですが、テストは動いてたまに失敗するだけなので、失敗原因の調査をしてもなかなか根本原因までに至らず苦労しました。
今後、Laravel Duskで新しいブラウザタブの切替をする人の少しでも役に立てば幸いです。