3 namespace Drupal\Tests\Core\Path;
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;
15 * @coversDefaultClass \Drupal\Core\Path\PathValidator
18 class PathValidatorTest extends UnitTestCase {
21 * The mocked access aware router.
23 * @var \Drupal\Core\Routing\AccessAwareRouterInterface|\PHPUnit_Framework_MockObject_MockObject
25 protected $accessAwareRouter;
28 * The mocked access unaware router.
29 * @var \Symfony\Component\Routing\Matcher\UrlMatcherInterface|\PHPUnit_Framework_MockObject_MockObject
31 protected $accessUnawareRouter;
36 * @var \Drupal\Core\Session\AccountInterface|\PHPUnit_Framework_MockObject_MockObject
43 * @var \Drupal\Core\PathProcessor\InboundPathProcessorInterface|\PHPUnit_Framework_MockObject_MockObject
45 protected $pathProcessor;
48 * The tested path validator.
50 * @var \Drupal\Core\Path\PathValidator
52 protected $pathValidator;
57 protected function setUp() {
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);
68 * Tests the isValid() method for the frontpage.
72 public function testIsValidWithFrontpage() {
73 $this->accessAwareRouter->expects($this->never())
76 $this->assertTrue($this->pathValidator->isValid('<front>'));
80 * Tests the isValid() method for <none> (used for jumplinks).
84 public function testIsValidWithNone() {
85 $this->accessAwareRouter->expects($this->never())
88 $this->assertTrue($this->pathValidator->isValid('<none>'));
92 * Tests the isValid() method for an external URL.
96 public function testIsValidWithExternalUrl() {
97 $this->accessAwareRouter->expects($this->never())
100 $this->assertTrue($this->pathValidator->isValid('https://www.drupal.org'));
104 * Tests the isValid() method with an invalid external URL.
108 public function testIsValidWithInvalidExternalUrl() {
109 $this->accessAwareRouter->expects($this->never())
112 $this->assertFalse($this->pathValidator->isValid('http://'));
116 * Tests the isValid() method with a 'link to any page' permission.
119 * @covers ::getPathAttributes
121 public function testIsValidWithLinkToAnyPageAccount() {
122 $this->account->expects($this->once())
123 ->method('hasPermission')
124 ->with('link to any page')
126 $this->accessAwareRouter->expects($this->never())
128 $this->accessUnawareRouter->expects($this->once())
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);
137 $this->assertTrue($this->pathValidator->isValid('test-path'));
141 * Tests the isValid() method without the 'link to any page' permission.
145 public function testIsValidWithoutLinkToAnyPageAccount() {
146 $this->account->expects($this->once())
147 ->method('hasPermission')
148 ->with('link to any page')
150 $this->accessUnawareRouter->expects($this->never())
152 $this->accessAwareRouter->expects($this->once())
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);
160 $this->assertTrue($this->pathValidator->isValid('test-path'));
164 * Tests the isValid() method with a path alias.
168 public function testIsValidWithPathAlias() {
169 $this->account->expects($this->once())
170 ->method('hasPermission')
171 ->with('link to any page')
173 $this->accessUnawareRouter->expects($this->never())
175 $this->accessAwareRouter->expects($this->once())
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');
184 $this->assertTrue($this->pathValidator->isValid('path-alias'));
188 * Tests the isValid() method with a user without access to the path.
191 * @covers ::getPathAttributes
193 public function testIsValidWithAccessDenied() {
194 $this->account->expects($this->once())
195 ->method('hasPermission')
196 ->with('link to any page')
198 $this->accessUnawareRouter->expects($this->never())
200 $this->accessAwareRouter->expects($this->once())
203 ->willThrowException(new AccessDeniedHttpException());
204 $this->pathProcessor->expects($this->once())
205 ->method('processInbound')
206 ->willReturnArgument(0);
208 $this->assertFalse($this->pathValidator->isValid('test-path'));
213 * @covers ::getPathAttributes
215 public function testIsValidWithResourceNotFound() {
216 $this->account->expects($this->once())
217 ->method('hasPermission')
218 ->with('link to any page')
220 $this->accessUnawareRouter->expects($this->never())
222 $this->accessAwareRouter->expects($this->once())
225 ->willThrowException(new ResourceNotFoundException());
226 $this->pathProcessor->expects($this->once())
227 ->method('processInbound')
228 ->willReturnArgument(0);
230 $this->assertFalse($this->pathValidator->isValid('test-path'));
235 * @covers ::getPathAttributes
237 public function testIsValidWithParamNotConverted() {
238 $this->account->expects($this->once())
239 ->method('hasPermission')
240 ->with('link to any page')
242 $this->accessUnawareRouter->expects($this->never())
244 $this->accessAwareRouter->expects($this->once())
247 ->willThrowException(new ParamNotConvertedException());
248 $this->pathProcessor->expects($this->once())
249 ->method('processInbound')
250 ->willReturnArgument(0);
252 $this->assertFalse($this->pathValidator->isValid('test-path'));
257 * @covers ::getPathAttributes
259 public function testIsValidWithMethodNotAllowed() {
260 $this->account->expects($this->once())
261 ->method('hasPermission')
262 ->with('link to any page')
264 $this->accessUnawareRouter->expects($this->never())
266 $this->accessAwareRouter->expects($this->once())
269 ->willThrowException(new MethodNotAllowedException([]));
270 $this->pathProcessor->expects($this->once())
271 ->method('processInbound')
272 ->willReturnArgument(0);
274 $this->assertFalse($this->pathValidator->isValid('test-path'));
278 * Tests the isValid() method with a not working param converting.
282 public function testIsValidWithFailingParameterConverting() {
283 $this->account->expects($this->once())
284 ->method('hasPermission')
285 ->with('link to any page')
287 $this->accessUnawareRouter->expects($this->never())
289 $this->accessAwareRouter->expects($this->once())
291 ->with('/entity-test/1')
292 ->willThrowException(new ParamNotConvertedException());
293 $this->pathProcessor->expects($this->once())
294 ->method('processInbound')
295 ->willReturnArgument(0);
297 $this->assertFalse($this->pathValidator->isValid('entity-test/1'));
301 * Tests the isValid() method with a not existing path.
305 public function testIsValidWithNotExistingPath() {
306 $this->account->expects($this->once())
307 ->method('hasPermission')
308 ->with('link to any page')
310 $this->accessUnawareRouter->expects($this->never())
312 $this->accessAwareRouter->expects($this->once())
314 ->with('/not-existing-path')
315 ->willThrowException(new ResourceNotFoundException());
316 $this->pathProcessor->expects($this->once())
317 ->method('processInbound')
318 ->willReturnArgument(0);
320 $this->assertFalse($this->pathValidator->isValid('not-existing-path'));
324 * Tests the getUrlIfValid() method when there is access.
326 * @covers ::getUrlIfValid
327 * @covers ::getPathAttributes
329 public function testGetUrlIfValidWithAccess() {
330 $this->account->expects($this->exactly(2))
331 ->method('hasPermission')
332 ->with('link to any page')
335 $this->accessAwareRouter->expects($this->exactly(2))
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);
343 $url = $this->pathValidator->getUrlIfValid('test-path');
344 $this->assertInstanceOf('Drupal\Core\Url', $url);
346 $this->assertEquals('test_route', $url->getRouteName());
347 $this->assertEquals(['key' => 'value'], $url->getRouteParameters());
349 // Test with leading /.
350 $url = $this->pathValidator->getUrlIfValid('/test-path');
351 $this->assertInstanceOf('Drupal\Core\Url', $url);
353 $this->assertEquals('test_route', $url->getRouteName());
354 $this->assertEquals(['key' => 'value'], $url->getRouteParameters());
358 * Tests the getUrlIfValid() method with a query in the path.
360 * @covers ::getUrlIfValid
362 public function testGetUrlIfValidWithQuery() {
363 $this->account->expects($this->once())
364 ->method('hasPermission')
365 ->with('link to any page')
368 $this->accessAwareRouter->expects($this->once())
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);
376 $url = $this->pathValidator->getUrlIfValid('test-path?k=bar');
377 $this->assertInstanceOf('Drupal\Core\Url', $url);
379 $this->assertEquals('test_route', $url->getRouteName());
380 $this->assertEquals(['k' => 'bar'], $url->getOptions()['query']);
384 * Tests the getUrlIfValid() method where there is no access.
386 * @covers ::getUrlIfValid
388 public function testGetUrlIfValidWithoutAccess() {
389 $this->account->expects($this->once())
390 ->method('hasPermission')
391 ->with('link to any page')
394 $this->accessAwareRouter->expects($this->once())
397 ->willThrowException(new AccessDeniedHttpException());
399 $this->pathProcessor->expects($this->once())
400 ->method('processInbound')
401 ->willReturnArgument(0);
403 $url = $this->pathValidator->getUrlIfValid('test-path');
404 $this->assertFalse($url);
408 * Tests the getUrlIfValid() method with a front page + query + fragments.
410 * @covers ::getUrlIfValid
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']);
420 * Tests the getUrlIfValidWithoutAccessCheck() method.
422 * @covers ::getUrlIfValidWithoutAccessCheck
423 * @covers ::getPathAttributes
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())
431 $this->accessUnawareRouter->expects($this->once())
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);
439 $url = $this->pathValidator->getUrlIfValidWithoutAccessCheck('test-path');
440 $this->assertInstanceOf('Drupal\Core\Url', $url);
442 $this->assertEquals('test_route', $url->getRouteName());
443 $this->assertEquals(['key' => 'value'], $url->getRouteParameters());