function FilterKernelTest::testCaptionFilter

Same name and namespace in other branches
  1. 9 core/modules/filter/tests/src/Kernel/FilterKernelTest.php \Drupal\Tests\filter\Kernel\FilterKernelTest::testCaptionFilter()
  2. 8.9.x core/modules/filter/tests/src/Kernel/FilterKernelTest.php \Drupal\Tests\filter\Kernel\FilterKernelTest::testCaptionFilter()
  3. 11.x core/modules/filter/tests/src/Kernel/FilterKernelTest.php \Drupal\Tests\filter\Kernel\FilterKernelTest::testCaptionFilter()

Tests the caption filter.

File

core/modules/filter/tests/src/Kernel/FilterKernelTest.php, line 103

Class

FilterKernelTest
Tests Filter module filters individually.

Namespace

Drupal\Tests\filter\Kernel

Code

public function testCaptionFilter() : void {
  /** @var \Drupal\Core\Render\RendererInterface $renderer */
  $renderer = \Drupal::service('renderer');
  $filter = $this->filters['filter_caption'];
  $test = function ($input) use ($filter, $renderer) {
    return $renderer->executeInRenderContext(new RenderContext(), function () use ($input, $filter) {
      return $filter->process($input, 'und');
    });
  };
  $attached_library = [
    'library' => [
      'filter/caption',
    ],
  ];
  // No data-caption attribute.
  $input = '<img src="llama.jpg" />';
  $expected = $input;
  $this->assertSame($expected, $test($input)->getProcessedText());
  // Data-caption attribute.
  $input = '<img src="llama.jpg" data-caption="Loquacious llama!" />';
  $expected = '<figure role="group">
<img src="llama.jpg">
<figcaption>Loquacious llama!</figcaption>
</figure>
';
  $output = $test($input);
  $this->assertSame($expected, $output->getProcessedText());
  $this->assertSame($attached_library, $output->getAttachments());
  // Empty data-caption attribute.
  $input = '<img src="llama.jpg" data-caption="" />';
  $expected = '<img src="llama.jpg">';
  $this->assertSame($expected, $test($input)->getProcessedText());
  // HTML entities in the caption.
  $input = '<img src="llama.jpg" data-caption="&ldquo;Loquacious llama!&rdquo;" />';
  $expected = '<figure role="group">
<img src="llama.jpg">
<figcaption>“Loquacious llama!”</figcaption>
</figure>
';
  $output = $test($input);
  $this->assertSame($expected, $output->getProcessedText());
  $this->assertSame($attached_library, $output->getAttachments());
  // HTML encoded as HTML entities in data-caption attribute.
  $input = '<img src="llama.jpg" data-caption="&lt;em&gt;Loquacious llama!&lt;/em&gt;" />';
  $expected = '<figure role="group">
<img src="llama.jpg">
<figcaption><em>Loquacious llama!</em></figcaption>
</figure>
';
  $output = $test($input);
  $this->assertSame($expected, $output->getProcessedText());
  $this->assertSame($attached_library, $output->getAttachments());
  // HTML (not encoded as HTML entities) in data-caption attribute, which is
  // not allowed by the HTML spec, but may happen when people manually write
  // HTML, so we explicitly support it.
  $input = '<img src="llama.jpg" data-caption="<em>Loquacious llama!</em>" />';
  $expected = '<figure role="group">
<img src="llama.jpg">
<figcaption><em>Loquacious llama!</em></figcaption>
</figure>
';
  $output = $test($input);
  $this->assertSame($expected, $output->getProcessedText());
  $this->assertSame($attached_library, $output->getAttachments());
  // Security test: attempt an XSS.
  $input = '<img src="llama.jpg" data-caption="<script>alert(\'Loquacious llama!\')</script>" />';
  $expected = '<figure role="group">
<img src="llama.jpg">
<figcaption>alert(\'Loquacious llama!\')</figcaption>
</figure>
';
  $output = $test($input);
  $this->assertSame($expected, $output->getProcessedText());
  $this->assertSame($attached_library, $output->getAttachments());
  // Ensure the filter also works with uncommon yet valid attribute quoting.
  $input = '<img src=llama.jpg data-caption=\'Loquacious llama!\' />';
  $expected = '<figure role="group">
<img src="llama.jpg">
<figcaption>Loquacious llama!</figcaption>
</figure>
';
  $output = $test($input);
  $this->assertSame($expected, $output->getProcessedText());
  $this->assertSame($attached_library, $output->getAttachments());
  // Finally, ensure that this also works on any other tag.
  $input = '<video src="llama.jpg" data-caption="Loquacious llama!" />';
  $expected = '<figure role="group">
<video src="llama.jpg"></video>
<figcaption>Loquacious llama!</figcaption>
</figure>
';
  $output = $test($input);
  $this->assertSame($expected, $output->getProcessedText());
  $this->assertSame($attached_library, $output->getAttachments());
  $input = '<foobar data-caption="Loquacious llama!">baz</foobar>';
  $expected = '<figure role="group">
<foobar>baz</foobar>
<figcaption>Loquacious llama!</figcaption>
</figure>
';
  $output = $test($input);
  $this->assertSame($expected, $output->getProcessedText());
  $this->assertSame($attached_library, $output->getAttachments());
  // Ensure the caption filter works for linked images.
  $input = '<a href="http://example.com/llamas/are/awesome/but/kittens/are/cool/too"><img src="llama.jpg" data-caption="Loquacious llama!" /></a>';
  $expected = '<figure role="group">
<a href="http://example.com/llamas/are/awesome/but/kittens/are/cool/too"><img src="llama.jpg"></a>
<figcaption>Loquacious llama!</figcaption>
</figure>
';
  $output = $test($input);
  $this->assertSame($expected, $output->getProcessedText());
  $this->assertSame($attached_library, $output->getAttachments());
  // So far we've tested that the caption filter works correctly. But we also
  // want to make sure that it works well in tandem with the "Limit allowed
  // HTML tags" filter, which it is typically used with.
  $html_filter = $this->filters['filter_html'];
  $html_filter->setConfiguration([
    'settings' => [
      'allowed_html' => '<img src data-align data-caption>',
      'filter_html_help' => 1,
      'filter_html_nofollow' => 0,
    ],
  ]);
  $test_with_html_filter = function ($input) use ($filter, $html_filter, $renderer) {
    return $renderer->executeInRenderContext(new RenderContext(), function () use ($input, $filter, $html_filter) {
      // 1. Apply HTML filter's processing step.
      $output = $html_filter->process($input, 'und');
      // 2. Apply caption filter's processing step.
      $output = $filter->process($output, 'und');
      return $output->getProcessedText();
    });
  };
  // Editor XSS filter.
  $test_editor_xss_filter = function ($input) {
    $dummy_filter_format = FilterFormat::create();
    return Standard::filterXss($input, $dummy_filter_format);
  };
  // All the tricky cases encountered at https://www.drupal.org/node/2105841.
  // A plain URL preceded by text.
  $input = '<img data-caption="See https://www.drupal.org" src="llama.jpg">';
  $expected = '<figure role="group">
<img src="llama.jpg">
<figcaption>See https://www.drupal.org</figcaption>
</figure>
';
  $this->assertSame($expected, $test_with_html_filter($input));
  $this->assertSame($input, $test_editor_xss_filter($input));
  // An anchor.
  $input = '<img data-caption="This is a &lt;a href=&quot;https://www.drupal.org&quot;&gt;quick&lt;/a&gt; test…" src="llama.jpg">';
  $expected = '<figure role="group">
<img src="llama.jpg">
<figcaption>This is a <a href="https://www.drupal.org">quick</a> test…</figcaption>
</figure>
';
  $this->assertSame($expected, $test_with_html_filter($input));
  $this->assertSame($input, $test_editor_xss_filter($input));
  // A plain URL surrounded by parentheses.
  $input = '<img data-caption="(https://www.drupal.org)" src="llama.jpg">';
  $expected = '<figure role="group">
<img src="llama.jpg">
<figcaption>(https://www.drupal.org)</figcaption>
</figure>
';
  $this->assertSame($expected, $test_with_html_filter($input));
  $this->assertSame($input, $test_editor_xss_filter($input));
  // A source being credited.
  $input = '<img data-caption="Source: Wikipedia" src="llama.jpg">';
  $expected = '<figure role="group">
<img src="llama.jpg">
<figcaption>Source: Wikipedia</figcaption>
</figure>
';
  $this->assertSame($expected, $test_with_html_filter($input));
  $this->assertSame($input, $test_editor_xss_filter($input));
  // A source being credited, without a space after the colon.
  $input = '<img data-caption="Source:Wikipedia" src="llama.jpg">';
  $expected = '<figure role="group">
<img src="llama.jpg">
<figcaption>Source:Wikipedia</figcaption>
</figure>
';
  $this->assertSame($expected, $test_with_html_filter($input));
  $this->assertSame($input, $test_editor_xss_filter($input));
  // A pretty crazy edge case where we have two colons.
  $input = '<img data-caption="Interesting (Scope resolution operator ::)" src="llama.jpg">';
  $expected = '<figure role="group">
<img src="llama.jpg">
<figcaption>Interesting (Scope resolution operator ::)</figcaption>
</figure>
';
  $this->assertSame($expected, $test_with_html_filter($input));
  $this->assertSame($input, $test_editor_xss_filter($input));
  // An evil anchor (to ensure XSS filtering is applied to the caption also).
  $input = '<img data-caption="This is an &lt;a href=&quot;javascript:alert();&quot;&gt;evil&lt;/a&gt; test…" src="llama.jpg">';
  $expected = '<figure role="group">
<img src="llama.jpg">
<figcaption>This is an <a href="alert();">evil</a> test…</figcaption>
</figure>
';
  $this->assertSame($expected, $test_with_html_filter($input));
  $expected_xss_filtered = '<img data-caption="This is an &lt;a href=&quot;alert();&quot;&gt;evil&lt;/a&gt; test…" src="llama.jpg">';
  $this->assertSame($expected_xss_filtered, $test_editor_xss_filter($input));
}

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