Тесты для браузера

Содержание:


Введение

Ларавел Dusk предлагает выразительное, легкое для использования автоматизация браузера и API тестирования. По умолчанию, Dusk не требует установки JDK или Selenium на вашу машину. Вместо этого, Dusk использует отдельный компонент ChromeDriver. Вы можете использовать любой другой совместивый с Selenium драйвер по вашему желанию.


Установка

Для начала, вам необходимо добавить зависимость Composer laravel/dusk в ваш проект:

composer require --dev laravel/dusk
При регистрирации сервис провайдер Dusk вручную вам никогда не нужно добавлять его в окружение продакшен-сервера, так как это может привести к тому, что случайные пользователи смогут пройти аутентификацию для вашего приложение.

После установки компонента Dusk, выполните команду Artisan dusk:install:

php artisan dusk:install

Директория Browser будет создана внутри вашей директории tests и будет содержать пример теста. Следующим шагом необходимо установить переменную окружения APP_URL в вашем файле .env. Это значение должно соотвествовать URL вашего приложения в браузере.

Для запуска ваших тестов, используйте команду Artisan dusk. Команда dusk принимает любые аргументы, которые принимаются командой phpunit:

php artisan dusk

Если у вас были неудачи теста при последнем исопльзовании команды dusk, вы можете сэкономить время путём перезапуска проваленных тестов заново используя команду dusk:fails:

php artisan dusk:fails

Управление установкой ChromeDriver

Если вы хотите установить версию ChromeDriver, котороя отличает от включённой с Laravel Dusk, вы можете использовать команду dusk:chrome-driver:

# 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 74

# Install a given version of ChromeDriver for all supported OSs...
php artisan dusk:chrome-driver --all
Dusk требует, чтобы двоичный код chromedriver был выполним. Если у вас есть проблемы при запуске Dusk, вам необходимо убедиться, что бинарный код выполним используя команду chmod -R 0755 vendor/laravel/dusk/bin/.

Использование других браузеров

По умолчанию, Dusk использует Google Chrome и отдельную установку ChromeDriver для выполнения тестов браузера. Однако, вы можете запустить ваш собвтвенный сервер Selenium и проводить ваши тесты для любого браузера.

Для начала, откройте ваш файл tests/DuskTestCase.php, который является базовым тестовым случаем Dusk для вашего приложения. Внутри файла вы можете убрать вызов метод startChromeDriver. Это приведет к тому, что Ларавел перестанет автоматически запускать драйвер ChromeDriver:

/**
 * Prepare for Dusk test execution.
 *
 * @beforeClass
 * @return void
 */
public static function prepare()
{
    // static::startChromeDriver();
}

Следующим шагом вы можете вносить изменения в метод driver, чтобы подсоединиться к URL и порту по вашему выбору. Дополнительно вы можете модифицировать "желаемые возможности", которые должны передаваться в драйвер:

/**
 * Create the RemoteWebDriver instance.
 *
 * @return \Facebook\WebDriver\Remote\RemoteWebDriver
 */
protected function driver()
{
    return RemoteWebDriver::create(
        'http://localhost:4444/wd/hub', DesiredCapabilities::phantomjs()
    );
}

Начало

Генерация тестов

Для генерации Dusk теста используйте команду Artisan dusk:make. Сгенерированный тест будет размещён в директории tests/Browser:

php artisan dusk:make LoginTest

Запуск тестов

Для запуска ваших тестов браузера используйте команду Artisan dusk:

php artisan dusk

Если у вас были неудачи тестов при выполнении команды dusk, можно сэкономить время путём перезапуска проваленных тестов используя команду dusk:fails:

php artisan dusk:fails

dusk принимает любые аргументы, которые обычно принимаются исполнителем тестов PHPUnit, что позволяет вам только выполнять тесты для данной группы:

php artisan dusk --group=foo

Запуск ChromeDriver вручную

По умолчанию, Dusk будет автоматически пытаться запустить ChromeDriver. Если это не работает в конкретно вашем случае, вы можете запустить драйвер ChromeDriver до выполнения команды dusk. Если вы выбрали запуск вручную, вам необходимо закомментировать следующую линию для вашего файла tests/DuskTestCase.php file:

/**
 * Prepare for Dusk test execution.
 *
 * @beforeClass
 * @return void
 */
public static function prepare()
{
    // static::startChromeDriver();
}

Дополнительно, если вы запустили ChromeDriver через порт отличный от 9515, необходимо внести изменения в метод driver для класса с таким же названием:

/**
 * Create the RemoteWebDriver instance.
 *
 * @return \Facebook\WebDriver\Remote\RemoteWebDriver
 */
