Skip to content

Commit 036a43d

Browse files
committed
Implements SymfonyHttpServer
1 parent 575250d commit 036a43d

File tree

3 files changed

+60
-53
lines changed

3 files changed

+60
-53
lines changed

src/Configuration.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace Pest\Browser;
66

7+
use Pest\Browser\Contracts\HttpServer;
78
use Pest\Browser\Enums\BrowserType;
89
use Pest\Browser\Enums\ColorScheme;
910
use Pest\Browser\Playwright\Playwright;
@@ -114,4 +115,16 @@ public function diff(): self
114115

115116
return $this;
116117
}
118+
119+
/**
120+
* Sets the browsers http server class.
121+
*
122+
* @param class-string<HttpServer> $class
123+
*/
124+
public function httpServer(string $class): self
125+
{
126+
ServerManager::setHttpServerClass($class);
127+
128+
return $this;
129+
}
117130
}

src/Drivers/SymfonyHttpServer.php

Lines changed: 25 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,15 @@
1212
use Amp\Http\Server\RequestHandler\ClosureRequestHandler;
1313
use Amp\Http\Server\Response;
1414
use Amp\Http\Server\SocketHttpServer;
15-
use Illuminate\Contracts\Debug\ExceptionHandler;
16-
use Illuminate\Contracts\Http\Kernel as HttpKernel;
17-
use Illuminate\Foundation\Testing\Concerns\WithoutExceptionHandlingHandler;
18-
use Illuminate\Http\Request;
19-
use Illuminate\Routing\UrlGenerator;
20-
use Illuminate\Support\Uri;
15+
use Exception;
2116
use Pest\Browser\Contracts\HttpServer;
2217
use Pest\Browser\Exceptions\ServerNotFoundException;
2318
use Pest\Browser\Execution;
2419
use Pest\Browser\GlobalState;
2520
use Psr\Log\NullLogger;
21+
use Symfony\Component\HttpFoundation\Request;
22+
use Symfony\Component\HttpKernel\KernelInterface;
23+
use Symfony\Component\HttpKernel\TerminableInterface;
2624
use Symfony\Component\Mime\MimeTypes;
2725
use Throwable;
2826

@@ -49,7 +47,7 @@ final class SymfonyHttpServer implements HttpServer
4947
private ?Throwable $lastThrowable = null;
5048

5149
/**
52-
* Creates a new laravel http server instance.
50+
* Creates a new Symfony http server instance.
5351
*/
5452
public function __construct(
5553
public readonly string $host,
@@ -79,13 +77,11 @@ public function rewrite(string $url): string
7977
}
8078

8179
$parts = parse_url($url);
82-
$queryParameters = [];
8380
$path = $parts['path'] ?? '/';
84-
parse_str($parts['query'] ?? '', $queryParameters);
81+
$query = $parts['query'] ?? '';
82+
$fragment = $parts['fragment'] ?? '';
8583

86-
return (string) Uri::of($this->url())
87-
->withPath($path)
88-
->withQuery($queryParameters);
84+
return $this->url().$path.($query !== '' ? '?'.$query : '').($fragment !== '' ? '#'.$fragment : '');
8985
}
9086

9187
/**
@@ -146,22 +142,8 @@ public function bootstrap(): void
146142
{
147143
$this->start();
148144

149-
$url = $this->url();
150-
151-
config(['app.url' => $url]);
152-
153-
config(['cors.paths' => ['*']]);
154-
155-
if (app()->bound('url')) {
156-
$urlGenerator = app('url');
157-
158-
assert($urlGenerator instanceof UrlGenerator);
159-
160-
$this->setOriginalAssetUrl($urlGenerator->asset(''));
161-
162-
$urlGenerator->useOrigin($url);
163-
$urlGenerator->useAssetOrigin($url);
164-
$urlGenerator->forceScheme('http');
145+
if (is_string($_ENV['DEFAULT_URI'])) {
146+
$this->setOriginalAssetUrl($_ENV['DEFAULT_URI']);
165147
}
166148
}
167149

@@ -184,11 +166,7 @@ public function throwLastThrowableIfNeeded(): void
184166
return;
185167
}
186168

187-
$exceptionHandler = app(ExceptionHandler::class);
188-
189-
if ($exceptionHandler instanceof WithoutExceptionHandlingHandler) {
190-
throw $this->lastThrowable;
191-
}
169+
throw $this->lastThrowable;
192170
}
193171

194172
/**
@@ -222,18 +200,20 @@ private function handleRequest(AmpRequest $request): Response
222200
Execution::instance()->tick();
223201
}
224202

225-
$uri = $request->getUri();
226-
$path = in_array($uri->getPath(), ['', '0'], true) ? '/' : $uri->getPath();
227-
$query = $uri->getQuery() ?? ''; // @phpstan-ignore-line
228-
$fullPath = $path.($query !== '' ? '?'.$query : '');
229-
$absoluteUrl = mb_rtrim($this->url(), '/').$fullPath;
230-
231-
$filepath = public_path($path);
203+
$publicPath = getcwd().DIRECTORY_SEPARATOR.(is_string($_ENV['PUBLIC_PATH']) ? $_ENV['PUBLIC_PATH'] : 'public');
204+
$filepath = $publicPath.$request->getUri()->getPath();
232205
if (file_exists($filepath) && ! is_dir($filepath)) {
233206
return $this->asset($filepath);
234207
}
235208

236-
$kernel = app()->make(HttpKernel::class);
209+
$kernelClass = is_string($_ENV['KERNEL_CLASS']) ? $_ENV['KERNEL_CLASS'] : 'App\Kernel';
210+
if (class_exists($kernelClass) === false) {
211+
$this->lastThrowable = new Exception('You must define the test kernel class environment variable: KERNEL_CLASS.');
212+
213+
throw $this->lastThrowable;
214+
}
215+
/** @var KernelInterface&TerminableInterface $kernel */
216+
$kernel = new $kernelClass($_ENV['APP_ENV'], (bool) $_ENV['APP_DEBUG']);
237217

