image_to_media_swapper-2.x-dev/tests/src/FunctionalJavascript/MediaSwapperCKEditorTestDisabled.php
tests/src/FunctionalJavascript/MediaSwapperCKEditorTestDisabled.php
<?php
declare(strict_types=1);
namespace Drupal\Tests\image_to_media_swapper\FunctionalJavascript;
use Drupal\editor\Entity\Editor;
use Drupal\file\FileInterface;
use Drupal\filter\Entity\FilterFormat;
use Drupal\Tests\ckeditor5\FunctionalJavascript\CKEditor5TestBase;
use Drupal\media\MediaInterface;
use Drupal\Tests\ckeditor5\Traits\CKEditor5TestTrait;
use Drupal\Tests\image_to_media_swapper\Traits\MediaFieldSetupTrait;
use Drupal\Tests\media\Traits\MediaTypeCreationTrait;
use Drupal\Tests\TestFileCreationTrait;
use Drupal\field\Entity\FieldConfig;
use Drupal\file\Entity\File;
use Drupal\media\Entity\Media;
use Drupal\node\Entity\Node;
use Drupal\user\RoleInterface;
use Drupal\user\UserInterface;
/**
* Tests CKEditor media swapping functionality.
*
* @group image_to_media_swapper
* @group ckeditor5
*/
class MediaSwapperCKEditorTestDisabled extends CKEditor5TestBase {
use CKEditor5TestTrait;
use MediaFieldSetupTrait;
use MediaTypeCreationTrait;
use TestFileCreationTrait;
/**
* {@inheritdoc}
*/
protected $defaultTheme = 'stark';
/**
* {@inheritdoc}
*/
protected static $modules = [
'node',
'ckeditor5',
'file',
'image',
'media',
'media_library',
'image_to_media_swapper',
'serialization',
'options',
];
/**
* A user with permission to create content and use media.
*
* @var \Drupal\user\UserInterface
*/
protected UserInterface $authorUser;
/**
* Test file entity.
*
* @var \Drupal\file\FileInterface
*/
protected FileInterface $testFile;
/**
* Test media entity.
*
* @var \Drupal\media\MediaInterface
*/
protected MediaInterface $testMedia;
/**
* {@inheritdoc}
*/
protected function setUp(): void {
parent::setUp();
// Create image media type using the trait.
$this->createMediaImageType();
// Setup text format with media swapper.
$this->setupTextFormatWithMediaSwapper();
// Configure the body field to allow our format.
$this->configureBodyField();
// Create user with comprehensive permissions.
$permissions = [
'administer filters',
'create page content',
'edit own page content',
'edit any page content',
'use text format ckeditor5',
'create media',
'access media overview',
'access content',
'view own unpublished content',
];
$user = $this->drupalCreateUser($permissions);
$this->drupalLogin($user);
$this->authorUser = $user;
// Create a test image file.
$test_files = $this->getTestFiles('image');
$this->testFile = File::create([
'uri' => $test_files[0]->uri,
'filename' => $test_files[0]->filename,
'filemime' => mime_content_type($test_files[0]->uri),
'status' => 1,
]);
$this->testFile->save();
// Create test media entity.
$this->testMedia = Media::create([
'bundle' => 'image',
'name' => 'Test Image',
'field_media_image' => [
'target_id' => $this->testFile->id(),
'alt' => 'Test image alt text',
],
]);
$this->testMedia->save();
}
/**
* Configure the body field to allow our text format.
*/
protected function configureBodyField(): void {
// Create a new filter format that's available to all authenticated users.
FilterFormat::create([
'format' => 'basic_html',
'name' => 'Basic HTML',
'roles' => [RoleInterface::AUTHENTICATED_ID],
'filters' => [
'filter_html' => [
'status' => TRUE,
'settings' => [
'allowed_html' => '<p> <br>',
],
],
],
])->save();
$field_config = FieldConfig::loadByName('node', 'page', 'body');
if (!$field_config) {
return;
}
// Allow both formats so there's a selector.
$settings = $field_config->getSettings();
$settings['allowed_formats'] = ['ckeditor5', 'basic_html'];
$settings['default_format'] = 'ckeditor5';
$field_config->setSettings($settings);
$field_config->save();
// Clear caches.
\Drupal::service('entity_field.manager')->clearCachedFieldDefinitions();
}
/**
* Sets up text format with media swapper functionality.
*
* @throws \Drupal\Core\Entity\EntityStorageException
*/
protected function setupTextFormatWithMediaSwapper(): void {
// Create filter format with proper HTML allowlist.
FilterFormat::create([
'format' => 'ckeditor5',
'name' => 'CKEditor 5',
'roles' => [RoleInterface::AUTHENTICATED_ID],
'filters' => [
'filter_html' => [
'status' => TRUE,
'settings' => [
'allowed_html' => '<br> <p> <h2> <h3> <h4> <h5> <h6> <strong> <em> <img alt height src width data-entity-type data-entity-uuid> <drupal-media data-entity-type data-entity-uuid alt data-view-mode>',
],
],
'filter_align' => ['status' => TRUE],
'filter_caption' => ['status' => TRUE],
],
])->save();
// Create editor configuration with proper toolbar including media swapper.
Editor::create([
'editor' => 'ckeditor5',
'format' => 'ckeditor5',
'settings' => [
'toolbar' => [
'items' => [
'bold',
'italic',
'drupalInsertImage',
],
],
'plugins' => [
'ckeditor5_heading' => [
'enabled_headings' => [
'heading2',
'heading3',
'heading4',
'heading5',
'heading6',
],
],
],
],
'image_upload' => [
'status' => FALSE,
],
])->save();
}
/**
* Tests that the media swapper button appears in CKEditor toolbar.
*
* @throws \Drupal\Core\Entity\EntityStorageException
* @throws \Drupal\Core\Entity\EntityMalformedException|\Behat\Mink\Exception\ElementNotFoundException
*/
/**
* Helper method to create a test node with CKEditor body field.
*
* @return \Drupal\node\Entity\Node
* The created node.
*/
protected function createTestNode(): Node {
$node = Node::create([
'type' => 'page',
'title' => 'Test Node',
'uid' => $this->authorUser->id(),
'status' => 1,
'body' => [
[
'value' => '<p>Test content</p>',
'format' => 'ckeditor5',
'summary' => '',
],
],
]);
$node->save();
return $node;
}
/**
* Helper method to insert an image into CKEditor using JavaScript.
*
* @param array $attributes
* Image attributes to set.
*/
protected function insertImageIntoEditor(array $attributes): void {
$attrs_js = json_encode($attributes);
$script = <<<JS
(function() {
const editorId = Object.keys(Drupal.CKEditor5Instances)[0];
if (!editorId) {
throw new Error('No CKEditor5 instances found');
}
const editor = Drupal.CKEditor5Instances[editorId];
editor.model.change(writer => {
const imageBlock = writer.createElement('imageBlock', {$attrs_js});
const root = editor.model.document.getRoot();
writer.insert(imageBlock, root, 'end');
});
})();
JS;
$this->getSession()->getDriver()->getWebDriverSession()->execute([
'script' => $script,
'args' => [],
]);
// Wait for image to appear in the editor.
$this->assertSession()->waitForElement('css', '.ck-editor__editable img', 10000);
}
/**
* Helper method to safely click confirm button with proper waits.
*
* @param string $selector
* CSS selector for the button to click.
*/
protected function clickConfirmButton(string $selector = '.confirm-yes'): void {
// First wait for the confirm container to exist with timeout.
$container = $this->assertSession()->waitForElement('css', '.custom-confirm-container', 10000);
$this->assertNotNull($container, 'Confirm dialog container should appear');
// Wait for the specific button to be visible and clickable.
$confirm_button = $this->assertSession()->waitForElementVisible('css', $selector, 5000);
// If the specific selector not found, try fallback buttons in order.
if (!$confirm_button) {
$possible_selectors = ['.confirm-yes', '.confirm-no', '.custom-confirm-box button'];
foreach ($possible_selectors as $fallback_selector) {
$confirm_button = $this->assertSession()->waitForElementVisible('css', $fallback_selector, 2000);
if ($confirm_button) {
break;
}
}
}
$this->assertNotNull($confirm_button, 'No clickable button found in confirm dialog. Tried selector: ' . $selector);
// Ensure the button is actually clickable before clicking.
$this->assertTrue($confirm_button->isVisible(), 'Button should be visible before clicking');
$confirm_button->click();
}
/**
* Tests that the media swapper button exists in the CKEditor toolbar.
*/
public function testMediaSwapperButtonExists(): void {
// Debug: Check current user permissions.
$current_user = \Drupal::currentUser();
$user_permissions = [];
if ($current_user->isAuthenticated()) {
$user_permissions = $current_user->getAccount()->getRoles();
}
// Create and visit test node.
$node = $this->createTestNode();
// Debug: Check node details.
if (!$node->id()) {
$this->fail('Node was not saved properly - no ID found');
}
// Debug: Try to load the node to make sure it exists.
$loaded_node = Node::load($node->id());
if (!$loaded_node) {
$this->fail('Created node could not be loaded from database');
}
$edit_url = $node->toUrl('edit-form')->toString();
$this->drupalGet($edit_url);
// Debug: Check what page we actually landed on.
$page = $this->getSession()->getPage();
$current_url = $this->getSession()->getCurrentUrl();
$page_title = $page->find('css', 'title')?->getText() ?? 'No title';
$page_h1 = $page->find('css', 'h1')?->getText() ?? 'No H1';
// Check for any error messages.
$error_messages = $page->findAll('css', '.messages--error');
$errors = [];
foreach ($error_messages as $error) {
$errors[] = $error->getText();
}
if (!empty($errors)) {
$this->fail('Page has error messages: ' . implode('; ', $errors) . '. URL: ' . $current_url);
}
// Check if we got redirected (common for permission issues)
if (strpos($current_url, '/edit') === FALSE) {
$this->fail("Got redirected away from edit form. Current URL: $current_url, Page title: $page_title, H1: $page_h1, User roles: " . implode(', ', $user_permissions));
}
// Debug: Let's see what fields are actually available on the page.
$form_elements = $page->findAll('css', 'input, textarea, select');
$available_fields = [];
foreach ($form_elements as $element) {
$name = $element->getAttribute('name');
$id = $element->getAttribute('id');
if ($name) {
$available_fields[] = "name: $name";
}
if ($id) {
$available_fields[] = "id: $id";
}
}
if (empty($available_fields)) {
// Get more info about the page content.
$page_content_sample = substr($page->getText(), 0, 500);
$this->fail("No form fields found. URL: $current_url, Title: $page_title, H1: $page_h1, Content sample: $page_content_sample");
}
// Try different possible body field selectors.
$possible_selectors = [
'body[0][value]',
'edit-body-0-value',
'body',
'edit-body',
'.field--name-body textarea',
'textarea[data-drupal-selector="edit-body-0-value"]',
];
$body_field = NULL;
foreach ($possible_selectors as $selector) {
try {
if (strpos($selector, '.') === 0 || strpos($selector, '[') !== FALSE) {
// CSS selector.
$body_field = $page->find('css', $selector);
}
else {
// Field name.
$body_field = $page->findField($selector);
}
if ($body_field) {
break;
}
}
catch (\Exception $e) {
// Continue trying other selectors.
}
}
if (!$body_field) {
$this->fail('Body field not found. Available fields: ' . implode(', ', array_slice($available_fields, 0, 20)));
}
// Debug: Check what text format selector is present.
$format_selector = $page->find('css', 'select[data-drupal-selector="edit-body-0-format--2"]');
if (!$format_selector) {
$format_selector = $page->find('css', 'select[name="body[0][format]"]');
}
if ($format_selector) {
$selected_format = $format_selector->getValue();
$available_options = [];
$options = $format_selector->findAll('css', 'option');
foreach ($options as $option) {
$available_options[] = $option->getValue() . ':' . $option->getText();
}
if ($selected_format !== 'ckeditor5') {
$this->fail("Wrong text format selected. Current: '$selected_format', Available: " . implode(', ', $available_options));
}
}
else {
$this->fail('No text format selector found - this suggests the field is not configured for multiple formats');
}
// Debug: Check if CKEditor instances are being created.
$script = "return typeof Drupal.CKEditor5Instances !== 'undefined' ? Object.keys(Drupal.CKEditor5Instances).length : 'undefined';";
$instances_count = $this->getSession()->evaluateScript($script);
// Wait for CKEditor to initialize.
$assert_session = $this->assertSession();
$editor_element = $assert_session->waitForElement('css', '.ck-editor', 15000);
if (!$editor_element) {
$this->fail("CKEditor (.ck-editor) element not found. CKEditor5 instances: $instances_count");
}
// Debug: Check what elements are actually present.
$ck_elements = $page->findAll('css', '[class*="ck-"]');
$ck_classes = [];
foreach (array_slice($ck_elements, 0, 10) as $element) {
$ck_classes[] = $element->getAttribute('class');
}
// First verify CKEditor basic functionality works.
$toolbar = $this->assertSession()
->waitForElement('css', '.ck-toolbar', 10000);
if (!$toolbar) {
$this->fail("CKEditor toolbar not found. CK elements found: " . implode(', ', $ck_classes));
}
// Debug: Check what buttons are actually in the toolbar.
$toolbar_buttons = $toolbar->findAll('css', '.ck-button');
$button_tooltips = [];
foreach ($toolbar_buttons as $button) {
$tooltip = $button->getAttribute('data-cke-tooltip-text');
if ($tooltip) {
$button_tooltips[] = $tooltip;
}
}
// Check for basic buttons to ensure editor is working.
$bold_button = $this->assertSession()
->waitForElement('css', '.ck-toolbar .ck-button[data-cke-tooltip-text="Bold"]', 5000);
if (!$bold_button) {
$this->fail("Bold button not found. Available buttons: " . implode(', ', $button_tooltips));
}
}
/**
* Tests that clicking the media swapper button works.
*/
public function testMediaSwapperButtonClick(): void {
// Create a test node.
$node = Node::create([
'type' => 'page',
'title' => 'Test Node',
'body' => [
'value' => '<p>Test content</p>',
'format' => 'ckeditor5',
],
]);
$node->save();
// Visit the node edit page.
$this->drupalGet($node->toUrl('edit-form'));
// Wait for CKEditor to initialize.
$this->waitForEditor();
// Insert a simple image for testing.
$file_uri = $this->testFile->getFileUri();
$image_url = \Drupal::service('file_url_generator')
->generateAbsoluteString($file_uri);
// Use the WebDriver session execute method like core tests.
$script = <<<JS
(function() {
const editorId = Object.keys(Drupal.CKEditor5Instances)[0];
const editor = Drupal.CKEditor5Instances[editorId];
editor.model.change(writer => {
const imageBlock = writer.createElement('imageBlock', {
dataEntityType: 'file',
dataEntityUuid: '{$this->testFile->uuid()}',
src: '{$image_url}',
alt: 'Test image'
});
const root = editor.model.document.getRoot();
writer.insert(imageBlock, root, 'end');
});
})();
JS;
$this->getSession()->getDriver()->getWebDriverSession()->execute([
'script' => $script,
'args' => [],
]);
// Wait for the image to appear.
$this->assertSession()->waitForElement('css', '.ck-editor__editable img');
// Click on the image to select it using more reliable method.
$image = $this->assertSession()->waitForElementVisible('css', '.ck-editor__editable img');
$this->assertNotNull($image, 'Image should be visible in editor');
$image->click();
$this->assertSession()->waitForElement('css', '.ck-widget.ck-widget_selected');
// Find and click the media swapper button with better waiting.
$button = $this->assertSession()->waitForElement('css', '.ck-toolbar .ck-button[data-cke-tooltip-text="Convert to Media"]');
$this->assertNotNull($button, 'Media Swapper button should be present');
$button->click();
// A custom dialog should appear asking to convert the image.
$this->assertSession()->waitForElement('css', '.custom-confirm-container');
$this->assertSession()
->elementTextContains('css', '.custom-confirm-box p', 'Convert this file-based image to a media entity?');
// Click the "Yes" button to accept the dialog.
$this->clickConfirmButton();
// Wait for dialog to disappear with timeout.
$this->assertSession()
->waitForElementRemoved('css', '.custom-confirm-container', 10000);
}
/**
* Tests that media swapper shows error for external images.
*
* @throws \Drupal\Core\Entity\EntityMalformedException
* @throws \Behat\Mink\Exception\ElementNotFoundException
* @throws \Drupal\Core\Entity\EntityStorageException|\Behat\Mink\Exception\ElementTextException
* @throws \Behat\Mink\Exception\ExpectationException
*/
public function testMediaSwapperWithExternalImage(): void {
// Create a test node.
$node = Node::create([
'type' => 'page',
'title' => 'Test Node',
'body' => [
'value' => '<p>Test content</p>',
'format' => 'ckeditor5',
],
]);
$node->save();
// Visit the node edit page.
$this->drupalGet($node->toUrl('edit-form'));
// Wait for CKEditor to initialize.
$this->waitForEditor();
// Insert an external image (no file entity attributes).
$script = <<<JS
(function() {
const editorId = Object.keys(Drupal.CKEditor5Instances)[0];
const editor = Drupal.CKEditor5Instances[editorId];
editor.model.change(writer => {
const imageBlock = writer.createElement('imageBlock', {
src: 'https://example.com/external-image.jpg',
alt: 'External image'
});
const root = editor.model.document.getRoot();
writer.insert(imageBlock, root, 'end');
});
})();
JS;
$this->getSession()->getDriver()->getWebDriverSession()->execute([
'script' => $script,
'args' => [],
]);
// Wait for the image to appear and click it.
$this->assertSession()->waitForElement('css', '.ck-editor__editable img');
$image = $this->assertSession()->waitForElement('css', '.ck-editor__editable img');
$this->assertNotNull($image, 'Image should be present');
$image->click();
$this->getSession()->wait(500);
// Click the media swapper button - should show error.
$button = $this->assertSession()->waitForElement('css', '.ck-toolbar .ck-button[data-cke-tooltip-text="Convert to Media"]');
$this->assertNotNull($button, 'Media swapper button should be present');
$button->click();
// Wait a bit for the API call to complete and error dialog to appear.
$this->getSession()->wait(1000);
// Verify error dialog appears.
$this->assertSession()->waitForElement('css', '.custom-confirm-container');
// Get the text of the error message.
$this->assertSession()->elementExists('css', '.custom-confirm-box p');
$this->assertSession()
->elementTextContains('css', '.custom-confirm-box p', 'Convert this file-based image to a media entity?');
// Click "Yes" to proceed with conversion.
$this->clickConfirmButton();
// Wait for dialog to disappear.
$this->assertSession()
->waitForElementRemoved('css', '.custom-confirm-container');
// Wait a bit for the API call to complete and error dialog to appear.
$this->getSession()->wait(1000);
// An error dialog should appear after the API call fails.
$this->assertSession()->waitForElement('css', '.custom-confirm-container');
}
/**
* Tests that media swapper shows error for untracked images.
*
* @throws \Drupal\Core\Entity\EntityMalformedException
* @throws \Behat\Mink\Exception\ElementNotFoundException
* @throws \Drupal\Core\Entity\EntityStorageException|\Behat\Mink\Exception\ElementTextException
* @throws \Behat\Mink\Exception\ExpectationException
*/
public function testMediaSwapperWithUntrackedImage(): void {
// Create a test node.
$node = Node::create([
'type' => 'page',
'title' => 'Test Node',
'body' => [
'value' => '<p>Test content</p>',
'format' => 'ckeditor5',
],
]);
$node->save();
// Visit the node edit page.
$this->drupalGet($node->toUrl('edit-form'));
// Wait for CKEditor to initialize.
$this->waitForEditor();
// Insert a simple image for testing.
$file_uri = $this->testFile->getFileUri();
$image_url = \Drupal::service('file_url_generator')
->generateAbsoluteString($file_uri);
$script = <<<JS
(function() {
const editorId = Object.keys(Drupal.CKEditor5Instances)[0];
const editor = Drupal.CKEditor5Instances[editorId];
editor.model.change(writer => {
const imageBlock = writer.createElement('imageBlock', {
src: '{$image_url}',
alt: 'Untracked image'
});
const root = editor.model.document.getRoot();
writer.insert(imageBlock, root, 'end');
});
})();
JS;
$this->getSession()->getDriver()->getWebDriverSession()->execute([
'script' => $script,
'args' => [],
]);
// Wait for the image to appear and click it.
$this->assertSession()->waitForElement('css', '.ck-editor__editable img');
$image = $this->getSession()
->getPage()
->find('css', '.ck-editor__editable img');
$image->click();
$this->getSession()->wait(500);
// Click the media swapper button - should show error.
$button = $this->getSession()
->getPage()
->find('css', '.ck-toolbar .ck-button[data-cke-tooltip-text="Convert to Media"]');
$button->click();
// Wait a bit for the API call to complete and error dialog to appear.
$this->getSession()->wait(1000);
// Verify error dialog appears.
$this->assertSession()->waitForElement('css', '.custom-confirm-container');
// Get the text of the error message.
$this->assertSession()->elementExists('css', '.custom-confirm-box p');
$this->assertSession()
->elementTextContains('css', '.custom-confirm-box p', 'Convert this file-based image to a media entity?');
}
/**
* Tests that media swapper works with valid remote files.
*
* @throws \Drupal\Core\Entity\EntityMalformedException
* @throws \Drupal\Core\Entity\EntityStorageException
* @throws \Behat\Mink\Exception\ElementNotFoundException
*/
public function testMediaSwapperWithValidRemoteFile(): void {
// Create a test node.
$node = Node::create([
'type' => 'page',
'title' => 'Test Node',
'body' => [
'value' => '<p>Test content</p>',
'format' => 'ckeditor5',
],
]);
$node->save();
// Visit the node edit page.
$this->drupalGet($node->toUrl('edit-form'));
// Wait for CKEditor to initialize.
$this->waitForEditor();
// Insert a remote image using a reliable placeholder service.
$remote_image_url = 'https://via.placeholder.com/300x200.jpg';
$script = <<<JS
(function() {
const editorId = Object.keys(Drupal.CKEditor5Instances)[0];
const editor = Drupal.CKEditor5Instances[editorId];
editor.model.change(writer => {
const imageBlock = writer.createElement('imageBlock', {
src: '{$remote_image_url}',
alt: 'Remote test image'
});
const root = editor.model.document.getRoot();
writer.insert(imageBlock, root, 'end');
});
})();
JS;
$this->getSession()->getDriver()->getWebDriverSession()->execute([
'script' => $script,
'args' => [],
]);
// Wait for the image to appear and click it.
$this->assertSession()->waitForElement('css', '.ck-editor__editable img');
$image = $this->getSession()
->getPage()
->find('css', '.ck-editor__editable img');
$image->click();
$this->getSession()->wait(500);
// Click the media swapper button.
$button = $this->getSession()
->getPage()
->find('css', '.ck-toolbar .ck-button[data-cke-tooltip-text="Convert to Media"]');
$this->assertNotNull($button, 'Media Swapper button should be present');
$button->click();
// Verify confirmation dialog appears.
$this->assertSession()->waitForElement('css', '.custom-confirm-container');
$this->assertSession()
->elementTextContains('css', '.custom-confirm-box p', 'Convert this file-based image to a media entity?');
// Click "Yes" to proceed with conversion.
$this->clickConfirmButton();
// Wait for dialog to disappear.
$this->assertSession()
->waitForElementRemoved('css', '.custom-confirm-container');
// Note: This test verifies the UI interaction. The actual API call
// to /media-api/swap-file-to-media/remote-uri would need to be mocked
// or implemented in the test environment to test the full workflow.
}
/**
* Test that clicking confirm-no leaves the content unchanged.
*
* @throws \Drupal\Core\Entity\EntityMalformedException
* @throws \Drupal\Core\Entity\EntityStorageException
* @throws \Behat\Mink\Exception\ElementNotFoundException|\Behat\Mink\Exception\ElementTextException
*/
public function testMediaSwapperConfirmNo(): void {
// Create a test node.
$node = Node::create([
'type' => 'page',
'title' => 'Test Node',
'body' => [
'value' => '<p>Test content</p>',
'format' => 'ckeditor5',
],
]);
$node->save();
// Visit the node edit page.
$this->drupalGet($node->toUrl('edit-form'));
// Wait for CKEditor to initialize.
$this->waitForEditor();
// Insert a simple image for testing.
$file_uri = $this->testFile->getFileUri();
$image_url = \Drupal::service('file_url_generator')
->generateAbsoluteString($file_uri);
$script = <<<JS
(function() {
const editorId = Object.keys(Drupal.CKEditor5Instances)[0];
const editor = Drupal.CKEditor5Instances[editorId];
editor.model.change(writer => {
const imageBlock = writer.createElement('imageBlock', {
dataEntityType: 'file',
dataEntityUuid: '{$this->testFile->uuid()}',
src: '{$image_url}',
alt: 'Test image'
});
const root = editor.model.document.getRoot();
writer.insert(imageBlock, root, 'end');
});
})();
JS;
$this->getSession()->getDriver()->getWebDriverSession()->execute([
'script' => $script,
'args' => [],
]);
// Wait for the image to appear.
$this->assertSession()->waitForElement('css', '.ck-editor__editable img');
// Click on the image to select it.
$image = $this->getSession()
->getPage()
->find('css', '.ck-editor__editable img');
$image->click();
$this->getSession()->wait(500);
// Find and click the media swapper button.
$button = $this->getSession()
->getPage()
->find('css', '.ck-toolbar .ck-button[data-cke-tooltip-text="Convert to Media"]');
$this->assertNotNull($button, 'Media Swapper button should be present');
// Click the media swapper button.
$button->click();
// A custom dialog should appear asking to convert the image.
$this->assertSession()->waitForElement('css', '.custom-confirm-container');
// Click the "No" button to cancel conversion.
$this->assertSession()->elementExists('css', '.custom-confirm-box p');
$this->assertSession()
->elementTextContains('css', '.custom-confirm-box p', 'Convert this file-based image to a media entity?');
$this->getSession()->getPage()->find('css', '.confirm-no')->click();
// Wait for dialog to disappear.
$this->assertSession()
->waitForElementRemoved('css', '.custom-confirm-container');
// Verify the image is still present in the editor.
$this->assertSession()->elementExists('css', '.ck-editor__editable img');
}
}
