class RouteProcessorCsrfTest

Same name in other branches
  1. 9 core/tests/Drupal/Tests/Core/Access/RouteProcessorCsrfTest.php \Drupal\Tests\Core\Access\RouteProcessorCsrfTest
  2. 8.9.x core/tests/Drupal/Tests/Core/Access/RouteProcessorCsrfTest.php \Drupal\Tests\Core\Access\RouteProcessorCsrfTest
  3. 10 core/tests/Drupal/Tests/Core/Access/RouteProcessorCsrfTest.php \Drupal\Tests\Core\Access\RouteProcessorCsrfTest

@coversDefaultClass \Drupal\Core\Access\RouteProcessorCsrf @group Access

Hierarchy

Expanded class hierarchy of RouteProcessorCsrfTest

File

core/tests/Drupal/Tests/Core/Access/RouteProcessorCsrfTest.php, line 20

Namespace

Drupal\Tests\Core\Access
View source
class RouteProcessorCsrfTest extends UnitTestCase {
    
    /**
     * The mock CSRF token generator.
     */
    protected CsrfTokenGenerator&MockObject $csrfToken;
    
    /**
     * The mock request stack.
     */
    protected RequestStack&MockObject $requestStack;
    
    /**
     * The route processor.
     */
    protected RouteProcessorCsrf $processor;
    
    /**
     * {@inheritdoc}
     */
    protected function setUp() : void {
        parent::setUp();
        $this->csrfToken = $this->getMockBuilder('Drupal\\Core\\Access\\CsrfTokenGenerator')
            ->disableOriginalConstructor()
            ->getMock();
        $this->requestStack = $this->getMockBuilder('Symfony\\Component\\HttpFoundation\\RequestStack')
            ->disableOriginalConstructor()
            ->getMock();
        $request = $this->createMock('Symfony\\Component\\HttpFoundation\\Request');
        $request->expects($this->any())
            ->method('getRequestFormat')
            ->willReturn('html');
        $this->requestStack
            ->expects($this->any())
            ->method('getCurrentRequest')
            ->willReturn($request);
        $this->processor = new RouteProcessorCsrf($this->csrfToken, $this->requestStack);
    }
    
    /**
     * Tests the processOutbound() method with no _csrf_token route requirement.
     */
    public function testProcessOutboundNoRequirement() : void {
        $this->csrfToken
            ->expects($this->never())
            ->method('get');
        $route = new Route('/test-path');
        $parameters = [];
        $bubbleable_metadata = new BubbleableMetadata();
        $this->processor
            ->processOutbound('test', $route, $parameters, $bubbleable_metadata);
        // No parameters should be added to the parameters array.
        $this->assertEmpty($parameters);
        // Cacheability of routes without a _csrf_token route requirement is
        // unaffected.
        $this->assertEquals(new BubbleableMetadata(), $bubbleable_metadata);
    }
    
    /**
     * Tests the processOutbound() method with a _csrf_token route requirement.
     */
    public function testProcessOutbound() : void {
        $route = new Route('/test-path', [], [
            '_csrf_token' => 'TRUE',
        ]);
        $parameters = [];
        $bubbleable_metadata = new BubbleableMetadata();
        $this->processor
            ->processOutbound('test', $route, $parameters, $bubbleable_metadata);
        // 'token' should be added to the parameters array.
        $this->assertArrayHasKey('token', $parameters);
        // Bubbleable metadata of routes with a _csrf_token route requirement is a
        // placeholder.
        $path = 'test-path';
        $placeholder = Crypt::hashBase64($path);
        $placeholder_render_array = [
            '#lazy_builder' => [
                'route_processor_csrf:renderPlaceholderCsrfToken',
                [
                    $path,
                ],
            ],
        ];
        $this->assertSame($parameters['token'], $placeholder);
        $this->assertEquals((new BubbleableMetadata())->setAttachments([
            'placeholders' => [
                $placeholder => $placeholder_render_array,
            ],
        ]), $bubbleable_metadata);
    }
    
    /**
     * Tests the processOutbound() method with a dynamic path and one replacement.
     */
    public function testProcessOutboundDynamicOne() : void {
        $route = new Route('/test-path/{slug}', [], [
            '_csrf_token' => 'TRUE',
        ]);
        $parameters = [
            'slug' => 100,
        ];
        $bubbleable_metadata = new BubbleableMetadata();
        $this->processor
            ->processOutbound('test', $route, $parameters, $bubbleable_metadata);
        // Bubbleable metadata of routes with a _csrf_token route requirement is a
        // placeholder.
        $path = 'test-path/100';
        $placeholder = Crypt::hashBase64($path);
        $placeholder_render_array = [
            '#lazy_builder' => [
                'route_processor_csrf:renderPlaceholderCsrfToken',
                [
                    $path,
                ],
            ],
        ];
        $this->assertEquals((new BubbleableMetadata())->setAttachments([
            'placeholders' => [
                $placeholder => $placeholder_render_array,
            ],
        ]), $bubbleable_metadata);
    }
    