protected function driver()
{
    return RemoteWebDriver::create(
        'http://localhost:9515', DesiredCapabilities::chrome()
    );
}

Настройка окружения

Чтобы заставить Dusk использовать собственное окружение при выполнении тестов, создайте файл .env.dusk.{environment} в корневой директории вашего проекта. Например, если вы запустите команду dusk из вашего local окружения, вам необходимо создать файл .env.dusk.local.

При выполнении тестов, Dusk сделает копию файла .env, а файл окружения Dusk будет переименован в .env. После выполнения тестов исходный файл .env будет восстановлен.

Создание браузеров

Для начала, давайте напишем тест, который проводит верификацию того, что мы можем войти в наше приложение. После генерации теста, мы можем изменить его и перенести страницу входа, ввести необходимые данные и нажать кнопку "войти". Для создания экземпляра браузера, вызовите метод browse:

<?php

namespace Tests\Browser;

use App\User;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Laravel\Dusk\Chrome;
use Tests\DuskTestCase;

class ExampleTest extends DuskTestCase
{
    use DatabaseMigrations;

    /**
     * A basic browser test example.
     *
     * @return void
     */
    public function testBasicExample()
    {
        $user = factory(User::class)->create([
            'email' => 'taylor@laravel.com',
        ]);

        $this->browse(function ($browser) use ($user) {
            $browser->visit('/login')
                    ->type('email', $user->email)
                    ->type('password', 'password')
                    ->press('Login')
                    ->assertPathIs('/home');
        });
    }
}

Как можно увидеть в примере выше, метод browse принимает обратную связь. Экземпляр браузера будет автоматически передан в обратную связь и является основным объектом для взаимодействия с приложением и выполнения утверждений.

Создание нескольких браузеров

Иногда может возникнуть ситуация, когда нужно использовать несколько браузеров для корректного проведения тестов. Например, несколько бразуеров могет понадобиться для тестирования чата, который взаимодействует с сокетами. Для создания нескольких браузеров в подписи для метода browse необходимо "запросить" требуемое количество:

$this->browse(function ($first, $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');
});

Изменение размера окна браузера

Вы можете использовать метод resize, чтобы утвердить размер окна браузера:

$browser->resize(1920, 1080);

Метод maximize может быть использован, чтобы максимизировать размеры окна браузера.

$browser->maximize();

Макросы браузера

Если вы хотите определить пользовательский метод браузера, который можно было бы использовать для ваших различных тестов, вы можете использовать метод macro для класса Browser. Обычно, вам необходимо вызвать этот мето из метода boot вашего сервис провайдера:

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Laravel\Dusk\Browser;

class DuskServiceProvider extends ServiceProvider
{
    /**
     * Register the Dusk's browser macros.
     *
     * @return void
     */
    public function boot()
    {
        Browser::macro('scrollToElement', function ($element = null) {
            $this->script("$('html, body').animate({ scrollTop: $('$element').offset().top }, 0);");

            return $this;
        });
    }
}

Функция macro принимает имя в качестве первого аргумента, и Замыкание в качестве второго. Макрос будет выполняться при обращении по имени в качестве метода для реализации Browser:

$this->browse(function ($browser) use ($user) {
    $browser->visit('/pay')
            ->scrollToElement('#credit-card-details')
            ->assertSee('Enter Credit Card Details');
});

Аутинтификация

Часто вам будет необходимо тестировать страницы, которые требуют аутентификации. Вы можете использовать метод Dusk loginAs, чтобы избежать взаимодействия с экраном входа для каждого теста. Метод loginAs принимает ID пользователя или экземпляр модели:

$this->browse(function ($first, $second) {
    $first->loginAs(User::find(1))
          ->visit('/home');
});
После использования метода loginAs, сессия пользователя будет поддерживаться для всех файлов внутри файла.

Миграции базы данных

Когда ваши тесты требуют миграций, как в примере аутентификации выше, вам никогда не стоит использовать трейт RefreshDatabase. Трейт RefreshDatabase использует транзации базы данных, которые будут неприменимы для HTTP запросов. Вместо этого, используйте трейт DatabaseMigrations:

<?php

namespace Tests\Browser;

use App\User;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Laravel\Dusk\Chrome;
use Tests\DuskTestCase;

class ExampleTest extends DuskTestCase
{
    use DatabaseMigrations;
}

Взаимодействие с элементами

Селекторы Dusk

Выбор хороших CSS селекторов для взаимодействия с элементамя — это одна и сложнейших задач написания тестов Dusk. Проходит время, меняются подходы и это может привести к тому, что следующие тесты перестанут работать:

// HTML...

<button>Login</button>

