Mercurial > hg > isophonics-drupal-site
comparison core/tests/Drupal/Tests/Core/UrlTest.php @ 0:4c8ae668cc8c
Initial import (non-working)
author | Chris Cannam |
---|---|
date | Wed, 29 Nov 2017 16:09:58 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:4c8ae668cc8c |
---|---|
1 <?php | |
2 | |
3 /** | |
4 * @file | |
5 * Contains \Drupal\Tests\Core\UrlTest. | |
6 */ | |
7 | |
8 namespace Drupal\Tests\Core; | |
9 | |
10 use Drupal\Component\Utility\UrlHelper; | |
11 use Drupal\Core\Access\AccessManagerInterface; | |
12 use Drupal\Core\DependencyInjection\ContainerBuilder; | |
13 use Drupal\Core\GeneratedUrl; | |
14 use Drupal\Core\Routing\RouteMatch; | |
15 use Drupal\Core\Url; | |
16 use Drupal\Tests\UnitTestCase; | |
17 use Symfony\Cmf\Component\Routing\RouteObjectInterface; | |
18 use Symfony\Component\HttpFoundation\ParameterBag; | |
19 use Symfony\Component\HttpFoundation\Request; | |
20 use Symfony\Component\Routing\Exception\InvalidParameterException; | |
21 use Symfony\Component\Routing\Exception\ResourceNotFoundException; | |
22 use Symfony\Component\Routing\Route; | |
23 | |
24 /** | |
25 * @coversDefaultClass \Drupal\Core\Url | |
26 * @group UrlTest | |
27 */ | |
28 class UrlTest extends UnitTestCase { | |
29 | |
30 /** | |
31 * @var \Symfony\Component\DependencyInjection\ContainerInterface | |
32 */ | |
33 protected $container; | |
34 | |
35 /** | |
36 * The URL generator | |
37 * | |
38 * @var \Drupal\Core\Routing\UrlGeneratorInterface|\PHPUnit_Framework_MockObject_MockObject | |
39 */ | |
40 protected $urlGenerator; | |
41 | |
42 /** | |
43 * The path alias manager. | |
44 * | |
45 * @var \Drupal\Core\Path\AliasManagerInterface|\PHPUnit_Framework_MockObject_MockObject | |
46 */ | |
47 protected $pathAliasManager; | |
48 | |
49 /** | |
50 * The router. | |
51 * | |
52 * @var \Drupal\Tests\Core\Routing\TestRouterInterface|\PHPUnit_Framework_MockObject_MockObject | |
53 */ | |
54 protected $router; | |
55 | |
56 /** | |
57 * An array of values to use for the test. | |
58 * | |
59 * @var array | |
60 */ | |
61 protected $map; | |
62 | |
63 /** | |
64 * The mocked path validator. | |
65 * | |
66 * @var \Drupal\Core\Path\PathValidatorInterface|\PHPUnit_Framework_MockObject_MockObject | |
67 */ | |
68 protected $pathValidator; | |
69 | |
70 /** | |
71 * {@inheritdoc} | |
72 */ | |
73 protected function setUp() { | |
74 parent::setUp(); | |
75 | |
76 $map = []; | |
77 $map[] = ['view.frontpage.page_1', [], [], FALSE, '/node']; | |
78 $map[] = ['node_view', ['node' => '1'], [], FALSE, '/node/1']; | |
79 $map[] = ['node_edit', ['node' => '2'], [], FALSE, '/node/2/edit']; | |
80 $this->map = $map; | |
81 | |
82 $alias_map = [ | |
83 // Set up one proper alias that can be resolved to a system path. | |
84 ['node-alias-test', NULL, FALSE, 'node'], | |
85 // Passing in anything else should return the same string. | |
86 ['node', NULL, FALSE, 'node'], | |
87 ['node/1', NULL, FALSE, 'node/1'], | |
88 ['node/2/edit', NULL, FALSE, 'node/2/edit'], | |
89 ['non-existent', NULL, FALSE, 'non-existent'], | |
90 ]; | |
91 | |
92 // $this->map has $collect_bubbleable_metadata = FALSE; also generate the | |
93 // $collect_bubbleable_metadata = TRUE case for ::generateFromRoute(). | |
94 $generate_from_route_map = []; | |
95 foreach ($this->map as $values) { | |
96 $generate_from_route_map[] = $values; | |
97 $generate_from_route_map[] = [$values[0], $values[1], $values[2], TRUE, (new GeneratedUrl())->setGeneratedUrl($values[4])]; | |
98 } | |
99 $this->urlGenerator = $this->getMock('Drupal\Core\Routing\UrlGeneratorInterface'); | |
100 $this->urlGenerator->expects($this->any()) | |
101 ->method('generateFromRoute') | |
102 ->will($this->returnValueMap($generate_from_route_map)); | |
103 | |
104 $this->pathAliasManager = $this->getMock('Drupal\Core\Path\AliasManagerInterface'); | |
105 $this->pathAliasManager->expects($this->any()) | |
106 ->method('getPathByAlias') | |
107 ->will($this->returnValueMap($alias_map)); | |
108 | |
109 $this->router = $this->getMock('Drupal\Tests\Core\Routing\TestRouterInterface'); | |
110 $this->pathValidator = $this->getMock('Drupal\Core\Path\PathValidatorInterface'); | |
111 | |
112 $this->container = new ContainerBuilder(); | |
113 $this->container->set('router.no_access_checks', $this->router); | |
114 $this->container->set('url_generator', $this->urlGenerator); | |
115 $this->container->set('path.alias_manager', $this->pathAliasManager); | |
116 $this->container->set('path.validator', $this->pathValidator); | |
117 \Drupal::setContainer($this->container); | |
118 } | |
119 | |
120 /** | |
121 * Tests creating a Url from a request. | |
122 */ | |
123 public function testUrlFromRequest() { | |
124 $this->router->expects($this->at(0)) | |
125 ->method('matchRequest') | |
126 ->with($this->getRequestConstraint('/node')) | |
127 ->willReturn([ | |
128 RouteObjectInterface::ROUTE_NAME => 'view.frontpage.page_1', | |
129 '_raw_variables' => new ParameterBag(), | |
130 ]); | |
131 $this->router->expects($this->at(1)) | |
132 ->method('matchRequest') | |
133 ->with($this->getRequestConstraint('/node/1')) | |
134 ->willReturn([ | |
135 RouteObjectInterface::ROUTE_NAME => 'node_view', | |
136 '_raw_variables' => new ParameterBag(['node' => '1']), | |
137 ]); | |
138 $this->router->expects($this->at(2)) | |
139 ->method('matchRequest') | |
140 ->with($this->getRequestConstraint('/node/2/edit')) | |
141 ->willReturn([ | |
142 RouteObjectInterface::ROUTE_NAME => 'node_edit', | |
143 '_raw_variables' => new ParameterBag(['node' => '2']), | |
144 ]); | |
145 | |
146 $urls = []; | |
147 foreach ($this->map as $index => $values) { | |
148 $path = array_pop($values); | |
149 $url = Url::createFromRequest(Request::create("$path")); | |
150 $expected = Url::fromRoute($values[0], $values[1], $values[2]); | |
151 $this->assertEquals($expected, $url); | |
152 $urls[$index] = $url; | |
153 } | |
154 return $urls; | |
155 } | |
156 | |
157 /** | |
158 * This constraint checks whether a Request object has the right path. | |
159 * | |
160 * @param string $path | |
161 * The path. | |
162 * | |
163 * @return \PHPUnit_Framework_Constraint_Callback | |
164 * The constraint checks whether a Request object has the right path. | |
165 */ | |
166 protected function getRequestConstraint($path) { | |
167 return $this->callback(function (Request $request) use ($path) { | |
168 return $request->getPathInfo() == $path; | |
169 }); | |
170 } | |
171 | |
172 /** | |
173 * Tests the fromRoute() method with the special <front> path. | |
174 * | |
175 * @covers ::fromRoute | |
176 */ | |
177 public function testFromRouteFront() { | |
178 $url = Url::fromRoute('<front>'); | |
179 $this->assertSame('<front>', $url->getRouteName()); | |
180 } | |
181 | |
182 /** | |
183 * Tests the fromUserInput method with valid paths. | |
184 * | |
185 * @covers ::fromUserInput | |
186 * @dataProvider providerFromValidInternalUri | |
187 */ | |
188 public function testFromUserInput($path) { | |
189 $url = Url::fromUserInput($path); | |
190 $uri = $url->getUri(); | |
191 | |
192 $this->assertInstanceOf('Drupal\Core\Url', $url); | |
193 $this->assertFalse($url->isRouted()); | |
194 $this->assertEquals(0, strpos($uri, 'base:')); | |
195 | |
196 $parts = UrlHelper::parse($path); | |
197 $options = $url->getOptions(); | |
198 | |
199 if (!empty($parts['fragment'])) { | |
200 $this->assertSame($parts['fragment'], $options['fragment']); | |
201 } | |
202 else { | |
203 $this->assertArrayNotHasKey('fragment', $options); | |
204 } | |
205 | |
206 if (!empty($parts['query'])) { | |
207 $this->assertEquals($parts['query'], $options['query']); | |
208 } | |
209 else { | |
210 $this->assertArrayNotHasKey('query', $options); | |
211 } | |
212 } | |
213 | |
214 /** | |
215 * Tests the fromUserInput method with invalid paths. | |
216 * | |
217 * @covers ::fromUserInput | |
218 * @dataProvider providerFromInvalidInternalUri | |
219 */ | |
220 public function testFromInvalidUserInput($path) { | |
221 $this->setExpectedException(\InvalidArgumentException::class); | |
222 $url = Url::fromUserInput($path); | |
223 } | |
224 | |
225 /** | |
226 * Tests fromUri() method with a user-entered path not matching any route. | |
227 * | |
228 * @covers ::fromUri | |
229 */ | |
230 public function testFromRoutedPathWithInvalidRoute() { | |
231 $this->pathValidator->expects($this->once()) | |
232 ->method('getUrlIfValidWithoutAccessCheck') | |
233 ->with('invalid-path') | |
234 ->willReturn(FALSE); | |
235 $url = Url::fromUri('internal:/invalid-path'); | |
236 $this->assertSame(FALSE, $url->isRouted()); | |
237 $this->assertSame('base:invalid-path', $url->getUri()); | |
238 } | |
239 | |
240 /** | |
241 * Tests fromUri() method with user-entered path matching a valid route. | |
242 * | |
243 * @covers ::fromUri | |
244 */ | |
245 public function testFromRoutedPathWithValidRoute() { | |
246 $url = Url::fromRoute('test_route'); | |
247 $this->pathValidator->expects($this->once()) | |
248 ->method('getUrlIfValidWithoutAccessCheck') | |
249 ->with('valid-path') | |
250 ->willReturn($url); | |
251 $result_url = Url::fromUri('internal:/valid-path'); | |
252 $this->assertSame($url, $result_url); | |
253 } | |
254 | |
255 /** | |
256 * Tests the createFromRequest method. | |
257 * | |
258 * @covers ::createFromRequest | |
259 */ | |
260 public function testCreateFromRequest() { | |
261 $attributes = [ | |
262 '_raw_variables' => new ParameterBag([ | |
263 'color' => 'chartreuse', | |
264 ]), | |
265 RouteObjectInterface::ROUTE_NAME => 'the_route_name', | |
266 ]; | |
267 $request = new Request([], [], $attributes); | |
268 | |
269 $this->router->expects($this->once()) | |
270 ->method('matchRequest') | |
271 ->with($request) | |
272 ->will($this->returnValue($attributes)); | |
273 | |
274 $url = Url::createFromRequest($request); | |
275 $expected = new Url('the_route_name', ['color' => 'chartreuse']); | |
276 $this->assertEquals($expected, $url); | |
277 } | |
278 | |
279 /** | |
280 * Tests that an invalid request will thrown an exception. | |
281 * | |
282 * @covers ::createFromRequest | |
283 */ | |
284 public function testUrlFromRequestInvalid() { | |
285 $request = Request::create('/test-path'); | |
286 | |
287 $this->router->expects($this->once()) | |
288 ->method('matchRequest') | |
289 ->with($request) | |
290 ->will($this->throwException(new ResourceNotFoundException())); | |
291 | |
292 $this->setExpectedException(ResourceNotFoundException::class); | |
293 Url::createFromRequest($request); | |
294 } | |
295 | |
296 /** | |
297 * Tests the isExternal() method. | |
298 * | |
299 * @depends testUrlFromRequest | |
300 * | |
301 * @covers ::isExternal | |
302 */ | |
303 public function testIsExternal($urls) { | |
304 foreach ($urls as $url) { | |
305 $this->assertFalse($url->isExternal()); | |
306 } | |
307 } | |
308 | |
309 /** | |
310 * Tests the getUri() method for internal URLs. | |
311 * | |
312 * @param \Drupal\Core\Url[] $urls | |
313 * Array of URL objects. | |
314 * | |
315 * @depends testUrlFromRequest | |
316 * | |
317 * @covers ::getUri | |
318 */ | |
319 public function testGetUriForInternalUrl($urls) { | |
320 $this->setExpectedException(\UnexpectedValueException::class); | |
321 foreach ($urls as $url) { | |
322 $url->getUri(); | |
323 } | |
324 } | |
325 | |
326 /** | |
327 * Tests the getUri() method for external URLs. | |
328 * | |
329 * @covers ::getUri | |
330 */ | |
331 public function testGetUriForExternalUrl() { | |
332 $url = Url::fromUri('http://example.com/test'); | |
333 $this->assertEquals('http://example.com/test', $url->getUri()); | |
334 } | |
335 | |
336 /** | |
337 * Tests the getUri() and isExternal() methods for protocol-relative URLs. | |
338 * | |
339 * @covers ::getUri | |
340 * @covers ::isExternal | |
341 */ | |
342 public function testGetUriForProtocolRelativeUrl() { | |
343 $url = Url::fromUri('//example.com/test'); | |
344 $this->assertEquals('//example.com/test', $url->getUri()); | |
345 $this->assertTrue($url->isExternal()); | |
346 } | |
347 | |
348 /** | |
349 * Tests the getInternalPath method(). | |
350 * | |
351 * @param \Drupal\Core\Url[] $urls | |
352 * Array of URL objects. | |
353 * | |
354 * @covers ::getInternalPath | |
355 * | |
356 * @depends testUrlFromRequest | |
357 */ | |
358 public function testGetInternalPath($urls) { | |
359 $map = []; | |
360 $map[] = ['view.frontpage.page_1', [], '/node']; | |
361 $map[] = ['node_view', ['node' => '1'], '/node/1']; | |
362 $map[] = ['node_edit', ['node' => '2'], '/node/2/edit']; | |
363 | |
364 foreach ($urls as $index => $url) { | |
365 // Clone the url so that there is no leak of internal state into the | |
366 // other ones. | |
367 $url = clone $url; | |
368 $url_generator = $this->getMock('Drupal\Core\Routing\UrlGeneratorInterface'); | |
369 $url_generator->expects($this->once()) | |
370 ->method('getPathFromRoute') | |
371 ->will($this->returnValueMap($map, $index)); | |
372 $url->setUrlGenerator($url_generator); | |
373 | |
374 $url->getInternalPath(); | |
375 $url->getInternalPath(); | |
376 } | |
377 } | |
378 | |
379 /** | |
380 * Tests the toString() method. | |
381 * | |
382 * @param \Drupal\Core\Url[] $urls | |
383 * An array of Url objects. | |
384 * | |
385 * @depends testUrlFromRequest | |
386 * | |
387 * @covers ::toString | |
388 */ | |
389 public function testToString($urls) { | |
390 foreach ($urls as $index => $url) { | |
391 $path = array_pop($this->map[$index]); | |
392 $this->assertSame($path, $url->toString()); | |
393 $generated_url = $url->toString(TRUE); | |
394 $this->assertSame($path, $generated_url->getGeneratedUrl()); | |
395 $this->assertInstanceOf('\Drupal\Core\Render\BubbleableMetadata', $generated_url); | |
396 } | |
397 } | |
398 | |
399 /** | |
400 * Tests the getRouteName() method. | |
401 * | |
402 * @param \Drupal\Core\Url[] $urls | |
403 * An array of Url objects. | |
404 * | |
405 * @depends testUrlFromRequest | |
406 * | |
407 * @covers ::getRouteName | |
408 */ | |
409 public function testGetRouteName($urls) { | |
410 foreach ($urls as $index => $url) { | |
411 $this->assertSame($this->map[$index][0], $url->getRouteName()); | |
412 } | |
413 } | |
414 | |
415 /** | |
416 * Tests the getRouteName() with an external URL. | |
417 * | |
418 * @covers ::getRouteName | |
419 */ | |
420 public function testGetRouteNameWithExternalUrl() { | |
421 $url = Url::fromUri('http://example.com'); | |
422 $this->setExpectedException(\UnexpectedValueException::class); | |
423 $url->getRouteName(); | |
424 } | |
425 | |
426 /** | |
427 * Tests the getRouteParameters() method. | |
428 * | |
429 * @param \Drupal\Core\Url[] $urls | |
430 * An array of Url objects. | |
431 * | |
432 * @depends testUrlFromRequest | |
433 * | |
434 * @covers ::getRouteParameters | |
435 */ | |
436 public function testGetRouteParameters($urls) { | |
437 foreach ($urls as $index => $url) { | |
438 $this->assertSame($this->map[$index][1], $url->getRouteParameters()); | |
439 } | |
440 } | |
441 | |
442 /** | |
443 * Tests the getRouteParameters() with an external URL. | |
444 * | |
445 * @covers ::getRouteParameters | |
446 */ | |
447 public function testGetRouteParametersWithExternalUrl() { | |
448 $url = Url::fromUri('http://example.com'); | |
449 $this->setExpectedException(\UnexpectedValueException::class); | |
450 $url->getRouteParameters(); | |
451 } | |
452 | |
453 /** | |
454 * Tests the getOptions() method. | |
455 * | |
456 * @param \Drupal\Core\Url[] $urls | |
457 * An array of Url objects. | |
458 * | |
459 * @depends testUrlFromRequest | |
460 * | |
461 * @covers ::getOptions | |
462 */ | |
463 public function testGetOptions($urls) { | |
464 foreach ($urls as $index => $url) { | |
465 $this->assertSame($this->map[$index][2], $url->getOptions()); | |
466 } | |
467 } | |
468 | |
469 /** | |
470 * Tests the setOptions() method. | |
471 * | |
472 * @covers ::setOptions | |
473 */ | |
474 public function testSetOptions() { | |
475 $url = Url::fromRoute('test_route', []); | |
476 $this->assertEquals([], $url->getOptions()); | |
477 $url->setOptions(['foo' => 'bar']); | |
478 $this->assertEquals(['foo' => 'bar'], $url->getOptions()); | |
479 $url->setOptions([]); | |
480 $this->assertEquals([], $url->getOptions()); | |
481 } | |
482 | |
483 /** | |
484 * Tests the mergeOptions() method. | |
485 * | |
486 * @covers ::mergeOptions | |
487 */ | |
488 public function testMergeOptions() { | |
489 $url = Url::fromRoute('test_route', [], ['foo' => 'bar', 'bar' => ['key' => 'value']]); | |
490 $url->mergeOptions(['bar' => ['key' => 'value1', 'key2' => 'value2']]); | |
491 $this->assertEquals(['foo' => 'bar', 'bar' => ['key' => 'value1', 'key2' => 'value2']], $url->getOptions()); | |
492 } | |
493 | |
494 /** | |
495 * Tests the access() method for routed URLs. | |
496 * | |
497 * @param bool $access | |
498 * | |
499 * @covers ::access | |
500 * @covers ::accessManager | |
501 * @dataProvider accessProvider | |
502 */ | |
503 public function testAccessRouted($access) { | |
504 $account = $this->getMock('Drupal\Core\Session\AccountInterface'); | |
505 $url = new TestUrl('entity.node.canonical', ['node' => 3]); | |
506 $url->setAccessManager($this->getMockAccessManager($access, $account)); | |
507 $this->assertEquals($access, $url->access($account)); | |
508 } | |
509 | |
510 /** | |
511 * Tests the access() method for unrouted URLs (they always have access). | |
512 * | |
513 * @covers ::access | |
514 */ | |
515 public function testAccessUnrouted() { | |
516 $account = $this->getMock('Drupal\Core\Session\AccountInterface'); | |
517 $url = TestUrl::fromUri('base:kittens'); | |
518 $access_manager = $this->getMock('Drupal\Core\Access\AccessManagerInterface'); | |
519 $access_manager->expects($this->never()) | |
520 ->method('checkNamedRoute'); | |
521 $url->setAccessManager($access_manager); | |
522 $this->assertTrue($url->access($account)); | |
523 } | |
524 | |
525 /** | |
526 * Tests the renderAccess() method. | |
527 * | |
528 * @param bool $access | |
529 * | |
530 * @covers ::renderAccess | |
531 * @dataProvider accessProvider | |
532 */ | |
533 public function testRenderAccess($access) { | |
534 $element = [ | |
535 '#url' => Url::fromRoute('entity.node.canonical', ['node' => 3]), | |
536 ]; | |
537 $this->container->set('current_user', $this->getMock('Drupal\Core\Session\AccountInterface')); | |
538 $this->container->set('access_manager', $this->getMockAccessManager($access)); | |
539 $this->assertEquals($access, TestUrl::renderAccess($element)); | |
540 } | |
541 | |
542 /** | |
543 * Tests the fromRouteMatch() method. | |
544 */ | |
545 public function testFromRouteMatch() { | |
546 $route = new Route('/test-route/{foo}'); | |
547 $route_match = new RouteMatch('test_route', $route, ['foo' => (object) [1]], ['foo' => 1]); | |
548 $url = Url::fromRouteMatch($route_match); | |
549 $this->assertSame('test_route', $url->getRouteName()); | |
550 $this->assertEquals(['foo' => '1'], $url->getRouteParameters()); | |
551 } | |
552 | |
553 /** | |
554 * Data provider for testing entity URIs | |
555 */ | |
556 public function providerTestEntityUris() { | |
557 return [ | |
558 [ | |
559 'entity:test_entity/1', | |
560 [], | |
561 'entity.test_entity.canonical', | |
562 ['test_entity' => '1'], | |
563 NULL, | |
564 NULL, | |
565 ], | |
566 [ | |
567 // Ensure a fragment of #0 is handled correctly. | |
568 'entity:test_entity/1#0', | |
569 [], | |
570 'entity.test_entity.canonical', | |
571 ['test_entity' => '1'], | |
572 NULL, | |
573 '0', | |
574 ], | |
575 // Ensure an empty fragment of # is in options discarded as expected. | |
576 [ | |
577 'entity:test_entity/1', | |
578 ['fragment' => ''], | |
579 'entity.test_entity.canonical', | |
580 ['test_entity' => '1'], | |
581 NULL, | |
582 NULL, | |
583 ], | |
584 // Ensure an empty fragment of # in the URI is discarded as expected. | |
585 [ | |
586 'entity:test_entity/1#', | |
587 [], | |
588 'entity.test_entity.canonical', | |
589 ['test_entity' => '1'], | |
590 NULL, | |
591 NULL, | |
592 ], | |
593 [ | |
594 'entity:test_entity/2?page=1&foo=bar#bottom', | |
595 [], 'entity.test_entity.canonical', | |
596 ['test_entity' => '2'], | |
597 ['page' => '1', 'foo' => 'bar'], | |
598 'bottom', | |
599 ], | |
600 [ | |
601 'entity:test_entity/2?page=1&foo=bar#bottom', | |
602 ['fragment' => 'top', 'query' => ['foo' => 'yes', 'focus' => 'no']], | |
603 'entity.test_entity.canonical', | |
604 ['test_entity' => '2'], | |
605 ['page' => '1', 'foo' => 'yes', 'focus' => 'no'], | |
606 'top', | |
607 ], | |
608 | |
609 ]; | |
610 } | |
611 | |
612 /** | |
613 * Tests the fromUri() method with an entity: URI. | |
614 * | |
615 * @covers ::fromUri | |
616 * | |
617 * @dataProvider providerTestEntityUris | |
618 */ | |
619 public function testEntityUris($uri, $options, $route_name, $route_parameters, $query, $fragment) { | |
620 $url = Url::fromUri($uri, $options); | |
621 $this->assertSame($route_name, $url->getRouteName()); | |
622 $this->assertEquals($route_parameters, $url->getRouteParameters()); | |
623 $this->assertEquals($url->getOption('query'), $query); | |
624 $this->assertSame($url->getOption('fragment'), $fragment); | |
625 } | |
626 | |
627 /** | |
628 * Tests the fromUri() method with an invalid entity: URI. | |
629 * | |
630 * @covers ::fromUri | |
631 */ | |
632 public function testInvalidEntityUriParameter() { | |
633 // Make the mocked URL generator behave like the actual one. | |
634 $this->urlGenerator->expects($this->once()) | |
635 ->method('generateFromRoute') | |
636 ->with('entity.test_entity.canonical', ['test_entity' => '1/blah']) | |
637 ->willThrowException(new InvalidParameterException('Parameter "test_entity" for route "/test_entity/{test_entity}" must match "[^/]++" ("1/blah" given) to generate a corresponding URL..')); | |
638 | |
639 $this->setExpectedException(InvalidParameterException::class); | |
640 Url::fromUri('entity:test_entity/1/blah')->toString(); | |
641 } | |
642 | |
643 /** | |
644 * Tests the toUriString() method with entity: URIs. | |
645 * | |
646 * @covers ::toUriString | |
647 * | |
648 * @dataProvider providerTestToUriStringForEntity | |
649 */ | |
650 public function testToUriStringForEntity($uri, $options, $uri_string) { | |
651 $url = Url::fromUri($uri, $options); | |
652 $this->assertSame($url->toUriString(), $uri_string); | |
653 } | |
654 | |
655 /** | |
656 * Data provider for testing string entity URIs | |
657 */ | |
658 public function providerTestToUriStringForEntity() { | |
659 return [ | |
660 ['entity:test_entity/1', [], 'route:entity.test_entity.canonical;test_entity=1'], | |
661 ['entity:test_entity/1', ['fragment' => 'top', 'query' => ['page' => '2']], 'route:entity.test_entity.canonical;test_entity=1?page=2#top'], | |
662 ['entity:test_entity/1?page=2#top', [], 'route:entity.test_entity.canonical;test_entity=1?page=2#top'], | |
663 ]; | |
664 } | |
665 | |
666 /** | |
667 * Tests the toUriString() method with internal: URIs. | |
668 * | |
669 * @covers ::toUriString | |
670 * | |
671 * @dataProvider providerTestToUriStringForInternal | |
672 */ | |
673 public function testToUriStringForInternal($uri, $options, $uri_string) { | |
674 $url = Url::fromRoute('entity.test_entity.canonical', ['test_entity' => '1']); | |
675 $this->pathValidator->expects($this->any()) | |
676 ->method('getUrlIfValidWithoutAccessCheck') | |
677 ->willReturnMap([ | |
678 ['test-entity/1', $url], | |
679 ['<front>', Url::fromRoute('<front>')], | |
680 ['<none>', Url::fromRoute('<none>')], | |
681 ]); | |
682 $url = Url::fromUri($uri, $options); | |
683 $this->assertSame($url->toUriString(), $uri_string); | |
684 } | |
685 | |
686 /** | |
687 * Data provider for testing internal URIs. | |
688 */ | |
689 public function providerTestToUriStringForInternal() { | |
690 return [ | |
691 // The four permutations of a regular path. | |
692 ['internal:/test-entity/1', [], 'route:entity.test_entity.canonical;test_entity=1'], | |
693 ['internal:/test-entity/1', ['fragment' => 'top'], 'route:entity.test_entity.canonical;test_entity=1#top'], | |
694 ['internal:/test-entity/1', ['fragment' => 'top', 'query' => ['page' => '2']], 'route:entity.test_entity.canonical;test_entity=1?page=2#top'], | |
695 ['internal:/test-entity/1?page=2#top', [], 'route:entity.test_entity.canonical;test_entity=1?page=2#top'], | |
696 | |
697 // The four permutations of the special '<front>' path. | |
698 ['internal:/', [], 'route:<front>'], | |
699 ['internal:/', ['fragment' => 'top'], 'route:<front>#top'], | |
700 ['internal:/', ['fragment' => 'top', 'query' => ['page' => '2']], 'route:<front>?page=2#top'], | |
701 ['internal:/?page=2#top', [], 'route:<front>?page=2#top'], | |
702 | |
703 // The four permutations of the special '<none>' path. | |
704 ['internal:', [], 'route:<none>'], | |
705 ['internal:', ['fragment' => 'top'], 'route:<none>#top'], | |
706 ['internal:', ['fragment' => 'top', 'query' => ['page' => '2']], 'route:<none>?page=2#top'], | |
707 ['internal:?page=2#top', [], 'route:<none>?page=2#top'], | |
708 ]; | |
709 } | |
710 | |
711 /** | |
712 * Tests the fromUri() method with a valid internal: URI. | |
713 * | |
714 * @covers ::fromUri | |
715 * @dataProvider providerFromValidInternalUri | |
716 */ | |
717 public function testFromValidInternalUri($path) { | |
718 $url = Url::fromUri('internal:' . $path); | |
719 $this->assertInstanceOf('Drupal\Core\Url', $url); | |
720 } | |
721 | |
722 /** | |
723 * Data provider for testFromValidInternalUri(). | |
724 */ | |
725 public function providerFromValidInternalUri() { | |
726 return [ | |
727 // Normal paths with a leading slash. | |
728 ['/kittens'], | |
729 ['/kittens/bengal'], | |
730 // Fragments with and without leading slashes. | |
731 ['/#about-our-kittens'], | |
732 ['/kittens#feeding'], | |
733 ['#feeding'], | |
734 // Query strings with and without leading slashes. | |
735 ['/kittens?page=1000'], | |
736 ['/?page=1000'], | |
737 ['?page=1000'], | |
738 ['?breed=bengal&page=1000'], | |
739 ['?referrer=https://kittenfacts'], | |
740 // Paths with various token formats but no leading slash. | |
741 ['/[duckies]'], | |
742 ['/%bunnies'], | |
743 ['/{{ puppies }}'], | |
744 // Disallowed characters in the authority (host name) that are valid | |
745 // elsewhere in the path. | |
746 ['/(:;2&+h^'], | |
747 ['/AKI@&hO@'], | |
748 ]; | |
749 } | |
750 | |
751 /** | |
752 * Tests the fromUri() method with an invalid internal: URI. | |
753 * | |
754 * @covers ::fromUri | |
755 * @dataProvider providerFromInvalidInternalUri | |
756 */ | |
757 public function testFromInvalidInternalUri($path) { | |
758 $this->setExpectedException(\InvalidArgumentException::class); | |
759 Url::fromUri('internal:' . $path); | |
760 } | |
761 | |
762 /** | |
763 * Data provider for testFromInvalidInternalUri(). | |
764 */ | |
765 public function providerFromInvalidInternalUri() { | |
766 return [ | |
767 // Normal paths without a leading slash. | |
768 'normal_path0' => ['kittens'], | |
769 'normal_path1' => ['kittens/bengal'], | |
770 // Path without a leading slash containing a fragment. | |
771 'fragment' => ['kittens#feeding'], | |
772 // Path without a leading slash containing a query string. | |
773 'without_leading_slash_query' => ['kittens?page=1000'], | |
774 // Paths with various token formats but no leading slash. | |
775 'path_with_tokens0' => ['[duckies]'], | |
776 'path_with_tokens1' => ['%bunnies'], | |
777 'path_with_tokens2' => ['{{ puppies }}'], | |
778 // Disallowed characters in the authority (host name) that are valid | |
779 // elsewhere in the path. | |
780 'disallowed_hostname_chars0' => ['(:;2&+h^'], | |
781 'disallowed_hostname_chars1' => ['AKI@&hO@'], | |
782 // Leading slash with a domain. | |
783 'leading_slash_with_domain' => ['/http://example.com'], | |
784 ]; | |
785 } | |
786 | |
787 /** | |
788 * Tests the fromUri() method with a base: URI starting with a number. | |
789 * | |
790 * @covers ::fromUri | |
791 */ | |
792 public function testFromUriNumber() { | |
793 $url = Url::fromUri('base:2015/10/06'); | |
794 $this->assertSame($url->toUriString(), 'base:/2015/10/06'); | |
795 } | |
796 | |
797 /** | |
798 * Tests the toUriString() method with route: URIs. | |
799 * | |
800 * @covers ::toUriString | |
801 * | |
802 * @dataProvider providerTestToUriStringForRoute | |
803 */ | |
804 public function testToUriStringForRoute($uri, $options, $uri_string) { | |
805 $url = Url::fromUri($uri, $options); | |
806 $this->assertSame($url->toUriString(), $uri_string); | |
807 } | |
808 | |
809 /** | |
810 * Data provider for testing route: URIs. | |
811 */ | |
812 public function providerTestToUriStringForRoute() { | |
813 return [ | |
814 ['route:entity.test_entity.canonical;test_entity=1', [], 'route:entity.test_entity.canonical;test_entity=1'], | |
815 ['route:entity.test_entity.canonical;test_entity=1', ['fragment' => 'top', 'query' => ['page' => '2']], 'route:entity.test_entity.canonical;test_entity=1?page=2#top'], | |
816 ['route:entity.test_entity.canonical;test_entity=1?page=2#top', [], 'route:entity.test_entity.canonical;test_entity=1?page=2#top'], | |
817 // Check that an empty fragment is discarded. | |
818 ['route:entity.test_entity.canonical;test_entity=1?page=2#', [], 'route:entity.test_entity.canonical;test_entity=1?page=2'], | |
819 // Check that an empty fragment is discarded. | |
820 ['route:entity.test_entity.canonical;test_entity=1?page=2', ['fragment' => ''], 'route:entity.test_entity.canonical;test_entity=1?page=2'], | |
821 // Check that a fragment of #0 is preserved. | |
822 ['route:entity.test_entity.canonical;test_entity=1?page=2#0', [], 'route:entity.test_entity.canonical;test_entity=1?page=2#0'], | |
823 ]; | |
824 } | |
825 | |
826 /** | |
827 * @covers ::fromUri | |
828 */ | |
829 public function testFromRouteUriWithMissingRouteName() { | |
830 $this->setExpectedException(\InvalidArgumentException::class, "The route URI 'route:' is invalid."); | |
831 Url::fromUri('route:'); | |
832 } | |
833 | |
834 /** | |
835 * Creates a mock access manager for the access tests. | |
836 * | |
837 * @param bool $access | |
838 * @param \Drupal\Core\Session\AccountInterface|null $account | |
839 * | |
840 * @return \Drupal\Core\Access\AccessManagerInterface|\PHPUnit_Framework_MockObject_MockObject | |
841 */ | |
842 protected function getMockAccessManager($access, $account = NULL) { | |
843 $access_manager = $this->getMock('Drupal\Core\Access\AccessManagerInterface'); | |
844 $access_manager->expects($this->once()) | |
845 ->method('checkNamedRoute') | |
846 ->with('entity.node.canonical', ['node' => 3], $account) | |
847 ->willReturn($access); | |
848 return $access_manager; | |
849 } | |
850 | |
851 /** | |
852 * Data provider for the access test methods. | |
853 */ | |
854 public function accessProvider() { | |
855 return [ | |
856 [TRUE], | |
857 [FALSE], | |
858 ]; | |
859 } | |
860 | |
861 } | |
862 | |
863 class TestUrl extends Url { | |
864 | |
865 /** | |
866 * Sets the access manager. | |
867 * | |
868 * @param \Drupal\Core\Access\AccessManagerInterface $access_manager | |
869 */ | |
870 public function setAccessManager(AccessManagerInterface $access_manager) { | |
871 $this->accessManager = $access_manager; | |
872 } | |
873 | |
874 } |