Skip to content

Commit 10e6ec3

Browse files
committed
Add ModifierKey and controlClick utils
1 parent d47cf2d commit 10e6ec3

File tree

6 files changed

+172
-17
lines changed

6 files changed

+172
-17
lines changed
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/*
6+
* This file is part of the playwright-php/playwright package.
7+
* For the full copyright and license information, please view
8+
* the LICENSE file that was distributed with this source code.
9+
*/
10+
11+
namespace PlaywrightPHP\Exception;
12+
13+
/**
14+
* @author Simon André <smn.andre@gmail.com>
15+
*/
16+
class InvalidArgumentException extends \InvalidArgumentException implements PlaywrightExceptionInterface
17+
{
18+
}

src/Input/ModifierKey.php

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/*
6+
* This file is part of the playwright-php/playwright package.
7+
* For the full copyright and license information, please view
8+
* the LICENSE file that was distributed with this source code.
9+
*/
10+
11+
namespace PlaywrightPHP\Input;
12+
13+
use PlaywrightPHP\Exception\InvalidArgumentException;
14+
15+
/**
16+
* @author Simon André <smn.andre@gmail.com>
17+
*/
18+
enum ModifierKey: string
19+
{
20+
case Alt = 'Alt';
21+
case Control = 'Control';
22+
case Meta = 'Meta';
23+
case Shift = 'Shift';
24+
25+
public static function fromString(string $modifier): self
26+
{
27+
return match (strtolower($modifier)) {
28+
'alt' => self::Alt,
29+
'control', 'ctrl' => self::Control,
30+
'meta', 'cmd', 'command' => self::Meta,
31+
'shift' => self::Shift,
32+
default => throw new InvalidArgumentException(sprintf('Unknown modifier key: "%s".', $modifier)),
33+
};
34+
}
35+
}

src/Network/Request.php

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ public function __construct(
2727

2828
public function url(): string
2929
{
30-
$url = $this->data['url'];
30+
$url = $this->data['url'] ?? null;
3131
if (!is_string($url)) {
3232
throw new ProtocolErrorException('Invalid URL in request data', 0);
3333
}
@@ -37,17 +37,20 @@ public function url(): string
3737

3838
public function method(): string
3939
{
40-
$method = $this->data['method'];
40+
$method = $this->data['method'] ?? null;
4141
if (!is_string($method)) {
4242
throw new ProtocolErrorException('Invalid method in request data', 0);
4343
}
4444

4545
return $method;
4646
}
4747

48+
/**
49+
* @return array<string, string>
50+
*/
4851
public function headers(): array
4952
{
50-
$headers = $this->data['headers'];
53+
$headers = $this->data['headers'] ?? [];
5154
if (!is_array($headers)) {
5255
return [];
5356
}
@@ -59,7 +62,6 @@ public function headers(): array
5962
}
6063
}
6164

62-
/* @var array<string, string> $stringHeaders */
6365
return $stringHeaders;
6466
}
6567