// Test...

$browser->click('.login-page .container div > button');

Селекторы Dusk позволяют вам сфокусироваться на написании эффективных тестов, а не попытках запомнить селекторы CSS. Для определения селектора, добавьте атрибут dusk в ваш HTML элемент. После, добавьте @, чтобы манипулировать добавленным элементов внутри теста Dusk:

// HTML...

<button dusk="login-button">Login</button>

// Test...

$browser->click('@login-button');

Чтобы кликнуть на ссылку, вы можете использовать метод clickLink для экземпляра браузера. Метод clickLink кликнет по ссылке, у которой указанный текст:

$browser->clickLink($linkText);
Этот метод взаимодействую с jQuery. Если jQuery не доступно на странице, Dusk автоматически внедрит данную библиотеку на страницу так, чтобы они была доступна во время теста.

Текст, значение, атрибуты

Получение и присвоение значений.

Dusk предлагает несколько методов для взаимодействия с текущим тестом, значением, атрибутами элементов на странице. Например, чтобы получить значение элемента с данным селектором, используйте метод value:

// Retrieve the value...
$value = $browser->value('selector');

// Set the value...
$browser->value('selector', 'value');

Получение текста

Метод text может быть использован для получения текста элемента для данного селектора:

$text = $browser->text('selector');

Получение атрибутов

Наконец, метод attribute может быть использован для получения атрибута элемента, который соотвествует данному селектору:

$attribute = $browser->attribute('selector', 'value');

Использование форм

Вписывание значений

Dusk предоставляет набор методов ддя взаимодействия с формами и элементами ввода. Первое, давайте взглянем на пример вписывания текста в форму:

$browser->type('email', 'taylor@laravel.com');

Нужно заметить, что на не обязательно передавать селектор CSS в метод type. Если селектор не указан, Dusk будет искать поле ввода для атрибута name. Наконец, Dusk будет пытаться найти textarea с данным атрибутом name.

Чтобы дополнить текст в поле ввода без очистки текущего контента, вы можете использовать метод append:

$browser->type('tags', 'foo')
        ->append('tags', ', bar, baz');

Вы можете очистить значение ввода используя метод clear:

$browser->clear('email');

Выпадающие списки

Чтобы выбрать значение из выпадающего списка, вы можете использовать метод select. Как и в случае с методом type не требует полного указания селектора. При передаче значения в метод select, вам необходимо передать значение опции, а не отображаемый текст:

$browser->select('size', 'Large');

Вы можете выбрать случайное значение просто пропустив второй параметр:

$browser->select('size');

Чекбоксов

Чтобы "отметить" поле чекбокса, вы можете использовать метод check. Как и для других методов, полный селектор CSS не требуется. Если нет точного соответствия, Dusk будет искать чекбокс с таким атрибутом name:

$browser->check('terms');

$browser->uncheck('terms');

Радиокнопки

Чтобы выделить радиокнопки, вы можете использовать метод radio. Как и для других методов работы с вводными данные, не требуется указывать полный CSS селектор не требуется. Если точного соответсвия не удается найти, Dusk будет искать радиокнопку и атрибутами name и value:

$browser->radio('version', 'php7');

Вложение файлов

Метод attach может быть использован, чтобы прикрепить файл к элементу ввода file. Как и для других методов работы с вводом, указание полного селектора CSS не требуется. Если точное соотвествие не удаётся найти, Dusk будет искать загрузчик файла соотвествующий атрибуту name:

$browser->attach('photo', __DIR__.'/photos/me.png');
Функция прикрепления требует установленного и доступного на сервере расширения PHP Zip.

Использование клавиатуры

Метод keys предоставляет расширенные возможности по сравнению с методом type. Например, вы можете зажимать кнопки "модификаторы" при вводе данных. В этом примере, кнопка shift будет зажата во время набора taylor. После того как слово taylor было напечатано, слово otwell будет написано без всяких модификаторов:

$browser->keys('selector', ['{shift}', 'taylor'], 'otwell');

Вы даже можете отправить "горячие клавиши" на основной селектор CSS, который и содержит ваше приложение:

$browser->keys('.app', ['{command}', 'j']);
Все ключи модификаторов обёрнуты символами {}, и соответствуют определенным константам в классе Facebook\WebDriver\WebDriverKeys, что можно найти на GitHub.

Использование мыши

Кликать на элементы

Метод click может быть использован для элемента, который соответствует данному селектору:

$browser->click('.selector');

Наведение курсора Мыши

Метод mouseover может быть использован, когда вам необходимо навести мышь на определённый элемент, который соотвествует данному селектору:

$browser->mouseover('.selector');

Перетаскивание элементов