    /**
     * Tests the processOutbound() method with two parameter replacements.
     */
    public function testProcessOutboundDynamicTwo() : void {
        $route = new Route('{slug_1}/test-path/{slug_2}', [], [
            '_csrf_token' => 'TRUE',
        ]);
        $parameters = [
            'slug_1' => 100,
            'slug_2' => 'test',
        ];
        $bubbleable_metadata = new BubbleableMetadata();
        $this->processor
            ->processOutbound('test', $route, $parameters, $bubbleable_metadata);
        // Bubbleable metadata of routes with a _csrf_token route requirement is a
        // placeholder.
        $path = '100/test-path/test';
        $placeholder = Crypt::hashBase64($path);
        $placeholder_render_array = [
            '#lazy_builder' => [
                'route_processor_csrf:renderPlaceholderCsrfToken',
                [
                    $path,
                ],
            ],
        ];
        $this->assertEquals((new BubbleableMetadata())->setAttachments([
            'placeholders' => [
                $placeholder => $placeholder_render_array,
            ],
        ]), $bubbleable_metadata);
    }
    
    /**
     * Tests JSON requests to get no placeholders, but real tokens.
     */
    public function testProcessOutboundJsonFormat() : void {
        // Create a new request mock that returns 'json' format.
        $request = $this->createMock('Symfony\\Component\\HttpFoundation\\Request');
        $request->expects($this->once())
            ->method('getRequestFormat')
            ->willReturn('json');
        $this->requestStack = $this->createMock('Symfony\\Component\\HttpFoundation\\RequestStack');
        $this->requestStack
            ->expects($this->once())
            ->method('getCurrentRequest')
            ->willReturn($request);
        // Mock that the CSRF token service should be called once with 'test-path'
        // and return a test token.
        $this->csrfToken
            ->expects($this->any())
            ->method('get')
            ->with('test-path')
            ->willReturn('real_token_value');
        $this->processor = new RouteProcessorCsrf($this->csrfToken, $this->requestStack);
        $route = new Route('/test-path', [], [
            '_csrf_token' => 'TRUE',
        ]);
        $parameters = [];
        // For JSON requests, the actual CSRF token should be in parameters,
        // regardless of whether cache metadata is present.
        $this->processor
            ->processOutbound('test', $route, $parameters);
        $this->assertEquals('real_token_value', $parameters['token']);
        $this->processor
            ->processOutbound('test', $route, $parameters, new BubbleableMetadata());
        $this->assertEquals('real_token_value', $parameters['token']);
    }

}

Members

Title Sort descending Modifiers Object type Summary Overriden Title
ExpectDeprecationTrait::expectDeprecation public function Adds an expected deprecation.
ExpectDeprecationTrait::setUpErrorHandler public function Sets up the test error handler.
ExpectDeprecationTrait::tearDownErrorHandler public function Tears down the test error handler.
RandomGeneratorTrait::getRandomGenerator protected function Gets the random generator for the utility methods.
RandomGeneratorTrait::randomMachineName protected function Generates a unique random string containing letters and numbers.
RandomGeneratorTrait::randomObject public function Generates a random PHP object.
RandomGeneratorTrait::randomString public function Generates a pseudo-random string of ASCII characters of codes 32 to 126.
RouteProcessorCsrfTest::$csrfToken protected property The mock CSRF token generator.
RouteProcessorCsrfTest::$processor protected property The route processor.
RouteProcessorCsrfTest::$requestStack protected property The mock request stack.
RouteProcessorCsrfTest::setUp protected function Overrides UnitTestCase::setUp
RouteProcessorCsrfTest::testProcessOutbound public function Tests the processOutbound() method with a _csrf_token route requirement.
RouteProcessorCsrfTest::testProcessOutboundDynamicOne public function Tests the processOutbound() method with a dynamic path and one replacement.
RouteProcessorCsrfTest::testProcessOutboundDynamicTwo public function Tests the processOutbound() method with two parameter replacements.
RouteProcessorCsrfTest::testProcessOutboundJsonFormat public function Tests JSON requests to get no placeholders, but real tokens.
RouteProcessorCsrfTest::testProcessOutboundNoRequirement public function Tests the processOutbound() method with no _csrf_token route requirement.
UnitTestCase::$root protected property The app root.
UnitTestCase::getClassResolverStub protected function Returns a stub class resolver.
UnitTestCase::getConfigFactoryStub public function Returns a stub config factory that behaves according to the passed array.
UnitTestCase::getContainerWithCacheTagsInvalidator protected function Sets up a container with a cache tags invalidator.
UnitTestCase::getStringTranslationStub public function Returns a stub translation manager that just returns the passed string.
UnitTestCase::setDebugDumpHandler public static function Registers the dumper CLI handler when the DebugDump extension is enabled.

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.