Skip to content

Commit e1f7612

Browse files
committed
[BrowserKit] Add proper exception hierarchy
1 parent da9f199 commit e1f7612

14 files changed

+129
-34
lines changed

AbstractBrowser.php

+12-9
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@
1212
namespace Symfony\Component\BrowserKit;
1313

1414
use Symfony\Component\BrowserKit\Exception\BadMethodCallException;
15+
use Symfony\Component\BrowserKit\Exception\InvalidArgumentException;
16+
use Symfony\Component\BrowserKit\Exception\LogicException;
17+
use Symfony\Component\BrowserKit\Exception\RuntimeException;
1518
use Symfony\Component\DomCrawler\Crawler;
1619
use Symfony\Component\DomCrawler\Form;
1720
use Symfony\Component\DomCrawler\Link;
@@ -110,12 +113,12 @@ public function getMaxRedirects(): int
110113
*
111114
* @return void
112115
*
113-
* @throws \RuntimeException When Symfony Process Component is not installed
116+
* @throws LogicException When Symfony Process Component is not installed
114117
*/
115118
public function insulate(bool $insulated = true)
116119
{
117120
if ($insulated && !class_exists(\Symfony\Component\Process\Process::class)) {
118-
throw new \LogicException('Unable to isolate requests as the Symfony Process Component is not installed.');
121+
throw new LogicException('Unable to isolate requests as the Symfony Process Component is not installed.');
119122
}
120123

121124
$this->insulated = $insulated;
@@ -335,7 +338,7 @@ public function submitForm(string $button, array $fieldValues = [], string $meth
335338
$buttonNode = $this->crawler->selectButton($button);
336339

337340
if (0 === $buttonNode->count()) {
338-
throw new \InvalidArgumentException(sprintf('There is no button with "%s" as its content, id, value or name.', $button));
341+
throw new InvalidArgumentException(sprintf('There is no button with "%s" as its content, id, value or name.', $button));
339342
}
340343

341344
$form = $buttonNode->form($fieldValues, $method);
@@ -459,7 +462,7 @@ protected function doRequestInProcess(object $request)
459462
}
460463

461464
if (!$process->isSuccessful() || !preg_match('/^O\:\d+\:/', $process->getOutput())) {
462-
throw new \RuntimeException(sprintf('OUTPUT: %s ERROR OUTPUT: %s.', $process->getOutput(), $process->getErrorOutput()));
465+
throw new RuntimeException(sprintf('OUTPUT: %s ERROR OUTPUT: %s.', $process->getOutput(), $process->getErrorOutput()));
463466
}
464467

465468
return unserialize($process->getOutput());
@@ -477,11 +480,11 @@ abstract protected function doRequest(object $request);
477480
*
478481
* @param object $request An origin request instance
479482
*
480-
* @throws \LogicException When this abstract class is not implemented
483+
* @throws LogicException When this abstract class is not implemented
481484
*/
482485
protected function getScript(object $request)
483486
{
484-
throw new \LogicException('To insulate requests, you need to override the getScript() method.');
487+
throw new LogicException('To insulate requests, you need to override the getScript() method.');
485488
}
486489

487490
/**
@@ -556,18 +559,18 @@ public function reload(): Crawler
556559
/**
557560
* Follow redirects?
558561
*
559-
* @throws \LogicException If request was not a redirect
562+
* @throws LogicException If request was not a redirect
560563
*/
561564
public function followRedirect(): Crawler
562565
{
563566
if (empty($this->redirect)) {
564-
throw new \LogicException('The request was not redirected.');
567+
throw new LogicException('The request was not redirected.');
565568
}
566569

567570
if (-1 !== $this->maxRedirects) {
568571
if ($this->redirectCount > $this->maxRedirects) {
569572
$this->redirectCount = 0;
570-
throw new \LogicException(sprintf('The maximum number (%d) of redirections was reached.', $this->maxRedirects));
573+
throw new LogicException(sprintf('The maximum number (%d) of redirections was reached.', $this->maxRedirects));
571574
}
572575
}
573576

Cookie.php

+7-4
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111

1212
namespace Symfony\Component\BrowserKit;
1313

14+
use Symfony\Component\BrowserKit\Exception\InvalidArgumentException;
15+
use Symfony\Component\BrowserKit\Exception\UnexpectedValueException;
16+
1417
/**
1518
* Cookie represents an HTTP cookie.
1619
*
@@ -74,7 +77,7 @@ public function __construct(string $name, ?string $value, string $expires = null
7477
if (null !== $expires) {
7578
$timestampAsDateTime = \DateTimeImmutable::createFromFormat('U', $expires);
7679
if (false === $timestampAsDateTime) {
77-
throw new \UnexpectedValueException(sprintf('The cookie expiration time "%s" is not valid.', $expires));
80+
throw new UnexpectedValueException(sprintf('The cookie expiration time "%s" is not valid.', $expires));
7881
}
7982

8083
$this->expires = $timestampAsDateTime->format('U');
@@ -119,14 +122,14 @@ public function __toString(): string
119122
/**
120123
* Creates a Cookie instance from a Set-Cookie header value.
121124
*
122-
* @throws \InvalidArgumentException
125+
* @throws InvalidArgumentException
123126
*/
124127
public static function fromString(string $cookie, string $url = null): static
125128
{
126129
$parts = explode(';', $cookie);
127130

128131
if (!str_contains($parts[0], '=')) {
129-
throw new \InvalidArgumentException(sprintf('The cookie string "%s" is not valid.', $parts[0]));
132+
throw new InvalidArgumentException(sprintf('The cookie string "%s" is not valid.', $parts[0]));
130133
}
131134

132135
[$name, $value] = explode('=', array_shift($parts), 2);
@@ -145,7 +148,7 @@ public static function fromString(string $cookie, string $url = null): static
145148

146149
if (null !== $url) {
147150
if ((false === $urlParts = parse_url($url)) || !isset($urlParts['host'])) {
148-
throw new \InvalidArgumentException(sprintf('The URL "%s" is not valid.', $url));
151+
throw new InvalidArgumentException(sprintf('The URL "%s" is not valid.', $url));
149152
}
150153

151154
$values['domain'] = $urlParts['host'];

CookieJar.php

+3-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111

1212
namespace Symfony\Component\BrowserKit;
1313

14+
use Symfony\Component\BrowserKit\Exception\InvalidArgumentException;
15+
1416
/**
1517
* CookieJar.
1618
*
@@ -129,7 +131,7 @@ public function updateFromSetCookie(array $setCookies, string $uri = null)
129131
foreach ($cookies as $cookie) {
130132
try {
131133
$this->set(Cookie::fromString($cookie, $uri));
132-
} catch (\InvalidArgumentException) {
134+
} catch (InvalidArgumentException) {
133135
// invalid cookies are just ignored
134136
}
135137
}

Exception/BadMethodCallException.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,6 @@
1111

1212
namespace Symfony\Component\BrowserKit\Exception;
1313

14-
class BadMethodCallException extends \BadMethodCallException
14+
class BadMethodCallException extends \BadMethodCallException implements ExceptionInterface
1515
{
1616
}

Exception/ExceptionInterface.php

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\BrowserKit\Exception;
13+
14+
/**
15+
* Base ExceptionInterface for the BrowserKit component.
16+
*
17+
* @author Fabien Potencier <[email protected]>
18+
*/
19+
interface ExceptionInterface extends \Throwable
20+
{
21+
}
+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\BrowserKit\Exception;
13+
14+
class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
15+
{
16+
}

Exception/JsonException.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,6 @@
1111

1212
namespace Symfony\Component\BrowserKit\Exception;
1313

14-
class JsonException extends \JsonException
14+
class JsonException extends \JsonException implements ExceptionInterface
1515
{
1616
}

Exception/LogicException.php

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\BrowserKit\Exception;
13+
14+
class LogicException extends \LogicException implements ExceptionInterface
15+
{
16+
}

Exception/RuntimeException.php

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\BrowserKit\Exception;
13+
14+
class RuntimeException extends \RuntimeException implements ExceptionInterface
15+
{
16+
}
+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\BrowserKit\Exception;
13+
14+
class UnexpectedValueException extends \UnexpectedValueException implements ExceptionInterface
15+
{
16+
}

History.php

+8-6
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111

1212
namespace Symfony\Component\BrowserKit;
1313

14+
use Symfony\Component\BrowserKit\Exception\LogicException;
15+
1416
/**
1517
* History.
1618
*
@@ -55,12 +57,12 @@ public function isEmpty(): bool
5557
/**
5658
* Goes back in the history.
5759
*
58-
* @throws \LogicException if the stack is already on the first page
60+
* @throws LogicException if the stack is already on the first page
5961
*/
6062
public function back(): Request
6163
{
6264
if ($this->position < 1) {
63-
throw new \LogicException('You are already on the first page.');
65+
throw new LogicException('You are already on the first page.');
6466
}
6567

6668
return clone $this->stack[--$this->position];
@@ -69,12 +71,12 @@ public function back(): Request
6971
/**
7072
* Goes forward in the history.
7173
*
72-
* @throws \LogicException if the stack is already on the last page
74+
* @throws LogicException if the stack is already on the last page
7375
*/
7476
public function forward(): Request
7577
{
7678
if ($this->position > \count($this->stack) - 2) {
77-
throw new \LogicException('You are already on the last page.');
79+
throw new LogicException('You are already on the last page.');
7880
}
7981

8082
return clone $this->stack[++$this->position];
@@ -83,12 +85,12 @@ public function forward(): Request
8385
/**
8486
* Returns the current element in the history.
8587
*
86-
* @throws \LogicException if the stack is empty
88+
* @throws LogicException if the stack is empty
8789
*/
8890
public function current(): Request
8991
{
9092
if (-1 === $this->position) {
91-
throw new \LogicException('The page history is empty.');
93+
throw new LogicException('The page history is empty.');
9294
}
9395

9496
return clone $this->stack[$this->position];

HttpBrowser.php

+3-2
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
namespace Symfony\Component\BrowserKit;
1313

14+
use Symfony\Component\BrowserKit\Exception\LogicException;
1415
use Symfony\Component\HttpClient\HttpClient;
1516
use Symfony\Component\Mime\Part\AbstractPart;
1617
use Symfony\Component\Mime\Part\DataPart;
@@ -31,7 +32,7 @@ class HttpBrowser extends AbstractBrowser
3132
public function __construct(HttpClientInterface $client = null, History $history = null, CookieJar $cookieJar = null)
3233
{
3334
if (!$client && !class_exists(HttpClient::class)) {
34-
throw new \LogicException(sprintf('You cannot use "%s" as the HttpClient component is not installed. Try running "composer require symfony/http-client".', __CLASS__));
35+
throw new LogicException(sprintf('You cannot use "%s" as the HttpClient component is not installed. Try running "composer require symfony/http-client".', __CLASS__));
3536
}
3637

3738
$this->client = $client ?? HttpClient::create();
@@ -66,7 +67,7 @@ private function getBodyAndExtraHeaders(Request $request, array $headers): array
6667
}
6768

6869
if (!class_exists(AbstractPart::class)) {
69-
throw new \LogicException('You cannot pass non-empty bodies as the Mime component is not installed. Try running "composer require symfony/mime".');
70+
throw new LogicException('You cannot pass non-empty bodies as the Mime component is not installed. Try running "composer require symfony/mime".');
7071
}
7172

7273
if (null !== $content = $request->getContent()) {

Tests/AbstractBrowserTest.php

+4-7
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use PHPUnit\Framework\TestCase;
1515
use Symfony\Component\BrowserKit\CookieJar;
1616
use Symfony\Component\BrowserKit\Exception\BadMethodCallException;
17+
use Symfony\Component\BrowserKit\Exception\InvalidArgumentException;
1718
use Symfony\Component\BrowserKit\History;
1819
use Symfony\Component\BrowserKit\Request;
1920
use Symfony\Component\BrowserKit\Response;
@@ -294,12 +295,8 @@ public function testClickLinkNotFound()
294295
$client->setNextResponse(new Response('<html><a href="/foo">foobar</a></html>'));
295296
$client->request('GET', 'http://www.example.com/foo/foobar');
296297

297-
try {
298-
$client->clickLink('foo');
299-
$this->fail('->clickLink() throws a \InvalidArgumentException if the link could not be found');
300-
} catch (\Exception $e) {
301-
$this->assertInstanceOf(\InvalidArgumentException::class, $e, '->clickLink() throws a \InvalidArgumentException if the link could not be found');
302-
}
298+
$this->expectException(\InvalidArgumentException::class);
299+
$client->clickLink('foo');
303300
}
304301

305302
public function testClickForm()
@@ -351,7 +348,7 @@ public function testSubmitFormNotFound()
351348
$client->request('GET', 'http://www.example.com/foo/foobar');
352349

353350
$this->expectExceptionObject(
354-
new \InvalidArgumentException('There is no button with "Register" as its content, id, value or name.')
351+
new InvalidArgumentException('There is no button with "Register" as its content, id, value or name.')
355352
);
356353

357354
$client->submitForm('Register', [

Tests/CookieTest.php

+5-3
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313

1414
use PHPUnit\Framework\TestCase;
1515
use Symfony\Component\BrowserKit\Cookie;
16+
use Symfony\Component\BrowserKit\Exception\InvalidArgumentException;
17+
use Symfony\Component\BrowserKit\Exception\UnexpectedValueException;
1618

1719
class CookieTest extends TestCase
1820
{
@@ -104,7 +106,7 @@ public function testFromStringWithUrl()
104106

105107
public function testFromStringThrowsAnExceptionIfCookieIsNotValid()
106108
{
107-
$this->expectException(\InvalidArgumentException::class);
109+
$this->expectException(InvalidArgumentException::class);
108110
Cookie::fromString('foo');
109111
}
110112

@@ -117,7 +119,7 @@ public function testFromStringIgnoresInvalidExpiresDate()
117119

118120
public function testFromStringThrowsAnExceptionIfUrlIsNotValid()
119121
{
120-
$this->expectException(\InvalidArgumentException::class);
122+
$this->expectException(InvalidArgumentException::class);
121123
Cookie::fromString('foo=bar', 'foobar');
122124
}
123125

@@ -200,7 +202,7 @@ public function testIsExpired()
200202

201203
public function testConstructException()
202204
{
203-
$this->expectException(\UnexpectedValueException::class);
205+
$this->expectException(UnexpectedValueException::class);
204206
$this->expectExceptionMessage('The cookie expiration time "string" is not valid.');
205207
new Cookie('foo', 'bar', 'string');
206208
}

0 commit comments

Comments
 (0)