Метод drag может быть использован, чтобы перетащить элемент соответсвующий данному селектору к другому элементу:

$browser->drag('.from-selector', '.to-selector');

Или можно перетаскивать элемент в определённом направлении:

$browser->dragLeft('.selector', 10);
$browser->dragRight('.selector', 10);
$browser->dragUp('.selector', 10);
$browser->dragDown('.selector', 10);

Диалоги JavaScript

Dusk предоставляет набор методов на взаимодействия с диалогами JavaScript:

// Wait for a dialog to appear:
$browser->waitForDialog($seconds = null);

// Assert that a dialog has been displayed and that its message matches the given value:
$browser->assertDialogOpened('value');

// Type the given value in an open JavaScript prompt dialog:
$browser->typeInDialog('Hello World');

Используйте следующий подход, чтобы закрыть открытый диалог JavaScript, нажав на кнопку "OK":

$browser->acceptDialog();

Чтобы закрыть диалог JavaScript путём нажатия кнопки "Отмена" (только для диалога-потверждения):

$browser->dismissDialog();

Селекторы областей действия

Иногда вы можете захотеть выполнить несколько операций одновременно в рамках данного селектора. Например, вы хотите утверждать, что текст существует только внутри таблицы и далее кликнуть на кнопку внутри этой таблицы. Вы можете использовать метод with для реализации задуманного. Все операции внутри метода with будут ограничены выбранным селектором:

$browser->with('.table', function ($table) {
    $table->assertSee('Hello World')
          ->clickLink('Delete');
});

Ожидание элементов

При тестировании приложений, которые используют активно используют JavaScript, часто может потребоваться ждать пока определённые элементы или данные будут доступны до момента проведения теста. Dusk позволяет легко и просто реализовать задуманное. Используя набор методов вы сможете ждать момента, когда элементы будут видимы на странице или даже до момента, когда данное JavaScript выражение станет true.

Ожидание

Если вам необходимо приостановить тест на определённое количество милисекунд, используйте метод pause:

$browser->pause(1000);

Ожидание селекторв

Метод waitFor может быть использован для того, чтобы остановить выполнение теста до тех пор, пока соответсвующий данному CSS элемент не будет показан на странице. По умолчанию, можно остановить тест на время до 5 секунд до момента получения исключения. При необходимости, вы можете передать пользовательское время таймаута в качестве второго аргумента в метод:

// 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);

Вы можете также ждать момента, когда данный селектор пропадёт со страницы:

$browser->waitUntilMissing('.selector');

$browser->waitUntilMissing('.selector', 1);

Группа селекторов при доступности

Может так случится, что вам необходимо дождаться данного селектора и уже после взаимодействовать с соответсвующим селектору элементом. Например, вы можете дождаться пока модальное окно станет доступным и после нажать кнопку "OK" внутри окна. Метод whenAvailable может быть использован в этом случае. Все операции элемента проводимые внутри будут будут привязаны к оригинальному селектору:

$browser->whenAvailable('.modal', function ($modal) {
    $modal->assertSee('Hello World')
          ->press('OK');
});

Ождание текста

Метод waitForText может быть использован, чтобы дождаться пока данный текст не появится на странице:

// 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);

Ожидание ссылок

Метод waitForLink может быть использован, чтобы дождаться пока данный текст-ссылка не появится на странцие:

// 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);

Ожидание на странице

Создание утрвеждений маршрута, таких как $browser->assertPathIs('/home'), может закончится неудачей, если window.location.pathname обновлялось асинхронно. Вы можете использовать метод waitForLocation, чтобы дождаться, пока местоположение будет иметь заданное значение:

$browser->waitForLocation('/secret');

Вы также можете ожидать названный маршрут локации:

$browser->waitForRoute($routeName, $parameters);

Ожидание перезагрузок страницы

Если вам необходимо сделать утверждения после перезагрузки страницы, используйте метод waitForReload:

$browser->click('.some-action')
        ->waitForReload()
        ->assertSee('something');

Ожидание выражений JavaScript

Иногда вам может понадобиться остановить выполнение теста до момента, пока какое-либо выражение не примет значение true. Вы можете легко так сделать используя метод waitUntil. При передаче выражение в этот метод, у вас нет необходимости включать слово return или точку с запятой в конце:

// Wait a maximum of five seconds for the expression to be true...
$browser->waitUntil('App.dataLoaded');

$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

Следующие методы могут быть использованы, чтобы дождаться, когда атрибут компонента Vue получат данное значение:

// 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');

Ожидание с обратной связью

