breakign dusk tests

This commit is contained in:
Mark Gregory
2026-06-19 11:30:34 +01:00
parent 030b1f5eb0
commit 978b477de3
+115 -22
View File
@@ -12,16 +12,26 @@ abstract class DuskTestCase extends BaseTestCase
{
use CreatesApplication;
/**
* Keep the local Laravel server process alive for the Dusk run.
*
* @var resource|null
*/
private static $laravelServerProcess = null;
/**
* Prepare for Dusk test execution.
*/
#[BeforeClass]
public static function prepare(): void
{
static::configureDuskBaseUrl();
static::ensureLaravelServerIsReachable();
if (! static::runningInSail()) {
static::ensureChromeDriverBinaryAlias();
static::startChromeDriver(['--port=9515']);
static::waitForChromeDriver();
static::waitForTcpPort('127.0.0.1', 9515, 8.0, 'ChromeDriver');
}
}
@@ -39,10 +49,11 @@ abstract class DuskTestCase extends BaseTestCase
'--disable-search-engine-choice-screen',
'--ignore-certificate-errors',
'--allow-insecure-localhost',
'--disable-features=Translate,BackForwardCache,AcceptCHFrame',
]);
return RemoteWebDriver::create(
$_ENV['DUSK_DRIVER_URL'] ?? 'http://localhost:9515',
$_ENV['DUSK_DRIVER_URL'] ?? 'http://127.0.0.1:9515',
DesiredCapabilities::chrome()->setCapability(
ChromeOptions::CAPABILITY,
$options
@@ -50,6 +61,108 @@ abstract class DuskTestCase extends BaseTestCase
);
}
private static function configureDuskBaseUrl(): void
{
$url = rtrim((string) ($_ENV['DUSK_APP_URL'] ?? getenv('DUSK_APP_URL') ?: 'http://127.0.0.1:8000'), '/');
$_ENV['APP_URL'] = $url;
$_SERVER['APP_URL'] = $url;
putenv('APP_URL='.$url);
if (property_exists(BaseTestCase::class, 'baseUrl')) {
static::$baseUrl = $url;
}
}
private static function ensureLaravelServerIsReachable(): void
{
$url = rtrim((string) ($_ENV['APP_URL'] ?? 'http://127.0.0.1:8000'), '/');
$parts = parse_url($url);
$scheme = $parts['scheme'] ?? 'http';
$host = $parts['host'] ?? '127.0.0.1';
$port = (int) ($parts['port'] ?? ($scheme === 'https' ? 443 : 80));
if (static::canConnect($host, $port)) {
return;
}
// Dusk should be deterministic in local/CI runs. If no reachable app
// server is already running, start Laravel's built-in server for the
// browser suite instead of failing every test with ERR_CONNECTION_REFUSED.
if (! in_array($host, ['127.0.0.1', 'localhost'], true)) {
$fallbackUrl = 'http://127.0.0.1:8000';
$_ENV['APP_URL'] = $fallbackUrl;
$_SERVER['APP_URL'] = $fallbackUrl;
putenv('APP_URL='.$fallbackUrl);
if (property_exists(BaseTestCase::class, 'baseUrl')) {
static::$baseUrl = $fallbackUrl;
}
$host = '127.0.0.1';
$port = 8000;
}
if (static::canConnect($host, $port)) {
return;
}
static::startLaravelServer($host, $port);
static::waitForTcpPort($host, $port, 15.0, 'Laravel Dusk application server');
}
private static function startLaravelServer(string $host, int $port): void
{
$root = dirname(__DIR__);
$logPath = $root.'/storage/logs/dusk-server.log';
if (! is_dir(dirname($logPath))) {
@mkdir(dirname($logPath), 0775, true);
}
$php = escapeshellarg(PHP_BINARY);
$artisan = escapeshellarg($root.'/artisan');
$hostArg = escapeshellarg($host);
$portArg = (string) $port;
$log = escapeshellarg($logPath);
$command = "{$php} {$artisan} serve --host={$hostArg} --port={$portArg} > {$log} 2>&1";
self::$laravelServerProcess = proc_open($command, [], $pipes, $root);
}
private static function canConnect(string $host, int $port): bool
{
$connection = @fsockopen($host, $port, $errno, $errstr, 0.25);
if (! is_resource($connection)) {
return false;
}
fclose($connection);
return true;
}
private static function waitForTcpPort(string $host, int $port, float $seconds, string $service): void
{
$deadline = microtime(true) + $seconds;
do {
if (static::canConnect($host, $port)) {
return;
}
usleep(100_000);
} while (microtime(true) < $deadline);
$log = dirname(__DIR__).'/storage/logs/dusk-server.log';
$hint = is_file($log) ? " Check {$log}." : '';
throw new \RuntimeException("{$service} is not reachable at {$host}:{$port}.{$hint}");
}
/**
* Dusk may install a differently named macOS Apple Silicon binary.
*
@@ -95,24 +208,4 @@ abstract class DuskTestCase extends BaseTestCase
@chmod($expected, 0755);
}
}
/**
* Wait until ChromeDriver is listening before the first browser session starts.
*/
private static function waitForChromeDriver(): void
{
$deadline = microtime(true) + 5.0;
do {
$connection = @fsockopen('127.0.0.1', 9515);
if (is_resource($connection)) {
fclose($connection);
return;
}
usleep(100_000);
} while (microtime(true) < $deadline);
}
}