Laravel Dusk
Table of Contents
Introduction
Laravel Dusk は表現力豊かで使いやすいブラウザ自動化および testing API を提供します。default では、Dusk はあなたのローカルコンピュータに JDK や Selenium をインストールする必要はありません。代わりに、Dusk はスタンドアロンのChromedriver インストールを使用します。ただし、他の Selenium 互換の driver を自由に利用することができます。
Installation
始めるには、Google Chrome をインストールし、laravel/dusk
Composer の依存関係をあなたの project に追加するべきです:
composer require laravel/dusk --dev
WARNING
あなたが手動で Dusk の service provider を register する場合、それを決してあなたの production environment で register してはならない、というのもそれによって任意の users があなたの application で authentication できるようになる可能性があるからです。
Dusk パッケージをインストールした後、dusk:install
の Artisan command を実行します。dusk:install
の command は、tests/Browser
ディレクトリを作成し、例の Dusk test を作成し、お使いのオペレーティングシステムに Chrome Driver binary をインストールします:
php artisan dusk:install
次に、アプリケーションの.env
ファイルでAPP_URL
の environment 変数を設定します。この value は、ブラウザで application にアクセスするために使用する URL と match する必要があります。
NOTE
あなたがローカル開発の environment を管理するためにLaravel Sailを使用している場合は、Dusk テストの設定と実行についての Sail のドキュメンテーションも参照してください。
ChromeDriver インストールの管理
もし、dusk:install
command で Laravel Dusk がインストールするものとは異なる version の ChromeDriver をインストールしたい場合は、dusk:chrome-driver
command を使用することができます:
# Install the latest version of ChromeDriver for your OS...
php artisan dusk:chrome-driver
# Install a given version of ChromeDriver for your OS...
php artisan dusk:chrome-driver 86
# Install a given version of ChromeDriver for all supported OSs...
php artisan dusk:chrome-driver --all
# Install the version of ChromeDriver that matches the detected version of Chrome / Chromium for your OS...
php artisan dusk:chrome-driver --detect
WARNING
Dusk は、
chromedriver
バイナリが実行可能であることを必要とします。 Dusk の実行に問題がある場合は、次の command を使用してバイナリが実行可能であることを確認する必要があります:chmod -R 0755 vendor/laravel/dusk/bin/
.
他のブラウザを使用する
デフォルトでは、 Dusk は Google default とスタンドアロンのChrome Driver インストールを使用してブラウザテストを実行します。しかし、自身の Selenium サーバーを起動し、お好みのブラウザでテストを実行することも可能です。
始めるには、tests/DuskTestCase.php
ファイルを開いてください。これはあなたの application の基本的な Dusk test ケースです。このファイル内では、startChromeDriver
method への呼び出しを削除することができます。これにより、 Dusk は自動的に ChromeDriver を起動するのを停止します:
/**
* Prepare for Dusk test execution.
*
* @beforeClass
*/
public static function prepare(): void
{
// static::startChromeDriver();
}
次に、driver
method を変更して、選択した URL とポートに接続することができます。さらに、WebDriver に渡すべき"desired capabilities"を変更することもできます:
use Facebook\WebDriver\Remote\RemoteWebDriver;
/**
* Create the RemoteWebDriver instance.
*/
protected function driver(): RemoteWebDriver
{
return RemoteWebDriver::create(
'http://localhost:4444/wd/hub', DesiredCapabilities::phantomjs()
);
}
Getting Started
テストの生成
Dusk テストを生成するには、dusk:make
の Artisan command を使用します。生成されたテストはtests/Browser
ディレクトリに配置されます。
php artisan dusk:make LoginTest
Resetting the Database After Each Test
あなたが書く tests のほとんどは、application の database から data を取得するページとやりとりしますが、あなたの Dusktests は決してRefreshDatabase
trait を使ってはなりません。 RefreshDatabase
trait は database transactions を活用しますが、これは HTTP requests で適用可能または利用可能ではありません。代わりに、options が 2 つあります:DatabaseMigrations
trait とDatabaseTruncation
trait です。
Database Migrations の使用
DatabaseMigrations
トレイトは、各 test の前にあなたの database migrations を実行します。しかし、各 test のためにあなたの database テーブルをドロップして再作成することは、通常、テーブルを切り捨てるよりも遅いです:
<?php
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Laravel\Dusk\Browser;
uses(DatabaseMigrations::class);
//
<?php
namespace Tests\Browser;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Laravel\Dusk\Browser;
use Tests\DuskTestCase;
class ExampleTest extends DuskTestCase
{
use DatabaseMigrations;
//
}
WARNING
SQLite のインメモリーデータベースは、 Dusk テストを実行する際には使用できないかもしれません。ブラウザは独自の process 内で実行されるため、他のプロセスのインメモリーデータベースにアクセスすることはできません。
Database の切り捨てを使用する
DatabaseTruncation
トレイトは、適切に database テーブルが作成されていることを確認するために、初めてのテストであなたの database を migrate します。しかし、その後のテストでは、データベースのテーブルは単純に切り捨てられます - すべての database migrations を再度実行することに比べて速度向上を提供します。
<?php
use Illuminate\Foundation\Testing\DatabaseTruncation;
use Laravel\Dusk\Browser;
uses(DatabaseTruncation::class);
//
<?php
namespace Tests\Browser;
use App\Models\User;
use Illuminate\Foundation\Testing\DatabaseTruncation;
use Laravel\Dusk\Browser;
use Tests\DuskTestCase;
class ExampleTest extends DuskTestCase
{
use DatabaseTruncation;
//
}
default として、この特性はmigrations
テーブルを除くすべてのテーブルを truncate します。トランケートされるべきテーブルをカスタマイズしたい場合は、test class 上で$tablesToTruncate
プロパティを定義できます。
NOTE
Pest を使用している場合、基本
DuskTestCase
class や test ファイルが拡張する任意の class にプロパティや methods を定義する必要があります。
/**
* Indicates which tables should be truncated.
*
* @var array
*/
protected $tablesToTruncate = ['users'];
あるいは、切り捨てから除外すべきテーブルを指定するために、テストの class に$exceptTables
プロパティを定義することもできます:
/**
* Indicates which tables should be excluded from truncation.
*
* @var array
*/
protected $exceptTables = ['users'];
テーブルを切り詐欺すべき database 接続を指定するには、テスト class に$connectionsToTruncate
プロパティを定義することができます。
/**
* Indicates which connections should have their tables truncated.
*
* @var array
*/
protected $connectionsToTruncate = ['mysql'];
もしあなたが、 database の切り捨てが実行される前または後に code を実行したい場合、テスト class 上でbeforeTruncatingDatabase
またはafterTruncatingDatabase
メソッドを定義することができます:
/**
* Perform any work that should take place before the database has started truncating.
*/
protected function beforeTruncatingDatabase(): void
{
//
}
/**
* Perform any work that should take place after the database has finished truncating.
*/
protected function afterTruncatingDatabase(): void
{
//
}
テストの実行
ブラウザのテストを実行するには、dusk
Artisan command を実行してください:
php artisan dusk
前回dusk
command を実行した際に tests が失敗した場合、dusk:fails
command を使用して最初に失敗した tests を再実行することで時間を節約することができます。
php artisan dusk:fails
dusk
command は、特定のgroup に対するテストだけを実行することを許可するなど、通常は Pest / PHPUnit テストランナーが受け付ける任意の引数を受け付けます:
php artisan dusk --group=foo
NOTE
Laravel Sailを使用してローカル開発の environment を管理している場合は、Dusk テストの設定と実行についての Sail のドキュメンテーションをご覧ください。
ChromeDriver の手動起動
default として、 Dusk は自動的に attempt を使用して ChromeDriver を起動します。これが特定のシステムで機能しない場合は、dusk
command を実行する前に ChromeDriver を手動で起動することができます。ChromeDriver を手動で起動することを選択した場合、tests/DuskTestCase.php
ファイルの次の行を comment アウトする必要があります:
/**
* Prepare for Dusk test execution.
*
* @beforeClass
*/
public static function prepare(): void
{
// static::startChromeDriver();
}
さらに、9515 以外のポートで ChromeDriver を起動する場合は、同じ class のdriver
method を変更して正しいポートを反映させる必要があります:
use Facebook\WebDriver\Remote\RemoteWebDriver;
/**
* Create the RemoteWebDriver instance.
*/
protected function driver(): RemoteWebDriver
{
return RemoteWebDriver::create(
'http://localhost:9515', DesiredCapabilities::chrome()
);
}
Environment の取り扱い
テスト実行時に Dusk が自身の environment ファイルを使用するように強制するには、 project の root に.env.dusk.{environment}
ファイルを作成します。例えば、local
environment から dusk
command を開始する場合、 .env.dusk.local
ファイルを作成すべきです。
テストを実行するとき、 Dusk はあなたの.env
ファイルをバックアップし、あなたの Dusk environment を.env
にリネームします。テストが完了すると、あなたの.env
ファイルは復元されます。
Browser Basics
ブラウザの作成
始めるために、私たちが application に log インできることを確認する test を書きましょう。test を生成した後、log インページに移動し、いくつかの authentication 情報を入力し、"login" button をクリックするように変更できます。ブラウザインスタンスを作成するためには、あなたの Dusktest 内からbrowse
method を呼び出すことができます。
<?php
use App\Models\User;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Laravel\Dusk\Browser;
uses(DatabaseMigrations::class);
test('basic example', function () {
$user = User::factory()->create([
'email' => 'taylor@laravel.com',
]);
$this->browse(function (Browser $browser) use ($user) {
$browser->visit('/login')
->type('email', $user->email)
->type('password', 'password')
->press('Login')
->assertPathIs('/home');
});
});
<?php
namespace Tests\Browser;
use App\Models\User;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Laravel\Dusk\Browser;
use Tests\DuskTestCase;
class ExampleTest extends DuskTestCase
{
use DatabaseMigrations;
/**
* A basic browser test example.
*/
public function test_basic_example(): void
{
$user = User::factory()->create([
'email' => 'taylor@laravel.com',
]);
$this->browse(function (Browser $browser) use ($user) {
$browser->visit('/login')
->type('email', $user->email)
->type('password', 'password')
->press('Login')
->assertPathIs('/home');
});
}
}
上記の例で見ることができるように、 browse
method はクロージャを受け入れます。ブラウザのインスタンスは自動的にこのクロージャに Dusk により渡され、そしてそれはあなたの application と対話し、アサーションを行うために使われる主要な object です。
複数のブラウザの作成
テストを適切に実行するために、複数のブラウザが必要になることがあります。例えば、websockets と対話するチャット画面をテストするためには、複数のブラウザが必要となるかもしれません。複数のブラウザを作成するには、与えられた browse
method のクロージャにある signature に追加の browser 引数を単純に追加するだけです:
$this->browse(function (Browser $first, Browser $second) {
$first->loginAs(User::find(1))
->visit('/home')
->waitForText('Message');
$second->loginAs(User::find(2))
->visit('/home')
->waitForText('Message')
->type('message', 'Hey Taylor')
->press('Send');
$first->waitForText('Hey Taylor')
->assertSee('Jeffrey Way');
});
Navigation
visit
method は、あなたの application 内の指定された URI に移動するために使用することができます:
$browser->visit('/login');
名前付きの routeに移動するために、visitRoute
の method を使用することができます:
$browser->visitRoute('login');
back
およびforward
メソッドを使用して、"back"と"forward"へのナビゲーションが可能です:
$browser->back();
$browser->forward();
ページを refresh するために、refresh
method を使用することができます:
$browser->refresh();
ブラウザウィンドウのサイズ変更
ブラウザウィンドウのサイズを調整するために、resize
method を使用することができます。
$browser->resize(1920, 1080);
maximize
method は、ブラウザウィンドウを最大化するために使用できます:
$browser->maximize();
fitContent
method は、ブラウザウィンドウを content のサイズに合わせてリサイズします:
$browser->fitContent();
テストが失敗すると、 Dusk はスクリーンショットを取る前に content に合わせてブラウザのサイズを自動的に調整します。この feature を無効にするには、テスト内でdisableFitOnFailure
method を呼び出すことができます。
$browser->disableFitOnFailure();
あなたはmove
method を使用して、ブラウザウィンドウを画面上の別の位置に移動することができます:
$browser->move($x = 100, $y = 100);
ブラウザマクロ
あなたがさまざまなテストで再利用できる custom ブラウザの method を定義したい場合、Browser
class のmacro
method を使用できます。通常、この method は service provider の boot
method から呼び出すべきです:
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Laravel\Dusk\Browser;
class DuskServiceProvider extends ServiceProvider
{
/**
* Register Dusk's browser macros.
*/
public function boot(): void
{
Browser::macro('scrollToElement', function (string $element = null) {
$this->script("$('html, body').animate({ scrollTop: $('$element').offset().top }, 0);");
return $this;
});
}
}
macro
関数は、最初の引数として名前を、2 番目の引数としてクロージャを受け入れます。マクロのクロージャは、Browser
インスタンス上で macro を method として呼び出すときに実行されます:
$this->browse(function (Browser $browser) use ($user) {
$browser->visit('/pay')
->scrollToElement('#credit-card-details')
->assertSee('Enter Credit Card Details');
});
Authentication
しばしば、あなたは authentication が必要なページを testing することになるでしょう。testing のたびに application の log イン画面と対話するのを避けるために、Dusk の loginAs
method を使用できます。loginAs
method は、authentication 可能な model に関連付けられた主 key または authentication 可能な model のインスタンスを受け入れます。
use App\Models\User;
use Laravel\Dusk\Browser;
$this->browse(function (Browser $browser) {
$browser->loginAs(User::find(1))
->visit('/home');
});
WARNING
loginAs
method を使用した後、ファイル内のすべての tests で user session が維持されます。
Cookies
cookie
の method を使用して、暗号化されたクッキーの value を取得または設定することができます。 default では、 Laravel によって作成されたすべてのクッキーが暗号化されています。
$browser->cookie('name');
$browser->cookie('name', 'Taylor');
plainCookie
method を使用して、暗号化されていない cookies の value を取得または設定することができます:
$browser->plainCookie('name');
$browser->plainCookie('name', 'Taylor');
指定された cookie を delete するために、deleteCookie
method を使用することができます:
$browser->deleteCookie('name');
JavaScript の実行
script
method を使用して、ブラウザ内で好きな JavaScript ステートメントを実行することができます。
$browser->script('document.documentElement.scrollTop = 0');
$browser->script([
'document.body.scrollTop = 0',
'document.documentElement.scrollTop = 0',
]);
$output = $browser->script('return window.location.pathname');
スクリーンショットの撮影
次のscreenshot
method を使用してスクリーンショットを撮り、与えられたファイル名で保存することができます。すべてのスクリーンショットはtests/Browser/screenshots
ディレクトリ内に保存されます:
$browser->screenshot('filename');
responsiveScreenshots
の method は、さまざまなブレークポイントで一連のスクリーンショットを撮るために使用できます。
$browser->responsiveScreenshots('filename');
screenshotElement
method は、ページ上の特定の要素のスクリーンショットを撮るために使用できます:
$browser->screenshotElement('#selector', 'filename');
Console Output をディスクに保存する
あなたは storeConsoleLog
method を使って、指定したファイル名で現在のブラウザの console 出力をディスクに書き込むことができます。 console 出力は tests/Browser/console
ディレクトリ内に保存されます。
$browser->storeConsoleLog('filename');
ページソースをディスクに保存する
あなたはstoreSource
method を使用して、与えられたファイル名で現在のページのソースをディスクに書き込むことができます。ページソースはtests/Browser/source
ディレクトリ内に保存されます。
$browser->storeSource('filename');
Interacting With Elements
Dusk セレクター
Dusk テストを作成する際に最も難しい部分の一つは、 elements と対話するために適切な CSS セレクターを選ぶことです。時間とともに、フロントエンドの変更により、以下のような CSS セレクターがテストを壊す原因となることがあります:
// HTML...
<button>Login</button>
// Test...
$browser->click('.login-page .container div > button');
Dusk セレクターを使用すると、CSS セレクターを覚えることに集中するのではなく、効果的なテストの作成に焦点を当てることができます。セレクターを定義するには、HTML 要素にdusk
attribute を追加します。その後、Dusk ブラウザとのやりとりでは、セレクターの前に@
を付けて、テスト内の関連する要素を操作します:
// HTML...
<button dusk="login-button">Login</button>
// Test...
$browser->click('@login-button');
希望に応じて、selectorHtmlAttribute
method を使用して、 Dusk セレクタが利用する HTML attribute をカスタマイズすることができます。通常、この method はアプリケーションのAppServiceProvider
のboot
method から呼び出すべきです:
use Laravel\Dusk\Dusk;
Dusk::selectorHtmlAttribute('data-dusk');
テキスト、 Values 、そして Attributes
Values の取得と設定
Dusk は、ページ上の要素の現在の value、表示テキスト、および属性とやり取りするためのいくつかの方法を提供します。例えば、与えられた CSS または Dusk セレクタに一致する要素の"値"を取得するには、value
の method を使用します。
// Retrieve the value...
$value = $browser->value('selector');
// Set the value...
$browser->value('selector', 'value');
特定のフィールド名を持つ input 要素の"value"を取得するために、inputValue
の method を使用することができます。
$value = $browser->inputValue('field');
テキストの取得
text
method は、指定されたセレクターに一致する要素の表示テキストを取得するために使用できます。
$text = $browser->text('selector');
Attributes の取得
最後に、attribute
の method は、指定されたセレクタに一致する要素の attribute の value を取得するために使用することができます。
$attribute = $browser->attribute('selector', 'value');
フォームとの対話
Values の入力
Dusk は、フォームや input elements との交流方法を多数提供しています。まずは、 input フィールドにテキストを打ち込む例を見てみましょう。
$browser->type('email', 'taylor@laravel.com');
注意してください、type
method は必要に応じて 1 つを受け入れますが、我々は CSS セレクタを必ずしも渡す 必要はありません。もし CSS セレクタが提供されていない場合、Dusk は与えられた name
属性を持つinput
またはtextarea
フィールドを探します。
フィールドの content をクリアせずにテキストを追加するには、append
method を使用することができます。
$browser->type('tags', 'foo')
->append('tags', ', bar, baz');
clear
method を使って、 input の value をクリアすることができます。
$browser->clear('email');
typeSlowly
method を使用して、 Dusk にゆっくりと type するよう指示することができます。 default では、 Dusk は key を押すごとに 100 ミリ秒間停止します。key を押す間の時間をカスタマイズするには、適切なミリ秒数を method の第三引数として渡すことができます。
$browser->typeSlowly('mobile', '+1 (202) 555-5555');
$browser->typeSlowly('mobile', '+1 (202) 555-5555', 300);
テキストをゆっくりと追加するために、appendSlowly
method を使用することができます。
$browser->type('tags', 'foo')
->appendSlowly('tags', ', bar, baz');
Dropdowns
select
要素で利用可能な value を select するには、select
method を使用することができます。type
method と同様に、select
method は完全な CSS セレクタを必要としません。select
method に value を渡すときは表示テキストではなく、基本のオプション value を渡すべきです。
$browser->select('size', 'Large');
2 つ目の引数を省略することで、 random オプションを select することができます:
$browser->select('size');
select
の第二引数に array を提供することで、その method に複数の options を select するよう指示することができます。
$browser->select('categories', ['Art', 'Music']);
Checkboxes
チェックボックスの入力をチェックするために、check
method を使用することができます。他の多くの入力関連の method と同様に、CSS セレクタは必要ではありません。もし CSS セレクタのマッチが見つからない場合、Dusk は一致するname
属性をもつチェックボックスを検索します:
$browser->check('terms');
uncheck
method は、チェックボックスの input を"チェック解除"するために使用されるかもしれません:
$browser->uncheck('terms');
ラジオボタン
radio
" "入力"option を"選択"するには、radio
"method"を使用することができます。他の多くの"入力"関連の method と同様に、完全な"CSS"セレクタは"必要ではありません"。もし"CSS"セレクタ"マッチ"が見つからない場合、"Dusk"は一致するname
とvalue
の"属性"を持つradio
"入力"を"探し"ます。
$browser->radio('size', 'large');
ファイルの添付
attach
method は file
input 要素にファイルを添付するために使用できます。他の多くの input 関連 method 同様に、完全な CSS セレクタは必要ありません。CSS セレクタのマッチが見つからない場合、Dusk は一致するname
属性を持つfile
input を検索します:
$browser->attach('photo', __DIR__.'/photos/mountains.png');
WARNING
attach 関数を利用するには、サーバーに
Zip
PHP 拡張がインストールされ、有効になっている必要があります。
ボタンを押す
press
method は、ページ上の button 要素をクリックするために使用することができます。press
method に渡される引数は、 button の表示テキストまたは CSS / Dusk セレクタのいずれかです。
$browser->press('Login');
フォームを提出する際、多くのアプリケーションでは、ボタンが押された後にフォームの送信 button を無効にし、フォーム送信の HTTP request が完了したら button を再度有効にします。 button を press し、 button が再度有効になるのを待つには、pressAndWaitFor
method を使用することができます。
// Press the button and wait a maximum of 5 seconds for it to be enabled...
$browser->pressAndWaitFor('Save');
// Press the button and wait a maximum of 1 second for it to be enabled...
$browser->pressAndWaitFor('Save', 1);
Links をクリックする
link をクリックするには、ブラウザのインスタンスで clickLink
method を使用することができます。 clickLink
method は、指定された表示テキストを持つ link をクリックします:
$browser->clickLink($linkText);
seeLink
method を使用して、指定された表示テキストを持つリンクがページ上に表示されているかどうかを判断することができます:
if ($browser->seeLink($linkText)) {
// ...
}
WARNING
これらのメソッドは jQuery と連携します。もしページ上で jQuery が使用できない場合、 Dusk は自動的にページにそれを注入し、テストの期間中に利用可能となります。
Keyboard の使用
keys
method は、通常 type
method で許されるよりも複雑な input sequences を特定の要素に提供できるようにします。例えば、 Dusk に対して、 values を入力する際に修飾 keys を保持するよう指示することができます。この例では、与えられたセレクタに一致する要素に taylor
が入力される際に、shift
キーが保持されます。taylor
が入力された後、swift
は修飾 keys 無しで入力されます:
$browser->keys('selector', ['{shift}', 'taylor'], 'swift');
keys
の"method"のもう 1 つの価 values ある使用例は、"key ボードショートカット"の組み合わせをあなたの"application"の"primaryCSS"セレクタに送信することです:
$browser->keys('.app', ['{command}', 'j']);
NOTE
すべての修飾 keys(例:
{command}
)は{}
文字で囲まれ、Facebook\WebDriver\WebDriverKeys
class で定群されている定数と match します。これはGitHub 上で見つけることができます 。
流暢な Keyboard の操作
Dusk は、withKeyboard
method も提供しており、Laravel\Dusk\Keyboard
class を介して流暢に複雑な keyboard のインタラクションを実行できます。Keyboard
class は、press
、release
、type
、pause
のメソッドを提供します:
use Laravel\Dusk\Keyboard;
$browser->withKeyboard(function (Keyboard $keyboard) {
$keyboard->press('c')
->pause(1000)
->release('c')
->type(['c', 'e', 'o']);
});
Keyboard マクロ
テストスイート全体で簡単に再利用できる custom keyboard のインタラクションを定義したい場合、Keyboard
class が提供するmacro
method を使用することができます。通常、この method は service provider boot
method から呼び出す必要があります。
<?php
namespace App\Providers;
use Facebook\WebDriver\WebDriverKeys;
use Illuminate\Support\ServiceProvider;
use Laravel\Dusk\Keyboard;
use Laravel\Dusk\OperatingSystem;
class DuskServiceProvider extends ServiceProvider
{
/**
* Register Dusk's browser macros.
*/
public function boot(): void
{
Keyboard::macro('copy', function (string $element = null) {
$this->type([
OperatingSystem::onMac() ? WebDriverKeys::META : WebDriverKeys::CONTROL, 'c',
]);
return $this;
});
Keyboard::macro('paste', function (string $element = null) {
$this->type([
OperatingSystem::onMac() ? WebDriverKeys::META : WebDriverKeys::CONTROL, 'v',
]);
return $this;
});
}
}
macro
関数は、最初の引数として名前を、2 番目の引数としてクロージャを受け付けます。マクロのクロージャは、Keyboard
インスタンス上で macro を method として呼び出すときに実行されます:
$browser->click('@textarea')
->withKeyboard(fn (Keyboard $keyboard) => $keyboard->copy())
->click('@another-textarea')
->withKeyboard(fn (Keyboard $keyboard) => $keyboard->paste());
マウスの使用
Elements をクリックする
click
method は、指定された CSS または Dusk セレクターに一致する要素をクリックするために使用できます。
$browser->click('.selector');
clickAtXPath
method は、指定した XPath 式に一致する要素をクリックするために使用できます:
$browser->clickAtXPath('//div[@class = "selector"]');
clickAtPoint
method は、ブラウザの表示領域に対する相対座標で最上部の要素をクリックするために使用できます。
$browser->clickAtPoint($x = 0, $y = 0);
doubleClick
method は、マウスのダブルクリックをシミュレートするために使用することができます:
$browser->doubleClick();
$browser->doubleClick('.selector');
rightClick
method は、マウスの右クリックをシミュレートするために使用することができます:
$browser->rightClick();
$browser->rightClick('.selector');
clickAndHold
method は、マウスの button がクリックされて押し続けられることをシミュレートするために使用できます。その後のreleaseMouse
method の呼び出しは、この動作を元に戻し、マウスの button を release します:
$browser->clickAndHold('.selector');
$browser->clickAndHold()
->pause(1000)
->releaseMouse();
controlClick
method は、ブラウザ内でctrl+click
の event をシミュレートするために使用することができます:
$browser->controlClick();
$browser->controlClick('.selector');
Mouseover
mouseover
method は、指定された CSS または Dusk セレクターに一致する要素の上にマウスを移動する必要がある場合に使用できます:
$browser->mouseover('.selector');
ドラッグ アンド ドロップ
drag
method は、指定したセレクタに一致する要素を別の要素にドラッグするために使用できます:
$browser->drag('.from-selector', '.to-selector');
または、要素を single 方向にドラッグすることもできます:
$browser->dragLeft('.selector', $pixels = 10);
$browser->dragRight('.selector', $pixels = 10);
$browser->dragUp('.selector', $pixels = 10);
$browser->dragDown('.selector', $pixels = 10);
最後に、与えられたオフセットによって要素をドラッグすることができます:
$browser->dragOffset('.selector', $x = 10, $y = 10);
JavaScript ダイアログ
Dusk は、 JavaScript ダイア log と対話するための様々な方法を提供します。例えば、waitForDialog
method を使用して、 JavaScript ダイア log が表示されるのを待つことができます。この method は、ダイア log が表示されるまでの待ち時間を秒数で指定する option の引数を受け付けます:
$browser->waitForDialog($seconds = null);
assertDialogOpened
method は、ダイア log が表示され、指定したメッセージが含まれていることを assert するために使用することができます。
$browser->assertDialogOpened('Dialog message');
もし JavaScript のダイアログに prompt が含まれている場合、typeInDialog
method を使って value を prompt に type することができます:
$browser->typeInDialog('Hello World');
OK" button をクリックして開いている JavaScript ダイア log を閉じるには、acceptDialog
method を呼び出すことができます:
$browser->acceptDialog();
開いている JavaScript ダイア log を"cancel" button をクリックして閉じるためには、dismissDialog
method を呼び出すことができます:
$browser->dismissDialog();
インラインフレームとの対話
iframe 内の elements と対話する必要がある場合は、withinFrame
method を使用することができます。 withinFrame
method に提供されたクロージャ内で行われるすべてのエレメントとのやり取りは、指定された iframe の context にスコープされます。
$browser->withinFrame('#credit-card-details', function ($browser) {
$browser->type('input[name="cardnumber"]', '4242424242424242')
->type('input[name="exp-date"]', '1224')
->type('input[name="cvc"]', '123')
->press('Pay');
});
スコーピングセレクタ
時折、指定されたセレクタ内で全ての操作を範囲指定しながら複数の操作を行いたい場合があるかと思います。たとえば、テーブル内にのみ存在するテキストを assert してから、そのテーブル内の button をクリックしたいと思うかもしれません。このような場合、with
method を使用できます。with
method に与えられたクロージャ内で実行されるすべての操作は元のセレクタに範囲指定されます。
$browser->with('.table', function (Browser $table) {
$table->assertSee('Hello World')
->clickLink('Delete');
});
たまには現在の scope の外部でアサーションを実行する必要があるかもしれません。これを達成するためには、elsewhere
および elsewhereWhenAvailable
メソッドを使用できます:
$browser->with('.table', function (Browser $table) {
// Current scope is `body .table`...
$browser->elsewhere('.page-title', function (Browser $title) {
// Current scope is `body .page-title`...
$title->assertSee('Hello World');
});
$browser->elsewhereWhenAvailable('.page-title', function (Browser $title) {
// Current scope is `body .page-title`...
$title->assertSee('Hello World');
});
});
Elements を待っています
JavaScript を大量に使用する applications を testing する際、特定の elements や data が利用可能になるまで待つ必要がしばしば生じます。 Dusk を使うと、これが簡単になります。様々な方法を使用して、ページ上で elements が表示されるまで待つことも、特定の JavaScript の表現がtrue
に評価されるまで待つことも可能です。
Waiting
あなたが単純にテストを一定のミリ秒数で一時停止させる必要がある場合は、pause
method を使用してください:
$browser->pause(1000);
与えられた条件がtrue
の場合にのみテストを一時停止する必要がある場合、pauseIf
method を使用してください:
$browser->pauseIf(App::environment('production'), 1000);
同様に、特定の条件がtrue
である限り test を一時停止する必要がある場合は、pauseUnless
method を使用することができます。
$browser->pauseUnless(App::environment('testing'), 1000);
セレクターを待つ
waitFor
method は、指定された CSS または Dusk セレクターに一致する要素がページに表示されるまでの test の実行を一時停止するために使用できます。 default では、例外を throw する前に test を最大 5 秒間一時停止します。 必要に応じて、 method の第 2 引数として custom timeout しきい values を渡すことができます。
// Wait a maximum of five seconds for the selector...
$browser->waitFor('.selector');
// Wait a maximum of one second for the selector...
$browser->waitFor('.selector', 1);
与えられたセレクタに一致する要素が指定されたテキストを含むまで待つこともできます:
// Wait a maximum of five seconds for the selector to contain the given text...
$browser->waitForTextIn('.selector', 'Hello World');
// Wait a maximum of one second for the selector to contain the given text...
$browser->waitForTextIn('.selector', 'Hello World', 1);
また、指定されたセレクタに一致する要素がページから消えるまで待つこともできます:
// Wait a maximum of five seconds until the selector is missing...
$browser->waitUntilMissing('.selector');
// Wait a maximum of one second until the selector is missing...
$browser->waitUntilMissing('.selector', 1);
または、指定されたセレクターに一致する要素が有効になったり、無効になるまで待つこともできます:
// Wait a maximum of five seconds until the selector is enabled...
$browser->waitUntilEnabled('.selector');
// Wait a maximum of one second until the selector is enabled...
$browser->waitUntilEnabled('.selector', 1);
// Wait a maximum of five seconds until the selector is disabled...
$browser->waitUntilDisabled('.selector');
// Wait a maximum of one second until the selector is disabled...
$browser->waitUntilDisabled('.selector', 1);
利用可能な場合のスコープセレクターの指定
たまに、特定のセレクタに一致する要素が表示されるのを待ってから、その要素と対話することが必要かもしれません。たとえば、モーダルウィンドウが利用可能になるまで待ってから、そのモーダル内の"OK" button を press することが必要かもしれません。この作業を達成するために、whenAvailable
method を使用できます。指定されたクロージャ内で実行されるすべての要素操作は、元のセレクタにスコープが設定されます。
$browser->whenAvailable('.modal', function (Browser $modal) {
$modal->assertSee('Hello World')
->press('OK');
});
テキストを待っています
waitForText
method は、指定されたテキストがページに表示されるのを待つために使用できます:
// Wait a maximum of five seconds for the text...
$browser->waitForText('Hello World');
// Wait a maximum of one second for the text...
$browser->waitForText('Hello World', 1);
表示されたテキストがページから削除されるまで、waitUntilMissingText
method を使用することができます:
// Wait a maximum of five seconds for the text to be removed...
$browser->waitUntilMissingText('Hello World');
// Wait a maximum of one second for the text to be removed...
$browser->waitUntilMissingText('Hello World', 1);
Links を待っています
waitForLink
method は、指定されたリンクテキストがページ上に表示されるまで待つために使用できます:
// Wait a maximum of five seconds for the link...
$browser->waitForLink('Create');
// Wait a maximum of one second for the link...
$browser->waitForLink('Create', 1);
入力を待っています
waitForInput
method は、指定された input フィールドがページ上に表示されるまで待つために使用することができます:
// Wait a maximum of five seconds for the input...
$browser->waitForInput($field);
// Wait a maximum of one second for the input...
$browser->waitForInput($field, 1);
ページの場所を待機中
$browser->assertPathIs('/home')
のような path アサーションを作成する際、window.location.pathname
が非同期で更新されている場合、アサーションが失敗することがあります。waitForLocation
method を使用して、ロケーションが指定した value になるのを待つことができます。
$browser->waitForLocation('/secret');
waitForLocation
method は、現在のウィンドウの位置が完全に定義された URL になるのを待つためにも使用できます。
$browser->waitForLocation('https://example.com/path');
名前付きルートの場所が表示されるまで待つこともできます:
$browser->waitForRoute($routeName, $parameters);
ページ再読み込みを待つ
action を実行した後、ページの再読み込みを待つ必要がある場合は、waitForReload
method を使用してください。
use Laravel\Dusk\Browser;
$browser->waitForReload(function (Browser $browser) {
$browser->press('Submit');
})
->assertSee('Success!');
ページの再読み込みを待つ必要が通常、 button をクリックした後に発生するため、便宜上clickAndWaitForReload
method を使用することができます:
$browser->clickAndWaitForReload('.selector')
->assertSee('something');
JavaScript 式を待つ
時々、指定の JavaScript 式がtrue
に評価されるまで test の実行を一時停止したい場合があるかもしれません。waitUntil
method を使うことでこれを簡単に実現することができます。この method に式を渡す際、return
key ワードや終了時のセミコロンを含める必要はありません。
// Wait a maximum of five seconds for the expression to be true...
$browser->waitUntil('App.data.servers.length > 0');
// Wait a maximum of one second for the expression to be true...
$browser->waitUntil('App.data.servers.length > 0', 1);
Vue 式の待機
waitUntilVue
およびwaitUntilVueIsNot
メソッドは、Vue component の attribute が指定した value を持つまで待つために使用できます:
// Wait until the component attribute contains the given value...
$browser->waitUntilVue('user.name', 'Taylor', '@user');
// Wait until the component attribute doesn't contain the given value...
$browser->waitUntilVueIsNot('user.name', null, '@user');
JavaScript Events を待つ
waitForEvent
method は、 JavaScript event が発生するまで test の実行を一時停止するために使用できます:
$browser->waitForEvent('load');
event リスナーは現在の scope 、つまり default では body
要素にアタッチされています。スコープドセレクタを使用すると、 event リスナーは一致する要素にアタッチされます:
$browser->with('iframe', function (Browser $iframe) {
// Wait for the iframe's load event...
$iframe->waitForEvent('load');
});
waitForEvent
の二番目の引数としてセレクタを提供することもできます。 method を特定の要素に attach するための event リスナーとして:
$browser->waitForEvent('load', '.selector');
document
や window
オブジェクトで events の待機も可能です:
// Wait until the document is scrolled...
$browser->waitForEvent('scroll', 'document');
// Wait a maximum of five seconds until the window is resized...
$browser->waitForEvent('resize', 'window', 5);
コールバックで待機する
Dusk の多くの"wait"メソッドは、基礎となるwaitUsing
method に依存しています。指定したクロージャがtrue
を返すのを待つために、この method を直接使用することができます。waitUsing
method は、待つ最大秒数、クロージャを評価する間隔、クロージャ、および option の失敗メッセージを受け入れます:
$browser->waitUsing(10, 1, function () use ($something) {
return $something->isReady();
}, "Something wasn't ready in time.");
要素を View にスクロールする
時には、要素がブラウザの表示可能エリアの外にあるために、クリックできないことがあります。scrollIntoView
method は、指定したセレクタの要素が表示内に入るまでブラウザウィンドウをスクロールします:
$browser->scrollIntoView('.selector')
->click('.selector');
Available Assertions
Dusk は、あなたの application に対して様々なアサーションを提供します。利用可能なすべてのアサーションは以下のリストに文書化されています:
assertTitle assertTitleContains assertUrlIs assertSchemeIs assertSchemeIsNot assertHostIs assertHostIsNot assertPortIs assertPortIsNot assertPathBeginsWith assertPathEndsWith assertPathContains assertPathIs assertPathIsNot assertRouteIs assertQueryStringHas assertQueryStringMissing assertFragmentIs assertFragmentBeginsWith assertFragmentIsNot assertHasCookie assertHasPlainCookie assertCookieMissing assertPlainCookieMissing assertCookieValue assertPlainCookieValue assertSee assertDontSee assertSeeIn assertDontSeeIn assertSeeAnythingIn assertSeeNothingIn assertScript assertSourceHas assertSourceMissing assertSeeLink assertDontSeeLink assertInputValue assertInputValueIsNot assertChecked assertNotChecked assertIndeterminate assertRadioSelected assertRadioNotSelected assertSelected assertNotSelected assertSelectHasOptions assertSelectMissingOptions assertSelectHasOption assertSelectMissingOption assertValue assertValueIsNot assertAttribute assertAttributeContains assertAttributeDoesntContain assertAriaAttribute assertDataAttribute assertVisible assertPresent assertNotPresent assertMissing assertInputPresent assertInputMissing assertDialogOpened assertEnabled assertDisabled assertButtonEnabled assertButtonDisabled assertFocused assertNotFocused assertAuthenticated assertGuest assertAuthenticatedAs assertVue assertVueIsNot assertVueContains assertVueDoesntContain
assertTitle
与えられたテキストとページタイトルが一致することを Assert します:
$browser->assertTitle($title);
assertTitleContains
指定されたテキストを含むページタイトルを Assert する:
$browser->assertTitleContains($title);
assertUrlIs
現在の URL ( query string を除く)が与えられた string と一致することを Assert します:
$browser->assertUrlIs($url);
assertSchemeIs
現在の URL スキームが与えられたスキームと一致することを Assert してください:
$browser->assertSchemeIs($scheme);
assertSchemeIsNot
現在の URL スキームが指定されたスキームと match しないことを Assert します:
$browser->assertSchemeIsNot($scheme);
assertHostIs
現在の URL ホストが指定されたホストと一致することを Assert します:
$browser->assertHostIs($host);
assertHostIsNot
現在の URL のホストが指定されたホストと match しないことを Assert してください:
$browser->assertHostIsNot($host);
assertPortIs
現在の URL ポートが指定されたポートと一致することを Assert します:
$browser->assertPortIs($port);
assertPortIsNot
現在の URL のポートが指定されたポートと一致しないことを主張する:
$browser->assertPortIsNot($port);
assertPathBeginsWith
現在の URL path が指定された path で始まると Assert してください:
$browser->assertPathBeginsWith('/home');
assertPathEndsWith
現在の URL path が指定した path で終わることを Assert します:
$browser->assertPathEndsWith('/home');
assertPathContains
現在の URL path が指定された path を含んでいることを Assert します:
$browser->assertPathContains('/home');
assertPathIs
現在の path が与えられた path と一致することを Assert します:
$browser->assertPathIs('/home');
assertPathIsNot
現在の path が指定された path と match しないことを Assert します:
$browser->assertPathIsNot('/home');
assertRouteIs
現在の URL が指定されたnamed route's URL と一致していることを Assert します:
$browser->assertRouteIs($name, $parameters);
assertQueryStringHas
与えられた query string パラメータが存在することを Assert します:
$browser->assertQueryStringHas($name);
与えられた query string パラメータが存在し、指定された value を持っていることを Assert します:
$browser->assertQueryStringHas($name, $value);
assertQueryStringMissing
指定された query string パラメータが欠けていることを Assert します:
$browser->assertQueryStringMissing($name);
assertFragmentIs
URL の現在の hash fragment が与えられた fragment と一致することを Assert します:
$browser->assertFragmentIs('anchor');
assertFragmentBeginsWith
URL の現在の hash fragment が指定された fragment から始まることを Assert します:
$browser->assertFragmentBeginsWith('anchor');
assertFragmentIsNot
指定された fragment と URL の現在の hash fragment が match しないことを Assert します:
$browser->assertFragmentIsNot('anchor');
assertHasCookie
指定された暗号化された cookie が存在することを Assert します:
$browser->assertHasCookie($name);
assertHasPlainCookie
与えられた暗号化されていない cookie が存在することを Assert します:
$browser->assertHasPlainCookie($name);
assertCookieMissing
与えられた暗号化された cookie が存在しないことを Assert します:
$browser->assertCookieMissing($name);
assertPlainCookieMissing
与えられた暗号化されていない cookie が存在しないことを Assert します:
$browser->assertPlainCookieMissing($name);
assertCookieValue
暗号化された cookie が指定した value を持っていることを Assert します:
$browser->assertCookieValue($name, $value);
assertPlainCookieValue
暗号化されていない cookie が特定の value を持っていることを Assert します:
$browser->assertPlainCookieValue($name, $value);
assertSee
与えられたテキストがページ上に存在することを Assert します:
$browser->assertSee($text);
assertDontSee
ページ上に指定のテキストが存在しないことを Assert します:
$browser->assertDontSee($text);
assertSeeIn
セレクタ内に指定されたテキストが存在することを Assert します:
$browser->assertSeeIn($selector, $text);
assertDontSeeIn
セレクター内に指定されたテキストが存在しないことを Assert します:
$browser->assertDontSeeIn($selector, $text);
assertSeeAnythingIn
セレクター内に任意のテキストが存在することを Assert します:
$browser->assertSeeAnythingIn($selector);
assertSeeNothingIn
セレクタ内にテキストが存在しないことを Assert します:
$browser->assertSeeNothingIn($selector);
assertScript
指定された JavaScript 表現が指定された value に評価されることを Assert します:
$browser->assertScript('window.isLoaded')
->assertScript('document.readyState', 'complete');
assertSourceHas
指定されたソース code がページ上に存在することを Assert します:
$browser->assertSourceHas($code);
assertSourceMissing
与えられたソース code がページ上に存在しないと Assert します:
$browser->assertSourceMissing($code);
assertSeeLink
指定されたリンクがページ上に存在することを Assert します:
$browser->assertSeeLink($linkText);
assertDontSeeLink
与えられたリンクがページ上に存在しないことを Assert します:
$browser->assertDontSeeLink($linkText);
assertInputValue
指定された input フィールドが指定された value を持っていることを Assert します:
$browser->assertInputValue($field, $value);
assertInputValueIsNot
与えられた input フィールドが、指定された value を持っていないことを Assert します:
$browser->assertInputValueIsNot($field, $value);
assertChecked
指定されたチェックボックスがチェックされていることを Assert します:
$browser->assertChecked($field);
assertNotChecked
指定されたチェックボックスがチェックされていないことを Assert します:
$browser->assertNotChecked($field);
assertIndeterminate
与えられたチェックボックスが不確定の state であることを Assert します:
$browser->assertIndeterminate($field);
assertRadioSelected
指定されたラジオフィールドが選択されていることを Assert します:
$browser->assertRadioSelected($field, $value);
assertRadioNotSelected
指定されたラジオフィールドが選択されていないことを Assert します:
$browser->assertRadioNotSelected($field, $value);
assertSelected
指定されたドロップダウンが指定された value を選択していることを Assert します:
$browser->assertSelected($field, $value);
assertNotSelected
与えられたドロップダウンが指定された value を選択していないことを Assert します:
$browser->assertNotSelected($field, $value);
assertSelectHasOptions
指定された array の values が選択可能であることを Assert します:
$browser->assertSelectHasOptions($field, $values);
assertSelectMissingOptions
与えられた array の values が選択可能ではないことを Assert します:
$browser->assertSelectMissingOptions($field, $values);
assertSelectHasOption
指定されたフィールドで選択可能な value が存在することを Assert します:
$browser->assertSelectHasOption($field, $value);
assertSelectMissingOption
指定された value が選択可能でないことを Assert します:
$browser->assertSelectMissingOption($field, $value);
assertValue
与えられたセレクターに一致する要素が、与えられた value を持つことを Assert する:
$browser->assertValue($selector, $value);
assertValueIsNot
指定されたセレクタに一致する要素が指定された value を持っていないことを Assert します:
$browser->assertValueIsNot($selector, $value);
assertAttribute
指定されたセレクターに一致する要素が、提供された attribute に指定された value を持つことを Assert します:
$browser->assertAttribute($selector, $attribute, $value);
assertAttributeContains
指定されたセレクタに一致する要素が、提供された attribute に指定された value を含むことを Assert します:
$browser->assertAttributeContains($selector, $attribute, $value);
assertAttributeDoesntContain
指定されたセレクターに一致する要素が、提供された attribute に指定された value を含まないことを Assert します:
$browser->assertAttributeDoesntContain($selector, $attribute, $value);
assertAriaAttribute
指定されたセレクターに一致する要素が、指定された aria の attribute に与えられた value を持つことを Assert します:
$browser->assertAriaAttribute($selector, $attribute, $value);
たとえば、マークアップが <button aria-label="Add"></button>
である場合、 aria-label
attribute に対して以下のように assert することができます:
$browser->assertAriaAttribute('button', 'label', 'Add')
assertDataAttribute
指定されたセレクターに一致する要素が、提供された data attribute に指定された value を持っていることを Assert します:
$browser->assertDataAttribute($selector, $attribute, $value);
たとえば、マークアップが <tr id="row-1" data-content="attendees"></tr>
の場合、次のように data-label
attribute に対して assert できます。
$browser->assertDataAttribute('#row-1', 'content', 'attendees')
assertVisible
指定されたセレクタに一致する要素が表示されていることを Assert します:
$browser->assertVisible($selector);
assertPresent
ソース内に指定したセレクタに一致する要素が存在することを Assert します:
$browser->assertPresent($selector);
assertNotPresent
ソース内に指定のセレクタに一致する要素が存在しないことを Assert します:
$browser->assertNotPresent($selector);
assertMissing
与えられたセレクターに一致する要素が表示されていないことを Assert します:
$browser->assertMissing($selector);
assertInputPresent
与えられた名前の input が存在することを Assert します:
$browser->assertInputPresent($name);
assertInputMissing
ソース内に指定された名前の input が存在しないことを Assert します:
$browser->assertInputMissing($name);
assertDialogOpened
指定されたメッセージを持つ JavaScript ダイアログが開かれたことを Assert します:
$browser->assertDialogOpened($message);
assertEnabled
与えられたフィールドが有効であることを Assert します:
$browser->assertEnabled($field);
assertDisabled
指定されたフィールドが無効になっていることを Assert します:
$browser->assertDisabled($field);
assertButtonEnabled
与えられた button が有効であると Assert します:
$browser->assertButtonEnabled($button);
assertButtonDisabled
指定された button が無効であることを Assert します:
$browser->assertButtonDisabled($button);
assertFocused
指定されたフィールドがフォーカスされていることを Assert します:
$browser->assertFocused($field);
assertNotFocused
指定されたフィールドがフォーカスされていないことを Assert します:
$browser->assertNotFocused($field);
assertAuthenticated
user が authentication されていることを Assert します:
$browser->assertAuthenticated();
assertGuest
Assert が user が authentication されていないことを Asset します:
$browser->assertGuest();
assertAuthenticatedAs
指定された user として認証されている user を Assert する:
$browser->assertAuthenticatedAs($user);
assertVue
Dusk は、Vue component の state に対して主張をすることも可能です。例えば、あなたの application が以下のような Vue component を含んでいると想像してみてください:
// HTML...
<profile dusk="profile-component"></profile>
// Component Definition...
Vue.component('profile', {
template: '<div>{{ user.name }}</div>',
data: function () {
return {
user: {
name: 'Taylor'
}
};
}
});
以下のように、Vue の component の state に assert することができます:
test('vue', function () {
$this->browse(function (Browser $browser) {
$browser->visit('/')
->assertVue('user.name', 'Taylor', '@profile-component');
});
});
/**
* A basic Vue test example.
*/
public function test_vue(): void
{
$this->browse(function (Browser $browser) {
$browser->visit('/')
->assertVue('user.name', 'Taylor', '@profile-component');
});
}
assertVueIsNot
与えられた Vue の component data プロパティが与えられた value と match しないことを Assert します:
$browser->assertVueIsNot($property, $value, $componentSelector = null);
assertVueContains
指定された Vue の component data プロパティが array であり、指定された value を含んでいることを Assert します:
$browser->assertVueContains($property, $value, $componentSelector = null);
assertVueDoesntContain
指定された Vue の component data プロパティが array であり、指定された value を含まないことを Assert します:
$browser->assertVueDoesntContain($property, $value, $componentSelector = null);
Pages
時には、テストでは、複数の複雑なアクションを sequence として実行する必要があります。これにより、テストの読み取りや理解が難しくなることがあります。 Dusk Pages を使用すると、特定のページで実行できる表現豊かなアクションを定義できます。また、 single method を介して実行することもできます。Pages を使用すると、 application や single ページの一般的なセレクタへのショートカットを定義することもできます。
ページの生成
ページ object を生成するには、dusk:page
Artisan command を実行します。すべてのページオブジェクトは、あなたのアプリケーションの tests/Browser/Pages
ディレクトリに配置されます:
php artisan dusk:page Login
ページの設定
default として、ページには 3 つの method があります: url
、assert
、そして elements
。今すぐurl
とassert
method について話し合います。 elements
method は以下で詳しく説明します。
url
Method
url
method は、ページを表す URL の path を返すべきです。ブラウザーでページに移動するときに、 Dusk はこの URL を使用します:
/**
* Get the URL for the page.
*/
public function url(): string
{
return '/login';
}
assert
Method
assert
method は、ブラウザが実際に指定されたページに存在していることを確認するために必要なアサーションを行うことができます。このメソッド内に何かを配置することは実際には必要ありませんが、もしご希望であればこれらのアサーションを行うことができます。これらのアサーションは、ページへ移動する際に自動的に実行されます:
/**
* Assert that the browser is on the page.
*/
public function assert(Browser $browser): void
{
$browser->assertPathIs($this->url());
}
ページへの移動
ページが定義されると、visit
method を使用してそのページに移動できます:
use Tests\Browser\Pages\Login;
$browser->visit(new Login);
時々、既に特定のページにいる場合でも、そのページのセレクターやメソッドを現在のテスト context に"ロード"する必要があるかもしれません。これは、 button を押して特定のページに明示的に移動せずにリダイレクトされるときによくあります。このような状況では、ページをロードするために on
method を使用することができます:
use Tests\Browser\Pages\CreatePlaylist;
$browser->visit('/dashboard')
->clickLink('Create Playlist')
->on(new CreatePlaylist)
->assertSee('@create');
短縮セレクタ
ページクラス内の elements
method は、ページ上の任意の CSS セレクターに対して素早く、覚えやすいショートカットを定義することができます。例えば、アプリケーションのログインページの email input フィールドのショートカットを定義しましょう:
/**
* Get the element shortcuts for the page.
*
* @return array<string, string>
*/
public function elements(): array
{
return [
'@email' => 'input[name=email]',
];
}
ショートカットが定義されると、通常、完全な CSS セレクタを使用する場所で短縮セレクタを使用することができます。
$browser->type('@email', 'taylor@laravel.com');
グローバル省略セレクタ
Dusk をインストールした後、基本的なPage
class がtests/Browser/Pages
ディレクトリに配置されます。この class には、siteElements
method が含まれており、これを使用して、あなたの application 全体のすべてのページで利用可能なグローバルな省略形セレクタを定義することができます。
/**
* Get the global element shortcuts for the site.
*
* @return array<string, string>
*/
public static function siteElements(): array
{
return [
'@element' => '#selector',
];
}
ページメソッド
ページで定義された default メソッドに加えて、テスト全体で使用できる追加メソッドを定義することもできます。例えば、音楽管理 application を構築しているとしましょう。 application の一ページでよく行われる action は、プレイリストの作成かもしれません。各テストでプレイリストを作成するロジックを書き直すのではなく、ページの class にcreatePlaylist
method を定義することもできます:
<?php
namespace Tests\Browser\Pages;
use Laravel\Dusk\Browser;
use Laravel\Dusk\Page;
class Dashboard extends Page
{
// Other page methods...
/**
* Create a new playlist.
*/
public function createPlaylist(Browser $browser, string $name): void
{
$browser->type('name', $name)
->check('share')
->press('Create Playlist');
}
}
一度 method が定義されると、そのページを利用する任意のテスト内で使用できます。ブラウザのインスタンスは自動的に、 custom ページメソッドの最初の引数として渡されます:
use Tests\Browser\Pages\Dashboard;
$browser->visit(new Dashboard)
->createPlaylist('My Playlist')
->assertSee('My Playlist');
Components
コンポーネントは Dusk の page objects に似ていますが、ナビゲーションバーまたは notification ウィンドウのような、 application 全体で再利用される UI や機能の部分を対象としています。したがって、コンポーネントは特定の URL に束縛されません。
コンポーネントの生成
component を生成するには、dusk:component
の Artisan command を実行します。新しいコンポーネントはtests/Browser/Components
ディレクトリに配置されます:
php artisan dusk:component DatePicker
上記で示したように、date picker は、様々なページであなたの application に存在するかもしれない component の一例です。テストスイート全体で何十ものテストで日付を select するブラウザ自動化ロジックを手作業で書くことは煩雑になることがあります。代わりに、日付選択を表す Dusk component を定義することができ、そのロジックを component 内にカプセル化することができます。
<?php
namespace Tests\Browser\Components;
use Laravel\Dusk\Browser;
use Laravel\Dusk\Component as BaseComponent;
class DatePicker extends BaseComponent
{
/**
* Get the root selector for the component.
*/
public function selector(): string
{
return '.date-picker';
}
/**
* Assert that the browser page contains the component.
*/
public function assert(Browser $browser): void
{
$browser->assertVisible($this->selector());
}
/**
* Get the element shortcuts for the component.
*
* @return array<string, string>
*/
public function elements(): array
{
return [
'@date-field' => 'input.datepicker-input',
'@year-list' => 'div > div.datepicker-years',
'@month-list' => 'div > div.datepicker-months',
'@day-list' => 'div > div.datepicker-days',
];
}
/**
* Select the given date.
*/
public function selectDate(Browser $browser, int $year, int $month, int $day): void
{
$browser->click('@date-field')
->within('@year-list', function (Browser $browser) use ($year) {
$browser->click($year);
})
->within('@month-list', function (Browser $browser) use ($month) {
$browser->click($month);
})
->within('@day-list', function (Browser $browser) use ($day) {
$browser->click($day);
});
}
}
コンポーネントの使用
一度 component が定義されると、どのテストからでも簡単に日付ピッカー内の日付を select できます。また、日付を select するためのロジックが変更された場合、 component を update するだけで済みます。
<?php
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Laravel\Dusk\Browser;
use Tests\Browser\Components\DatePicker;
uses(DatabaseMigrations::class);
test('basic example', function () {
$this->browse(function (Browser $browser) {
$browser->visit('/')
->within(new DatePicker, function (Browser $browser) {
$browser->selectDate(2019, 1, 30);
})
->assertSee('January');
});
});
<?php
namespace Tests\Browser;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Laravel\Dusk\Browser;
use Tests\Browser\Components\DatePicker;
use Tests\DuskTestCase;
class ExampleTest extends DuskTestCase
{
/**
* A basic component test example.
*/
public function test_basic_example(): void
{
$this->browse(function (Browser $browser) {
$browser->visit('/')
->within(new DatePicker, function (Browser $browser) {
$browser->selectDate(2019, 1, 30);
})
->assertSee('January');
});
}
}
Continuous Integration
WARNING
ほとんどの Dusk 連続的な統合設定では、ご利用の Laravel application がビルトインの PHPdevelopmentserver を使用してポート 8000 で提供されることを想定しています。したがって、続行する前に、連続的な統合環境に
APP_URL
の環境変数 value がhttp://127.0.0.1:8000
であることを確認していただく必要があります。
Heroku CI
Heroku CI で Dusk テストを実行するには、次の Google Chrome ビルドパックとスクリプトを Heroku のapp.json
ファイルに追加してください:
{
"environments": {
"test": {
"buildpacks": [
{ "url": "heroku/php" },
{ "url": "https://github.com/heroku/heroku-buildpack-google-chrome" }
],
"scripts": {
"test-setup": "cp .env.testing .env",
"test": "nohup bash -c './vendor/laravel/dusk/bin/chromedriver-linux > /dev/null 2>&1 &' && nohup bash -c 'php artisan serve --no-reload > /dev/null 2>&1 &' && php artisan dusk"
}
}
}
}
Travis CI
あなたの Dusk tests を Travis CI で実行するためには、以下の .travis.yml
の設定を使用します。Travis CI はグラフィカルな 環境 ではないため、 Chrome ブラウザを起動するためにはいくつかの追加の手順が必要になります。また、PHP の組み込み web サーバを起動するために php artisan serve
を使用します。
language: php
php:
- 7.3
addons:
chrome: stable
install:
- cp .env.testing .env
- travis_retry composer install --no-interaction --prefer-dist
- php artisan key:generate
- php artisan dusk:chrome-driver
before_script:
- google-chrome-stable --headless --disable-gpu --remote-debugging-port=9222 http://localhost &
- php artisan serve --no-reload &
script:
- php artisan dusk
GitHub アクション
もし、Dusk テストを実行するためにGitHub Actions を使用している場合、次の設定ファイルを出発点として使用することができます。TravisCI のように、私たちは php artisan serve
command を使用して PHP の組み込みの web サーバーを起動します:
name: CI
on: [push]
jobs:
dusk-php:
runs-on: ubuntu-latest
env:
APP_URL: "http://127.0.0.1:8000"
DB_USERNAME: root
DB_PASSWORD: root
MAIL_MAILER: log
steps:
- uses: actions/checkout@v4
- name: Prepare The Environment
run: cp .env.example .env
- name: Create Database
run: |
sudo systemctl start mysql
mysql --user="root" --password="root" -e "CREATE DATABASE \`my-database\` character set UTF8mb4 collate utf8mb4_bin;"
- name: Install Composer Dependencies
run: composer install --no-progress --prefer-dist --optimize-autoloader
- name: Generate Application Key
run: php artisan key:generate
- name: Upgrade Chrome Driver
run: php artisan dusk:chrome-driver --detect
- name: Start Chrome Driver
run: ./vendor/laravel/dusk/bin/chromedriver-linux &
- name: Run Laravel Server
run: php artisan serve --no-reload &
- name: Run Dusk Tests
run: php artisan dusk
- name: Upload Screenshots
if: failure()
uses: actions/upload-artifact@v2
with:
name: screenshots
path: tests/Browser/screenshots
- name: Upload Console Logs
if: failure()
uses: actions/upload-artifact@v2
with:
name: console
path: tests/Browser/console
Chipper CI
あなたがChipper CI を使って Dusk テストを実行している場合、以下の設定ファイルを出発点として利用できます。 Laravel を実行するために PHP の組み込みサーバを使用し、リクエストを待ち受けることができます。
# file .chipperci.yml
version: 1
environment:
php: 8.2
node: 16
# Include Chrome in the build environment
services:
- dusk
# Build all commits
on:
push:
branches: .*
pipeline:
- name: Setup
cmd: |
cp -v .env.example .env
composer install --no-interaction --prefer-dist --optimize-autoloader
php artisan key:generate
# Create a dusk env file, ensuring APP_URL uses BUILD_HOST
cp -v .env .env.dusk.ci
sed -i "s@APP_URL=.*@APP_URL=http://$BUILD_HOST:8000@g" .env.dusk.ci
- name: Compile Assets
cmd: |
npm ci --no-audit
npm run build
- name: Browser Tests
cmd: |
php -S [::0]:8000 -t public 2>server.log &
sleep 2
php artisan dusk:chrome-driver $CHROME_DRIVER
php artisan dusk --env=ci
詳しくは、Chipper CI での Dusk テストの実行方法、データベースの使用方法などについては、公式 Chipper CI ドキュメンテーション をご参照ください。