Многие методы "ожидания" в Dusk опираются на метод waitUsing. Вы можете использовать данный метод напрямую, чтобы ждать обратной связи и вернуть true. Метод waitUsing принимает число секунд для ожидания, интервал оценки замыкания, само Замыкание и сообщение необязательное сообщение неудачи:

$browser->waitUsing(10, 1, function () use ($something) {
    return $something->isReady();
}, "Something wasn't ready in time.");

Сделать утверждение Vue

Dusk даже позволяет вам делать утверждения для данных компонента Vue. Например, представим, что ваше приложение содержит следующий компанент Vue:

// HTML...

<profile dusk="profile-component"></profile>

// Component Definition...

Vue.component('profile', {
    template: '<div>{{ user.name }}</div>',

    data: function () {
        return {
            user: {
              name: 'Taylor'
            }
        };
    }
});

Вы можете делать утверждения для компонента Vue следующим образом:

/**
 * A basic Vue test example.
 *
 * @return void
 */
public function testVue()
{
    $this->browse(function (Browser $browser) {
        $browser->visit('/')
                ->assertVue('user.name', 'Taylor', '@profile-component');
    });
}

Доступные утверждения

Dusk предоставялет набор утверждений, которые вы можете делать для вашего приложения. Ниже представлены доступные утверждение и их описание:

assertTitle

Утверждает, что заголовок страницы сотвествует данному тексту:

$browser->assertTitle($title);

assertTitleContains

Утверждает, что заголовок содержит данный текст:

$browser->assertTitleContains($title);

assertUrlIs

Утверждает, что данный URL (без строки запросов) соотвествует данной строке:

$browser->assertUrlIs($url);

assertSchemeIs

Утверждает, что текущая схема URL соответсвует данной схеме:

$browser->assertSchemeIs($scheme);

assertSchemeIsNot

Утверждает, что текущая схема URL не соотвествует данной схеме:

$browser->assertSchemeIsNot($scheme);

assertHostIs

Утверждает, что текущий URL-адрес хоста соответствует данному хосту:

$browser->assertHostIs($host);

assertHostIsNot

Утверждает, что текущий URL-адрес хоста не соответствует данному хосту:

$browser->assertHostIsNot($host);

assertPortIs

Утверждает, что текущий порт URL соотвествует данному порту:

$browser->assertPortIs($port);

assertPortIsNot

Утверждает, что текущнй порт URL не соотвествует данному порту:

$browser->assertPortIsNot($port);

assertPathBeginsWith

Утверждает, что текущий URL путь начинается с данного пути:

$browser->assertPathBeginsWith($path);

assertPathIs

Утверждает, что текущий маршрут соотвествует данному маршруту:

$browser->assertPathIs('/home');

assertPathIsNot

Утверждает, что текущий путь не соотвествует данному пути:

$browser->assertPathIsNot('/home');

assertRouteIs

Утверждает, что текущий URL соответствует данному имени маршрута URL:

$browser->assertRouteIs($name, $parameters);

assertQueryStringHas

Утверждает, что данные параметры запроса присутсвуют:

$browser->assertQueryStringHas($name);

Утверждает, что данный параметр запроса присуствует и имеет следующее значение:

$browser->assertQueryStringHas($name, $value);

assertQueryStringMissing

Утверждает, что данный параметр запроса отсутсвует:

$browser->assertQueryStringMissing($name);

assertFragmentIs

Утверждает, что текущний фрагмент соответсвует данному фрагменту:

$browser->assertFragmentIs('anchor');

assertFragmentBeginsWith

Утверждает, что текущий фрагмент начинается с данного фрагмента:

$browser->assertFragmentBeginsWith('anchor');

assertFragmentIsNot

Утверждает, что текущий фрагмент не соотвествует данному фрагменту:

$browser->assertFragmentIsNot('anchor');

assertHasCookie

Утверждает, что данные куки присутсвуют:

$browser->assertHasCookie($name);

assertCookieMissing

Утверждает, что данные куки не присутсвуют:

$browser->assertCookieMissing($name);

assertCookieValue

Утверждает, что у куки следующее значение:

$browser->assertCookieValue($name, $value);

assertPlainCookieValue

Утверждает, что незашифрованные куки имеют следующее значение:

$browser->assertPlainCookieValue($name, $value);

assertSee

Утверждает, что данный текст присутсвует на странице:

$browser->assertSee($text);

assertDontSee

Утверждает, что данный текст не присутсвует на странице:

$browser->assertDontSee($text);

assertSeeIn

Утверждает, что данный текст присуствует внутри селектора:

$browser->assertSeeIn($selector, $text);

assertDontSeeIn

Утверждает, что данный текст не присуствует внутри селектора:

$browser->assertDontSeeIn($selector, $text);

