3 namespace Drupal\Tests\Core\EventSubscriber;
5 use Drupal\Component\Utility\UrlHelper;
6 use Drupal\Core\Access\AccessResult;
7 use Drupal\Core\DependencyInjection\ContainerBuilder;
8 use Drupal\Core\EventSubscriber\CustomPageExceptionHtmlSubscriber;
9 use Drupal\Core\Render\HtmlResponse;
10 use Drupal\Core\Routing\AccessAwareRouterInterface;
12 use Drupal\Tests\UnitTestCase;
13 use Symfony\Component\HttpFoundation\Request;
14 use Symfony\Component\HttpFoundation\Response;
15 use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
16 use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
17 use Symfony\Component\Routing\RequestContext;
20 * @coversDefaultClass \Drupal\Core\EventSubscriber\CustomPageExceptionHtmlSubscriber
21 * @group EventSubscriber
23 class CustomPageExceptionHtmlSubscriberTest extends UnitTestCase {
26 * The mocked HTTP kernel.
28 * @var \Symfony\Component\HttpKernel\HttpKernelInterface|\PHPUnit_Framework_MockObject_MockObject
33 * The mocked config factory
35 * @var \Drupal\Core\Config\ConfigFactoryInterface|\PHPUnit_Framework_MockObject_MockObject
37 protected $configFactory;
42 * @var \Psr\Log\LoggerInterface
47 * The PHP error log settings before the test.
54 * The tested custom page exception subscriber.
56 * @var \Drupal\Core\EventSubscriber\CustomPageExceptionHtmlSubscriber|\Drupal\Tests\Core\EventSubscriber\TestCustomPageExceptionHtmlSubscriber
58 protected $customPageSubscriber;
61 * The mocked redirect.destination service.
63 * @var \Drupal\Core\Routing\RedirectDestinationInterface|\PHPUnit_Framework_MockObject_MockObject
65 protected $redirectDestination;
68 * The mocked access unaware router.
69 * @var \Symfony\Component\Routing\Matcher\UrlMatcherInterface|\PHPUnit_Framework_MockObject_MockObject
71 protected $accessUnawareRouter;
76 * @var \Drupal\Core\Access\AccessManagerInterface
78 protected $accessManager;
83 protected function setUp() {
84 $this->configFactory = $this->getConfigFactoryStub(['system.site' => ['page.403' => '/access-denied-page', 'page.404' => '/not-found-page']]);
86 $this->kernel = $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface');
87 $this->logger = $this->getMock('Psr\Log\LoggerInterface');
88 $this->redirectDestination = $this->getMock('\Drupal\Core\Routing\RedirectDestinationInterface');
89 $this->redirectDestination->expects($this->any())
90 ->method('getAsArray')
91 ->willReturn(['destination' => 'test']);
92 $this->accessUnawareRouter = $this->getMock('Symfony\Component\Routing\Matcher\UrlMatcherInterface');
93 $this->accessUnawareRouter->expects($this->any())
96 '_controller' => 'mocked',
98 $this->accessManager = $this->getMock('Drupal\Core\Access\AccessManagerInterface');
99 $this->accessManager->expects($this->any())
100 ->method('checkNamedRoute')
101 ->willReturn(AccessResult::allowed()->addCacheTags(['foo', 'bar']));
103 $this->customPageSubscriber = new CustomPageExceptionHtmlSubscriber($this->configFactory, $this->kernel, $this->logger, $this->redirectDestination, $this->accessUnawareRouter, $this->accessManager);
105 $path_validator = $this->getMock('Drupal\Core\Path\PathValidatorInterface');
106 $path_validator->expects($this->any())
107 ->method('getUrlIfValidWithoutAccessCheck')
108 ->willReturn(Url::fromRoute('foo', ['foo' => 'bar']));
109 $container = new ContainerBuilder();
110 $container->set('path.validator', $path_validator);
111 \Drupal::setContainer($container);
113 // You can't create an exception in PHP without throwing it. Store the
114 // current error_log, and disable it temporarily.
115 $this->errorLog = ini_set('error_log', file_exists('/dev/null') ? '/dev/null' : 'nul');
121 protected function tearDown() {
122 ini_set('error_log', $this->errorLog);
126 * Tests onHandleException with a POST request.
128 public function testHandleWithPostRequest() {
129 $request = Request::create('/test', 'POST', ['name' => 'druplicon', 'pass' => '12345']);
131 $request_context = new RequestContext();
132 $request_context->fromRequest($request);
133 $this->accessUnawareRouter->expects($this->any())
134 ->method('getContext')
135 ->willReturn($request_context);
137 $this->kernel->expects($this->once())->method('handle')->will($this->returnCallback(function (Request $request) {
138 return new HtmlResponse($request->getMethod());
141 $event = new GetResponseForExceptionEvent($this->kernel, $request, 'foo', new NotFoundHttpException('foo'));
143 $this->customPageSubscriber->onException($event);
145 $response = $event->getResponse();
146 $result = $response->getContent() . " " . UrlHelper::buildQuery($request->request->all());
147 $this->assertEquals('POST name=druplicon&pass=12345', $result);
148 $this->assertEquals(AccessResult::allowed()->addCacheTags(['foo', 'bar']), $request->attributes->get(AccessAwareRouterInterface::ACCESS_RESULT));
152 * Tests onHandleException with a GET request.
154 public function testHandleWithGetRequest() {
155 $request = Request::create('/test', 'GET', ['name' => 'druplicon', 'pass' => '12345']);
156 $request->attributes->set(AccessAwareRouterInterface::ACCESS_RESULT, AccessResult::forbidden()->addCacheTags(['druplicon']));
158 $request_context = new RequestContext();
159 $request_context->fromRequest($request);
160 $this->accessUnawareRouter->expects($this->any())
161 ->method('getContext')
162 ->willReturn($request_context);
164 $this->kernel->expects($this->once())->method('handle')->will($this->returnCallback(function (Request $request) {
165 return new Response($request->getMethod() . ' ' . UrlHelper::buildQuery($request->query->all()));
168 $event = new GetResponseForExceptionEvent($this->kernel, $request, 'foo', new NotFoundHttpException('foo'));
169 $this->customPageSubscriber->onException($event);
171 $response = $event->getResponse();
172 $result = $response->getContent() . " " . UrlHelper::buildQuery($request->request->all());
173 $this->assertEquals('GET name=druplicon&pass=12345&destination=test&_exception_statuscode=404 ', $result);
174 $this->assertEquals(AccessResult::forbidden()->addCacheTags(['druplicon', 'foo', 'bar']), $request->attributes->get(AccessAwareRouterInterface::ACCESS_RESULT));