238218
$contentType = $request->getHeader('content-type') ?? '';
239219
$method = mb_strtoupper($request->getMethod());
@@ -244,7 +224,7 @@ private function handleRequest(AmpRequest $request): Response
244224
}
245225

246226
$symfonyRequest = Request::create(
247-
$absoluteUrl,
227+
(string) $request->getUri(),
248228
$method,
249229
$parameters,
250230
$request->getCookies(),
@@ -255,21 +235,15 @@ private function handleRequest(AmpRequest $request): Response
255235

256236
$symfonyRequest->headers->add($request->getHeaders());
257237

258-
$debug = config('app.debug');
259-
260238
try {
261-
config(['app.debug' => false]);
262-
263-
$response = $kernel->handle($laravelRequest = Request::createFromBase($symfonyRequest));
239+
$response = $kernel->handle($symfonyRequest);
264240
} catch (Throwable $e) {
265241
$this->lastThrowable = $e;
266242

267243
throw $e;
268-
} finally {
269-
config(['app.debug' => $debug]);
270244
}
271245

272-
$kernel->terminate($laravelRequest, $response);
246+
$kernel->terminate($symfonyRequest, $response);
273247

274248
if (property_exists($response, 'exception') && $response->exception !== null) {
275249
assert($response->exception instanceof Throwable);
@@ -312,7 +286,7 @@ private function asset(string $filepath): Response
312286

313287
$contentType = $contentType[0] ?? 'application/octet-stream';
314288

315-
if (str_ends_with($filepath, '.js')) {
289+
if (str_ends_with($filepath, '.js') || str_ends_with($filepath, '.css')) {
316290
$temporaryStream = fopen('php://temp', 'r+');
317291
assert($temporaryStream !== false, 'Failed to open temporary stream.');
318292

src/ServerManager.php

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,13 @@ final class ServerManager
4141
*/
4242
private ?HttpServer $http = null;
4343

44+
/**
45+
* The HTTP server class.
46+
*
47+
* @param class-string<HttpServer> $class
48+
*/
49+
private static ?string $httpServerClass = null;
50+
4451
/**
4552
* Gets the singleton instance of the server manager.
4653
*/
@@ -49,6 +56,16 @@ public static function instance(): self
4956
return self::$instance ??= new self();
5057
}
5158

59+
/**
60+
* Sets the browsers http server class.
61+
*
62+
* @param class-string<HttpServer> $class
63+
*/
64+
public static function setHttpServerClass(string $class): void
65+
{
66+
self::$httpServerClass = $class;
67+
}
68+
5269
/**
5370
* Returns the Playwright server process instance.
5471
*/
@@ -81,8 +98,11 @@ public function playwright(): PlaywrightServer
8198
*/
8299
public function http(): HttpServer
83100
{
84-
return $this->http ??= match (function_exists('app_path')) {
85-
true => new LaravelHttpServer(
101+
$httpServer = self::$httpServerClass !== null ? new self::$httpServerClass(self::DEFAULT_HOST, Port::find()) : null;
102+
103+
return $this->http ??= match (true) {
104+
$httpServer instanceof HttpServer => $httpServer,
105+
function_exists('app_path') => new LaravelHttpServer(
86106
self::DEFAULT_HOST,
87107
Port::find(),
88108
),

0 commit comments

Comments
 (0)