0a46582299c8cfdf3c1e4ff7e22bb1a80cc75cb4
[yaffs-website] / web / core / tests / Drupal / Tests / Core / Utility / UnroutedUrlAssemblerTest.php
1 <?php
2
3 namespace Drupal\Tests\Core\Utility;
4
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;
11
12 /**
13  * @coversDefaultClass \Drupal\Core\Utility\UnroutedUrlAssembler
14  * @group Utility
15  */
16 class UnroutedUrlAssemblerTest extends UnitTestCase {
17
18   /**
19    * The request stack.
20    *
21    * @var \Symfony\Component\HttpFoundation\RequestStack
22    */
23   protected $requestStack;
24
25   /**
26    * The mocked config factory.
27    *
28    * @var \Drupal\Core\Config\ConfigFactoryInterface|\PHPUnit_Framework_MockObject_MockObject
29    */
30   protected $configFactory;
31
32   /**
33    * The tested unrouted URL assembler.
34    *
35    * @var \Drupal\Core\Utility\UnroutedUrlAssembler
36    */
37   protected $unroutedUrlAssembler;
38
39   /**
40    * The mocked outbound path processor.
41    *
42    * @var \Drupal\Core\PathProcessor\OutboundPathProcessorInterface|\PHPUnit_Framework_MockObject_MockObject
43    */
44   protected $pathProcessor;
45
46   /**
47    * {@inheritdoc}
48    */
49   protected function setUp() {
50     parent::setUp();
51
52     $this->requestStack = new RequestStack();
53     $this->pathProcessor = $this->getMock('Drupal\Core\PathProcessor\OutboundPathProcessorInterface');
54     $this->unroutedUrlAssembler = new UnroutedUrlAssembler($this->requestStack, $this->pathProcessor);
55   }
56
57   /**
58    * @covers ::assemble
59    */
60   public function testAssembleWithNeitherExternalNorDomainLocalUri() {
61     $this->setExpectedException(\InvalidArgumentException::class);
62     $this->unroutedUrlAssembler->assemble('wrong-url');
63   }
64
65   /**
66    * @covers ::assemble
67    */
68   public function testAssembleWithLeadingSlash() {
69     $this->setExpectedException(\InvalidArgumentException::class);
70     $this->unroutedUrlAssembler->assemble('/drupal.org');
71   }
72
73   /**
74    * @covers ::assemble
75    * @covers ::buildExternalUrl
76    *
77    * @dataProvider providerTestAssembleWithExternalUrl
78    */
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);
85   }
86
87   /**
88    * Provides test data for testAssembleWithExternalUrl
89    */
90   public function providerTestAssembleWithExternalUrl() {
91     return [
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'],
104     ];
105   }
106
107   /**
108    * @covers ::assemble
109    * @covers::buildLocalUrl
110    *
111    * @dataProvider providerTestAssembleWithLocalUri
112    */
113   public function testAssembleWithLocalUri($uri, array $options, $subdir, $expected) {
114     $this->setupRequestStack($subdir);
115
116     $this->assertEquals($expected, $this->unroutedUrlAssembler->assemble($uri, $options));
117   }
118
119   /**
120    * @return array
121    */
122   public function providerTestAssembleWithLocalUri() {
123     return [
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'],
133     ];
134   }
135
136   /**
137    * @covers ::assemble
138    */
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);
145   }
146
147   /**
148    * @covers ::assemble
149    */
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']);
157         }
158         return 'test-other-uri';
159       });
160
161     $result = $this->unroutedUrlAssembler->assemble('base:test-uri', ['path_processing' => TRUE]);
162     $this->assertEquals('/test-other-uri', $result);
163
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);
169   }
170
171   /**
172    * Setups the request stack for a given subdir.
173    *
174    * @param string $subdir
175    *   The wanted subdir.
176    */
177   protected function setupRequestStack($subdir) {
178     $server = [];
179     if ($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.
183       $server = [
184         'SCRIPT_NAME' => '/subdir/index.php',
185         'SCRIPT_FILENAME' => $this->root . '/index.php',
186         'SERVER_NAME' => 'http://www.example.com',
187       ];
188       $request = Request::create('/subdir/');
189     }
190     else {
191       $request = Request::create('/');
192     }
193     $request->server->add($server);
194     $this->requestStack->push($request);
195   }
196
197 }