Skip to content
Snippets Groups Projects
Verified Commit 2d94b30e authored by Théodore Biadala's avatar Théodore Biadala
Browse files

Issue #3463456 by catch, smustgrave: Consolidate ckeditor5's FunctionalJavascript tests

parent bc4668cb
Branches
Tags
20 merge requests!11131[10.4.x-only-DO-NOT-MERGE]: Issue ##2842525 Ajax attached to Views exposed filter form does not trigger callbacks,!9470[10.3.x-only-DO-NOT-MERGE]: #3331771 Fix file_get_contents(): Passing null to parameter,!8736Update the Documention As per the Function uses.,!8513Issue #3453786: DefaultSelection should document why values for target_bundles NULL and [] behave as they do,!3878Removed unused condition head title for views,!3818Issue #2140179: $entity->original gets stale between updates,!3742Issue #3328429: Create item list field formatter for displaying ordered and unordered lists,!3731Claro: role=button on status report items,!3154Fixes #2987987 - CSRF token validation broken on routes with optional parameters.,!3133core/modules/system/css/components/hidden.module.css,!2964Issue #2865710 : Dependencies from only one instance of a widget are used in display modes,!2812Issue #3312049: [Followup] Fix Drupal.Commenting.FunctionComment.MissingReturnType returns for NULL,!2378Issue #2875033: Optimize joins and table selection in SQL entity query implementation,!2062Issue #3246454: Add weekly granularity to views date sort,!10223132456: Fix issue where views instances are emptied before an ajax request is complete,!877Issue #2708101: Default value for link text is not saved,!617Issue #3043725: Provide a Entity Handler for user cancelation,!579Issue #2230909: Simple decimals fail to pass validation,!560Move callback classRemove outside of the loop,!555Issue #3202493
Pipeline #239161 passed
Pipeline: drupal

