You are here

public function RendererPlaceholdersTest::testRenderChildrenPlaceholdersDifferentArguments in Drupal 9

Same name and namespace in other branches
  1. 8 core/tests/Drupal/Tests/Core/Render/RendererPlaceholdersTest.php \Drupal\Tests\Core\Render\RendererPlaceholdersTest::testRenderChildrenPlaceholdersDifferentArguments()
  2. 10 core/tests/Drupal/Tests/Core/Render/RendererPlaceholdersTest.php \Drupal\Tests\Core\Render\RendererPlaceholdersTest::testRenderChildrenPlaceholdersDifferentArguments()

Create an element with a child and subchild. Each element has the same #lazy_builder callback, but with different contexts. They don't modify markup, only attach additional drupalSettings.

@covers ::render @covers ::doRender @covers \Drupal\Core\Render\RenderCache::get @covers ::replacePlaceholders

File

core/tests/Drupal/Tests/Core/Render/RendererPlaceholdersTest.php, line 987
Contains \Drupal\Tests\Core\Render\RendererPlaceholdersTest.

Class

RendererPlaceholdersTest
@coversDefaultClass \Drupal\Core\Render\Renderer @covers \Drupal\Core\Render\RenderCache @covers \Drupal\Core\Render\PlaceholderingRenderCache @group Render

Namespace

Drupal\Tests\Core\Render

Code

public function testRenderChildrenPlaceholdersDifferentArguments() {
  $this
    ->setUpRequest();
  $this
    ->setupMemoryCache();
  $this->cacheContextsManager
    ->expects($this
    ->any())
    ->method('convertTokensToKeys')
    ->willReturnArgument(0);
  $this->controllerResolver
    ->expects($this
    ->any())
    ->method('getControllerFromDefinition')
    ->willReturnArgument(0);
  $this
    ->setupThemeManagerForDetails();
  $args_1 = [
    'foo',
    TRUE,
  ];
  $args_2 = [
    'bar',
    TRUE,
  ];
  $args_3 = [
    'baz',
    TRUE,
  ];
  $test_element = $this
    ->generatePlaceholdersWithChildrenTestElement($args_1, $args_2, $args_3);
  $element = $test_element;
  $output = $this->renderer
    ->renderRoot($element);
  $expected_output = <<<HTML
<details>
  <summary>Parent</summary>
  <div class="details-wrapper"><details>
  <summary>Child</summary>
  <div class="details-wrapper">Subchild</div>
</details></div>
</details>
HTML;
  $this
    ->assertSame($expected_output, (string) $output, 'Output is not overridden.');
  $this
    ->assertTrue(isset($element['#printed']), 'No cache hit');
  $this
    ->assertSame($expected_output, (string) $element['#markup'], '#markup is not overridden.');
  $expected_js_settings = [
    'foo' => 'bar',
    'dynamic_animal' => [
      $args_1[0] => TRUE,
      $args_2[0] => TRUE,
      $args_3[0] => TRUE,
    ],
  ];
  $this
    ->assertSame($element['#attached']['drupalSettings'], $expected_js_settings, '#attached is modified; both the original JavaScript setting and the ones added by each placeholder #lazy_builder callback exist.');

  // GET request: validate cached data.
  $cached_element = $this->memoryCache
    ->get('simpletest:renderer:children_placeholders')->data;
  $expected_element = [
    '#attached' => [
      'drupalSettings' => [
        'foo' => 'bar',
      ],
      'placeholders' => [
        'parent-x-parent' => [
          '#lazy_builder' => [
            __NAMESPACE__ . '\\PlaceholdersTest::callback',
            $args_1,
          ],
        ],
        'child-x-child' => [
          '#lazy_builder' => [
            __NAMESPACE__ . '\\PlaceholdersTest::callback',
            $args_2,
          ],
        ],
        'subchild-x-subchild' => [
          '#lazy_builder' => [
            __NAMESPACE__ . '\\PlaceholdersTest::callback',
            $args_3,
          ],
        ],
      ],
    ],
    '#cache' => [
      'contexts' => [],
      'tags' => [],
      'max-age' => Cache::PERMANENT,
    ],
  ];

  // Verify that the correct data is cached: the stored #markup is not
  // affected by placeholder #lazy_builder callbacks.
  $dom = Html::load($cached_element['#markup']);
  $xpath = new \DOMXPath($dom);
  $this
    ->assertNotEmpty($xpath
    ->query('//details/summary[text()="Parent"]')->length);
  $this
    ->assertNotEmpty($xpath
    ->query('//details/div[@class="details-wrapper"]/details/summary[text()="Child"]')->length);
  $this
    ->assertNotEmpty($xpath
    ->query('//details/div[@class="details-wrapper"]/details/div[@class="details-wrapper" and text()="Subchild"]')->length);

  // Remove markup because it's compared above in the xpath.
  unset($cached_element['#markup']);
  $this
    ->assertEquals($cached_element, $expected_element, 'The correct data is cached: the stored #attached properties are not affected by placeholder #lazy_builder callbacks.');

  // GET request: #cache enabled, cache hit.
  $element = $test_element;
  $output = $this->renderer
    ->renderRoot($element);
  $this
    ->assertSame($expected_output, (string) $output, 'Output is not overridden.');
  $this
    ->assertFalse(isset($element['#printed']), 'Cache hit');
  $this
    ->assertSame($element['#attached']['drupalSettings'], $expected_js_settings, '#attached is modified; both the original JavaScript setting and the ones added by each placeholder #lazy_builder callback exist.');

  // Use the exact same element, but now unset #cache; ensure we get the same
  // result.
  unset($test_element['#cache']);
  $element = $test_element;
  $output = $this->renderer
    ->renderRoot($element);
  $this
    ->assertSame($expected_output, (string) $output, 'Output is not overridden.');
  $this
    ->assertSame($expected_output, (string) $element['#markup'], '#markup is not overridden.');
  $this
    ->assertSame($element['#attached']['drupalSettings'], $expected_js_settings, '#attached is modified; both the original JavaScript setting and the ones added by each #lazy_builder callback exist.');
}