3 namespace Drupal\Tests\Core\Utility;
5 use Drupal\Core\GeneratedUrl;
6 use Drupal\Core\Render\BubbleableMetadata;
7 use Drupal\Core\Utility\UnroutedUrlAssembler;
8 use Drupal\Tests\UnitTestCase;
9 use Symfony\Component\HttpFoundation\Request;
10 use Symfony\Component\HttpFoundation\RequestStack;
13 * @coversDefaultClass \Drupal\Core\Utility\UnroutedUrlAssembler
16 class UnroutedUrlAssemblerTest extends UnitTestCase {
21 * @var \Symfony\Component\HttpFoundation\RequestStack
23 protected $requestStack;
26 * The mocked config factory.
28 * @var \Drupal\Core\Config\ConfigFactoryInterface|\PHPUnit_Framework_MockObject_MockObject
30 protected $configFactory;
33 * The tested unrouted URL assembler.
35 * @var \Drupal\Core\Utility\UnroutedUrlAssembler
37 protected $unroutedUrlAssembler;
40 * The mocked outbound path processor.
42 * @var \Drupal\Core\PathProcessor\OutboundPathProcessorInterface|\PHPUnit_Framework_MockObject_MockObject
44 protected $pathProcessor;
49 protected function setUp() {
52 $this->requestStack = new RequestStack();
53 $this->pathProcessor = $this->getMock('Drupal\Core\PathProcessor\OutboundPathProcessorInterface');
54 $this->unroutedUrlAssembler = new UnroutedUrlAssembler($this->requestStack, $this->pathProcessor);
60 public function testAssembleWithNeitherExternalNorDomainLocalUri() {
61 $this->setExpectedException(\InvalidArgumentException::class);
62 $this->unroutedUrlAssembler->assemble('wrong-url');
68 public function testAssembleWithLeadingSlash() {
69 $this->setExpectedException(\InvalidArgumentException::class);
70 $this->unroutedUrlAssembler->assemble('/drupal.org');
75 * @covers ::buildExternalUrl
77 * @dataProvider providerTestAssembleWithExternalUrl
79 public function testAssembleWithExternalUrl($uri, array $options, $expected) {
80 $this->setupRequestStack(FALSE);
81 $this->assertEquals($expected, $this->unroutedUrlAssembler->assemble($uri, $options));
82 $generated_url = $this->unroutedUrlAssembler->assemble($uri, $options, TRUE);
83 $this->assertEquals($expected, $generated_url->getGeneratedUrl());
84 $this->assertInstanceOf('\Drupal\Core\Render\BubbleableMetadata', $generated_url);
88 * Provides test data for testAssembleWithExternalUrl
90 public function providerTestAssembleWithExternalUrl() {
92 ['http://example.com/test', [], 'http://example.com/test'],
93 ['http://example.com/test', ['fragment' => 'example'], 'http://example.com/test#example'],
94 ['http://example.com/test', ['fragment' => 'example'], 'http://example.com/test#example'],
95 ['http://example.com/test', ['query' => ['foo' => 'bar']], 'http://example.com/test?foo=bar'],
96 ['http://example.com/test', ['https' => TRUE], 'https://example.com/test'],
97 ['https://example.com/test', ['https' => FALSE], 'http://example.com/test'],
98 ['https://example.com/test?foo=1#bar', [], 'https://example.com/test?foo=1#bar'],
99 'override-query' => ['https://example.com/test?foo=1#bar', ['query' => ['foo' => 2]], 'https://example.com/test?foo=2#bar'],
100 'override-query-merge' => ['https://example.com/test?foo=1#bar', ['query' => ['bar' => 2]], 'https://example.com/test?foo=1&bar=2#bar'],
101 'override-deep-query-merge' => ['https://example.com/test?foo=1#bar', ['query' => ['bar' => ['baz' => 'foo']]], 'https://example.com/test?foo=1&bar%5Bbaz%5D=foo#bar'],
102 'override-fragment' => ['https://example.com/test?foo=1#bar', ['fragment' => 'baz'], 'https://example.com/test?foo=1#baz'],
103 ['//www.drupal.org', [], '//www.drupal.org'],
109 * @covers::buildLocalUrl
111 * @dataProvider providerTestAssembleWithLocalUri
113 public function testAssembleWithLocalUri($uri, array $options, $subdir, $expected) {
114 $this->setupRequestStack($subdir);
116 $this->assertEquals($expected, $this->unroutedUrlAssembler->assemble($uri, $options));
122 public function providerTestAssembleWithLocalUri() {
124 ['base:example', [], FALSE, '/example'],
125 ['base:example', ['query' => ['foo' => 'bar']], FALSE, '/example?foo=bar'],
126 ['base:example', ['query' => ['foo' => '"bar"']], FALSE, '/example?foo=%22bar%22'],
127 ['base:example', ['query' => ['foo' => '"bar"', 'zoo' => 'baz']], FALSE, '/example?foo=%22bar%22&zoo=baz'],
128 ['base:example', ['fragment' => 'example'], FALSE, '/example#example'],
129 ['base:example', [], TRUE, '/subdir/example'],
130 ['base:example', ['query' => ['foo' => 'bar']], TRUE, '/subdir/example?foo=bar'],
131 ['base:example', ['fragment' => 'example'], TRUE, '/subdir/example#example'],
132 ['base:/drupal.org', [], FALSE, '/drupal.org'],
139 public function testAssembleWithNotEnabledProcessing() {
140 $this->setupRequestStack(FALSE);
141 $this->pathProcessor->expects($this->never())
142 ->method('processOutbound');
143 $result = $this->unroutedUrlAssembler->assemble('base:test-uri', []);
144 $this->assertEquals('/test-uri', $result);
150 public function testAssembleWithEnabledProcessing() {
151 $this->setupRequestStack(FALSE);
152 $this->pathProcessor->expects($this->exactly(2))
153 ->method('processOutbound')
154 ->willReturnCallback(function ($path, &$options = [], Request $request = NULL, BubbleableMetadata $bubbleable_metadata = NULL) {
155 if ($bubbleable_metadata) {
156 $bubbleable_metadata->setCacheContexts(['some-cache-context']);
158 return 'test-other-uri';
161 $result = $this->unroutedUrlAssembler->assemble('base:test-uri', ['path_processing' => TRUE]);
162 $this->assertEquals('/test-other-uri', $result);
164 $result = $this->unroutedUrlAssembler->assemble('base:test-uri', ['path_processing' => TRUE], TRUE);
165 $expected_generated_url = new GeneratedUrl();
166 $expected_generated_url->setGeneratedUrl('/test-other-uri')
167 ->setCacheContexts(['some-cache-context']);
168 $this->assertEquals($expected_generated_url, $result);
172 * Setups the request stack for a given subdir.
174 * @param string $subdir
177 protected function setupRequestStack($subdir) {
180 // Setup a fake request which looks like a Drupal installed under the
181 // subdir "subdir" on the domain www.example.com.
182 // To reproduce the values install Drupal like that and use a debugger.
184 'SCRIPT_NAME' => '/subdir/index.php',
185 'SCRIPT_FILENAME' => $this->root . '/index.php',
186 'SERVER_NAME' => 'http://www.example.com',
188 $request = Request::create('/subdir/');
191 $request = Request::create('/');
193 $request->server->add($server);
194 $this->requestStack->push($request);