#239164

    ......@@ -13,6 +13,7 @@
    * BigPipe regression tests.
    *
    * @group big_pipe
    * @group #slow
    */
    class BigPipeRegressionTest extends WebDriverTestBase {
    ......
    ......@@ -22,6 +22,7 @@
    * Tests for CKEditor 5.
    *
    * @group ckeditor5
    * @group #slow
    * @internal
    */
    class CKEditor5Test extends CKEditor5TestBase {
    ......
    ......@@ -160,10 +160,8 @@ public function testAttributeRetentionDuringUpcasting(): void {
    /**
    * Tests that arbitrary attributes are allowed via GHS.
    *
    * @dataProvider providerLinkability
    */
    public function testImageArbitraryHtml(string $image_type, bool $unrestricted): void {
    public function testImageArbitraryHtml(): void {
    $editor = Editor::load('test_format');
    $settings = $editor->getSettings();
    ......@@ -171,32 +169,36 @@ public function testImageArbitraryHtml(string $image_type, bool $unrestricted):
    $settings['plugins']['ckeditor5_sourceEditing']['allowed_tags'] = ['<img data-foo>'];
    $editor->setSettings($settings);
    $editor->save();
    $format = FilterFormat::load('test_format');
    $original_config = $format->filters('filter_html')
    ->getConfiguration();
    // Disable filter_html.
    if ($unrestricted) {
    FilterFormat::load('test_format')
    ->setFilterConfig('filter_html', ['status' => FALSE])
    foreach ($this->providerLinkability() as $data) {
    [$image_type, $unrestricted] = $data;
    $format_config = $unrestricted ? ['status' => FALSE] : $original_config;
    $format->setFilterConfig('filter_html', $format_config)
    ->save();
    }
    // Make the test content have either a block image or an inline image.
    $img_tag = '<img data-foo="bar" alt="drupalimage test image" data-entity-type="file" ' . $this->imageAttributesAsString() . ' />';
    $this->host->body->value .= $image_type === 'block'
    ? $img_tag
    : "<p>$img_tag</p>";
    $this->host->save();
    // Make the test content have either a block image or an inline image.
    $img_tag = '<img data-foo="bar" alt="drupalimage test image" data-entity-type="file" ' . $this->imageAttributesAsString() . ' />';
    $this->host->body->value .= $image_type === 'block'
    ? $img_tag
    : "<p>$img_tag</p>";
    $this->host->save();
    $expected_widget_selector = $image_type === 'block' ? 'image img' : 'image-inline';
    $expected_widget_selector = $image_type === 'block' ? 'image img' : 'image-inline';
    $this->drupalGet($this->host->toUrl('edit-form'));
    $this->waitForEditor();
    $this->drupalGet($this->host->toUrl('edit-form'));
    $this->waitForEditor();
    $drupalimage = $this->assertSession()->waitForElementVisible('css', ".ck-content .ck-widget.$expected_widget_selector");
    $this->assertNotEmpty($drupalimage);
    $this->assertEquals('bar', $drupalimage->getAttribute('data-foo'));
    $drupalimage = $this->assertSession()->waitForElementVisible('css', ".ck-content .ck-widget.$expected_widget_selector");
    $this->assertNotEmpty($drupalimage);
    $this->assertEquals('bar', $drupalimage->getAttribute('data-foo'));
    $xpath = new \DOMXPath($this->getEditorDataAsDom());
    $this->assertNotEmpty($xpath->query('//img[@data-foo="bar"]'));
    $xpath = new \DOMXPath($this->getEditorDataAsDom());
    $this->assertNotEmpty($xpath->query('//img[@data-foo="bar"]'));
    }
    }
    /**
    ......@@ -207,151 +209,154 @@ public function testImageArbitraryHtml(string $image_type, bool $unrestricted):
    * These are CKEditor 5 concepts.
    *
    * @see https://ckeditor.com/docs/ckeditor5/latest/framework/guides/architecture/editing-engine.html#conversion
    *
    * @dataProvider providerLinkability
    */
    public function testLinkability(string $image_type, bool $unrestricted): void {
    assert($image_type === 'inline' || $image_type === 'block');
    // Disable filter_html.
    if ($unrestricted) {
    FilterFormat::load('test_format')
    ->setFilterConfig('filter_html', ['status' => FALSE])
    public function testLinkability(): void {
    $format = FilterFormat::load('test_format');
    $original_config = $format->filters('filter_html')
    ->getConfiguration();
    $original_body_value = $this->host->body->value;
    foreach ($this->providerLinkability() as $data) {
    [$image_type, $unrestricted] = $data;
    assert($image_type === 'inline' || $image_type === 'block');
    $format_config = $unrestricted ? ['status' => FALSE] : $original_config;
    $format->setFilterConfig('filter_html', $format_config)
    ->save();
    }
    // Make the test content have either a block image or an inline image.
    $img_tag = '<img alt="drupalimage test image" data-entity-type="file" ' . $this->imageAttributesAsString() . ' />';
    $this->host->body->value .= $image_type === 'block'
    ? $img_tag
    : "<p>$img_tag</p>";
    $this->host->save();
    // Adjust the expectations accordingly.
    $expected_widget_class = $image_type === 'block' ? 'image' : 'image-inline';
    $page = $this->getSession()->getPage();
    $this->drupalGet($this->host->toUrl('edit-form'));
    $this->waitForEditor();
    $assert_session = $this->assertSession();
    // Initial state: the image CKEditor Widget is not selected.
    $drupalimage = $assert_session->waitForElementVisible('css', ".ck-content .ck-widget.$expected_widget_class");
    $this->assertNotEmpty($drupalimage);
    $this->assertFalse($drupalimage->hasClass('.ck-widget_selected'));
    $src = basename($this->imageAttributes()['src']);
    // Assert the "editingDowncast" HTML before making changes.
    $assert_session->elementExists('css', '.ck-content .ck-widget.' . $expected_widget_class . ' > img[src*="' . $src . '"][alt="drupalimage test image"]');
    // Assert the "dataDowncast" HTML before making changes.
    $xpath = new \DOMXPath($this->getEditorDataAsDom());
    $this->assertNotEmpty($xpath->query('//img[@alt="drupalimage test image"]'));
    $this->assertEmpty($xpath->query('//a'));
    // Assert the link button is present and not pressed.
    $link_button = $this->getEditorButton('Link');
    $this->assertSame('false', $link_button->getAttribute('aria-pressed'));
    // Tests linking images.
    $drupalimage->click();
    $this->assertTrue($drupalimage->hasClass('ck-widget_selected'));
    $this->assertEditorButtonEnabled('Link');
    // Assert structure of image toolbar balloon.
    $this->assertVisibleBalloon('.ck-toolbar[aria-label="Image toolbar"]');
    $link_image_button = $this->getBalloonButton('Link image');
    // Click the "Link image" button.
    $this->assertSame('false', $link_image_button->getAttribute('aria-pressed'));
    $link_image_button->press();
    // Assert structure of link form balloon.
    $balloon = $this->assertVisibleBalloon('.ck-link-form');
    $url_input = $balloon->find('css', '.ck-labeled-field-view__input-wrapper .ck-input-text');
    // Fill in link form balloon's <input> and hit "Save".
    $url_input->setValue('http://www.drupal.org/association');
    $balloon->pressButton('Save');
    // Assert the "editingDowncast" HTML after making changes. First assert the
    // link exists, then assert the expected DOM structure in detail.
    $assert_session->elementExists('css', '.ck-content a[href*="//www.drupal.org/association"]');
    // For inline images, the link is wrapping the widget; for block images the
    // link lives inside the widget. (This is how it is implemented upstream, it
    // could be implemented differently, we just want to ensure we do not break
    // it. Drupal only cares about having its own "dataDowncast", the
    // "editingDowncast" is considered an implementation detail.)
    $assert_session->elementExists('css', $image_type === 'inline'
    ? '.ck-content a[href*="//www.drupal.org/association"] .ck-widget.' . $expected_widget_class . ' > img[src*="' . $src . '"][alt="drupalimage test image"]'
    : '.ck-content .ck-widget.' . $expected_widget_class . ' a[href*="//www.drupal.org/association"] > img[src*="' . $src . '"][alt="drupalimage test image"]'
    );
    // Assert the "dataDowncast" HTML after making changes.
    $xpath = new \DOMXPath($this->getEditorDataAsDom());
    $this->assertCount(1, $xpath->query('//a[@href="http://www.drupal.org/association"]/img[@alt="drupalimage test image"]'));
    $this->assertEmpty($xpath->query('//a[@href="http://www.drupal.org/association" and @class="trusted"]'));
    // Add `class="trusted"` to the link.
    $xpath = new \DOMXPath($this->getEditorDataAsDom());
    $this->assertEmpty($xpath->query('//a[@href="http://www.drupal.org/association" and @class="trusted"]'));
    $this->pressEditorButton('Source');
    $source_text_area = $assert_session->waitForElement('css', '.ck-source-editing-area textarea');
    $this->assertNotEmpty($source_text_area);
    $new_value = str_replace('<a ', '<a class="trusted" ', $source_text_area->getValue());
    $source_text_area->setValue('<p>temp</p>');
    $source_text_area->setValue($new_value);
    $this->pressEditorButton('Source');
    // When unrestricted, additional attributes on links should be retained.
    $xpath = new \DOMXPath($this->getEditorDataAsDom());
    $this->assertCount($unrestricted ? 1 : 0, $xpath->query('//a[@href="http://www.drupal.org/association" and @class="trusted"]'));
    // Save the entity whose text field is being edited.
    $page->pressButton('Save');
    // Assert the HTML the end user sees.
    $assert_session->elementExists('css', $unrestricted
    ? 'a[href="http://www.drupal.org/association"].trusted img[src*="' . $src . '"]'
    : 'a[href="http://www.drupal.org/association"] img[src*="' . $src . '"]');
    // Go back to edit the now *linked* <drupal-media>. Everything from this
    // point onwards is effectively testing "upcasting" and proving there is no
    // data loss.
    $this->drupalGet($this->host->toUrl('edit-form'));
    $this->waitForEditor();
    // Assert the "dataDowncast" HTML before making changes.
    $xpath = new \DOMXPath($this->getEditorDataAsDom());
    $this->assertNotEmpty($xpath->query('//img[@alt="drupalimage test image"]'));
    $this->assertNotEmpty($xpath->query('//a[@href="http://www.drupal.org/association"]'));
    $this->assertNotEmpty($xpath->query('//a[@href="http://www.drupal.org/association"]/img[@alt="drupalimage test image"]'));
    $this->assertCount($unrestricted ? 1 : 0, $xpath->query('//a[@href="http://www.drupal.org/association" and @class="trusted"]'));
    // Tests unlinking images.
    $drupalimage->click();
    $this->assertEditorButtonEnabled('Link');
    $this->assertSame('true', $this->getEditorButton('Link')->getAttribute('aria-pressed'));
    // Assert structure of image toolbar balloon.
    $this->assertVisibleBalloon('.ck-toolbar[aria-label="Image toolbar"]');
    $link_image_button = $this->getBalloonButton('Link image');
    $this->assertSame('true', $link_image_button->getAttribute('aria-pressed'));
    $link_image_button->click();
    // Assert structure of link actions balloon.
    $this->getBalloonButton('Edit link');
    $unlink_image_button = $this->getBalloonButton('Unlink');
    // Click the "Unlink" button.
    $unlink_image_button->click();
    $this->assertSame('false', $this->getEditorButton('Link')->getAttribute('aria-pressed'));
    // Assert the "editingDowncast" HTML after making changes. Assert the
    // widget exists but not the link, or *any* link for that matter. Then
    // assert the expected DOM structure in detail.
    $assert_session->elementExists('css', '.ck-content .ck-widget.' . $expected_widget_class);
    $assert_session->elementNotExists('css', '.ck-content a');
    $assert_session->elementExists('css', '.ck-content .ck-widget.' . $expected_widget_class . ' > img[src*="' . $src . '"][alt="drupalimage test image"]');
    // Assert the "dataDowncast" HTML after making changes.
    $xpath = new \DOMXPath($this->getEditorDataAsDom());
    $this->assertCount(0, $xpath->query('//a[@href="http://www.drupal.org/association"]/img[@alt="drupalimage test image"]'));
    $this->assertCount(1, $xpath->query('//img[@alt="drupalimage test image"]'));
    $this->assertCount(0, $xpath->query('//a'));
    // Make the test content have either a block image or an inline image.
    $img_tag = '<img alt="drupalimage test image" data-entity-type="file" ' . $this->imageAttributesAsString() . ' />';
    $this->host->body->value = $original_body_value . ($image_type === 'block'
    ? $img_tag
    : "<p>$img_tag</p>");
    $this->host->save();
    $this->drupalGet($this->host->toUrl('edit-form'));
    $page = $this->getSession()->getPage();
    // Adjust the expectations accordingly.
    $expected_widget_class = $image_type === 'block' ? 'image' : 'image-inline';
    $this->waitForEditor();
    $assert_session = $this->assertSession();
    // Initial state: the image CKEditor Widget is not selected.
    $drupalimage = $assert_session->waitForElementVisible('css', ".ck-content .ck-widget.$expected_widget_class");
    $this->assertNotEmpty($drupalimage);
    $this->assertFalse($drupalimage->hasClass('.ck-widget_selected'));
    $src = basename($this->imageAttributes()['src']);
    // Assert the "editingDowncast" HTML before making changes.
    $assert_session->elementExists('css', '.ck-content .ck-widget.' . $expected_widget_class . ' > img[src*="' . $src . '"][alt="drupalimage test image"]');
    // Assert the "dataDowncast" HTML before making changes.
    $xpath = new \DOMXPath($this->getEditorDataAsDom());
    $this->assertNotEmpty($xpath->query('//img[@alt="drupalimage test image"]'));
    $this->assertEmpty($xpath->query('//a'));
    // Assert the link button is present and not pressed.
    $link_button = $this->getEditorButton('Link');
    $this->assertSame('false', $link_button->getAttribute('aria-pressed'));
    // Tests linking images.
    $drupalimage->click();
    $this->assertTrue($drupalimage->hasClass('ck-widget_selected'));
    $this->assertEditorButtonEnabled('Link');
    // Assert structure of image toolbar balloon.
    $this->assertVisibleBalloon('.ck-toolbar[aria-label="Image toolbar"]');
    $link_image_button = $this->getBalloonButton('Link image');
    // Click the "Link image" button.
    $this->assertSame('false', $link_image_button->getAttribute('aria-pressed'));
    $link_image_button->press();
    // Assert structure of link form balloon.
    $balloon = $this->assertVisibleBalloon('.ck-link-form');
    $url_input = $balloon->find('css', '.ck-labeled-field-view__input-wrapper .ck-input-text');
    // Fill in link form balloon's <input> and hit "Save".
    $url_input->setValue('http://www.drupal.org/association');
    $balloon->pressButton('Save');
    // Assert the "editingDowncast" HTML after making changes. First assert the
    // link exists, then assert the expected DOM structure in detail.
    $assert_session->elementExists('css', '.ck-content a[href*="//www.drupal.org/association"]');
    // For inline images, the link is wrapping the widget; for block images the
    // link lives inside the widget. (This is how it is implemented upstream, it
    // could be implemented differently, we just want to ensure we do not break
    // it. Drupal only cares about having its own "dataDowncast", the
    // "editingDowncast" is considered an implementation detail.)
    $assert_session->elementExists('css', $image_type === 'inline'
    ? '.ck-content a[href*="//www.drupal.org/association"] .ck-widget.' . $expected_widget_class . ' > img[src*="' . $src . '"][alt="drupalimage test image"]'
    : '.ck-content .ck-widget.' . $expected_widget_class . ' a[href*="//www.drupal.org/association"] > img[src*="' . $src . '"][alt="drupalimage test image"]'
    );
    // Assert the "dataDowncast" HTML after making changes.
    $xpath = new \DOMXPath($this->getEditorDataAsDom());
    $this->assertCount(1, $xpath->query('//a[@href="http://www.drupal.org/association"]/img[@alt="drupalimage test image"]'));
    $this->assertEmpty($xpath->query('//a[@href="http://www.drupal.org/association" and @class="trusted"]'));
    // Add `class="trusted"` to the link.
    $xpath = new \DOMXPath($this->getEditorDataAsDom());
    $this->assertEmpty($xpath->query('//a[@href="http://www.drupal.org/association" and @class="trusted"]'));
    $this->pressEditorButton('Source');
    $source_text_area = $assert_session->waitForElement('css', '.ck-source-editing-area textarea');
    $this->assertNotEmpty($source_text_area);
    $new_value = str_replace('<a ', '<a class="trusted" ', $source_text_area->getValue());
    $source_text_area->setValue('<p>temp</p>');
    $source_text_area->setValue($new_value);
    $this->pressEditorButton('Source');
    // When unrestricted, additional attributes on links should be retained.
    $xpath = new \DOMXPath($this->getEditorDataAsDom());
    $this->assertCount($unrestricted ? 1 : 0, $xpath->query('//a[@href="http://www.drupal.org/association" and @class="trusted"]'));
    // Save the entity whose text field is being edited.
    $page->pressButton('Save');
    // Assert the HTML the end user sees.
    $assert_session->elementExists('css', $unrestricted
    ? 'a[href="http://www.drupal.org/association"].trusted img[src*="' . $src . '"]'
    : 'a[href="http://www.drupal.org/association"] img[src*="' . $src . '"]');
    // Go back to edit the now *linked* <drupal-media>. Everything from this
    // point onwards is effectively testing "upcasting" and proving there is no
    // data loss.
    $this->drupalGet($this->host->toUrl('edit-form'));
    $this->waitForEditor();
    // Assert the "dataDowncast" HTML before making changes.
    $xpath = new \DOMXPath($this->getEditorDataAsDom());
    $this->assertNotEmpty($xpath->query('//img[@alt="drupalimage test image"]'));
    $this->assertNotEmpty($xpath->query('//a[@href="http://www.drupal.org/association"]'));
    $this->assertNotEmpty($xpath->query('//a[@href="http://www.drupal.org/association"]/img[@alt="drupalimage test image"]'));
    $this->assertCount($unrestricted ? 1 : 0, $xpath->query('//a[@href="http://www.drupal.org/association" and @class="trusted"]'));
    // Tests unlinking images.
    $drupalimage->click();
    $this->assertEditorButtonEnabled('Link');
    $this->assertSame('true', $this->getEditorButton('Link')->getAttribute('aria-pressed'));
    // Assert structure of image toolbar balloon.
    $this->assertVisibleBalloon('.ck-toolbar[aria-label="Image toolbar"]');
    $link_image_button = $this->getBalloonButton('Link image');
    $this->assertSame('true', $link_image_button->getAttribute('aria-pressed'));
    $link_image_button->click();
    // Assert structure of link actions balloon.
    $this->getBalloonButton('Edit link');
    $unlink_image_button = $this->getBalloonButton('Unlink');
    // Click the "Unlink" button.
    $unlink_image_button->click();
    $this->assertSame('false', $this->getEditorButton('Link')->getAttribute('aria-pressed'));
    // Assert the "editingDowncast" HTML after making changes. Assert the
    // widget exists but not the link, or *any* link for that matter. Then
    // assert the expected DOM structure in detail.
    $assert_session->elementExists('css', '.ck-content .ck-widget.' . $expected_widget_class);
    $assert_session->elementNotExists('css', '.ck-content a');
    $assert_session->elementExists('css', '.ck-content .ck-widget.' . $expected_widget_class . ' > img[src*="' . $src . '"][alt="drupalimage test image"]');
    // Assert the "dataDowncast" HTML after making changes.
    $xpath = new \DOMXPath($this->getEditorDataAsDom());
    $this->assertCount(0, $xpath->query('//a[@href="http://www.drupal.org/association"]/img[@alt="drupalimage test image"]'));
    $this->assertCount(1, $xpath->query('//img[@alt="drupalimage test image"]'));
    $this->assertCount(0, $xpath->query('//a'));
    }
    }
    /**
    ......@@ -457,7 +462,7 @@ public static function providerAltTextRequired(): array {
    ];
    }
    public static function providerLinkability(): array {
    protected function providerLinkability(): array {
    return [
    'BLOCK image, restricted' => ['block', FALSE],
    'BLOCK image, unrestricted' => ['block', TRUE],
    ......
    ......@@ -27,10 +27,22 @@
    */
    class MediaTest extends MediaTestBase {
    /**
    * Tests the drupal-media tag.
    */
    public function testDrupalMedia(): void {
    $this->testConversion();
    $this->testOnlyDrupalMediaTagProcessed();
    $this->testEditableCaption();
    $this->testAlignment();
    $this->testAlt();
    $this->testMediaSplitList();
    }
    /**
    * Tests that `<drupal-media>` is converted into a block element.
    */
    public function testConversion(): void {
    protected function testConversion(): void {
    // Wrap the `<drupal-media>` markup in a `<p>`.
    $original_value = $this->host->body->value;
    $this->host->body->value = '<p>foo' . $original_value . '</p>';
    ......@@ -50,7 +62,7 @@ public function testConversion(): void {
    *
    * @see \Drupal\Tests\media\Kernel\MediaEmbedFilterTest::testOnlyDrupalMediaTagProcessed()
    */
    public function testOnlyDrupalMediaTagProcessed(): void {
    protected function testOnlyDrupalMediaTagProcessed(): void {
    $original_value = $this->host->body->value;
    $this->host->body->value = str_replace('drupal-media', 'p', $original_value);
    $this->host->save();
    ......@@ -75,7 +87,7 @@ public function testOnlyDrupalMediaTagProcessed(): void {
    /**
    * Tests adding media to a list does not split the list.
    */
    public function testMediaSplitList(): void {
    protected function testMediaSplitList(): void {
    $assert_session = $this->assertSession();
    $editor = Editor::load('test_format');
    ......@@ -193,7 +205,7 @@ function (ConstraintViolation $v) {
    /**
    * Tests caption editing in the CKEditor widget.
    */
    public function testEditableCaption(): void {
    protected function testEditableCaption(): void {
    $page = $this->getSession()->getPage();
    $assert_session = $this->assertSession();
    // Test that setting caption to blank string doesn't break 'Edit media'
    ......@@ -362,7 +374,7 @@ public function testAltDisabled(): void {
    /**
    * Tests the CKEditor 5 media plugin can override image media's alt attribute.
    */
    public function testAlt(): void {
    protected function testAlt(): void {
    $page = $this->getSession()->getPage();
    $assert_session = $this->assertSession();
    $this->drupalGet($this->host->toUrl('edit-form'));
    ......@@ -572,7 +584,7 @@ public function testTranslationAlt(): void {
    * the media style toolbar allows altering the alignment and that the changes
    * are reflected on the widget and downcast drupal-media tag.
    */
    public function testAlignment(): void {
    protected function testAlignment(): void {
    $assert_session = $this->assertSession();
    $page = $this->getSession()->getPage();
    $this->drupalGet($this->host->toUrl('edit-form'));
    ......
    ......@@ -68,28 +68,31 @@ public function testSourceEditingSettingsForm(): void {
    /**
    * Tests allowing extra attributes on already supported tags using GHS.
    *
    * @dataProvider providerAllowingExtraAttributes
    */
    public function testAllowingExtraAttributes(string $original_markup, string $expected_markup, ?string $allowed_elements_string = NULL): void {
    $this->host->body->value = $original_markup;
    $this->host->save();
    if ($allowed_elements_string) {
    public function testAllowingExtraAttributes(): void {
    $original_text_editor = Editor::load('test_format');
    $original_text_format = FilterFormat::load('test_format');
    $allowed_elements = HTMLRestrictions::fromTextFormat($original_text_format);
    $filter_html_config = $original_text_format->filters('filter_html')
    ->getConfiguration();
    foreach ($this->providerAllowingExtraAttributes() as $data) {
    $text_editor = clone $original_text_editor;
    $text_format = clone $original_text_format;
    [$original_markup, $expected_markup, $allowed_elements_string] = $data;
    // Allow creating additional HTML using SourceEditing.
    $text_editor = Editor::load('test_format');
    $settings = $text_editor->getSettings();
    $settings['plugins']['ckeditor5_sourceEditing']['allowed_tags'][] = $allowed_elements_string;
    if ($allowed_elements_string) {
    $settings['plugins']['ckeditor5_sourceEditing']['allowed_tags'][] = $allowed_elements_string;
    }
    $text_editor->setSettings($settings);
    // Keep the allowed HTML tags in sync.
    $text_format = FilterFormat::load('test_format');
    $allowed_elements = HTMLRestrictions::fromTextFormat($text_format);
    $updated_allowed_tags = $allowed_elements->merge(HTMLRestrictions::fromString($allowed_elements_string));
    $filter_html_config = $text_format->filters('filter_html')
    ->getConfiguration();
    $filter_html_config['settings']['allowed_html'] = $updated_allowed_tags->toFilterHtmlAllowedTagsString();
    $text_format->setFilterConfig('filter_html', $filter_html_config);
    $new_config = $filter_html_config;
    if ($allowed_elements_string) {
    // Keep the allowed HTML tags in sync.
    $updated_allowed_tags = $allowed_elements->merge(HTMLRestrictions::fromString($allowed_elements_string));
    $new_config['settings']['allowed_html'] = $updated_allowed_tags->toFilterHtmlAllowedTagsString();
    }
    $text_format->setFilterConfig('filter_html', $new_config);
    // Verify the text format and editor are still a valid pair.
    $this->assertSame([], array_map(
    ......@@ -105,8 +108,16 @@ function (ConstraintViolation $v) {
    // If valid, save both.
    $text_format->save();
    $text_editor->save();
    $this->doTestAllowingExtraAttributes($original_markup, $expected_markup, $allowed_elements_string);
    }
    }
    /**
    * Tests extra attributes with a specific data set.
    */
    protected function doTestAllowingExtraAttributes(string $original_markup, string $expected_markup, string $allowed_elements_string): void {
    $this->host->body->value = $original_markup;
    $this->host->save();
    $this->drupalGet($this->host->toUrl('edit-form'));
    $this->waitForEditor();
    $this->assertSame($expected_markup, $this->getEditorDataAsHtmlString());
    ......@@ -118,12 +129,13 @@ function (ConstraintViolation $v) {
    * @return array
    * The test cases.
    */
    public static function providerAllowingExtraAttributes(): array {
    protected function providerAllowingExtraAttributes(): array {
    $general_test_case_markup = '<div class="llama" data-llama="🦙"><p data-llama="🦙">The <a href="https://example.com/pirate" class="button" data-grammar="subject">pirate</a> is <a href="https://example.com/irate" class="use-ajax" data-grammar="adjective">irate</a>.</p></div>';
    return [
    'no extra attributes allowed' => [
    $general_test_case_markup,
    '<div class="llama"><p>The <a href="https://example.com/pirate">pirate</a> is <a href="https://example.com/irate">irate</a>.</p></div>',
    '',
    ],
    // Common case: any attribute that is not `style` or `class`.
    ......@@ -224,6 +236,7 @@ public static function providerAllowingExtraAttributes(): array {
    'no numberedList-related additions to the Source Editing configuration' => [
    '<ol type="A"><li>foo</li><li>bar</li></ol>',
    '<ol><li>foo</li><li>bar</li></ol>',
    '',
    ],
    '<ol type>' => [
    '<ol type="A"><li>foo</li><li>bar</li></ol>',
    ......@@ -238,6 +251,7 @@ public static function providerAllowingExtraAttributes(): array {
    'no bulletedList-related additions to the Source Editing configuration' => [
    '<ul type="circle"><li>foo</li><li>bar</li></ul>',
    '<ul><li>foo</li><li>bar</li></ul>',
    '',
    ],
    '<ul type>' => [
    '<ul type="circle"><li>foo</li><li>bar</li></ul>',
    ......
    ......@@ -13,6 +13,7 @@
    * Tests the Media library entity reference widget.
    *
    * @group media_library
    * @group #slow
    */
    class EntityReferenceWidgetTest extends MediaLibraryTestBase {
    ......
    0% Loading or .
    You are about to add 0 people to the discussion. Proceed with caution.
    Please register or to comment