assertSourceHas

Утверждает, что данный код присуствует на странице:

$browser->assertSourceHas($code);

assertSourceMissing

Утверждает, что данный код не присутвует на странице:

$browser->assertSourceMissing($code);

assertSeeLink

Утверждает, что данная ссылка присутсвует на странице:

$browser->assertSeeLink($linkText);

assertDontSeeLink

Утверждает, что данная ссылка не присуствует на странице:

$browser->assertDontSeeLink($linkText);

assertInputValue

Утверждает, что данное поле ввода содержит следующий текст:

$browser->assertInputValue($field, $value);

assertInputValueIsNot

Утверждает, что данное поле ввода не имеет следующего значения:

$browser->assertInputValueIsNot($field, $value);

assertChecked

Утверждает, что данный чекбокс выбран:

$browser->assertChecked($field);

assertNotChecked

Утверждает, что данный чекбокс не выбран:

$browser->assertNotChecked($field);

assertRadioSelected

Утверждает, что данная радио-кнопка выбрана:

$browser->assertRadioSelected($field, $value);

assertRadioNotSelected

Утверждает, что данная радио-кнопка не выбрана:

$browser->assertRadioNotSelected($field, $value);

assertSelected

Утверждает, что у данного выпадающего списка выбрано следующее значение:

$browser->assertSelected($field, $value);

assertNotSelected

Утверждает, что у данного выпадающего списка не выбрано следующее значение:

$browser->assertNotSelected($field, $value);

assertSelectHasOptions

Утверждает, что данный массив значений доступен для выбора:

$browser->assertSelectHasOptions($field, $values);

assertSelectMissingOptions

Утверждает, что данный массив значение не доступен для выбора:

$browser->assertSelectMissingOptions($field, $values);

assertSelectHasOption

Утверждает, что данное значение доступно для выбора для данного поля:

$browser->assertSelectHasOption($field, $value);

assertValue

Утверждает, что элемент соответвующий данному селектору имеет следующее значение:

$browser->assertValue($selector, $value);

assertVisible

Утверждает, что элемент соотвествующий данному селектору виден.

$browser->assertVisible($selector);

assertPresent

Утверждает, что элемент соответсвующий данному селектору присутсвует:

$browser->assertPresent($selector);

assertMissing

Утверждает, что элемент соответсвующий данному селектору не виден:

$browser->assertMissing($selector);

assertDialogOpened

Утверждает, что диалоговое окно JavaScript с данным сообщение открыто:

$browser->assertDialogOpened($message);

assertEnabled

Утверждает, что данное поле включено:

$browser->assertEnabled($field);

assertDisabled

Утверждает, что данное поле выключено:

$browser->assertDisabled($field);

assertButtonEnabled

Утверждает, что данная кнопка включена:

$browser->assertButtonEnabled($button);

assertButtonDisabled

Утверждает, что данная кнопка выключена:

$browser->assertButtonDisabled($button);

assertFocused

Утверждает, что данное поле выбрано в фокус:

$browser->assertFocused($field);

assertNotFocused

Утверждает, что данное поле не выбрано в фокус:

$browser->assertNotFocused($field);

assertVue

Утверждает, что данные компнента Vue соответствуют данному значению:

$browser->assertVue($property, $value, $componentSelector = null);

assertVueIsNot

Утверждает, что указаныне данные свойства компонента Vue не соответсвуют данному значению:

$browser->assertVueIsNot($property, $value, $componentSelector = null);

assertVueContains

Утверждает, что данные свойства компонента Vue являются массивом и содержат данное значение:

$browser->assertVueContains($property, $value, $componentSelector = null);

assertVueDoesNotContain

Утверждает, что данные свойства компонента Vue являются массивом и не содержат данное значение:

$browser->assertVueDoesNotContain($property, $value, $componentSelector = null);

Страницы

Иногда, тесты требуют последовательного выполнения нескольких сложных действий. Такие моменты могут усложнить понимание и чтение ваших тестов. Страницы позволяют вам определить действия, которые после будут представлены на данной странице используя один метод. Страницы также позволяют вам определить короткий путь к общим селекторам для вашего приложения или страницы.

Генерация страниц

Для генерации объекта страницы, используйте команду Artisan dusk:page. Все объекты страниц будут размещены в директории tests/Browser/Pages:

php artisan dusk:page Login

Конфигурация страниц

По умолчанию, у страниц есть 3 метода: url, assert и elements. Давайте обсудим методы url и assert сейчас. Метод elements мы рассмотрим более подробно ниже.

Метод url

Метод url должен вернуть маршрут от URL, который представляет данную страницу. Dusk будет использовать этот URL при навигации на эту страницу в браузере:

