Create a CKEditor element for webdriver with python

Recently, while writing some automated tests for Examiner.com, I ran into some issues with CKEditor. We use CKEditor as the default wysiwyg editor on the site. When you configure CKEditor you attach it to a normal textarea element that is then hidden and replaced by the CKEditor field. In this post I will demonstrate how I implemented an custom element class to interact with CKEditor as if it were any other field. When you enable CKEditor, it is attached to a textarea element and you html structure will look something like this:

1
2
3
4
<textarea id="editor1" style="display:none"></textarea>
<span id="cke_editor1">
...
</span>

The text area is disabled and CKEditor adds the code for the editor. Conveniently, every editor’s id property will begin with ‘cke_’ followed by the CKEditor instance. You can interact with a CKEeditor instance using javascript. Let’s look at an example on ckeditor’s demo website. Go to http://ckeditor.com/demo and (assuming you use Firefox with the Firebug extension) open the Firebug console and enter the following javascript:

1
CKEDITOR.instances['editor1'].setData('Hello World!');

You should see “Hello World!” replace the existing text in the wysiwyg editor.

Hello World

Now all we need to do is create a CKEditor object for webdriver. We will recreate the clear(), send_keys() methods and the text property that are standard to other webelements.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
from selenium.webdriver.remote.command import Command
 
class Ckeditor(object):
  ## Constructor.
  #
  # @param webelement The span or div webelement containing the ckeditor field.
  def __init__(self, webelement):
    self.element = webelement
    # Strip 'cke_' to get the CKEditor instance id.
    self.id = webelement.get_attribute('id')[4:]
 
  # Execute a command against CKEditor.
  def execute(self, method, *args):
    if len(args) > 0:
      converted_args = "'" + "', '".join(args) + "'"
    else:
      converted_args = ''
    script = "return CKEDITOR.instances['%s'].%s(%s);" % (self.id, method, converted_args)
    return self.element._execute(Command.EXECUTE_SCRIPT, {'script':script})['value']
 
  # Clear the field.
  def clear(self):
    return self.execute('setData', '')
 
  # Enter a value into the field.
  def send_keys(self, value):
    return self.execute('setData', value)
 
  # Retrieve the current value of the field
  @property
  def text(self):
    return self.execute('getData')

Now you can use this within a Selenium Webdriver script just like you would any other element.

1
2
3
4
5
6
7
8
9
10
11
12
#!/usr/bin/python
 
from webdriver import Firefox
from selenium.webdriver.common.by import By
 
driver = Firefox()
driver.get('www.ckeditor.com/demo')
cke_element = Ckeditor(driver.find_element(By.id, 'cke_editor1'))
cke_element.clear()
cke_element.send_keys('Hello World!')
print cke_element.text
driver.quit()
Tweet

Comments:

Subscribe & Contact

Know how to listen, and you will profit even from those who talk badly.
~ Plutarch ~