You are here

public function RendererBubblingTest::testBubblingWithPrerender in Drupal 9

Same name and namespace in other branches
  1. 8 core/tests/Drupal/Tests/Core/Render/RendererBubblingTest.php \Drupal\Tests\Core\Render\RendererBubblingTest::testBubblingWithPrerender()

Tests bubbling of bubbleable metadata added by #pre_render callbacks.

@dataProvider providerTestBubblingWithPrerender

File

core/tests/Drupal/Tests/Core/Render/RendererBubblingTest.php, line 537
Contains \Drupal\Tests\Core\Render\RendererBubblingTest.

Class

RendererBubblingTest
@coversDefaultClass \Drupal\Core\Render\Renderer @group Render

Namespace

Drupal\Tests\Core\Render

Code

public function testBubblingWithPrerender($test_element) {
  $this
    ->setUpRequest();
  $this
    ->setupMemoryCache();

  // Mock the State service.
  $memory_state = new State(new KeyValueMemoryFactory());
  \Drupal::getContainer()
    ->set('state', $memory_state);
  $this->controllerResolver
    ->expects($this
    ->any())
    ->method('getControllerFromDefinition')
    ->willReturnArgument(0);

  // Simulate the theme system/Twig: a recursive call to Renderer::render(),
  // just like the theme system or a Twig template would have done.
  $this->themeManager
    ->expects($this
    ->any())
    ->method('render')
    ->willReturnCallback(function ($hook, $vars) {
    return $this->renderer
      ->render($vars['foo']);
  });

  // ::bubblingPreRender() verifies that a #pre_render callback for a render
  // array that is cacheable and …
  // - … is cached does NOT get called. (Also mock a render cache item.)
  // - … is not cached DOES get called.
  \Drupal::state()
    ->set('bubbling_nested_pre_render_cached', FALSE);
  \Drupal::state()
    ->set('bubbling_nested_pre_render_uncached', FALSE);
  $this->memoryCache
    ->set('cached_nested', [
    '#markup' => 'Cached nested!',
    '#attached' => [],
    '#cache' => [
      'contexts' => [],
      'tags' => [],
    ],
  ]);

  // Simulate the rendering of an entire response (i.e. a root call).
  $output = $this->renderer
    ->renderRoot($test_element);

  // First, assert the render array is of the expected form.
  $this
    ->assertEquals('Cache context!Cache tag!Asset!Placeholder!barquxNested!Cached nested!', trim($output), 'Expected HTML generated.');
  $this
    ->assertEquals([
    'child.cache_context',
  ], $test_element['#cache']['contexts'], 'Expected cache contexts found.');
  $this
    ->assertEquals([
    'child:cache_tag',
  ], $test_element['#cache']['tags'], 'Expected cache tags found.');
  $expected_attached = [
    'drupalSettings' => [
      'foo' => 'bar',
    ],
    'placeholders' => [],
  ];
  $this
    ->assertEquals($expected_attached, $test_element['#attached'], 'Expected attachments found.');

  // Second, assert that #pre_render callbacks are only executed if they don't
  // have a render cache hit (and hence a #pre_render callback for a render
  // cached item cannot bubble more metadata).
  $this
    ->assertTrue(\Drupal::state()
    ->get('bubbling_nested_pre_render_uncached'));
  $this
    ->assertFalse(\Drupal::state()
    ->get('bubbling_nested_pre_render_cached'));
}