/**
 * Get the URL for the page.
 *
 * @return string
 */
public function url()
{
    return '/login';
}

Метод assert

Метод assert может сделать любое утверждение, необходимое для верификации того, что браузер находится на данной странице. Заполнять этот метод необязательно; однако вы легко можете сделать такие утверждения по желанию. Эти утверждения будут выполняться автоматически при навигации на эту страницу:

/**
 * Assert that the browser is on the page.
 *
 * @return void
 */
public function assert(Browser $browser)
{
    $browser->assertPathIs($this->url());
}

После настройки конфигурации страницы, вы можете пользоваться навигацией страниц используя метод visit:

use Tests\Browser\Pages\Login;

$browser->visit(new Login);

Иногда вы можете уже быть на странице и вам лишь необходимо "загрузить" селекторы страниц и методы в текущий контекст теста. Это частая ситуация при перенаправлении на эту же страницу после нажатия кнопки без точного указания адреса навигации. В этом случае вы можете использовать метод on для загрузки страницы:

use Tests\Browser\Pages\CreatePlaylist;

$browser->visit('/dashboard')
        ->clickLink('Create Playlist')
        ->on(new CreatePlaylist)
        ->assertSee('@create');

Сокращенные селекторы

Метод elements в контексте использования страниц позволяет вам быстрый, простой для запоминания ярлык для любого CSS селектора на вашей странице. Например, давайте определим ярлык для поля ввода "email" для страницы входа вашего приложения:

/**
 * Get the element shortcuts for the page.
 *
 * @return array
 */
public function elements()
{
    return [
        '@email' => 'input[name=email]',
    ];
}

Теперь вы можете использовать этот сокращенный селектор в любом месте, где бы вы обыкновенно хотели использовать полный CSS селектор:

$browser->type('@email', 'taylor@laravel.com');

Глобальные ярлыки селекторов.

После установки Dusk, базовый класс Page будет размещен в директории tests/Browser/Pages. Этот класс содержит метод siteElements, который может быть использован для определения глобальных ярклыков селекторов, которые должны быть доступны для каждой страницы вашего приложения:

/**
 * Get the global element shortcuts for the site.
 *
 * @return array
 */
public static function siteElements()
{
    return [
        '@element' => '#selector',
    ];
}

Страничные методы

Дополнительно к базовым методам определённых на страницах, вы можете определить дополнительные методы, которые могут быть использованы для любых ваших тестов. Например, давайте представим ситуацию, когда необходимо построить приложение по управлению музыкой. Общим действием для страницы приложение может быть создание плейлиста. Вместо того, чтобы писать логику создания плейлиста в каждом тесте, вы можете определить метод createPlaylist в классе страниц:

<?php

namespace Tests\Browser\Pages;

use Laravel\Dusk\Browser;

class Dashboard extends Page
{
    // Other page methods...

    /**
     * Create a new playlist.
     *
     * @param  \Laravel\Dusk\Browser  $browser
     * @param  string  $name
     * @return void
     */
    public function createPlaylist(Browser $browser, $name)
    {
        $browser->type('name', $name)
                ->check('share')
                ->press('Create Playlist');
    }
}

После определения метода, вы можете использовать его внутри любого теста, который использует данную страницу. Экземпляр браузера будет автоматически передан в метод страницы:

use Tests\Browser\Pages\Dashboard;

$browser->visit(new Dashboard)
        ->createPlaylist('My Playlist')
        ->assertSee('My Playlist');

Компоненты

Компоненты похожи на "объекты страниц" Dusk, но предназначены для частей пользовательского интерфейса и функциональности, которую можно повторить для всего вашего приложения такие как навигация или окно уведомлений. Кроме того, компоненты не привязаны к определённым страницам.

Генерация компонентов

Чтобы сгенерировать компонент используйте команду Artisan dusk:component. Новые компоненты размещены в директории test/Browser/Components:

php artisan dusk:component DatePicker

Как показано выше, "выборщик даты" это пример компонента, который должен распростроняться на всё приложение и применяться для большого количества страниц. Это может быть очень обременительным писать вручную логику браузера для выбора даты для десятков тестов в наборе ваших тестов. Вместо этого мы можем определить компонент Dusk, который и будет представлять выборщика даты, что позволит избежать повторения, а всю логику поместить внутри компонента:

