You are here

public function FieldKernelTest::testFieldTokens in Drupal 9

Same name and namespace in other branches
  1. 8 core/modules/views/tests/src/Kernel/Handler/FieldKernelTest.php \Drupal\Tests\views\Kernel\Handler\FieldKernelTest::testFieldTokens()

Tests the field tokens, row level and field level.

File

core/modules/views/tests/src/Kernel/Handler/FieldKernelTest.php, line 268

Class

FieldKernelTest
Tests the generic field handler.

Namespace

Drupal\Tests\views\Kernel\Handler

Code

public function testFieldTokens() {

  /** @var \Drupal\Core\Render\RendererInterface $renderer */
  $renderer = \Drupal::service('renderer');
  $view = Views::getView('test_field_tokens');
  $this
    ->executeView($view);
  $name_field_0 = $view->field['name'];
  $name_field_1 = $view->field['name_1'];
  $name_field_2 = $view->field['name_2'];
  $row = $view->result[0];
  $name_field_0->options['alter']['alter_text'] = TRUE;
  $name_field_0->options['alter']['text'] = '{{ name }}';
  $name_field_1->options['alter']['alter_text'] = TRUE;
  $name_field_1->options['alter']['text'] = '{{ name_1 }} {{ name }}';
  $name_field_2->options['alter']['alter_text'] = TRUE;
  $name_field_2->options['alter']['text'] = '{% if name_2|length > 3 %}{{ name_2 }} {{ name_1 }}{% endif %}';
  foreach ($view->result as $row) {
    $expected_output_0 = $row->views_test_data_name;
    $expected_output_1 = "{$row->views_test_data_name} {$row->views_test_data_name}";
    $expected_output_2 = "{$row->views_test_data_name} {$row->views_test_data_name} {$row->views_test_data_name}";
    $output = $renderer
      ->executeInRenderContext(new RenderContext(), function () use ($name_field_0, $row) {
      return $name_field_0
        ->advancedRender($row);
    });
    $this
      ->assertEquals($expected_output_0, $output, new FormattableMarkup('Test token replacement: "@token" gave "@output"', [
      '@token' => $name_field_0->options['alter']['text'],
      '@output' => $output,
    ]));
    $output = $renderer
      ->executeInRenderContext(new RenderContext(), function () use ($name_field_1, $row) {
      return $name_field_1
        ->advancedRender($row);
    });
    $this
      ->assertEquals($expected_output_1, $output, new FormattableMarkup('Test token replacement: "@token" gave "@output"', [
      '@token' => $name_field_1->options['alter']['text'],
      '@output' => $output,
    ]));
    $output = $renderer
      ->executeInRenderContext(new RenderContext(), function () use ($name_field_2, $row) {
      return $name_field_2
        ->advancedRender($row);
    });
    $this
      ->assertEquals($expected_output_2, $output, new FormattableMarkup('Test token replacement: "@token" gave "@output"', [
      '@token' => $name_field_2->options['alter']['text'],
      '@output' => $output,
    ]));
  }
  $job_field = $view->field['job'];
  $job_field->options['alter']['alter_text'] = TRUE;
  $job_field->options['alter']['text'] = '{{ job }}';
  $random_text = $this
    ->randomMachineName();
  $job_field
    ->setTestValue($random_text);
  $output = $renderer
    ->executeInRenderContext(new RenderContext(), function () use ($job_field, $row) {
    return $job_field
      ->advancedRender($row);
  });
  $this
    ->assertSubString($output, $random_text, new FormattableMarkup('Make sure the self token (@token => @value) appears in the output (@output)', [
    '@value' => $random_text,
    '@output' => $output,
    '@token' => $job_field->options['alter']['text'],
  ]));

  // Verify the token format used in D7 and earlier does not get substituted.
  $old_token = '[job]';
  $job_field->options['alter']['text'] = $old_token;
  $random_text = $this
    ->randomMachineName();
  $job_field
    ->setTestValue($random_text);
  $output = $renderer
    ->executeInRenderContext(new RenderContext(), function () use ($job_field, $row) {
    return $job_field
      ->advancedRender($row);
  });
  $this
    ->assertEquals($old_token, $output, new FormattableMarkup('Make sure the old token style (@token => @value) is not changed in the output (@output)', [
    '@value' => $random_text,
    '@output' => $output,
    '@token' => $job_field->options['alter']['text'],
  ]));

  // Verify HTML tags are allowed in rewrite templates while token
  // replacements are escaped.
  $job_field->options['alter']['text'] = '<h1>{{ job }}</h1>';
  $random_text = $this
    ->randomMachineName();
  $job_field
    ->setTestValue('<span>' . $random_text . '</span>');
  $output = $renderer
    ->executeInRenderContext(new RenderContext(), function () use ($job_field, $row) {
    return $job_field
      ->advancedRender($row);
  });
  $this
    ->assertEquals('<h1>&lt;span&gt;' . $random_text . '&lt;/span&gt;</h1>', $output, 'Valid tags are allowed in rewrite templates and token replacements.');

  // Verify <script> tags are correctly removed from rewritten text.
  $rewrite_template = '<script>alert("malicious");</script>';
  $job_field->options['alter']['text'] = $rewrite_template;
  $random_text = $this
    ->randomMachineName();
  $job_field
    ->setTestValue($random_text);
  $output = $renderer
    ->executeInRenderContext(new RenderContext(), function () use ($job_field, $row) {
    return $job_field
      ->advancedRender($row);
  });
  $this
    ->assertNotSubString($output, '<script>', 'Ensure a script tag in the rewrite template is removed.');
  $rewrite_template = '<script>{{ job }}</script>';
  $job_field->options['alter']['text'] = $rewrite_template;
  $random_text = $this
    ->randomMachineName();
  $job_field
    ->setTestValue($random_text);
  $output = $renderer
    ->executeInRenderContext(new RenderContext(), function () use ($job_field, $row) {
    return $job_field
      ->advancedRender($row);
  });
  $this
    ->assertEquals($random_text, $output, new FormattableMarkup('Make sure a script tag in the template (@template) is removed, leaving only the replaced token in the output (@output)', [
    '@output' => $output,
    '@template' => $rewrite_template,
  ]));
}