3 namespace Drupal\Tests\redirect\Unit;
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;
16 * Tests the redirect logic.
20 * @coversDefaultClass Drupal\redirect\EventSubscriber\RedirectRequestSubscriber
22 class RedirectRequestSubscriberTest extends UnitTestCase {
25 * @covers ::onKernelRequestCheckRedirect
26 * @dataProvider getRedirectData
28 public function testRedirectLogicWithQueryRetaining($request_uri, $request_query, $redirect_uri, $redirect_query) {
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;
34 $url = $this->getMockBuilder('Drupal\Core\Url')
35 ->disableOriginalConstructor()
38 $url->expects($this->once())
39 ->method('setAbsolute')
43 $url->expects($this->once())
46 ->willReturn($redirect_query);
48 $url->expects($this->once())
50 ->with('query', $final_query);
52 $url->expects($this->once())
54 ->willReturn($redirect_uri);
56 $redirect = $this->getRedirectStub($url);
57 $event = $this->callOnKernelRequestCheckRedirect($redirect, $request_uri, $request_query, TRUE);
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'));
67 * @covers ::onKernelRequestCheckRedirect
68 * @dataProvider getRedirectData
70 public function testRedirectLogicWithoutQueryRetaining($request_uri, $request_query, $redirect_uri) {
72 $url = $this->getMockBuilder('Drupal\Core\Url')
73 ->disableOriginalConstructor()
76 $url->expects($this->once())
77 ->method('setAbsolute')
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');
87 $url->expects($this->once())
89 ->willReturn($redirect_uri);
91 $redirect = $this->getRedirectStub($url);
92 $event = $this->callOnKernelRequestCheckRedirect($redirect, $request_uri, $request_query, FALSE);
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'));
102 * Data provider for both tests.
104 public function getRedirectData() {
106 ['non-existing', ['key' => 'val'], '/test-path', ['dummy' => 'value']],
107 ['non-existing/', ['key' => 'val'], '/test-path', ['dummy' => 'value']],
112 * Instantiates the subscriber and runs onKernelRequestCheckRedirect()
115 * The redirect entity.
116 * @param $request_uri
117 * The URI of the request.
118 * @param array $request_query
119 * The query that is supposed to come via request.
120 * @param bool $retain_query
121 * Flag if to retain the query through the redirect.
123 * @return \Symfony\Component\HttpKernel\Event\GetResponseEvent
124 * THe response event.
126 protected function callOnKernelRequestCheckRedirect($redirect, $request_uri, $request_query, $retain_query) {
128 $event = $this->getGetResponseEventStub($request_uri, http_build_query($request_query));
129 $request = $event->getRequest();
131 $checker = $this->getMockBuilder('Drupal\redirect\RedirectChecker')
132 ->disableOriginalConstructor()
134 $checker->expects($this->any())
135 ->method('canRedirect')
136 ->will($this->returnValue(TRUE));
137 $checker->expects($this->any())
139 ->will($this->returnValue(FALSE));
141 $context = $this->getMock('Symfony\Component\Routing\RequestContext');
143 $inbound_path_processor = $this->getMockBuilder('Drupal\Core\PathProcessor\InboundPathProcessorInterface')
144 ->disableOriginalConstructor()
146 $inbound_path_processor->expects($this->any())
147 ->method('processInbound')
148 ->with($request->getPathInfo(), $request)
149 ->will($this->returnValue($request->getPathInfo()));
151 $alias_manager = $this->getMockBuilder('Drupal\Core\Path\AliasManager')
152 ->disableOriginalConstructor()
154 $module_handler = $this->getMockBuilder('Drupal\Core\Extension\ModuleHandlerInterface')
156 $entity_manager = $this->getMockBuilder('Drupal\Core\Entity\EntityManagerInterface')
159 $subscriber = new RedirectRequestSubscriber(
160 $this->getRedirectRepositoryStub('findMatchingRedirect', $redirect),
161 $this->getLanguageManagerStub(),
162 $this->getConfigFactoryStub(array('redirect.settings' => array('passthrough_querystring' => $retain_query))),
168 $inbound_path_processor
171 // Run the main redirect method.
172 $subscriber->onKernelRequestCheckRedirect($event);
177 * Gets the redirect repository mock object.
180 * Method to mock - either load() or findMatchingRedirect().
182 * The redirect object to be returned.
184 * @return PHPUnit_Framework_MockObject_MockObject
185 * The redirect repository.
187 protected function getRedirectRepositoryStub($method, $redirect) {
188 $repository = $this->getMockBuilder('Drupal\redirect\RedirectRepository')
189 ->disableOriginalConstructor()
192 $repository->expects($this->any())
194 ->will($this->returnValue($redirect));
200 * Gets the redirect mock object.
203 * Url to be returned from getRedirectUrl
204 * @param int $status_code
205 * The redirect status code.
207 * @return PHPUnit_Framework_MockObject_MockObject
208 * The mocked redirect object.
210 protected function getRedirectStub($url, $status_code = 301) {
211 $redirect = $this->getMockBuilder('Drupal\redirect\Entity\Redirect')
212 ->disableOriginalConstructor()
214 $redirect->expects($this->once())
215 ->method('getRedirectUrl')
216 ->will($this->returnValue($url));
217 $redirect->expects($this->any())
218 ->method('getStatusCode')
219 ->will($this->returnValue($status_code));
220 $redirect->expects($this->any())
223 $redirect->expects($this->once())
224 ->method('getCacheTags')
225 ->willReturn(['redirect:1']);
231 * Gets post response event.
233 * @param array $headers
234 * Headers to be set into the response.
236 * @return \Symfony\Component\HttpKernel\Event\PostResponseEvent
237 * The post response event object.
239 protected function getPostResponseEvent($headers = array()) {
240 $http_kernel = $this->getMockBuilder('\Symfony\Component\HttpKernel\HttpKernelInterface')
242 $request = $this->getMockBuilder('Symfony\Component\HttpFoundation\Request')
243 ->disableOriginalConstructor()
246 $response = new Response('', 301, $headers);
248 return new PostResponseEvent($http_kernel, $request, $response);
252 * Gets response event object.
255 * @param $query_string
257 * @return GetResponseEvent
259 protected function getGetResponseEventStub($path_info, $query_string) {
260 $request = Request::create($path_info . '?' . $query_string, 'GET', [], [], [], ['SCRIPT_NAME' => 'index.php']);
262 $http_kernel = $this->getMockBuilder('\Symfony\Component\HttpKernel\HttpKernelInterface')
264 return new GetResponseEvent($http_kernel, $request, 'test');
268 * Gets the language manager mock object.
270 * @return \Drupal\language\ConfigurableLanguageManagerInterface|PHPUnit_Framework_MockObject_MockObject
272 protected function getLanguageManagerStub() {
273 $language_manager = $this->getMockBuilder('Drupal\language\ConfigurableLanguageManagerInterface')
275 $language_manager->expects($this->any())
276 ->method('getCurrentLanguage')
277 ->will($this->returnValue(new Language(array('id' => 'en'))));
279 return $language_manager;