tests/src/Kernel/EntityEmbedFilterTest.php | 36 ++++++++++++++++++-- tests/src/Kernel/EntityEmbedFilterTestBase.php | 46 +++++++++++++++++++++++++- 2 files changed, 79 insertions(+), 3 deletions(-) diff --git a/tests/src/Kernel/EntityEmbedFilterTest.php b/tests/src/Kernel/EntityEmbedFilterTest.php index b347fcd..465b3e5 100644 --- a/tests/src/Kernel/EntityEmbedFilterTest.php +++ b/tests/src/Kernel/EntityEmbedFilterTest.php @@ -2,6 +2,8 @@ namespace Drupal\Tests\entity_embed\Kernel; +use Drupal\Core\Cache\Cache; +use Drupal\Core\Cache\CacheableMetadata; use Drupal\Core\Entity\TranslatableInterface; use Drupal\Core\Render\RenderContext; @@ -26,7 +28,7 @@ class EntityEmbedFilterTest extends EntityEmbedFilterTestBase { * * @dataProvider providerTestFilter */ - public function testFilter(array $embed_attributes, array $contains, array $not_contains, array $expected_attributes, $is_published, $allowed_to_view_unpublished) { + public function testFilter(array $embed_attributes, array $contains, array $not_contains, array $expected_attributes, $is_published, $allowed_to_view_unpublished, CacheableMetadata $expected_cacheability, array $expected_asset_libraries) { $content = $this->createEmbedCode($embed_attributes); $entity = $this->loadEntityByAttributes($embed_attributes); @@ -41,7 +43,7 @@ class EntityEmbedFilterTest extends EntityEmbedFilterTestBase { $this->container->get('current_user') ->addRole($this->drupalCreateRole($permissions)); - $this->applyFilter($content); + $result = $this->applyFilter($content); if (!$is_published && !$allowed_to_view_unpublished) { $this->assertEmpty($this->getRawContent()); @@ -59,12 +61,25 @@ class EntityEmbedFilterTest extends EntityEmbedFilterTestBase { if (empty($embed_attributes['data-entity-id'])) { $this->assertFalse(isset($embedded_entity_container['data-entity-id'])); } + + // Expected bubbleable metadata. + $this->assertSame($result->getCacheTags(), $expected_cacheability->getCacheTags()); + $this->assertSame($result->getCacheContexts(), $expected_cacheability->getCacheContexts()); + $this->assertSame($result->getCacheMaxAge(), $expected_cacheability->getCacheMaxAge()); + $this->assertSame(['library'], array_keys($result->getAttachments())); + $this->assertSame($result->getAttachments()['library'], $expected_asset_libraries); } /** * Data provider for testFilter. */ public function providerTestFilter() { + $expected_cacheability = (new CacheableMetadata()) + ->setCacheTags(['config:filter.format.plain_text', 'config:filter.settings', 'node:1', 'node_view', 'user:2', 'user_view']) + ->setCacheContexts(['timezone', 'user.permissions']) + ->setCacheMaxAge(Cache::PERMANENT); + $expected_asset_libraries = ['entity_embed/caption']; + return [ 'using entity ID and view mode' => [ 'embed_attributes' => [ @@ -87,6 +102,8 @@ class EntityEmbedFilterTest extends EntityEmbedFilterTestBase { ], 'published' => TRUE, 'view_unpublished' => FALSE, + 'expected_cacheability' => $expected_cacheability, + 'expected_asset_libraries' => $expected_asset_libraries, ], 'embedded entity is not rendered if unpublished' => [ 'embed_attributes' => [ @@ -99,6 +116,8 @@ class EntityEmbedFilterTest extends EntityEmbedFilterTestBase { 'expected_attributes' => [], 'published' => FALSE, 'view_unpublished' => FALSE, + 'expected_cacheability' => $expected_cacheability, + 'expected_asset_libraries' => $expected_asset_libraries, ], 'Unpublished and current user has view unpublished permission' => [ 'embed_attributes' => [ @@ -119,6 +138,9 @@ class EntityEmbedFilterTest extends EntityEmbedFilterTestBase { ], 'published' => FALSE, 'view_unpublished' => TRUE, + 'expected_cacheability' => CacheableMetadata::createFromObject($expected_cacheability) + ->setCacheContexts(['timezone', 'user', 'user.permissions']), + 'expected_asset_libraries' => $expected_asset_libraries, ], 'using entity UUID and view mode' => [ 'embed_attributes' => [ @@ -140,6 +162,8 @@ class EntityEmbedFilterTest extends EntityEmbedFilterTestBase { ], 'published' => TRUE, 'view_unpublished' => FALSE, + 'expected_cacheability' => $expected_cacheability, + 'expected_asset_libraries' => $expected_asset_libraries, ], 'Ensure that UUID is preferred over ID when both attributes are present' => [ 'embed_attributes' => [ @@ -163,6 +187,8 @@ class EntityEmbedFilterTest extends EntityEmbedFilterTestBase { ], 'published' => TRUE, 'view_unpublished' => FALSE, + 'expected_cacheability' => $expected_cacheability, + 'expected_asset_libraries' => $expected_asset_libraries, ], 'Test deprecated default Entity Embed Display plugin.' => [ 'embed_attributes' => [ @@ -184,6 +210,8 @@ class EntityEmbedFilterTest extends EntityEmbedFilterTestBase { ], 'published' => TRUE, 'view_unpublished' => FALSE, + 'expected_cacheability' => $expected_cacheability, + 'expected_asset_libraries' => $expected_asset_libraries, ], 'Ensure that Entity Embed Display plugin is preferred over view mode when both are present' => [ 'embed_attributes' => [ @@ -207,6 +235,8 @@ class EntityEmbedFilterTest extends EntityEmbedFilterTestBase { ], 'published' => TRUE, 'view_unpublished' => FALSE, + 'expected_cacheability' => $expected_cacheability, + 'expected_asset_libraries' => $expected_asset_libraries, ], 'Ensure that custom attributes are retained' => [ 'embed_attributes' => [ @@ -232,6 +262,8 @@ class EntityEmbedFilterTest extends EntityEmbedFilterTestBase { ], 'published' => TRUE, 'view_unpublished' => FALSE, + 'expected_cacheability' => $expected_cacheability, + 'expected_asset_libraries' => $expected_asset_libraries, ], ]; } diff --git a/tests/src/Kernel/EntityEmbedFilterTestBase.php b/tests/src/Kernel/EntityEmbedFilterTestBase.php index ce07679..c4cfe81 100644 --- a/tests/src/Kernel/EntityEmbedFilterTestBase.php +++ b/tests/src/Kernel/EntityEmbedFilterTestBase.php @@ -3,7 +3,10 @@ namespace Drupal\Tests\entity_embed\Kernel; use Drupal\Component\Utility\Html; +use Drupal\Core\Render\BubbleableMetadata; +use Drupal\Core\Render\RenderContext; use Drupal\filter\FilterPluginCollection; +use Drupal\filter\FilterProcessResult; use Drupal\KernelTests\KernelTestBase; use Drupal\Tests\node\Traits\ContentTypeCreationTrait; use Drupal\Tests\node\Traits\NodeCreationTrait; @@ -134,17 +137,22 @@ abstract class EntityEmbedFilterTestBase extends KernelTestBase { * @param string $langcode * The language code of the text to be filtered. * + * @return \Drupal\filter\FilterProcessResult + * The filtered text, wrapped in a FilterProcessResult object, and possibly + * with associated assets, cacheability metadata and placeholders. + * * @see \Drupal\Tests\entity_embed\Kernel\EntityEmbedFilterTestBase::createEmbedCode() * @see \Drupal\KernelTests\AssertContentTrait::setRawContent() */ protected function applyFilter($text, $langcode = 'en') { $this->assertContains('assertContains('This placeholder should not be rendered.', $text); - $filter_result = $this->filter->process($text, $langcode); + $filter_result = $this->processText([$this->filter], $text, $langcode); $output = $filter_result->getProcessedText(); $this->assertNotContains('assertNotContains('This placeholder should not be rendered.', $output); $this->setRawContent($output); + return $filter_result; } /** @@ -161,4 +169,40 @@ abstract class EntityEmbedFilterTestBase extends KernelTestBase { } } + /** + * Processes text through the provided filters. + * + * @param \Drupal\filter\Plugin\FilterInterface[] $filters + * The filter plugin instances to apply to the given text, in the order they + * are being requested to be executed. + * @param string $text + * The text string to be filtered. + * @param string $langcode + * The language code of the text to be filtered. + * + * @return \Drupal\filter\FilterProcessResult + * The filtered text, wrapped in a FilterProcessResult object, and possibly + * with associated assets, cacheability metadata and placeholders. + * + * @see \Drupal\filter\Element\ProcessedText::preRenderText() + */ + protected function processText(array $filters, $text, $langcode = 'und') { + $render_context = new RenderContext(); + /** @var \Drupal\filter\FilterProcessResult $filter_result */ + $filter_result = $this->renderer->executeInRenderContext($render_context, function () use ($text, $filters, $langcode) { + $metadata = new BubbleableMetadata(); + foreach ($filters as $filter) { + /** @var \Drupal\filter\FilterProcessResult $result */ + $result = $filter->process($text, $langcode); + $metadata = $metadata->merge($result); + $text = $result->getProcessedText(); + } + return (new FilterProcessResult($text))->merge($metadata); + }); + if (!$render_context->isEmpty()) { + $filter_result = $filter_result->merge($render_context->pop()); + } + return $filter_result; + } + }