ckeditor5-1.0.x-dev/tests/src/Kernel/CKEditor5PluginManagerTest.php
tests/src/Kernel/CKEditor5PluginManagerTest.php
<?php
namespace Drupal\Tests\ckeditor5\Kernel;
use Drupal\editor\Entity\Editor;
use Drupal\KernelTests\KernelTestBase;
use Drupal\filter\Entity\FilterFormat;
use Symfony\Component\Yaml\Yaml;
// cspell:ignore layercake everyblock justblockquote
/**
* Tests different ways of enabling CKEditor 5 plugins.
*
* @group ckeditor5
*/
class CKEditor5PluginManagerTest extends KernelTestBase {
/**
* {@inheritdoc}
*/
protected static $modules = [
'system',
'user',
'filter',
'editor',
'ckeditor5',
'media',
];
/**
* The manager for "CKEditor 5 plugin" plugins.
*
* @var \Drupal\Component\Plugin\PluginManagerInterface
*/
protected $manager;
/**
* {@inheritdoc}
*/
protected function setUp(): void {
parent::setUp();
FilterFormat::create(
Yaml::parseFile('core/profiles/standard/config/install/filter.format.basic_html.yml')
)->save();
Editor::create([
'format' => 'basic_html',
'editor' => 'ckeditor5',
])->save();
FilterFormat::create(
Yaml::parseFile('core/profiles/standard/config/install/filter.format.full_html.yml')
)->save();
Editor::create([
'format' => 'full_html',
'editor' => 'ckeditor5',
])->save();
$this->manager = $this->container->get('plugin.manager.ckeditor5.plugin');
}
/**
* Tests the enabling of plugins.
*/
public function testEnabledPlugins() {
$editor = Editor::load('basic_html');
// Case 1: no extra CKEditor 5 plugins.
$definitions = array_keys($this->manager->getEnabledDefinitions($editor));
$default_plugins = [
'ckeditor5.bold',
'ckeditor5.emphasis',
'ckeditor5.essentials',
'ckeditor5.paragraph',
'ckeditor5heading',
];
$this->assertSame($default_plugins, $definitions, 'No CKEditor 5 plugins found besides the built-in ones.');
$default_libraries = [
'ckeditor5/ckeditor5.basic',
'ckeditor5/ckeditor5.internal',
'ckeditor5/drupal.ckeditor5',
'ckeditor5/drupal.ckeditor5.emphasis',
];
$this->assertSame($default_libraries, $this->manager->getEnabledLibraries($editor));
// Enable the CKEditor 5 Test module, which has the layercake plugin and
// clear the editor manager's static cache so that it is picked up.
$this->enableModules(['ckeditor5_test']);
$this->manager = $this->container->get('plugin.manager.ckeditor5.plugin');
$this->manager->clearCachedDefinitions();
// Case 2: The CKEditor 5 layercake plugin is available and library should
// NOT be loaded if its toolbar items are not enabled.
$this->assertSame($default_plugins, array_keys($this->manager->getEnabledDefinitions($editor)));
$this->assertSame($default_libraries, $this->manager->getEnabledLibraries($editor));
// Case 3: The CKEditor 5 layercake plugin is available and library should
// be loaded without having to enable plugins.
$settings = $editor->getSettings();
$settings['toolbar']['items'][] = 'simpleBox';
$editor->setSettings($settings);
$plugin_ids = array_keys($this->manager->getEnabledDefinitions($editor));
$default_plugins_with_layercake = array_merge($default_plugins, ['ckeditor5_test.layercake']);
// Sort on plugin id.
asort($default_plugins_with_layercake);
$this->assertSame(array_values($default_plugins_with_layercake), $plugin_ids);
$this->assertSame(array_merge($default_libraries, [
'ckeditor5_test/layercake',
]), $this->manager->getEnabledLibraries($editor));
// Enable media embed filter which the CKEditor 5 media plugin requires.
$editor->getFilterFormat()->setFilterConfig('media_embed', ['status' => TRUE])->save();
// Case 4: The CKEditor 5 media plugin should be enabled and the library
// should be available now that the media_embed is enabled.
$plugin_ids = array_keys($this->manager->getEnabledDefinitions($editor));
$expected_plugins = array_merge($default_plugins, [
'ckeditor5_test.layercake',
'ckeditor5.media',
]);
sort($expected_plugins);
$this->assertSame($expected_plugins, $plugin_ids);
$this->assertSame(array_merge($default_libraries, [
'ckeditor5/drupal.ckeditor5.media',
'ckeditor5_test/layercake',
]), $this->manager->getEnabledLibraries($editor));
// Case 5: GHS is only enabled for Full HTML (or any other text format that
// has no TYPE_HTML_RESTRICTOR filters).
$editor = Editor::load('full_html');
$definitions = array_keys($this->manager->getEnabledDefinitions($editor));
$default_plugins = [
'ckeditor5.bold',
'ckeditor5.emphasis',
'ckeditor5.essentials',
'ckeditor5.htmlSupport',
'ckeditor5.paragraph',
'ckeditor5heading',
];
$this->assertSame($default_plugins, $definitions, 'No CKEditor 5 plugins found besides the built-in ones.');
$default_libraries = [
'ckeditor5/ckeditor5.basic',
'ckeditor5/ckeditor5.htmlSupport',
'ckeditor5/ckeditor5.internal',
'ckeditor5/drupal.ckeditor5',
'ckeditor5/drupal.ckeditor5.emphasis',
];
$this->assertSame($default_libraries, $this->manager->getEnabledLibraries($editor));
}
/**
* Tests the parsing of CKEditor 5 plugin element config.
*
* @param string[] $plugins
* The plugins to parse the elements list from.
* @param array $expected_elements
* An array of expected allowed elements an attributes in the structure
* used by filter_html.
* @param string $expected_readable_string
* The expected allowed tags and attributes as a string, typically used
* in the filter_html "Allowed tags" field.
*
* @covers \Drupal\ckeditor5\Plugin\CKEditor5PluginManager::getProvidedElements
* @covers \Drupal\ckeditor5\Plugin\CKEditor5PluginManager::getReadableElements
* @dataProvider providerTestProvidedElements
*/
public function testProvidedElements(array $plugins, array $expected_elements, string $expected_readable_string) {
$this->enableModules(['ckeditor5_plugin_elements_test']);
$provided_elements = $this->manager->getProvidedElements($plugins);
$this->assertSame($expected_elements, $provided_elements);
$readable_string = $this->manager->getReadableElements($provided_elements);
$this->assertSame($expected_readable_string, $readable_string);
}
/**
* Provides uses cases enabling different elements and the expected results.
*/
public function providerTestProvidedElements() : array {
$text_align_classes = [
'text-align-left' => TRUE,
'text-align-center' => TRUE,
'text-align-right' => TRUE,
'text-align-justify' => TRUE,
];
return [
'language' => [
'plugins' => ['language'],
'expected_elements' => [
'span' => [
'lang' => TRUE,
'dir' => TRUE,
],
],
'expected_readable_string' => '<span lang dir>',
],
'alignment and heading' => [
'plugins' => [
'ckeditor5.alignment',
'ckeditor5heading',
'ckeditor5.paragraph',
],
'expected_elements' => [
'p' => [
'class' => $text_align_classes,
],
'br' => FALSE,
'h1' => [
'class' => $text_align_classes,
],
'h2' => [
'class' => $text_align_classes,
],
'h3' => [
'class' => $text_align_classes,
],
'h4' => [
'class' => $text_align_classes,
],
'h5' => [
'class' => $text_align_classes,
],
'h6' => [
'class' => $text_align_classes,
],
],
'expected_readable_string' => '<p class="text-align-left text-align-center text-align-right text-align-justify"> <br> <h1 class="text-align-left text-align-center text-align-right text-align-justify"> <h2 class="text-align-left text-align-center text-align-right text-align-justify"> <h3 class="text-align-left text-align-center text-align-right text-align-justify"> <h4 class="text-align-left text-align-center text-align-right text-align-justify"> <h5 class="text-align-left text-align-center text-align-right text-align-justify"> <h6 class="text-align-left text-align-center text-align-right text-align-justify">',
],
'alignment and heading, but all class values allowed for headings' => [
'plugins' => [
'ckeditor5.alignment',
'ckeditor5heading',
'ckeditor5.paragraph',
'headings.use.class.any.value',
],
'expected_elements' => [
'p' => [
'class' => $text_align_classes,
],
'br' => FALSE,
'h1' => [
'class' => TRUE,
],
'h2' => [
'class' => TRUE,
],
'h3' => [
'class' => TRUE,
],
'h4' => [
'class' => TRUE,
],
'h5' => [
'class' => TRUE,
],
'h6' => [
'class' => TRUE,
],
],
'expected_readable_string' => '<p class="text-align-left text-align-center text-align-right text-align-justify"> <br> <h1 class> <h2 class> <h3 class> <h4 class> <h5 class> <h6 class>',
],
'blockquote combo' => [
'plugins' => [
'blockquote.combo',
'ckeditor5.paragraph',
],
'expected_elements' => [
'p' => [
'data-everyblock' => TRUE,
],
'br' => FALSE,
'blockquote' => [
'data-justblockquote' => TRUE,
'data-everyblock' => TRUE,
],
],
'expected_readable_string' => '<p data-everyblock> <br> <blockquote data-justblockquote data-everyblock>',
],
'headings plus headings with attributes' => [
'plugins' => [
'headings.with.other.attributes',
'ckeditor5heading',
],
'expected_elements' => [
'h1' => [
'data-just-h1' => TRUE,
],
'h2' => [
'class' => [
'additional-allowed-class' => TRUE,
],
],
'h3' => [
'data-just-h3' => TRUE,
'data-just-h3-limited' => [
'i-am-the-only-allowed-value' => TRUE,
],
],
'h4' => FALSE,
'h5' => [
'data-just-h5-limited' => [
'first-allowed-value' => TRUE,
'second-allowed-value' => TRUE,
],
],
'h6' => FALSE,
],
'expected_readable_string' => '<h1 data-just-h1> <h2 class="additional-allowed-class"> <h3 data-just-h3 data-just-h3-limited="i-am-the-only-allowed-value"> <h4> <h5 data-just-h5-limited="first-allowed-value second-allowed-value"> <h6>',
],
'headings plus headings with attributes and alignment' => [
'plugins' => [
'headings.with.other.attributes',
'ckeditor5heading',
'ckeditor5.alignment',
],
'expected_elements' => [
'h1' => [
'data-just-h1' => TRUE,
'class' => $text_align_classes,
],
'h2' => [
'class' => ['additional-allowed-class' => TRUE] + $text_align_classes,
],
'h3' => [
'data-just-h3' => TRUE,
'data-just-h3-limited' => [
'i-am-the-only-allowed-value' => TRUE,
],
'class' => $text_align_classes,
],
'h4' => [
'class' => $text_align_classes,
],
'h5' => [
'data-just-h5-limited' => [
'first-allowed-value' => TRUE,
'second-allowed-value' => TRUE,
],
'class' => $text_align_classes,
],
'h6' => [
'class' => $text_align_classes,
],
],
'expected_readable_string' => '<h1 data-just-h1 class="text-align-left text-align-center text-align-right text-align-justify"> <h2 class="additional-allowed-class text-align-left text-align-center text-align-right text-align-justify"> <h3 data-just-h3 data-just-h3-limited="i-am-the-only-allowed-value" class="text-align-left text-align-center text-align-right text-align-justify"> <h4 class="text-align-left text-align-center text-align-right text-align-justify"> <h5 data-just-h5-limited="first-allowed-value second-allowed-value" class="text-align-left text-align-center text-align-right text-align-justify"> <h6 class="text-align-left text-align-center text-align-right text-align-justify">',
],
];
}
}
