Version 1
[yaffs-website] / web / core / tests / Drupal / Tests / Core / Path / PathValidatorTest.php
1 <?php
2
3 namespace Drupal\Tests\Core\Path;
4
5 use Drupal\Core\ParamConverter\ParamNotConvertedException;
6 use Drupal\Core\Path\PathValidator;
7 use Drupal\Tests\UnitTestCase;
8 use Symfony\Cmf\Component\Routing\RouteObjectInterface;
9 use Symfony\Component\HttpFoundation\ParameterBag;
10 use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
11 use Symfony\Component\Routing\Exception\MethodNotAllowedException;
12 use Symfony\Component\Routing\Exception\ResourceNotFoundException;
13
14 /**
15  * @coversDefaultClass \Drupal\Core\Path\PathValidator
16  * @group Routing
17  */
18 class PathValidatorTest extends UnitTestCase {
19
20   /**
21    * The mocked access aware router.
22    *
23    * @var \Drupal\Core\Routing\AccessAwareRouterInterface|\PHPUnit_Framework_MockObject_MockObject
24    */
25   protected $accessAwareRouter;
26
27   /**
28    * The mocked access unaware router.
29    * @var \Symfony\Component\Routing\Matcher\UrlMatcherInterface|\PHPUnit_Framework_MockObject_MockObject
30    */
31   protected $accessUnawareRouter;
32
33   /**
34    * The mocked account.
35    *
36    * @var \Drupal\Core\Session\AccountInterface|\PHPUnit_Framework_MockObject_MockObject
37    */
38   protected $account;
39
40   /**
41    * The path processor.
42    *
43    * @var \Drupal\Core\PathProcessor\InboundPathProcessorInterface|\PHPUnit_Framework_MockObject_MockObject
44    */
45   protected $pathProcessor;
46
47   /**
48    * The tested path validator.
49    *
50    * @var \Drupal\Core\Path\PathValidator
51    */
52   protected $pathValidator;
53
54   /**
55    * {@inheritdoc}
56    */
57   protected function setUp() {
58     parent::setUp();
59
60     $this->accessAwareRouter = $this->getMock('Drupal\Core\Routing\AccessAwareRouterInterface');
61     $this->accessUnawareRouter = $this->getMock('Symfony\Component\Routing\Matcher\UrlMatcherInterface');
62     $this->account = $this->getMock('Drupal\Core\Session\AccountInterface');
63     $this->pathProcessor = $this->getMock('Drupal\Core\PathProcessor\InboundPathProcessorInterface');
64     $this->pathValidator = new PathValidator($this->accessAwareRouter, $this->accessUnawareRouter, $this->account, $this->pathProcessor);
65   }
66
67   /**
68    * Tests the isValid() method for the frontpage.
69    *
70    * @covers ::isValid
71    */
72   public function testIsValidWithFrontpage() {
73     $this->accessAwareRouter->expects($this->never())
74       ->method('match');
75
76     $this->assertTrue($this->pathValidator->isValid('<front>'));
77   }
78
79   /**
80    * Tests the isValid() method for <none> (used for jumplinks).
81    *
82    * @covers ::isValid
83    */
84   public function testIsValidWithNone() {
85     $this->accessAwareRouter->expects($this->never())
86       ->method('match');
87
88     $this->assertTrue($this->pathValidator->isValid('<none>'));
89   }
90
91   /**
92    * Tests the isValid() method for an external URL.
93    *
94    * @covers ::isValid
95    */
96   public function testIsValidWithExternalUrl() {
97     $this->accessAwareRouter->expects($this->never())
98       ->method('match');
99
100     $this->assertTrue($this->pathValidator->isValid('https://www.drupal.org'));
101   }
102
103   /**
104    * Tests the isValid() method with an invalid external URL.
105    *
106    * @covers ::isValid
107    */
108   public function testIsValidWithInvalidExternalUrl() {
109     $this->accessAwareRouter->expects($this->never())
110       ->method('match');
111
112     $this->assertFalse($this->pathValidator->isValid('http://'));
113   }
114
115   /**
116    * Tests the isValid() method with a 'link to any page' permission.
117    *
118    * @covers ::isValid
119    * @covers ::getPathAttributes
120    */
121   public function testIsValidWithLinkToAnyPageAccount() {
122     $this->account->expects($this->once())
123       ->method('hasPermission')
124       ->with('link to any page')
125       ->willReturn(TRUE);
126     $this->accessAwareRouter->expects($this->never())
127       ->method('match');
128     $this->accessUnawareRouter->expects($this->once())
129       ->method('match')
130       ->with('/test-path')
131       ->willReturn([RouteObjectInterface::ROUTE_NAME => 'test_route', '_raw_variables' => new ParameterBag(['key' => 'value'])]);
132     $this->pathProcessor->expects($this->once())
133       ->method('processInbound')
134       ->willReturnArgument(0);
135
136
137     $this->assertTrue($this->pathValidator->isValid('test-path'));
138   }
139
140   /**
141    * Tests the isValid() method without the 'link to any page' permission.
142    *
143    * @covers ::isValid
144    */
145   public function testIsValidWithoutLinkToAnyPageAccount() {
146     $this->account->expects($this->once())
147       ->method('hasPermission')
148       ->with('link to any page')
149       ->willReturn(FALSE);
150     $this->accessUnawareRouter->expects($this->never())
151       ->method('match');
152     $this->accessAwareRouter->expects($this->once())
153       ->method('match')
154       ->with('/test-path')
155       ->willReturn([RouteObjectInterface::ROUTE_NAME => 'test_route', '_raw_variables' => new ParameterBag(['key' => 'value'])]);
156     $this->pathProcessor->expects($this->once())
157       ->method('processInbound')
158       ->willReturnArgument(0);
159
160     $this->assertTrue($this->pathValidator->isValid('test-path'));
161   }
162
163   /**
164    * Tests the isValid() method with a path alias.
165    *
166    * @covers ::isValid
167    */
168   public function testIsValidWithPathAlias() {
169     $this->account->expects($this->once())
170       ->method('hasPermission')
171       ->with('link to any page')
172       ->willReturn(FALSE);
173     $this->accessUnawareRouter->expects($this->never())
174       ->method('match');
175     $this->accessAwareRouter->expects($this->once())
176       ->method('match')
177       ->with('/test-path')
178       ->willReturn([RouteObjectInterface::ROUTE_NAME => 'test_route', '_raw_variables' => new ParameterBag(['key' => 'value'])]);
179     $this->pathProcessor->expects($this->once())
180       ->method('processInbound')
181       ->with('/path-alias', $this->anything())
182       ->willReturn('/test-path');
183
184     $this->assertTrue($this->pathValidator->isValid('path-alias'));
185   }
186
187   /**
188    * Tests the isValid() method with a user without access to the path.
189    *
190    * @covers ::isValid
191    * @covers ::getPathAttributes
192    */
193   public function testIsValidWithAccessDenied() {
194     $this->account->expects($this->once())
195       ->method('hasPermission')
196       ->with('link to any page')
197       ->willReturn(FALSE);
198     $this->accessUnawareRouter->expects($this->never())
199       ->method('match');
200     $this->accessAwareRouter->expects($this->once())
201       ->method('match')
202       ->with('/test-path')
203       ->willThrowException(new AccessDeniedHttpException());
204     $this->pathProcessor->expects($this->once())
205       ->method('processInbound')
206       ->willReturnArgument(0);
207
208     $this->assertFalse($this->pathValidator->isValid('test-path'));
209   }
210
211   /**
212    * @covers ::isValid
213    * @covers ::getPathAttributes
214    */
215   public function testIsValidWithResourceNotFound() {
216     $this->account->expects($this->once())
217       ->method('hasPermission')
218       ->with('link to any page')
219       ->willReturn(FALSE);
220     $this->accessUnawareRouter->expects($this->never())
221       ->method('match');
222     $this->accessAwareRouter->expects($this->once())
223       ->method('match')
224       ->with('/test-path')
225       ->willThrowException(new ResourceNotFoundException());
226     $this->pathProcessor->expects($this->once())
227       ->method('processInbound')
228       ->willReturnArgument(0);
229
230     $this->assertFalse($this->pathValidator->isValid('test-path'));
231   }
232
233   /**
234    * @covers ::isValid
235    * @covers ::getPathAttributes
236    */
237   public function testIsValidWithParamNotConverted() {
238     $this->account->expects($this->once())
239       ->method('hasPermission')
240       ->with('link to any page')
241       ->willReturn(FALSE);
242     $this->accessUnawareRouter->expects($this->never())
243       ->method('match');
244     $this->accessAwareRouter->expects($this->once())
245       ->method('match')
246       ->with('/test-path')
247       ->willThrowException(new ParamNotConvertedException());
248     $this->pathProcessor->expects($this->once())
249       ->method('processInbound')
250       ->willReturnArgument(0);
251
252     $this->assertFalse($this->pathValidator->isValid('test-path'));
253   }
254
255   /**
256    * @covers ::isValid
257    * @covers ::getPathAttributes
258    */
259   public function testIsValidWithMethodNotAllowed() {
260     $this->account->expects($this->once())
261       ->method('hasPermission')
262       ->with('link to any page')
263       ->willReturn(FALSE);
264     $this->accessUnawareRouter->expects($this->never())
265       ->method('match');
266     $this->accessAwareRouter->expects($this->once())
267       ->method('match')
268       ->with('/test-path')
269       ->willThrowException(new MethodNotAllowedException([]));
270     $this->pathProcessor->expects($this->once())
271       ->method('processInbound')
272       ->willReturnArgument(0);
273
274     $this->assertFalse($this->pathValidator->isValid('test-path'));
275   }
276
277   /**
278    * Tests the isValid() method with a not working param converting.
279    *
280    * @covers ::isValid
281    */
282   public function testIsValidWithFailingParameterConverting() {
283     $this->account->expects($this->once())
284       ->method('hasPermission')
285       ->with('link to any page')
286       ->willReturn(FALSE);
287     $this->accessUnawareRouter->expects($this->never())
288       ->method('match');
289     $this->accessAwareRouter->expects($this->once())
290       ->method('match')
291       ->with('/entity-test/1')
292       ->willThrowException(new ParamNotConvertedException());
293     $this->pathProcessor->expects($this->once())
294       ->method('processInbound')
295       ->willReturnArgument(0);
296
297     $this->assertFalse($this->pathValidator->isValid('entity-test/1'));
298   }
299
300   /**
301    * Tests the isValid() method with a not existing path.
302    *
303    * @covers ::isValid
304    */
305   public function testIsValidWithNotExistingPath() {
306     $this->account->expects($this->once())
307       ->method('hasPermission')
308       ->with('link to any page')
309       ->willReturn(FALSE);
310     $this->accessUnawareRouter->expects($this->never())
311       ->method('match');
312     $this->accessAwareRouter->expects($this->once())
313       ->method('match')
314       ->with('/not-existing-path')
315       ->willThrowException(new ResourceNotFoundException());
316     $this->pathProcessor->expects($this->once())
317       ->method('processInbound')
318       ->willReturnArgument(0);
319
320     $this->assertFalse($this->pathValidator->isValid('not-existing-path'));
321   }
322
323   /**
324    * Tests the getUrlIfValid() method when there is access.
325    *
326    * @covers ::getUrlIfValid
327    * @covers ::getPathAttributes
328    */
329   public function testGetUrlIfValidWithAccess() {
330     $this->account->expects($this->exactly(2))
331       ->method('hasPermission')
332       ->with('link to any page')
333       ->willReturn(FALSE);
334
335     $this->accessAwareRouter->expects($this->exactly(2))
336       ->method('match')
337       ->with('/test-path')
338       ->willReturn([RouteObjectInterface::ROUTE_NAME => 'test_route', '_raw_variables' => new ParameterBag(['key' => 'value'])]);
339     $this->pathProcessor->expects($this->exactly(2))
340       ->method('processInbound')
341       ->willReturnArgument(0);
342
343     $url = $this->pathValidator->getUrlIfValid('test-path');
344     $this->assertInstanceOf('Drupal\Core\Url', $url);
345
346     $this->assertEquals('test_route', $url->getRouteName());
347     $this->assertEquals(['key' => 'value'], $url->getRouteParameters());
348
349     // Test with leading /.
350     $url = $this->pathValidator->getUrlIfValid('/test-path');
351     $this->assertInstanceOf('Drupal\Core\Url', $url);
352
353     $this->assertEquals('test_route', $url->getRouteName());
354     $this->assertEquals(['key' => 'value'], $url->getRouteParameters());
355   }
356
357   /**
358    * Tests the getUrlIfValid() method with a query in the path.
359    *
360    * @covers ::getUrlIfValid
361    */
362   public function testGetUrlIfValidWithQuery() {
363     $this->account->expects($this->once())
364       ->method('hasPermission')
365       ->with('link to any page')
366       ->willReturn(FALSE);
367
368     $this->accessAwareRouter->expects($this->once())
369       ->method('match')
370       ->with('/test-path?k=bar')
371       ->willReturn([RouteObjectInterface::ROUTE_NAME => 'test_route', '_raw_variables' => new ParameterBag()]);
372     $this->pathProcessor->expects($this->once())
373       ->method('processInbound')
374       ->willReturnArgument(0);
375
376     $url = $this->pathValidator->getUrlIfValid('test-path?k=bar');
377     $this->assertInstanceOf('Drupal\Core\Url', $url);
378
379     $this->assertEquals('test_route', $url->getRouteName());
380     $this->assertEquals(['k' => 'bar'], $url->getOptions()['query']);
381   }
382
383   /**
384    * Tests the getUrlIfValid() method where there is no access.
385    *
386    * @covers ::getUrlIfValid
387    */
388   public function testGetUrlIfValidWithoutAccess() {
389     $this->account->expects($this->once())
390       ->method('hasPermission')
391       ->with('link to any page')
392       ->willReturn(FALSE);
393
394     $this->accessAwareRouter->expects($this->once())
395       ->method('match')
396       ->with('/test-path')
397       ->willThrowException(new AccessDeniedHttpException());
398
399     $this->pathProcessor->expects($this->once())
400       ->method('processInbound')
401       ->willReturnArgument(0);
402
403     $url = $this->pathValidator->getUrlIfValid('test-path');
404     $this->assertFalse($url);
405   }
406
407   /**
408    * Tests the getUrlIfValid() method with a front page + query + fragments.
409    *
410    * @covers ::getUrlIfValid
411    */
412   public function testGetUrlIfValidWithFrontPageAndQueryAndFragments() {
413     $url = $this->pathValidator->getUrlIfValid('<front>?hei=sen#berg');
414     $this->assertEquals('<front>', $url->getRouteName());
415     $this->assertEquals(['hei' => 'sen'], $url->getOptions()['query']);
416     $this->assertEquals('berg', $url->getOptions()['fragment']);
417   }
418
419   /**
420    * Tests the getUrlIfValidWithoutAccessCheck() method.
421    *
422    * @covers ::getUrlIfValidWithoutAccessCheck
423    * @covers ::getPathAttributes
424    */
425   public function testGetUrlIfValidWithoutAccessCheck() {
426     $this->account->expects($this->never())
427       ->method('hasPermission')
428       ->with('link to any page');
429     $this->accessAwareRouter->expects($this->never())
430       ->method('match');
431     $this->accessUnawareRouter->expects($this->once())
432       ->method('match')
433       ->with('/test-path')
434       ->willReturn([RouteObjectInterface::ROUTE_NAME => 'test_route', '_raw_variables' => new ParameterBag(['key' => 'value'])]);
435     $this->pathProcessor->expects($this->once())
436       ->method('processInbound')
437       ->willReturnArgument(0);
438
439     $url = $this->pathValidator->getUrlIfValidWithoutAccessCheck('test-path');
440     $this->assertInstanceOf('Drupal\Core\Url', $url);
441
442     $this->assertEquals('test_route', $url->getRouteName());
443     $this->assertEquals(['key' => 'value'], $url->getRouteParameters());
444   }
445
446 }