Skip to content

Commit d1c6f19

Browse files
authored
Merge branch 'pestphp:4.x' into feature/configurable-browser-launch-args
2 parents 2f23d3c + 615fbf0 commit d1c6f19

File tree

11 files changed

+105
-11
lines changed

11 files changed

+105
-11
lines changed

composer.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@
1717
"amphp/amp": "^3.1.1",
1818
"amphp/http-server": "^3.4.3",
1919
"amphp/websocket-client": "^2.0.2",
20-
"pestphp/pest": "^4.0.4",
20+
"pestphp/pest": "^4.1.0",
2121
"pestphp/pest-plugin": "^4.0.0",
22-
"symfony/process": "^7.3.3"
22+
"symfony/process": "^7.3.4"
2323
},
2424
"autoload": {
2525
"psr-4": {

src/Api/Concerns/MakesElementAssertions.php

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,19 @@ public function assertSourceHas(string $code): Webpage
199199
return $this;
200200
}
201201

202+
/**
203+
* Assert that the given source code is present within the selector.
204+
*/
205+
public function assertSourceInHas(string $selector, string $code): Webpage
206+
{
207+
$locator = $this->guessLocator($selector);
208+
$html = $locator->innerHTML();
209+
$message = "Expected page source to contain [{$code}] on the page initially with the url [{$this->initialUrl}], but it was not found.";
210+
expect(str_contains($html, $code))->toBeTrue($message);
211+
212+
return $this;
213+
}
214+
202215
/**
203216
* Assert that the given source code is not present on the page.
204217
*/
@@ -211,6 +224,19 @@ public function assertSourceMissing(string $code): Webpage
211224
return $this;
212225
}
213226

227+
/**
228+
* Assert that the given source code is not present within the selector.
229+
*/
230+
public function assertSourceInMissing(string $selector, string $code): Webpage
231+
{
232+
$locator = $this->guessLocator($selector);
233+
$html = $locator->innerHTML();
234+
$message = "Expected page source not to contain [{$code}] on the page initially with the url [{$this->initialUrl}], but it was found.";
235+
expect(str_contains($html, $code))->toBeFalse($message);
236+
237+
return $this;
238+
}
239+
214240
/**
215241
* Assert that the given link is present on the page.
216242
*/

src/Browsable.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,4 +60,12 @@ public function visit(array|string $url, array $options = []): ArrayablePendingA
6060
), $url),
6161
);
6262
}
63+
64+
/**
65+
* @return array <string, string>
66+
*/
67+
protected function serverVariables(): array
68+
{
69+
return property_exists($this, 'serverVariables') ? $this->serverVariables : [];
70+
}
6371
}

src/Drivers/LaravelHttpServer.php

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace Pest\Browser\Drivers;
66

77
use Amp\ByteStream\ReadableResourceStream;
8+
use Amp\Http\Cookie\RequestCookie;
89
use Amp\Http\Server\DefaultErrorHandler;
910
use Amp\Http\Server\HttpServer as AmpHttpServer;
1011
use Amp\Http\Server\HttpServerStatus;
@@ -242,14 +243,18 @@ private function handleRequest(AmpRequest $request): Response
242243
if ($method !== 'GET' && str_starts_with(mb_strtolower($contentType), 'application/x-www-form-urlencoded')) {
243244
parse_str($rawBody, $parameters);
244245
}
246+
$cookies = array_map(fn (RequestCookie $cookie): string => urldecode($cookie->getValue()), $request->getCookies());
247+
$cookies = array_merge($cookies, test()->prepareCookiesForRequest()); // @phpstan-ignore-line
248+
/** @var array<string, string> $serverVariables */
249+
$serverVariables = test()->serverVariables(); // @phpstan-ignore-line
245250

246251
$symfonyRequest = Request::create(
247252
$absoluteUrl,
248253
$method,
249254
$parameters,
250-
$request->getCookies(),
255+
$cookies,
251256
[], // @TODO files...
252-
[], // @TODO server variables...
257+
$serverVariables,
253258
$rawBody
254259
);
255260

src/Support/JavaScriptSerializer.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ public static function parseValue(mixed $value): mixed
148148

149149
// Handle arrays
150150
if (isset($value['a'])) {
151-
return array_map(fn (mixed $item): mixed => self::parseValue($item), $value['a']);
151+
return array_map(self::parseValue(...), $value['a']);
152152
}
153153

154154
// Handle objects

src/Support/Selector.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,16 @@ public static function isExplicit(string $selector): bool
2121
return false;
2222
}
2323

24-
$cssSpecialChars = ['[', ']', '#', '.', '>', '+', '~', ':', '*', '|', '^', ',', '=', ',', '(', ')'];
24+
$cssSpecialChars = ['[', ']', '#', '>', '+', '~', ':', '*', '|', '^', ',', '=', ',', '(', ')'];
2525

