Updated all the contrib modules to their latest versions.
[yaffs-website] / web / modules / contrib / redirect / tests / src / Unit / RedirectRequestSubscriberTest.php
1 <?php
2
3 namespace Drupal\Tests\redirect\Unit;
4
5 use Drupal\Core\Language\Language;
6 use Drupal\redirect\EventSubscriber\RedirectRequestSubscriber;
7 use Drupal\Tests\UnitTestCase;
8 use PHPUnit_Framework_MockObject_MockObject;
9 use Symfony\Component\HttpFoundation\RedirectResponse;
10 use Symfony\Component\HttpFoundation\Request;
11 use Symfony\Component\HttpFoundation\Response;
12 use Symfony\Component\HttpKernel\Event\GetResponseEvent;
13 use Symfony\Component\HttpKernel\Event\PostResponseEvent;
14
15 /**
16  * Tests the redirect logic.
17  *
18  * @group redirect
19  *
20  * @coversDefaultClass Drupal\redirect\EventSubscriber\RedirectRequestSubscriber
21  */
22 class RedirectRequestSubscriberTest extends UnitTestCase {
23
24   /**
25    * @covers ::onKernelRequestCheckRedirect
26    * @dataProvider getRedirectData
27    */
28   public function testRedirectLogicWithQueryRetaining($request_uri, $request_query, $redirect_uri, $redirect_query) {
29
30     // The expected final query. This query must contain values defined
31     // by the redirect entity and values from the accessed url.
32     $final_query = $redirect_query + $request_query;
33
34     $url = $this->getMockBuilder('Drupal\Core\Url')
35       ->disableOriginalConstructor()
36       ->getMock();
37
38     $url->expects($this->once())
39       ->method('setAbsolute')
40       ->with(TRUE)
41       ->willReturn($url);
42
43     $url->expects($this->once())
44       ->method('getOption')
45       ->with('query')
46       ->willReturn($redirect_query);
47
48     $url->expects($this->once())
49       ->method('setOption')
50       ->with('query', $final_query);
51
52     $url->expects($this->once())
53       ->method('toString')
54       ->willReturn($redirect_uri);
55
56     $redirect = $this->getRedirectStub($url);
57     $event = $this->callOnKernelRequestCheckRedirect($redirect, $request_uri, $request_query, TRUE);
58
59     $this->assertTrue($event->getResponse() instanceof RedirectResponse);
60     $response = $event->getResponse();
61     $this->assertEquals('/test-path', $response->getTargetUrl());
62     $this->assertEquals(301, $response->getStatusCode());
63     $this->assertEquals(1, $response->headers->get('X-Redirect-ID'));
64   }
65
66   /**
67    * @covers ::onKernelRequestCheckRedirect
68    * @dataProvider getRedirectData
69    */
70   public function testRedirectLogicWithoutQueryRetaining($request_uri, $request_query, $redirect_uri) {
71
72     $url = $this->getMockBuilder('Drupal\Core\Url')
73       ->disableOriginalConstructor()
74       ->getMock();
75
76     $url->expects($this->once())
77       ->method('setAbsolute')
78       ->with(TRUE)
79       ->willReturn($url);
80
81     // No query retaining, so getOption should not be called.
82     $url->expects($this->never())
83       ->method('getOption');
84     $url->expects($this->never())
85       ->method('setOption');
86
87     $url->expects($this->once())
88       ->method('toString')
89       ->willReturn($redirect_uri);
90
91     $redirect = $this->getRedirectStub($url);
92     $event = $this->callOnKernelRequestCheckRedirect($redirect, $request_uri, $request_query, FALSE);
93
94     $this->assertTrue($event->getResponse() instanceof RedirectResponse);
95     $response = $event->getResponse();
96     $this->assertEquals($redirect_uri, $response->getTargetUrl());
97     $this->assertEquals(301, $response->getStatusCode());
98     $this->assertEquals(1, $response->headers->get('X-Redirect-ID'));
99   }
100
101   /**
102    * Data provider for both tests.
103    */
104   public function getRedirectData() {
105     return [
106       ['non-existing', ['key' => 'val'], '/test-path', ['dummy' => 'value']],
107       ['non-existing/', ['key' => 'val'], '/test-path', ['dummy' => 'value']],
108       ['system/files/file.txt', [], '/test-path', []],
109     ];
110   }
111
112   /**
113    * Instantiates the subscriber and runs onKernelRequestCheckRedirect()
114    *
115    * @param $redirect
116    *   The redirect entity.
117    * @param $request_uri
118    *   The URI of the request.
119    * @param array $request_query
120    *   The query that is supposed to come via request.
121    * @param bool $retain_query
122    *   Flag if to retain the query through the redirect.
123    *
124    * @return \Symfony\Component\HttpKernel\Event\GetResponseEvent
125    *   THe response event.
126    */
127   protected function callOnKernelRequestCheckRedirect($redirect, $request_uri, $request_query, $retain_query) {
128
129     $event = $this->getGetResponseEventStub($request_uri, http_build_query($request_query));
130     $request = $event->getRequest();
131
132     $checker = $this->getMockBuilder('Drupal\redirect\RedirectChecker')
133       ->disableOriginalConstructor()
134       ->getMock();
135     $checker->expects($this->any())
136       ->method('canRedirect')
137       ->will($this->returnValue(TRUE));
138
139     $context = $this->getMock('Symfony\Component\Routing\RequestContext');
140
141     $inbound_path_processor = $this->getMockBuilder('Drupal\Core\PathProcessor\InboundPathProcessorInterface')
142       ->disableOriginalConstructor()
143       ->getMock();
144     $inbound_path_processor->expects($this->any())
145       ->method('processInbound')
146       ->with($request->getPathInfo(), $request)
147       ->willReturnCallback(function ($path, Request $request) {
148         if (strpos($path, '/system/files/') === 0 && !$request->query->has('file')) {
149           // Private files paths are split by the inbound path processor and the
150           // relative file path is moved to the 'file' query string parameter.
151           // This is because the route system does not allow an arbitrary amount
152           // of parameters.
153           // @see \Drupal\system\PathProcessor\PathProcessorFiles::processInbound()
154           $path = '/system/files';
155         }
156         return $path;
157       });
158
159     $alias_manager = $this->getMockBuilder('Drupal\Core\Path\AliasManager')
160       ->disableOriginalConstructor()
161       ->getMock();
162     $module_handler = $this->getMockBuilder('Drupal\Core\Extension\ModuleHandlerInterface')
163       ->getMock();
164     $entity_manager = $this->getMockBuilder('Drupal\Core\Entity\EntityManagerInterface')
165       ->getMock();
166
167     $subscriber = new RedirectRequestSubscriber(
168       $this->getRedirectRepositoryStub('findMatchingRedirect', $redirect),
169       $this->getLanguageManagerStub(),
170       $this->getConfigFactoryStub(array('redirect.settings' => array('passthrough_querystring' => $retain_query))),
171       $alias_manager,
172       $module_handler,
173       $entity_manager,
174       $checker,
175       $context,
176       $inbound_path_processor
177     );
178
179     // Run the main redirect method.
180     $subscriber->onKernelRequestCheckRedirect($event);
181     return $event;
182   }
183
184   /**
185    * Gets the redirect repository mock object.
186    *
187    * @param $method
188    *   Method to mock - either load() or findMatchingRedirect().
189    * @param $redirect
190    *   The redirect object to be returned.
191    *
192    * @return PHPUnit_Framework_MockObject_MockObject
193    *   The redirect repository.
194    */
195   protected function getRedirectRepositoryStub($method, $redirect) {
196     $repository = $this->getMockBuilder('Drupal\redirect\RedirectRepository')
197       ->disableOriginalConstructor()
198       ->getMock();
199
200     if ($method === 'findMatchingRedirect') {
201       $repository->expects($this->any())
202         ->method($method)
203         ->willReturnCallback(function ($source_path) use ($redirect) {
204           // No redirect with source path 'system/files' exists. The stored
205           // redirect has 'system/files/file.txt' as source path.
206           return $source_path === 'system/files' ? NULL : $redirect;
207         });
208     }
209     else {
210       $repository->expects($this->any())
211         ->method($method)
212         ->will($this->returnValue($redirect));
213     }
214
215     return $repository;
216   }
217
218   /**
219    * Gets the redirect mock object.
220    *
221    * @param $url
222    *   Url to be returned from getRedirectUrl
223    * @param int $status_code
224    *   The redirect status code.
225    *
226    * @return PHPUnit_Framework_MockObject_MockObject
227    *   The mocked redirect object.
228    */
229   protected function getRedirectStub($url, $status_code = 301) {
230     $redirect = $this->getMockBuilder('Drupal\redirect\Entity\Redirect')
231       ->disableOriginalConstructor()
232       ->getMock();
233     $redirect->expects($this->once())
234       ->method('getRedirectUrl')
235       ->will($this->returnValue($url));
236     $redirect->expects($this->any())
237       ->method('getStatusCode')
238       ->will($this->returnValue($status_code));
239     $redirect->expects($this->any())
240       ->method('id')
241       ->willReturn(1);
242     $redirect->expects($this->once())
243       ->method('getCacheTags')
244       ->willReturn(['redirect:1']);
245
246     return $redirect;
247   }
248
249   /**
250    * Gets post response event.
251    *
252    * @param array $headers
253    *   Headers to be set into the response.
254    *
255    * @return \Symfony\Component\HttpKernel\Event\PostResponseEvent
256    *   The post response event object.
257    */
258   protected function getPostResponseEvent($headers = array()) {
259     $http_kernel = $this->getMockBuilder('\Symfony\Component\HttpKernel\HttpKernelInterface')
260       ->getMock();
261     $request = $this->getMockBuilder('Symfony\Component\HttpFoundation\Request')
262       ->disableOriginalConstructor()
263       ->getMock();
264
265     $response = new Response('', 301, $headers);
266
267     return new PostResponseEvent($http_kernel, $request, $response);
268   }
269
270   /**
271    * Gets response event object.
272    *
273    * @param $path_info
274    * @param $query_string
275    *
276    * @return GetResponseEvent
277    */
278   protected function getGetResponseEventStub($path_info, $query_string) {
279     $request = Request::create($path_info . '?' . $query_string, 'GET', [], [], [], ['SCRIPT_NAME' => 'index.php']);
280
281     $http_kernel = $this->getMockBuilder('\Symfony\Component\HttpKernel\HttpKernelInterface')
282       ->getMock();
283     return new GetResponseEvent($http_kernel, $request, 'test');
284   }
285
286   /**
287    * Gets the language manager mock object.
288    *
289    * @return \Drupal\language\ConfigurableLanguageManagerInterface|PHPUnit_Framework_MockObject_MockObject
290    */
291   protected function getLanguageManagerStub() {
292     $language_manager = $this->getMockBuilder('Drupal\language\ConfigurableLanguageManagerInterface')
293       ->getMock();
294     $language_manager->expects($this->any())
295       ->method('getCurrentLanguage')
296       ->will($this->returnValue(new Language(array('id' => 'en'))));
297
298     return $language_manager;
299   }
300
301 }