<?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.
     *
     * @return string
     */
    public function selector()
    {
        return '.date-picker';
    }

    /**
     * Assert that the browser page contains the component.
     *
     * @param  Browser  $browser
     * @return void
     */
    public function assert(Browser $browser)
    {
        $browser->assertVisible($this->selector());
    }

    /**
     * Get the element shortcuts for the component.
     *
     * @return array
     */
    public function elements()
    {
        return [
            '@date-field' => 'input.datepicker-input',
            '@month-list' => 'div > div.datepicker-months',
            '@day-list' => 'div > div.datepicker-days',
        ];
    }

    /**
     * Select the given date.
     *
     * @param  \Laravel\Dusk\Browser  $browser
     * @param  int  $month
     * @param  int  $day
     * @return void
     */
    public function selectDate($browser, $month, $day)
    {
        $browser->click('@date-field')
                ->within('@month-list', function ($browser) use ($month) {
                    $browser->click($month);
                })
                ->within('@day-list', function ($browser) use ($day) {
                    $browser->click($day);
                });
    }
}

Использование компонентов

После определения компонента, мы можем легко выбрать дату из любого теста. Если необходимо внести изменения в логику, то можно обновить компонент:

<?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.
     *
     * @return void
     */
    public function testBasicExample()
    {
        $this->browse(function (Browser $browser) {
            $browser->visit('/')
                    ->within(new DatePicker, function ($browser) {
                        $browser->selectDate(1, 2018);
                    })
                    ->assertSee('January');
        });
    }
}

Дальнейшая интеграция

CircleCI

Если вы используете CircleCI для выполнения ваших тестов Dusk, вы можете использовать этот файл конфигурации в качестве отправной точки. Как и для TravisCI, мы будем использовать команду php artisan serve для запуска встроенного веб-сервера PHP:

version: 2
jobs:
    build:
        steps:
            - run: sudo apt-get install -y libsqlite3-dev
            - run: cp .env.testing .env
            - run: composer install -n --ignore-platform-reqs
            - run: npm install
            - run: npm run production
            - run: vendor/bin/phpunit

            - run:
                name: Start Chrome Driver
                command: ./vendor/laravel/dusk/bin/chromedriver-linux
                background: true

            - run:
                name: Run Laravel Server
                command: php artisan serve
                background: true

            - run:
                name: Run Laravel Dusk Tests
                command: php artisan dusk

            - store_artifacts:
                path: tests/Browser/screenshots

Codeship

Для выполнения тестов Dusk Codeship, добавьте следующие в ваш проект Codeship. Эти команды являются отправной точкой и вы можете легко добавлять команды по вашему желанию:

phpenv local 7.2
cp .env.testing .env
mkdir -p ./bootstrap/cache
composer install --no-interaction --prefer-dist
php artisan key:generate
nohup bash -c "php artisan serve 2>&1 &" && sleep 5
php artisan dusk

Heroku CI

Для выполнения тестов Dusk на Heroku CI, добавьте следующие строки в ваш Heroku app.json файл в соотвествующие разделы (buildpack и scripts):

{
  "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 > /dev/null 2>&1 &' && php artisan dusk"
      }
    }
  }
}

Travis CI

Для выполнения ваших тестов Dusk на Travis CI, используйте следующий файл конфигурации .travis.yml. В силу того, что Travis CI не является графической средой, нам потребуется сделать некоторые шаги для запуска браузера Chrome. Дополнительно мы будем использовать команду php artisan serve для запуска встроенного веб-сервера PHP:

language: php

php:
  - 7.3

addons:
  chrome: stable

install:
  - cp .env.testing .env
  - travis_retry composer install --no-interaction --prefer-dist --no-suggest
  - php artisan key:generate

before_script:
  - google-chrome-stable --headless --disable-gpu --remote-debugging-port=9222 http://localhost &
  - php artisan serve &

script:
  - php artisan dusk

Действия GitHub

Если вы используете Github Actions для запуска ваших Dusk тестов, вы можете использовать эти файлы конфигурации как отправную точку. Как и для TravisCI, мы будем использовать команду php artisan serve для запуска встроенного веб-сервера PHP:

name: CI
on: [push]
jobs:

  dusk-php:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - name: Prepare The Environment
        run: cp .env.example .env
      - name: Install Composer Dependencies
        run: composer install --no-progress --no-suggest --prefer-dist --optimize-autoloader
      - name: Generate Application Key
        run: php artisan key:generate
      - name: Upgrade Chrome Driver
        run: php artisan dusk:chrome-driver
      - name: Start Chrome Driver
        run: ./vendor/laravel/dusk/bin/chromedriver-linux > /dev/null 2>&1 &
      - name: Run Laravel Server
        run: php artisan serve > /dev/null 2>&1 &
      - name: Run Dusk Tests
        run: php artisan dusk

В вашем файле .env.testing настройте значение APP_URL:

APP_URL=http://127.0.0.1:8000