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.
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()
Comments: