MenuLinkContentCacheabilityBubblingTest.php

Same filename and directory in other branches
  1. 9 core/modules/menu_link_content/tests/src/Kernel/MenuLinkContentCacheabilityBubblingTest.php
  2. 10 core/modules/menu_link_content/tests/src/Kernel/MenuLinkContentCacheabilityBubblingTest.php
  3. 11.x core/modules/menu_link_content/tests/src/Kernel/MenuLinkContentCacheabilityBubblingTest.php

Namespace

Drupal\Tests\menu_link_content\Kernel

File

core/modules/menu_link_content/tests/src/Kernel/MenuLinkContentCacheabilityBubblingTest.php

View source
<?php

namespace Drupal\Tests\menu_link_content\Kernel;

use Drupal\Core\Cache\Cache;
use Drupal\Core\Language\LanguageInterface;
use Drupal\Core\Menu\MenuTreeParameters;
use Drupal\Core\Render\BubbleableMetadata;
use Drupal\KernelTests\KernelTestBase;
use Drupal\menu_link_content\Entity\MenuLinkContent;
use Drupal\Tests\user\Traits\UserCreationTrait;
use Drupal\user\Entity\User;
use Symfony\Cmf\Component\Routing\RouteObjectInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Route;

/**
 * Ensures that rendered menu links bubble the necessary bubbleable metadata
 * for outbound path/route processing.
 *
 * @group menu_link_content
 */
class MenuLinkContentCacheabilityBubblingTest extends KernelTestBase {
    use UserCreationTrait;
    
    /**
     * {@inheritdoc}
     */
    public static $modules = [
        'menu_link_content',
        'system',
        'link',
        'outbound_processing_test',
        'url_alter_test',
        'user',
    ];
    
    /**
     * {@inheritdoc}
     */
    protected function setUp() {
        parent::setUp();
        $this->setUpCurrentUser([
            'uid' => 0,
        ]);
        $this->installEntitySchema('menu_link_content');
        // Ensure that the weight of module_link_content is higher than system.
        // @see menu_link_content_install()
        module_set_weight('menu_link_content', 1);
    }
    
    /**
     * Tests bubbleable metadata of menu links' outbound route/path processing.
     */
    public function testOutboundPathAndRouteProcessing() {
        \Drupal::service('router.builder')->rebuild();
        $request_stack = \Drupal::requestStack();
        
        /** @var \Symfony\Component\Routing\RequestContext $request_context */
        $request_context = \Drupal::service('router.request_context');
        $request = Request::create('/');
        $request->attributes
            ->set(RouteObjectInterface::ROUTE_NAME, '<front>');
        $request->attributes
            ->set(RouteObjectInterface::ROUTE_OBJECT, new Route('/'));
        $request_stack->push($request);
        $request_context->fromRequest($request);
        $menu_tree = \Drupal::menuTree();
        $renderer = \Drupal::service('renderer');
        $default_menu_cacheability = (new BubbleableMetadata())->setCacheMaxAge(Cache::PERMANENT)
            ->setCacheTags([
            'config:system.menu.tools',
        ])
            ->setCacheContexts([
            'languages:' . LanguageInterface::TYPE_INTERFACE,
            'theme',
            'user.permissions',
        ]);
        User::create([
            'uid' => 1,
            'name' => $this->randomString(),
        ])
            ->save();
        User::create([
            'uid' => 2,
            'name' => $this->randomString(),
        ])
            ->save();
        // Five test cases, four asserting one outbound path/route processor, and
        // together covering one of each:
        // - no cacheability metadata,
        // - a cache context,
        // - a cache tag,
        // - a cache max-age.
        // Plus an additional test case to verify that multiple links adding
        // cacheability metadata of the same type is working (two links with cache
        // tags).
        $test_cases = [
            // \Drupal\Core\RouteProcessor\RouteProcessorCurrent: 'route' cache context.
[
                'uri' => 'route:<current>',
                'cacheability' => (new BubbleableMetadata())->setCacheContexts([
                    'route',
                ]),
            ],
            // \Drupal\Core\Access\RouteProcessorCsrf: placeholder.
[
                'uri' => 'route:outbound_processing_test.route.csrf',
                'cacheability' => (new BubbleableMetadata())->setCacheContexts([
                    'session',
                ])
                    ->setAttachments([
                    'placeholders' => [],
                ]),
            ],
            // \Drupal\Core\PathProcessor\PathProcessorFront: permanently cacheable.
[
                'uri' => 'internal:/',
                'cacheability' => new BubbleableMetadata(),
            ],
            // \Drupal\url_alter_test\PathProcessorTest: user entity's cache tags.
[
                'uri' => 'internal:/user/1',
                'cacheability' => (new BubbleableMetadata())->setCacheTags(User::load(1)->getCacheTags()),
            ],
            [
                'uri' => 'internal:/user/2',
                'cacheability' => (new BubbleableMetadata())->setCacheTags(User::load(2)->getCacheTags()),
            ],
        ];
        // Test each expectation individually.
        foreach ($test_cases as $expectation) {
            $menu_link_content = MenuLinkContent::create([
                'link' => [
                    'uri' => $expectation['uri'],
                ],
                'menu_name' => 'tools',
                'title' => 'Link test',
            ]);
            $menu_link_content->save();
            $tree = $menu_tree->load('tools', new MenuTreeParameters());
            $build = $menu_tree->build($tree);
            $renderer->renderRoot($build);
            $expected_cacheability = $default_menu_cacheability->merge($expectation['cacheability']);
            $this->assertEqual($expected_cacheability, BubbleableMetadata::createFromRenderArray($build));
            $menu_link_content->delete();
        }
        // Now test them all together in one menu: the rendered menu's cacheability
        // metadata should be the combination of the cacheability of all links, and
        // thus of all tested outbound path & route processors.
        $expected_cacheability = new BubbleableMetadata();
        foreach ($test_cases as $expectation) {
            $menu_link_content = MenuLinkContent::create([
                'link' => [
                    'uri' => $expectation['uri'],
                ],
                'menu_name' => 'tools',
                'title' => 'Link test',
            ]);
            $menu_link_content->save();
            $expected_cacheability = $expected_cacheability->merge($expectation['cacheability']);
        }
        $tree = $menu_tree->load('tools', new MenuTreeParameters());
        $build = $menu_tree->build($tree);
        $renderer->renderRoot($build);
        $expected_cacheability = $expected_cacheability->merge($default_menu_cacheability);
        $this->assertEqual($expected_cacheability, BubbleableMetadata::createFromRenderArray($build));
    }

}

Classes

Title Deprecated Summary
MenuLinkContentCacheabilityBubblingTest Ensures that rendered menu links bubble the necessary bubbleable metadata for outbound path/route processing.

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