diff --git a/core/modules/big_pipe/tests/src/FunctionalJavascript/BigPipeRegressionTest.php b/core/modules/big_pipe/tests/src/FunctionalJavascript/BigPipeRegressionTest.php index d811b561d8e195ade9e606da96dfa66003853806..6d4b1634c6f979a6800a6ab8e1b1e4cf9a55eafd 100644 --- a/core/modules/big_pipe/tests/src/FunctionalJavascript/BigPipeRegressionTest.php +++ b/core/modules/big_pipe/tests/src/FunctionalJavascript/BigPipeRegressionTest.php @@ -13,6 +13,7 @@ * BigPipe regression tests. * * @group big_pipe + * @group #slow */ class BigPipeRegressionTest extends WebDriverTestBase { diff --git a/core/modules/ckeditor5/tests/src/FunctionalJavascript/CKEditor5Test.php b/core/modules/ckeditor5/tests/src/FunctionalJavascript/CKEditor5Test.php index 901714da565048c28974aa24156b1b2bdf888a4e..9584aaa446c94284cd6fda74f91317ef6664653b 100644 --- a/core/modules/ckeditor5/tests/src/FunctionalJavascript/CKEditor5Test.php +++ b/core/modules/ckeditor5/tests/src/FunctionalJavascript/CKEditor5Test.php @@ -22,6 +22,7 @@ * Tests for CKEditor 5. * * @group ckeditor5 + * @group #slow * @internal */ class CKEditor5Test extends CKEditor5TestBase { diff --git a/core/modules/ckeditor5/tests/src/FunctionalJavascript/ImageTestBase.php b/core/modules/ckeditor5/tests/src/FunctionalJavascript/ImageTestBase.php index 8a064df5afc115de5108cda638556f635eb6a956..46fca1290ad0c7407dfec6d5d9bbf09891698144 100644 --- a/core/modules/ckeditor5/tests/src/FunctionalJavascript/ImageTestBase.php +++ b/core/modules/ckeditor5/tests/src/FunctionalJavascript/ImageTestBase.php @@ -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], diff --git a/core/modules/ckeditor5/tests/src/FunctionalJavascript/MediaTest.php b/core/modules/ckeditor5/tests/src/FunctionalJavascript/MediaTest.php index 32f0ef191bb2b64ceb5a317da1fb619cb3fc5532..e67981212006872a5026cb591627587e82c87f1d 100644 --- a/core/modules/ckeditor5/tests/src/FunctionalJavascript/MediaTest.php +++ b/core/modules/ckeditor5/tests/src/FunctionalJavascript/MediaTest.php @@ -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')); diff --git a/core/modules/ckeditor5/tests/src/FunctionalJavascript/SourceEditingTest.php b/core/modules/ckeditor5/tests/src/FunctionalJavascript/SourceEditingTest.php index ea925522dda6533bacec7aa7c1f9f3db8152c09b..2f9d70884bef7fd4da93bbb2fbc8968ddfbe59ca 100644 --- a/core/modules/ckeditor5/tests/src/FunctionalJavascript/SourceEditingTest.php +++ b/core/modules/ckeditor5/tests/src/FunctionalJavascript/SourceEditingTest.php @@ -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>', diff --git a/core/modules/media_library/tests/src/FunctionalJavascript/EntityReferenceWidgetTest.php b/core/modules/media_library/tests/src/FunctionalJavascript/EntityReferenceWidgetTest.php index 7dbc6f886d893656e2ba89651832c6c9eba89e84..ac1f7922252036c258bffe00cc619238ce6f82df 100644 --- a/core/modules/media_library/tests/src/FunctionalJavascript/EntityReferenceWidgetTest.php +++ b/core/modules/media_library/tests/src/FunctionalJavascript/EntityReferenceWidgetTest.php @@ -13,6 +13,7 @@ * Tests the Media library entity reference widget. * * @group media_library + * @group #slow */ class EntityReferenceWidgetTest extends MediaLibraryTestBase {