Skip to content

Commit 749310c

Browse files
committed
feat: add object page support to visit()
1 parent 0314d37 commit 749310c

19 files changed

+636
-58
lines changed

src/Api/AwaitableWebpage.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
use Pest\Browser\Exceptions\BrowserExpectationFailedException;
88
use Pest\Browser\Execution;
9+
use Pest\Browser\Page as BrowserPage;
910
use Pest\Browser\Playwright\Page;
1011
use Pest\Browser\Playwright\Playwright;
1112
use Pest\Browser\ServerManager;
@@ -24,7 +25,7 @@
2425
*/
2526
public function __construct(
2627
private Page $page,
27-
private string $initialUrl,
28+
private string|BrowserPage $initialUrl,
2829
private array $nonAwaitableMethods = [
2930
'assertScreenshotMatches',
3031
'assertNoAccessibilityIssues',

src/Api/Concerns/InteractsWithToolbar.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace Pest\Browser\Api\Concerns;
66

77
use Pest\Browser\Api\Webpage;
8+
use Pest\Browser\Page as BrowserPage;
89
use Pest\Browser\Support\ComputeUrl;
910

1011
/**
@@ -27,8 +28,10 @@ public function refresh(): self
2728
*
2829
* @param array<string, mixed> $options
2930
*/
30-
public function navigate(string $url, array $options = []): self
31+
public function navigate(string|BrowserPage $url, array $options = []): self
3132
{
33+
$this->page->setShorthandElements($url);
34+
3235
$url = ComputeUrl::from($url);
3336

3437
$this->page->goto($url, $options);

src/Api/Concerns/MakesConsoleAssertions.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ public function assertNoBrokenImages(): Webpage
3939

4040
expect($brokenImages)->toBeEmpty(sprintf(
4141
'Expected no broken images on the page initially with the url [%s], but found %s: %s',
42-
$this->initialUrl,
42+
$this->initialUrl(),
4343
count($brokenImages),
4444
implode(', ', $brokenImages),
4545
));
@@ -64,7 +64,7 @@ public function assertNoConsoleLogs(): Webpage
6464

6565
expect($consoleLogs)->toBeEmpty(sprintf(
6666
'Expected no console logs on the page initially with the url [%s], but found %s: %s',
67-
$this->initialUrl,
67+
$this->initialUrl(),
6868
count($consoleLogs),
6969
implode(', ', array_map(fn (array $log) => $log['message'], $consoleLogs)),
7070
));
@@ -81,7 +81,7 @@ public function assertNoJavaScriptErrors(): Webpage
8181

8282
expect($javaScriptErrors)->toBeEmpty(sprintf(
8383
'Expected no JavaScript errors on the page initially with the url [%s], but found %s: %s',
84-
$this->initialUrl,
84+
$this->initialUrl(),
8585
count($javaScriptErrors),
8686
implode(', ', array_map(fn (array $log) => $log['message'], $javaScriptErrors)),
8787
));

src/Api/Concerns/MakesElementAssertions.php

Lines changed: 37 additions & 37 deletions
Large diffs are not rendered by default.

src/Api/From.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use Pest\Browser\Enums\BrowserType;
99
use Pest\Browser\Enums\Cities;
1010
use Pest\Browser\Enums\Device;
11+
use Pest\Browser\Page as BrowserPage;
1112

1213
/**
1314
* @mixin PendingAwaitablePage
@@ -22,7 +23,7 @@
2223
public function __construct(
2324
private BrowserType $browserType,
2425
private Device $device,
25-
private string $url,
26+
private string|BrowserPage $url,
2627
private array $options,
2728
) {
2829
//

src/Api/On.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
use Pest\Browser\Enums\BrowserType;
88
use Pest\Browser\Enums\Device;
9+
use Pest\Browser\Page as BrowserPage;
910

1011
/**
1112
* @mixin PendingAwaitablePage
@@ -20,7 +21,7 @@
2021
public function __construct(
2122
private BrowserType $browserType,
2223
private Device $device,
23-
private string $url,
24+
private string|BrowserPage $url,
2425
private array $options,
2526
) {
2627
//

src/Api/PendingAwaitablePage.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
use Pest\Browser\Enums\Cities;
1010
use Pest\Browser\Enums\ColorScheme;
1111
use Pest\Browser\Enums\Device;
12+
use Pest\Browser\Page as BrowserPage;
1213
use Pest\Browser\Playwright\InitScript;
1314
use Pest\Browser\Playwright\Playwright;
1415
use Pest\Browser\Support\ComputeUrl;
@@ -31,7 +32,7 @@ final class PendingAwaitablePage
3132
public function __construct(
3233
private readonly BrowserType $browserType,
3334
private readonly Device $device,
34-
private readonly string $url,
35+
private readonly string|BrowserPage $url,
3536
private readonly array $options,
3637
) {
3738
//
@@ -177,8 +178,8 @@ private function createAwaitablePage(): AwaitableWebpage
177178
$url = ComputeUrl::from($this->url);
178179

179180
return new AwaitableWebpage(
180-
$context->newPage()->goto($url, $this->options),
181-
$url,
181+
$context->newPage()->setShorthandElements($this->url)->goto($url, $this->options),
182+
$this->url,
182183
);
183184
}
184185
}

src/Api/Webpage.php

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44

55
namespace Pest\Browser\Api;
66

7+
use BadMethodCallException;
78
use Pest\Browser\Execution;
9+
use Pest\Browser\Page as BrowserPage;
810
use Pest\Browser\Playwright\Locator;
911
use Pest\Browser\Playwright\Page;
1012
use Pest\Browser\Support\GuessLocator;
@@ -31,11 +33,32 @@ final class Webpage
3133
*/
3234
public function __construct(
3335
private readonly Page $page,
34-
private readonly string $initialUrl,
36+
private readonly string|BrowserPage $initialUrl,
3537
) {
3638
//
3739
}
3840

41+
/**
42+
* Dynamically call a method on the browser.
43+
*
44+
* @param array<int, mixed> $arguments
45+
*
46+
* @throws BadMethodCallException
47+
*/
48+
public function __call(string $method, array $arguments): self
49+
{
50+
if ($this->initialUrl instanceof BrowserPage && method_exists($this->initialUrl, $method)) {
51+
array_unshift($arguments, $this);
52+
53+
// @phpstan-ignore-next-line method.dynamicName
54+
$this->initialUrl->{$method}(...$arguments);
55+
56+
return $this;
57+
}
58+
59+
throw new BadMethodCallException("Call to undefined method [{$method}].");
60+
}
61+
3962
/**
4063
* Dumps the current page's content and stops the execution.
4164
*/
@@ -72,6 +95,18 @@ public function url(): string
7295
return $this->page->url();
7396
}
7497

98+
/**
99+
* Gets the page's initial URL.
100+
*/
101+
public function initialUrl(): string
102+
{
103+
if ($this->initialUrl instanceof BrowserPage) {
104+
return $this->initialUrl->url();
105+
}
106+
107+
return $this->initialUrl;
108+
}
109+
75110
/**
76111
* Submits the first form found on the page.
77112
*/
@@ -100,6 +135,8 @@ public function value(string $selector): string
100135

101136
public function within(string $selector, callable $callback): self
102137
{
138+
$selector = $this->resolveShorthandSelector($selector);
139+
103140
$previousScope = $this->currentScope;
104141

105142
$this->currentScope = $previousScope !== null ? $previousScope.' >> '.$selector : $selector;
@@ -118,6 +155,20 @@ public function within(string $selector, callable $callback): self
118155
*/
119156
private function guessLocator(string $selector, ?string $value = null): Locator
120157
{
158+
$selector = $this->resolveShorthandSelector($selector);
159+
121160
return (new GuessLocator($this->page, $this->currentScope))->for($selector, $value);
122161
}
162+
163+
/**
164+
* Resolve the shorthand selector for the given page.
165+
*/
166+
private function resolveShorthandSelector(string $selector): string
167+
{
168+
$shorthandElements = $this->page->shorthandElements();
169+
170+
return str_replace(
171+
array_keys($shorthandElements), array_values($shorthandElements), $selector
172+
);
173+
}
123174
}

src/Browsable.php

Lines changed: 51 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,29 @@ public function __markAsBrowserTest(): void
3434
/**
3535
* Browse to the given URL.
3636
*
37-
* @template TUrl of array<int, string>|string
37+
* @template TUrl of array<int, string|Page>|string|Page
3838
*
3939
* @param TUrl $url
4040
* @param array<string, mixed> $options
41-
* @return (TUrl is array<int, string> ? ArrayablePendingAwaitablePage : PendingAwaitablePage)
41+
* @return (TUrl is array<int, string|Page> ? ArrayablePendingAwaitablePage : PendingAwaitablePage)
4242
*/
43-
public function visit(array|string $url, array $options = []): ArrayablePendingAwaitablePage|PendingAwaitablePage
43+
public function visit(array|string|Page $url, array $options = []): ArrayablePendingAwaitablePage|PendingAwaitablePage
4444
{
45+
if ($url instanceof Page) {
46+
$options = [
47+
...$this->pageTimezone($url),
48+
...$this->pageLocale($url),
49+
...$options,
50+
];
51+
52+
return new PendingAwaitablePage(
53+
$url->browserType(),
54+
$url->device(),
55+
$url,
56+
$options,
57+
);
58+
}
59+
4560
if (is_string($url)) {
4661
return new PendingAwaitablePage(
4762
Playwright::defaultBrowserType(),
@@ -52,12 +67,39 @@ public function visit(array|string $url, array $options = []): ArrayablePendingA
5267
}
5368

5469
return new ArrayablePendingAwaitablePage(
55-
array_map(fn (string $singleUrl): PendingAwaitablePage => new PendingAwaitablePage(
56-
Playwright::defaultBrowserType(),
57-
Device::DESKTOP,
58-
$singleUrl,
59-
$options,
60-
), $url),
70+
array_map(fn (string|Page $singleUrl): PendingAwaitablePage => $this->visit($singleUrl, $options), $url),
6171
);
6272
}
73+
74+
/**
75+
* Get the locale from page.
76+
*
77+
* @return array{locale?: string}
78+
*/
79+
private function pageLocale(Page $page): array
80+
{
81+
$locale = $page->locale();
82+
83+
if ($locale === '') {
84+
return [];
85+
}
86+
87+
return ['locale' => $locale];
88+
}
89+
90+
/**
91+
* Get the timezone from page.
92+
*
93+
* @return array{timezoneId?: string}
94+
*/
95+
private function pageTimezone(Page $page): array
96+
{
97+
$timezone = $page->timezone();
98+
99+
if ($timezone === '') {
100+
return [];
101+
}
102+
103+
return ['timezoneId' => $timezone];
104+
}
63105
}

src/Page.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Pest\Browser;
6+
7+
abstract class Page
8+
{
9+
use PageConfiguration;
10+
11+
/**
12+
* Get the URL for the page.
13+
*/
14+
abstract public function url(): string;
15+
}

0 commit comments

Comments
 (0)