Skip to content

Instantly share code, notes, and snippets.

@kbond
Last active March 16, 2023 11:44
Show Gist options
  • Save kbond/bf86368e46090fb2ffaec0e5cbe91ea8 to your computer and use it in GitHub Desktop.
Save kbond/bf86368e46090fb2ffaec0e5cbe91ea8 to your computer and use it in GitHub Desktop.
Laravel Dusk in a non-laravel (Symfony) app
<?php
namespace App\Tests\Browser;
use App\Tests\HasDuskBrowser;
class ExampleTest extends \PHPUnit_Framework_TestCase
{
use HasDuskBrowser;
public function testBasicExample()
{
$this->browse(function ($browser) use ($user) {
$browser->visit('/login')
->type('username', 'myusername')
->type('password', 'secret')
->press('Login')
->assertPathIs('/home');
});
}
}
<?php
namespace App\Tests;
use Facebook\WebDriver\Remote\DesiredCapabilities;
use Facebook\WebDriver\Remote\RemoteWebDriver;
use Illuminate\Support\Collection;
use Laravel\Dusk\Browser;
use Laravel\Dusk\SupportsChrome;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\Finder\Finder;
/**
* @see Laravel\Dusk\TestCase
*/
trait HasDuskBrowser
{
use SupportsChrome;
protected static $browsers = [];
protected static $afterClassCallbacks = [];
/**
* @beforeClass
*/
public static function setupDuskClass()
{
static::startChromeDriver();
}
/**
* @afterClass
*/
public static function teardownDuskClass()
{
Collection::make(static::$browsers)->each(function (Browser $browser) {
$browser->quit();
});
static::$browsers = collect();
foreach (static::$afterClassCallbacks as $callback) {
$callback();
}
}
public static function afterClass(\Closure $callback)
{
static::$afterClassCallbacks[] = $callback;
}
/**
* @before
*/
public function setupDuskTest()
{
Browser::$baseUrl = $_SERVER['DUSK_BASE_URL'];
Browser::$screenshotDir = realpath($_SERVER['DUSK_SCREENSHOT_DIR']);
$this->clearExistingScreenshots(Browser::$screenshotDir);
}
public function browse(\Closure $callback)
{
$browsers = $this->createBrowsersFor($callback);
try {
$callback(...$browsers->all());
} catch (\Exception $e) {
$this->captureFailuresFor($browsers);
throw $e;
} catch (\Throwable $e) {
$this->captureFailuresFor($browsers);
throw $e;
} finally {
static::$browsers = $this->closeAllButPrimary($browsers);
}
}
protected function createBrowsersFor(\Closure $callback)
{
if (count(static::$browsers) === 0) {
static::$browsers = collect([new Browser($this->createWebDriver())]);
}
$additional = $this->browsersNeededFor($callback) - 1;
for ($i = 0; $i < $additional; ++$i) {
static::$browsers->push(new Browser($this->createWebDriver()));
}
return static::$browsers;
}
protected function browsersNeededFor(\Closure $callback)
{
return (new \ReflectionFunction($callback))->getNumberOfParameters();
}
protected function closeAllButPrimary(Collection $browsers)
{
$browsers->slice(1)->each(function (Browser $browser) {
$browser->quit();
});
return $browsers->take(1);
}
protected function createWebDriver()
{
return RemoteWebDriver::create(
'http://localhost:9515', DesiredCapabilities::chrome()
);
}
protected function captureFailuresFor(Collection $browsers)
{
$browsers->each(function (Browser $browser, $key) {
$browser->screenshot(sprintf('%s-%s',
$this->getScreenshotPrefix(),
$key
));
});
}
protected function getScreenshotPrefix()
{
return sprintf('failure-%s-%s',
class_basename($this),
$this->getName()
);
}
protected function clearExistingScreenshots($dir)
{
$filesystem = new Filesystem();
if (!is_dir($dir)) {
$filesystem->mkdir($dir);
}
$files = Finder::create()
->files()
->in($dir)
->name($this->getScreenshotPrefix().'*')
;
$filesystem->remove($files);
}
}
<?xml version="1.0" encoding="UTF-8"?>
<phpunit>
<php>
<!-- ... -->
<server name="DUSK_SCREENSHOT_DIR" value="var/screenshots" />
<server name="DUSK_BASE_URL" value="http://127.0.0.1:8000" />
<!-- ... -->
</php>
<!-- ... -->
</phpunit>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment