From 82afe9758fa11bcf27455e5191d0afce04620581 Mon Sep 17 00:00:00 2001 From: Tinywan <756684177@qq.com> Date: Sun, 17 May 2026 10:12:03 +0800 Subject: [PATCH 1/3] feat: add support for external Playwright server URL Allow connecting to an already-running Playwright server instead of starting a local one. This enables setups where Playwright runs on the host machine while Pest runs inside a container (e.g. Docker). Usage via configuration: pest()->browser()->withPlaywrightServer('http://192.168.1.100:9999') Usage via environment variable: PEST_BROWSER_PLAYWRIGHT_URL=http://192.168.1.100:9999 Co-Authored-By: Claude Opus 4.7 --- src/Configuration.php | 11 +++++++++++ src/Playwright/Playwright.php | 22 ++++++++++++++++++++++ src/ServerManager.php | 9 +++++++++ 3 files changed, 42 insertions(+) diff --git a/src/Configuration.php b/src/Configuration.php index bf3c458f..5c4a13c7 100644 --- a/src/Configuration.php +++ b/src/Configuration.php @@ -105,6 +105,17 @@ public function withHost(?string $host): self return $this; } + /** + * Sets the URL of an already-running Playwright server (e.g. http://192.168.1.100:9999). + * When set, the plugin connects to this server instead of starting a local one. + */ + public function withPlaywrightServer(?string $serverUrl): self + { + Playwright::setPlaywrightServerUrl($serverUrl); + + return $this; + } + /** * Enables debug mode for assertions. */ diff --git a/src/Playwright/Playwright.php b/src/Playwright/Playwright.php index c0cffae1..cd878492 100644 --- a/src/Playwright/Playwright.php +++ b/src/Playwright/Playwright.php @@ -59,6 +59,12 @@ final class Playwright */ private static ?string $host = null; + /** + * The URL of an already-running Playwright server (e.g. http://192.168.1.100:9999). + * When set, the plugin connects to this server instead of starting a local one. + */ + private static ?string $playwrightServerUrl = null; + /** * Get a browser factory for the given browser type. */ @@ -155,6 +161,22 @@ public static function host(): ?string return self::$host; } + /** + * Set the URL of an external already-running Playwright server. + */ + public static function setPlaywrightServerUrl(?string $serverUrl): void + { + self::$playwrightServerUrl = $serverUrl; + } + + /** + * Get the URL of the external Playwright server, if set. + */ + public static function playwrightServerUrl(): ?string + { + return self::$playwrightServerUrl ?? getenv('PEST_BROWSER_PLAYWRIGHT_URL') ?: null; + } + /** * Get the default color scheme. */ diff --git a/src/ServerManager.php b/src/ServerManager.php index 4e406fd9..62e83607 100644 --- a/src/ServerManager.php +++ b/src/ServerManager.php @@ -55,6 +55,15 @@ public static function instance(): self */ public function playwright(): PlaywrightServer { + $serverUrl = Playwright::playwrightServerUrl(); + if ($serverUrl) { + $parts = parse_url($serverUrl); + $host = $parts['host']; + $port = $parts['port'] ?? 9999; + AlreadyStartedPlaywrightServer::persist($host, $port); + return $this->playwright ??= new AlreadyStartedPlaywrightServer($host, $port); + } + if (Parallel::isWorker()) { return AlreadyStartedPlaywrightServer::fromPersisted(); } From 4e0866eee09c4286a0fdb3667230db36c53c01bd Mon Sep 17 00:00:00 2001 From: Tinywan <756684177@qq.com> Date: Sun, 17 May 2026 10:19:14 +0800 Subject: [PATCH 2/3] fix: use class_exists check instead of function_exists for Laravel detection The `app_path()` function is also defined by webman and other frameworks, causing false Laravel detection which leads to `config()` call errors. Using `class_exists(Illuminate\Foundation\Application::class)` is a more reliable check. Co-Authored-By: Claude Opus 4.7 --- PR_DESCRIPTION.md | 56 +++++++++++++++++++++++++++++++++++++++++++ src/ServerManager.php | 2 +- 2 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 PR_DESCRIPTION.md diff --git a/PR_DESCRIPTION.md b/PR_DESCRIPTION.md new file mode 100644 index 00000000..e098af5a --- /dev/null +++ b/PR_DESCRIPTION.md @@ -0,0 +1,56 @@ +## Summary + +Allow connecting to an already-running Playwright server instead of starting a local one. This enables setups where Playwright runs on the host machine while Pest runs inside a container (e.g., Docker, CI). + +## Problem + +Currently `pest-plugin-browser` always starts a local Playwright server via `npx playwright run-server`. This fails when: + +1. The PHP environment runs in an Alpine Linux container (musl libc) — Playwright's bundled Chromium requires glibc and crashes with `posix_fallocate64: symbol not found` +2. The host machine already has a running Playwright server that the container could connect to + +There's no way to tell the plugin "don't start a server, connect to this existing one instead." + +## Solution + +Three small additions: + +### 1. `Playwright::setPlaywrightServerUrl()` + getter + +New static property `$playwrightServerUrl`. The getter checks both programmatic config and the `PEST_BROWSER_PLAYWRIGHT_URL` environment variable: + +```php +public static function playwrightServerUrl(): ?string +{ + return self::$playwrightServerUrl ?? getenv('PEST_BROWSER_PLAYWRIGHT_URL') ?: null; +} +``` + +### 2. `Configuration::withPlaywrightServer(?string $serverUrl)` + +New fluent config method, usable in `tests/Pest.php`: + +```php +pest()->browser()->withPlaywrightServer('http://192.168.1.100:9999'); +``` + +### 3. `ServerManager::playwright()` check + +When a server URL is set, the plugin uses `AlreadyStartedPlaywrightServer` (existing class) to connect to the external server instead of calling `PlaywrightNpmServer::create()`. + +## Usage + +```php +// In tests/Pest.php +pest()->browser() + ->withPlaywrightServer('http://192.168.1.100:9999') + ->inChrome(); +``` + +Or via environment variable: + +```bash +PEST_BROWSER_PLAYWRIGHT_URL=http://192.168.1.100:9999 php vendor/bin/pest tests/Browser/ +``` + +When not set, behavior is identical to before — fully backward compatible. diff --git a/src/ServerManager.php b/src/ServerManager.php index 62e83607..5a9dcedb 100644 --- a/src/ServerManager.php +++ b/src/ServerManager.php @@ -92,7 +92,7 @@ public function playwright(): PlaywrightServer */ public function http(): HttpServer { - return $this->http ??= match (function_exists('app_path')) { + return $this->http ??= match (class_exists(\Illuminate\Foundation\Application::class)) { true => new LaravelHttpServer( self::DEFAULT_HOST, // Always bind to 127.0.0.1 for server Port::find(), From 4fff74f4246fe3b08a58c0c5666cc06c9828aeb6 Mon Sep 17 00:00:00 2001 From: Tinywan <756684177@qq.com> Date: Sun, 17 May 2026 10:21:05 +0800 Subject: [PATCH 3/3] chore: remove PR description file from repo Co-Authored-By: Claude Opus 4.7 --- PR_DESCRIPTION.md | 56 ----------------------------------------------- 1 file changed, 56 deletions(-) delete mode 100644 PR_DESCRIPTION.md diff --git a/PR_DESCRIPTION.md b/PR_DESCRIPTION.md deleted file mode 100644 index e098af5a..00000000 --- a/PR_DESCRIPTION.md +++ /dev/null @@ -1,56 +0,0 @@ -## Summary - -Allow connecting to an already-running Playwright server instead of starting a local one. This enables setups where Playwright runs on the host machine while Pest runs inside a container (e.g., Docker, CI). - -## Problem - -Currently `pest-plugin-browser` always starts a local Playwright server via `npx playwright run-server`. This fails when: - -1. The PHP environment runs in an Alpine Linux container (musl libc) — Playwright's bundled Chromium requires glibc and crashes with `posix_fallocate64: symbol not found` -2. The host machine already has a running Playwright server that the container could connect to - -There's no way to tell the plugin "don't start a server, connect to this existing one instead." - -## Solution - -Three small additions: - -### 1. `Playwright::setPlaywrightServerUrl()` + getter - -New static property `$playwrightServerUrl`. The getter checks both programmatic config and the `PEST_BROWSER_PLAYWRIGHT_URL` environment variable: - -```php -public static function playwrightServerUrl(): ?string -{ - return self::$playwrightServerUrl ?? getenv('PEST_BROWSER_PLAYWRIGHT_URL') ?: null; -} -``` - -### 2. `Configuration::withPlaywrightServer(?string $serverUrl)` - -New fluent config method, usable in `tests/Pest.php`: - -```php -pest()->browser()->withPlaywrightServer('http://192.168.1.100:9999'); -``` - -### 3. `ServerManager::playwright()` check - -When a server URL is set, the plugin uses `AlreadyStartedPlaywrightServer` (existing class) to connect to the external server instead of calling `PlaywrightNpmServer::create()`. - -## Usage - -```php -// In tests/Pest.php -pest()->browser() - ->withPlaywrightServer('http://192.168.1.100:9999') - ->inChrome(); -``` - -Or via environment variable: - -```bash -PEST_BROWSER_PLAYWRIGHT_URL=http://192.168.1.100:9999 php vendor/bin/pest tests/Browser/ -``` - -When not set, behavior is identical to before — fully backward compatible.