@@ -76,27 +78,23 @@ public function postDataJSON(): ?array
7678
if (null === $postData) {
7779
return null;
7880
}
79-
80-
$decoded = json_decode($postData, true);
81-
82-
if (!is_array($decoded)) {
81+
82+
if (!json_validate($postData)) {
8383
return null;
8484
}
8585

86-
$result = [];
87-
foreach ($decoded as $key => $value) {
88-
if (!is_string($key)) {
89-
return null;
90-
}
91-
$result[$key] = $value;
86+
$decoded = json_decode($postData, false, 512, JSON_THROW_ON_ERROR);
87+
88+
if (!$decoded instanceof \stdClass) {
89+
return null;
9290
}
9391

94-
return $result;
92+
return (array) $decoded;
9593
}
9694

9795
public function resourceType(): string
9896
{
99-
$resourceType = $this->data['resourceType'];
97+
$resourceType = $this->data['resourceType'] ?? null;
10098
if (!is_string($resourceType)) {
10199
throw new ProtocolErrorException('Invalid resourceType in request data', 0);
102100
}

src/Page/Page.php

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
use PlaywrightPHP\Frame\FrameLocatorInterface;
2727
use PlaywrightPHP\Input\Keyboard;
2828
use PlaywrightPHP\Input\KeyboardInterface;
29+
use PlaywrightPHP\Input\ModifierKey;
2930
use PlaywrightPHP\Input\Mouse;
3031
use PlaywrightPHP\Input\MouseInterface;
3132
use PlaywrightPHP\Locator\Locator;
@@ -45,8 +46,11 @@
4546
final class Page implements PageInterface, EventDispatcherInterface
4647
{
4748
private KeyboardInterface $keyboard;
49+
4850
private MouseInterface $mouse;
51+
4952
private PageEventHandlerInterface $eventHandler;
53+
5054
private LoggerInterface $logger;
5155

5256
public function __construct(
@@ -287,6 +291,30 @@ public function click(string $selector, array $options = []): self
287291
return $this;
288292
}
289293

294+
/**
295+
* @param array<string, mixed> $options
296+
*/
297+
public function altClick(string $selector, array $options = []): self
298+
{
299+
return $this->click($selector, [...$options, 'modifiers' => ModifierKey::Alt]);
300+
}
301+
302+
/**
303+
* @param array<string, mixed> $options
304+
*/
305+
public function controlClick(string $selector, array $options = []): self
306+
{
307+
return $this->click($selector, [...$options, 'modifiers' => ModifierKey::Control]);
308+
}
309+
310+
/**
311+
* @param array<string, mixed> $options
312+
*/
313+
public function shiftClick(string $selector, array $options = []): self
314+
{
315+
return $this->click($selector, [...$options, 'modifiers' => ModifierKey::Shift]);
316+
}
317+
290318
/**
291319
* @param array<string, mixed> $options
292320
*/

src/Page/PageInterface.php

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,21 @@ public function goto(string $url, array $options = []): ?ResponseInterface;
3535
*/
3636
public function click(string $selector, array $options = []): self;
3737

38+
/**
39+
* @param array<string, mixed> $options
40+
*/
41+
public function altClick(string $selector, array $options = []): self;
42+
43+
/**
44+
* @param array<string, mixed> $options
45+
*/
46+
public function controlClick(string $selector, array $options = []): self;
47+
48+
/**
49+
* @param array<string, mixed> $options
50+
*/
51+
public function shiftClick(string $selector, array $options = []): self;
52+
3853
/**
3954
* @param array<string, mixed> $options
4055
*/
@@ -63,7 +78,8 @@ public function context(): BrowserContextInterface;
6378
/**
6479
* @param array<string>|null $urls
6580
*
66-
* @return array<array{name: string, value: string, domain: string, path: string, expires: int, httpOnly: bool, secure: bool, sameSite: 'Strict'|'Lax'|'None'}>
81+
* @return array<array{name: string, value: string, domain: string, path: string, expires: int, httpOnly: bool,
82+
* secure: bool, sameSite: 'Strict'|'Lax'|'None'}>
6783
*/
6884
public function cookies(?array $urls = null): array;
6985

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/*
6+
* This file is part of the playwright-php/playwright package.
7+
* For the full copyright and license information, please view
8+
* the LICENSE file that was distributed with this source code.
9+
*/
10+
11+
namespace PlaywrightPHP\Tests\Unit\Input;
12+
13+
use PHPUnit\Framework\Attributes\CoversClass;
14+
use PHPUnit\Framework\Attributes\DataProvider;
15+
use PHPUnit\Framework\TestCase;
16+
use PlaywrightPHP\Exception\InvalidArgumentException;
17+
use PlaywrightPHP\Input\ModifierKey;
18+
19+
#[CoversClass(ModifierKey::class)]
20+
final class ModifierKeyTest extends TestCase
21+
{
22+
public function testEnumValues(): void
23+
{
24+
$this->assertSame('Alt', ModifierKey::Alt->value);
25+
$this->assertSame('Control', ModifierKey::Control->value);
26+
$this->assertSame('Meta', ModifierKey::Meta->value);
27+
$this->assertSame('Shift', ModifierKey::Shift->value);
28+
}
29+
30+
#[DataProvider('provideFromStringData')]
31+
public function testFromString(ModifierKey $expected, string $input): void
32+
{
33+
$this->assertSame($expected, ModifierKey::fromString($input));
34+
}
35+
36+
public static function provideFromStringData(): array
37+
{
38+
return [
39+
'alt lowercase' => [ModifierKey::Alt, 'alt'],
40+
'alt uppercase' => [ModifierKey::Alt, 'Alt'],
41+
'control lowercase' => [ModifierKey::Control, 'control'],
42+
'control uppercase' => [ModifierKey::Control, 'Control'],
43+
'control short' => [ModifierKey::Control, 'ctrl'],
44+
'meta lowercase' => [ModifierKey::Meta, 'meta'],
45+
'meta uppercase' => [ModifierKey::Meta, 'Meta'],
46+
'meta cmd' => [ModifierKey::Meta, 'cmd'],
47+
'meta command' => [ModifierKey::Meta, 'command'],
48+
'shift lowercase' => [ModifierKey::Shift, 'shift'],
49+
'shift uppercase' => [ModifierKey::Shift, 'Shift'],
50+
];
51+
}
52+
53+
public function testFromStringWithInvalidModifier(): void
54+
{
55+
$this->expectException(InvalidArgumentException::class);
56+
$this->expectExceptionMessage('Unknown modifier key: "invalid".');
57+
58+
ModifierKey::fromString('invalid');
59+
}
60+
}

0 commit comments

Comments
 (0)