2626
foreach ($cssSpecialChars as $cssSpecialChar) {
2727
if (str_contains($selector, $cssSpecialChar)) {
2828
return true;
2929
}
3030
}
3131

32-
return false;
32+
// A period is a CSS selector if it's followed by a valid CSS class name pattern
33+
return (bool) preg_match('/\.[a-zA-Z_-][a-zA-Z0-9_-]*/', $selector);
3334
}
3435

3536
/**

tests/Browser/Visit/SingleUrl.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727

2828
$page->assertSee('Experience elegance across every device.')
2929
->assertScreenshotMatches();
30-
})->with($methods)->skipOnCI();
30+
})->with($methods)->onlyOnMac()->skipOnCI();
3131

3232
it('may visit a page in light/dark mode', function (ColorScheme $scheme): void {
3333
Route::get('/', fn (): string => '
@@ -71,7 +71,7 @@
7171
};
7272

7373
$page->assertScreenshotMatches();
74-
})->with(ColorScheme::cases())->skipOnCI();
74+
})->with(ColorScheme::cases())->onlyOnMac()->skipOnCI();
7575

7676
it('may visit a page with custom locale and timezone', function (): void {
7777
Route::get('/', fn (): string => '

tests/Browser/Webpage/AssertScreenshotMatchesTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
declare(strict_types=1);
44

5-
beforeEach()->skipOnCI();
5+
beforeEach()->onlyOnMac()->skipOnCI();
66

77
it('may match a screenshot', function (): void {
88
Route::get('/', fn (): string => '

tests/Browser/Webpage/AssertSourceTest.php

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,22 @@
2020
$page->assertSourceHas('<div id="content">Hello Universe</div>');
2121
})->throws(ExpectationFailedException::class);
2222

23+
it('may assert source code is present within a selector', function (): void {
24+
Route::get('/', fn (): string => '<div id="content"><strong>Hello World</strong></div>');
25+
26+
$page = visit('/');
27+
28+
$page->assertSourceInHas('#content', '<strong>Hello World</strong>');
29+
});
30+
31+
it('may fail when asserting source code is present within a selector but it is not', function (): void {
32+
Route::get('/', fn (): string => '<div id="content">Hello World</div>');
33+
34+
$page = visit('/');
35+
36+
$page->assertSourceInHas('#content', '<strong>Hello World</strong>');
37+
})->throws(ExpectationFailedException::class);
38+
2339
it('may assert source code is not present on the page', function (): void {
2440
Route::get('/', fn (): string => '<div id="content">Hello World</div>');
2541

@@ -35,3 +51,19 @@
3551

3652
$page->assertSourceMissing('<div id="content">Hello World</div>');
3753
})->throws(ExpectationFailedException::class);
54+
55+
it('may assert source code is not present within a selector', function (): void {
56+
Route::get('/', fn (): string => '<div id="content">Hello World</div>');
57+
58+
$page = visit('/');
59+
60+
$page->assertSourceInMissing('#content', '<strong>Hello World</strong>');
61+
});
62+
63+
it('may fail when asserting source code is not present within a selector but it is', function (): void {
64+
Route::get('/', fn (): string => '<div id="content"><strong>Hello World</strong></div>');
65+
66+
$page = visit('/');
67+
68+
$page->assertSourceInMissing('#content', '<strong>Hello World</strong>');
69+
})->throws(ExpectationFailedException::class);

tests/Unit/Drivers/Laravel/LaravelHttpServerTest.php

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22

33
declare(strict_types=1);
44

5+
use Illuminate\Http\Request;
6+
7+
use function Pest\Laravel\withServerVariables;
8+
use function Pest\Laravel\withUnencryptedCookie;
9+
510
it('rewrites the URLs on JS files', function (): void {
611
@file_put_contents(
712
public_path('app.js'),
@@ -15,3 +20,19 @@
1520
$page->assertSee('http://127.0.0.1')
1621
->assertDontSee('http://localhost');
1722
});
23+
24+
it('includes cookies set in the test', function (): void {
25+
Route::get('/cookies', fn (Request $request): array => $request->cookies->all());
26+
27+
withUnencryptedCookie('test-cookie', value: 'test value');
28+
visit('/cookies')
29+
->assertSee(json_encode(['test-cookie' => 'test value']));
30+
});
31+
32+
it('includes server variables set in the test', function (): void {
33+
Route::get('/server-variables', fn (Request $request): array => $request->server->all());
34+
35+
withServerVariables(['test-server-key' => 'test value']);
36+
visit('/server-variables')
37+
->assertSee('"test-server-key":"test value"');
38+
});

0 commit comments

Comments
 (0)