Skip to content

Commit

Permalink
Support Ckeditor 4 - 5 for web driver support javascript.
Browse files Browse the repository at this point in the history
  • Loading branch information
tannguyen04 committed Dec 28, 2023
1 parent 8bb402f commit a92b539
Showing 1 changed file with 28 additions and 40 deletions.
68 changes: 28 additions & 40 deletions src/WysiwygTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,65 +28,53 @@ public function wysiwygFillField(string $field, string $value): void {

$page = $this->getSession()->getPage();
$element = $page->findField($field);

if ($element === NULL) {
throw new ElementNotFoundException($this->getSession()->getDriver(), 'form field', 'id|name|label|value|placeholder', $field);
}

$driver = $this->getSession()->getDriver();
try {
$driver->evaluateScript('true');
$driver->evaluateScript(TRUE);
}
catch (UnsupportedDriverActionException $exception) {
// For non-JS drivers process field in a standard way.
$element->setValue($value);

return;
}

// For a JS-capable driver, try to find WYSIWYG iframe as a child of the
// following sibling.
$iframe_xpath = $element->getXpath() . "/following-sibling::div[contains(@class, 'cke')]//iframe";
$page_iframe_elements = $driver->find($iframe_xpath);
if (empty($page_iframe_elements[0])) {
throw new ElementNotFoundException($this->getSession()->getDriver(), 'WYSIWYG form field', 'id|name|label|value|placeholder', $field);
$fieldId = $element->getAttribute('id');
if (empty($fieldId)) {
throw new ElementNotFoundException($this->getSession()->getDriver());
}

$iframe_element = reset($page_iframe_elements);

// @note: Selenium's frame() expects frame id as an HTML element "id"
// attribute value or as an 0-based index of the iframe on the page.
// WYSIWYG iframe does not contain HTML "id" attribute, so we need to find
// the index of the iframe on the page.
//
// Find all iframes on the page.
$page_iframe_elements = $driver->find('//iframe');
$parent_element = $element->getParent();

// Filter all iframes by finding parent WYSIWYG wrapper and comparing the
// iframe element being filtered to the found per-field iframe element from
// above.
// Note that, at this point, we are guaranteed to find at least one matching
// iframe element as an exception would be thrown otherwise.
$index = 0;
foreach ($page_iframe_elements as $page_iframe_element) {
$wrapper_xpath = $page_iframe_element->getXpath() . "/ancestor::div[contains(@class, 'cke')]";
$found_wrappers = $driver->find($wrapper_xpath);
if (!empty($found_wrappers) && $page_iframe_element->getOuterHtml() == $iframe_element->getOuterHtml()) {
break;
}
$index++;
}

// Select WYSIWYG iframe frame.
$driver->switchToIFrame((string) $index);
// Support Ckeditor 4.
$is_ckeditor_4 = !empty($driver->find($parent_element->getXpath() . "/div[contains(@class,'cke')]"));
if ($is_ckeditor_4) {
$this->getSession()
->executeScript("CKEDITOR.instances[\"$fieldId\"].setData(\"$value\");");

// Type value as keys into 'body' of iframe.
foreach (str_split($value) as $char) {
$this->keyboardTriggerKey('//body', $char);
return;
}

// Reset frame to the default window.
$driver->switchToIFrame(NULL);
// Support Ckeditor 5.
$ckeditor_5_element_selector = ".{$parent_element->getAttribute('class')} .ck-editor__editable";
$this->getSession()
->executeScript(
"
const domEditableElement = document.querySelector(\"$ckeditor_5_element_selector\");
if (domEditableElement.ckeditorInstance) {
const editorInstance = domEditableElement.ckeditorInstance;
if (editorInstance) {
editorInstance.setData(\"$value\");
} else {
throw new Exception('Could not get the editor instance!');
}
} else {
throw new Exception('Could not find the element!');
}
");
}

/**
Expand Down

0 comments on commit a92b539

Please sign in to comment.