Skip to content

Commit e7a0c20

Browse files
committed
added PHPUnit assertions in various components
1 parent 2f8040e commit e7a0c20

32 files changed

+1884
-262
lines changed

src/Symfony/Bundle/FrameworkBundle/Test/WebTestAssertions.php

+100-258
Large diffs are not rendered by default.

src/Symfony/Bundle/FrameworkBundle/Test/WebTestCase.php

+5-3
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,14 @@ abstract class WebTestCase extends KernelTestCase
2323
{
2424
use WebTestAssertions;
2525

26+
/** @var Client|null */
27+
protected static $client;
28+
2629
protected function doTearDown(): void
2730
{
2831
parent::doTearDown();
29-
if (static::$client) {
30-
static::$client = null;
31-
}
32+
33+
static::$client = null;
3234
}
3335

3436
/**
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,288 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
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\Bundle\FrameworkBundle\Tests\Test;
13+
14+
use PHPUnit\Framework\AssertionFailedError;
15+
use PHPUnit\Framework\TestCase;
16+
use Symfony\Bundle\FrameworkBundle\KernelBrowser;
17+
use Symfony\Bundle\FrameworkBundle\Test\WebTestAssertions;
18+
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
19+
use Symfony\Component\BrowserKit\Cookie;
20+
use Symfony\Component\BrowserKit\CookieJar;
21+
use Symfony\Component\DomCrawler\Crawler;
22+
use Symfony\Component\HttpFoundation\Cookie as HttpFoundationCookie;
23+
use Symfony\Component\HttpFoundation\Request;
24+
use Symfony\Component\HttpFoundation\Response;
25+
26+
class WebTestCaseTest extends TestCase
27+
{
28+
public function testAssertResponseIsSuccessful()
29+
{
30+
$this->getResponseTester(new Response())->assertResponseIsSuccessful();
31+
$this->expectException(AssertionFailedError::class);
32+
$this->expectExceptionMessage("Failed asserting that the Response is successful.\nHTTP/1.0 404 Not Found");
33+
$this->getResponseTester(new Response('', 404))->assertResponseIsSuccessful();
34+
}
35+
36+
public function testAssertResponseStatusCodeSame()
37+
{
38+
$this->getResponseTester(new Response())->assertResponseStatusCodeSame(200);
39+
$this->getResponseTester(new Response('', 404))->assertResponseStatusCodeSame(404);
40+
$this->expectException(AssertionFailedError::class);
41+
$this->expectExceptionMessage("Failed asserting that the Response status code is 200.\nHTTP/1.0 404 Not Found");
42+
$this->getResponseTester(new Response('', 404))->assertResponseStatusCodeSame(200);
43+
}
44+
45+
public function testAssertResponseRedirects()
46+
{
47+
$this->getResponseTester(new Response('', 301))->assertResponseRedirects();
48+
$this->expectException(AssertionFailedError::class);
49+
$this->expectExceptionMessage("Failed asserting that the Response is redirected.\nHTTP/1.0 200 OK");
50+
$this->getResponseTester(new Response())->assertResponseRedirects();
51+
}
52+
53+
public function testAssertResponseRedirectsWithLocation()
54+
{
55+
$this->getResponseTester(new Response('', 301, ['Location' => 'https://example.com/']))->assertResponseRedirects('https://example.com/');
56+
$this->expectException(AssertionFailedError::class);
57+
$this->expectExceptionMessage('is redirected and has header "Location" with value "https://example.com/".');
58+
$this->getResponseTester(new Response('', 301))->assertResponseRedirects('https://example.com/');
59+
}
60+
61+
public function testAssertResponseRedirectsWithStatusCode()
62+
{
63+
$this->getResponseTester(new Response('', 302))->assertResponseRedirects(null, 302);
64+
$this->expectException(AssertionFailedError::class);
65+
$this->expectExceptionMessage('is redirected and status code is 301.');
66+
$this->getResponseTester(new Response('', 302))->assertResponseRedirects(null, 301);
67+
}
68+
69+
public function testAssertResponseRedirectsWithLocationAndStatusCode()
70+
{
71+
$this->getResponseTester(new Response('', 302, ['Location' => 'https://example.com/']))->assertResponseRedirects('https://example.com/', 302);
72+
$this->expectException(AssertionFailedError::class);
73+
$this->expectExceptionMessage('is redirected and has header "Location" with value "https://example.com/" and status code is 301.');
74+
$this->getResponseTester(new Response('', 302))->assertResponseRedirects('https://example.com/', 301);
75+
}
76+
77+
public function testAssertResponseHasHeader()
78+
{
79+
$this->getResponseTester(new Response())->assertResponseHasHeader('Date');
80+
$this->expectException(AssertionFailedError::class);
81+
$this->expectExceptionMessage('Failed asserting that the Response has header "X-Date".');
82+
$this->getResponseTester(new Response())->assertResponseHasHeader('X-Date');
83+
}
84+
85+
public function testAssertResponseNotHasHeader()
86+
{
87+
$this->getResponseTester(new Response())->assertResponseNotHasHeader('X-Date');
88+
$this->expectException(AssertionFailedError::class);
89+
$this->expectExceptionMessage('Failed asserting that the Response does not have header "Date".');
90+
$this->getResponseTester(new Response())->assertResponseNotHasHeader('Date');
91+
}
92+
93+
public function testAssertResponseHeaderSame()
94+
{
95+
$this->getResponseTester(new Response())->assertResponseHeaderSame('Cache-Control', 'no-cache, private');
96+
$this->expectException(AssertionFailedError::class);
97+
$this->expectExceptionMessage('Failed asserting that the Response has header "Cache-Control" with value "public".');
98+
$this->getResponseTester(new Response())->assertResponseHeaderSame('Cache-Control', 'public');
99+
}
100+
101+
public function testAssertResponseHeaderNotSame()
102+
{
103+
$this->getResponseTester(new Response())->assertResponseHeaderNotSame('Cache-Control', 'public');
104+
$this->expectException(AssertionFailedError::class);
105+
$this->expectExceptionMessage('Failed asserting that the Response does not have header "Cache-Control" with value "no-cache, private".');
106+
$this->getResponseTester(new Response())->assertResponseHeaderNotSame('Cache-Control', 'no-cache, private');
107+
}
108+
109+
public function testAssertResponseHasCookie()
110+
{
111+
$response = new Response();
112+
$response->headers->setCookie(HttpFoundationCookie::create('foo', 'bar'));
113+
114+
$this->getResponseTester($response)->assertResponseHasCookie('foo');
115+
$this->expectException(AssertionFailedError::class);
116+
$this->expectExceptionMessage('Failed asserting that the Response has cookie "bar".');
117+
$this->getResponseTester($response)->assertResponseHasCookie('bar');
118+
}
119+
120+
public function testAssertResponseNotHasCookie()
121+
{
122+
$response = new Response();
123+
$response->headers->setCookie(HttpFoundationCookie::create('foo', 'bar'));
124+
125+
$this->getResponseTester($response)->assertResponseNotHasCookie('bar');
126+
$this->expectException(AssertionFailedError::class);
127+
$this->expectExceptionMessage('Failed asserting that the Response does not have cookie "foo".');
128+
$this->getResponseTester($response)->assertResponseNotHasCookie('foo');
129+
}
130+
131+
public function testAssertResponseCookieValueSame()
132+
{
133+
$response = new Response();
134+
$response->headers->setCookie(HttpFoundationCookie::create('foo', 'bar'));
135+
136+
$this->getResponseTester($response)->assertResponseCookieValueSame('foo', 'bar');
137+
$this->expectException(AssertionFailedError::class);
138+
$this->expectExceptionMessage('has cookie "bar" and has cookie "bar" with value "bar".');
139+
$this->getResponseTester($response)->assertResponseCookieValueSame('bar', 'bar');
140+
}
141+
142+
public function testAssertBrowserHasCookie()
143+
{
144+
$this->getClientTester()->assertBrowserHasCookie('foo', '/path');
145+
$this->expectException(AssertionFailedError::class);
146+
$this->expectExceptionMessage('Failed asserting that the Browser has cookie "bar".');
147+
$this->getClientTester()->assertBrowserHasCookie('bar');
148+
}
149+
150+
public function testAssertBrowserNotHasCookie()
151+
{
152+
$this->getClientTester()->assertBrowserNotHasCookie('bar');
153+
$this->expectException(AssertionFailedError::class);
154+
$this->expectExceptionMessage('Failed asserting that the Browser does not have cookie "foo" with path "/path".');
155+
$this->getClientTester()->assertBrowserNotHasCookie('foo', '/path');
156+
}
157+
158+
public function testAssertBrowserCookieValueSame()
159+
{
160+
$this->getClientTester()->assertBrowserCookieValueSame('foo', 'bar', false, '/path');
161+
$this->expectException(AssertionFailedError::class);
162+
$this->expectExceptionMessage('has cookie "foo" with path "/path" and has cookie "foo" with path "/path" with value "babar".');
163+
$this->getClientTester()->assertBrowserCookieValueSame('foo', 'babar', false, '/path');
164+
}
165+
166+
public function testAssertSelectorExists()
167+
{
168+
$this->getCrawlerTester(new Crawler('<html><body><h1>'))->assertSelectorExists('body > h1');
169+
$this->expectException(AssertionFailedError::class);
170+
$this->expectExceptionMessage('matches selector "body > h1".');
171+
$this->getCrawlerTester(new Crawler('<html><head><title>Foo'))->assertSelectorExists('body > h1');
172+
}
173+
174+
public function testAssertSelectorNotExists()
175+
{
176+
$this->getCrawlerTester(new Crawler('<html><head><title>Foo'))->assertSelectorNotExists('body > h1');
177+
$this->expectException(AssertionFailedError::class);
178+
$this->expectExceptionMessage('does not match selector "body > h1".');
179+
$this->getCrawlerTester(new Crawler('<html><body><h1>'))->assertSelectorNotExists('body > h1');
180+
}
181+
182+
public function testAssertSelectorTextNotContains()
183+
{
184+
$this->getCrawlerTester(new Crawler('<html><body><h1>Foo'))->assertSelectorTextNotContains('body > h1', 'Bar');
185+
$this->expectException(AssertionFailedError::class);
186+
$this->expectExceptionMessage('matches selector "body > h1" and does not have a node matching selector "body > h1" with content containing "Foo".');
187+
$this->getCrawlerTester(new Crawler('<html><body><h1>Foo'))->assertSelectorTextNotContains('body > h1', 'Foo');
188+
}
189+
190+
public function testAssertPageTitleSame()
191+
{
192+
$this->getCrawlerTester(new Crawler('<html><head><title>Foo'))->assertPageTitleSame('Foo');
193+
$this->expectException(AssertionFailedError::class);
194+
$this->expectExceptionMessage('matches selector "title" and has a node matching selector "title" with content "Bar".');
195+
$this->getCrawlerTester(new Crawler('<html><head><title>Foo'))->assertPageTitleSame('Bar');
196+
}
197+
198+
public function testAssertPageTitleContains()
199+
{
200+
$this->getCrawlerTester(new Crawler('<html><head><title>Foobar'))->assertPageTitleContains('Foo');
201+
$this->expectException(AssertionFailedError::class);
202+
$this->expectExceptionMessage('matches selector "title" and has a node matching selector "title" with content containing "Bar".');
203+
$this->getCrawlerTester(new Crawler('<html><head><title>Foo'))->assertPageTitleContains('Bar');
204+
}
205+
206+
public function testAssertInputValueSame()
207+
{
208+
$this->getCrawlerTester(new Crawler('<html><body><form><input type="text" name="username" value="Fabien">'))->assertInputValueSame('username', 'Fabien');
209+
$this->expectException(AssertionFailedError::class);
210+
$this->expectExceptionMessage('matches selector "input[name="password"]" and has a node matching selector "input[name="password"]" with attribute "value" of value "pa$$".');
211+
$this->getCrawlerTester(new Crawler('<html><head><title>Foo'))->assertInputValueSame('password', 'pa$$');
212+
}
213+
214+
public function testAssertInputValueNotSame()
215+
{
216+
$this->getCrawlerTester(new Crawler('<html><body><input type="text" name="username" value="Helene">'))->assertInputValueNotSame('username', 'Fabien');
217+
$this->expectException(AssertionFailedError::class);
218+
$this->expectExceptionMessage('matches selector "input[name="password"]" and does not have a node matching selector "input[name="password"]" with attribute "value" of value "pa$$".');
219+
$this->getCrawlerTester(new Crawler('<html><body><form><input type="text" name="password" value="pa$$">'))->assertInputValueNotSame('password', 'pa$$');
220+
}
221+
222+
public function testAssertRequestAttributeValueSame()
223+
{
224+
$this->getRequestTester()->assertRequestAttributeValueSame('foo', 'bar');
225+
$this->expectException(AssertionFailedError::class);
226+
$this->expectExceptionMessage('Failed asserting that the Request has attribute "foo" with value "baz".');
227+
$this->getRequestTester()->assertRequestAttributeValueSame('foo', 'baz');
228+
}
229+
230+
public function testAssertRouteSame()
231+
{
232+
$this->getRequestTester()->assertRouteSame('homepage', ['foo' => 'bar']);
233+
$this->expectException(AssertionFailedError::class);
234+
$this->expectExceptionMessage('Failed asserting that the Request has attribute "_route" with value "articles".');
235+
$this->getRequestTester()->assertRouteSame('articles');
236+
}
237+
238+
private function getResponseTester(Response $response): WebTestCase
239+
{
240+
$client = $this->createMock(KernelBrowser::class);
241+
$client->expects($this->any())->method('getResponse')->will($this->returnValue($response));
242+
243+
return $this->getTester($client);
244+
}
245+
246+
private function getCrawlerTester(Crawler $crawler): WebTestCase
247+
{
248+
$client = $this->createMock(KernelBrowser::class);
249+
$client->expects($this->any())->method('getCrawler')->will($this->returnValue($crawler));
250+
251+
return $this->getTester($client);
252+
}
253+
254+
private function getClientTester(): WebTestCase
255+
{
256+
$client = $this->createMock(KernelBrowser::class);
257+
$jar = new CookieJar();
258+
$jar->set(new Cookie('foo', 'bar', null, '/path', 'example.com'));
259+
$client->expects($this->any())->method('getCookieJar')->will($this->returnValue($jar));
260+
261+
return $this->getTester($client);
262+
}
263+
264+
private function getRequestTester(): WebTestCase
265+
{
266+
$client = $this->createMock(KernelBrowser::class);
267+
$request = new Request();
268+
$request->attributes->set('foo', 'bar');
269+
$request->attributes->set('_route', 'homepage');
270+
$client->expects($this->any())->method('getRequest')->will($this->returnValue($request));
271+
272+
return $this->getTester($client);
273+
}
274+
275+
private function getTester(KernelBrowser $client): WebTestCase
276+
{
277+
return new class($client) extends WebTestCase {
278+
use WebTestAssertions;
279+
280+
protected static $client;
281+
282+
public function __construct(KernelBrowser $client)
283+
{
284+
static::$client = $client;
285+
}
286+
};
287+
}
288+
}

src/Symfony/Bundle/FrameworkBundle/composer.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
"symfony/browser-kit": "^4.3",
3737
"symfony/console": "^4.3",
3838
"symfony/css-selector": "~3.4|~4.0",
39-
"symfony/dom-crawler": "~3.4|~4.0",
39+
"symfony/dom-crawler": "^4.3",
4040
"symfony/polyfill-intl-icu": "~1.0",
4141
"symfony/security": "~3.4|~4.0",
4242
"symfony/form": "^4.3",
@@ -72,6 +72,7 @@
7272
"symfony/browser-kit": "<4.3",
7373
"symfony/console": "<4.3",
7474
"symfony/dotenv": "<4.2",
75+
"symfony/dom-crawler": "<4.3",
7576
"symfony/form": "<4.3",
7677
"symfony/messenger": "<4.3",
7778
"symfony/property-info": "<3.4",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
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\Test\Constraint;
13+
14+
use PHPUnit\Framework\Constraint\Constraint;
15+
use Symfony\Component\BrowserKit\AbstractBrowser;
16+
17+
final class BrowserCookieValueSame extends Constraint
18+
{
19+
private $name;
20+
private $value;
21+
private $raw;
22+
private $path;
23+
private $domain;
24+
25+
public function __construct(string $name, string $value, bool $raw = false, string $path = '/', string $domain = null)
26+
{
27+
$this->name = $name;
28+
$this->path = $path;
29+
$this->domain = $domain;
30+
$this->value = $value;
31+
$this->raw = $raw;
32+
}
33+
34+
/**
35+
* {@inheritdoc}
36+
*/
37+
public function toString(): string
38+
{
39+
$str = sprintf('has cookie "%s"', $this->name);
40+
if ('/' !== $this->path) {
41+
$str .= sprintf(' with path "%s"', $this->path);
42+
}
43+
if ($this->domain) {
44+
$str .= sprintf(' for domain "%s"', $this->domain);
45+
}
46+
$str .= sprintf(' with %svalue "%s"', $this->raw ? 'raw ' : '', $this->value);
47+
48+
return $str;
49+
}
50+
51+
/**
52+
* @param AbstractBrowser $browser
53+
*
54+
* {@inheritdoc}
55+
*/
56+
protected function matches($browser): bool
57+
{
58+
$cookie = $browser->getCookieJar()->get($this->name, $this->path, $this->domain);
59+
if (!$cookie) {
60+
return false;
61+
}
62+
63+
return $this->value === ($this->raw ? $cookie->getRawValue() : $cookie->getValue());
64+
}
65+
66+
/**
67+
* @param AbstractBrowser $browser
68+
*
69+
* {@inheritdoc}
70+
*/
71+
protected function failureDescription($browser): string
72+
{
73+
return 'the Browser '.$this->toString();
74+
}
75+
}

0 commit comments

Comments
 (0)