Search

Just Another Tech Blog

A mind is like a parachute. It doesn't work if it is not open.

Category

Automation

How To Add Robot Framework Syntax in Sublime Text and VIM editor


By default, files for the Robot Framework do not show any syntax on Sublime Text or VIM, with some tweaks we can add Robot Framework syntax.

For Sublime Text 2:

Open Sublime Text 2 and click Preferences -> Browse Packages to open the packages directory. Then create a directory named Robot Framework containing the contents of the following repository:

https://github.com/seeamkhan/sublime-robot-plugin

Note: The contents of the repository should be directly under the Robot Framework directory.

Now close the Sublime Text 2 editor if it’s already been opened and then open a file with Robot Framework syntax, the syntax should be now visible like below:

Selection_012

For VIM Text Editor:

Clone the git repository in any place:

git clone https://github.com/seeamkhan/robotframework-vim

Go to the content directory:

cd robotframework-vim

Make sure the directory ~/.vim/ already exist for the current user, if not then create the directory:

mkdir ~/.vim

Now copy all the contents to ~/.vim/ location:

cp -R * ~/.vim/

Now open any files with Robot Framework syntax in the VIM editor, the syntax should be visible like below:

Selection_014

Prepare CentOS 6.x or 7.x Server for Selenium


We need to install the following things in the server to run the Python test scripts after WordPress auto update:

  1. Need to be installed Python 2.6.x or 2.7.x
  2. Install WP CLI, see detail: http://wp-cli.org/
  3. Install pip:For RHEL 6.x and CentOS 6.x (x86_64)
    rpm -ivh http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm

    For RHEL 6.x and CentOS 6.x (i386)

    rpm -ivh http://dl.fedoraproject.org/pub/epel/6/i386/epel-release-6-8.noarch.rpm

    Now install pip with yum command:

    yum install -y python-pip

    If you can not install pip be following the above steps then try the below steps:

    curl "https://bootstrap.pypa.io/get-pip.py" -o "get-pip.py"
    python get-pip.py
    
  4. Install Selenium:
    pip install selenium
    
  5. Install python-detenv:
    pip install python-dotenv
    
  6. Install python requests library:

    pip install requests
  7. Download Phantomjsfrom:http://phantomjs.org/download.html
  8. Copy Phantomjs to /usr/local/share/:
    cp -f phantomjs /usr/local/share/phantomjs

    Note: Keep the phantomjs nonexecutable while the wp-auto-update will run the script will make it executable and make it nonexecutable once it’s done.

  9. Make symlinks of Phantomjs:
    ln -s /usr/local/share/phantomjs /usr/local/bin/phantomjs
    ln -s /usr/local/share/phantomjs /usr/bin/phantomjs
    
  10. Install additional dependency for Phantomjs:
    yum install freetype
    yum install fontconfig

XPath in Selenium WebDriver: Complete Tutorial


In Selenium automation, if the elements are not found by the general locators like id, class, name, etc. then XPath is used to find an element on the web page .

In this tutorial, we will learn about the xpath and different XPath expression to find the complex or dynamic elements, whose attributes changes dynamically on refresh or any operations.

What is XPath

XPath is defined as XML path. It is a syntax or language for finding any element on the web page using XML path expression. XPath is used to find the location of any element on a webpage using HTML DOM structure. The basic format of XPath is explained below with screen shot.

XPath in Selenium WebDriver: Complete Tutorial

Syntax for XPath:

XPath contains the path of the element situated at the web page. Standard syntax for creating XPath is.

Xpath=//tagname[@attribute='value']
  • // : Select current node.
  • Tagname: Tagname of the particular node.
  • @: Select attribute.
  • Attribute: Attribute name of the node.
  • Value: Value of the attribute.

To find the element on web pages accurately there are different types of locators:

XPath Locators Find different elements on web page
ID To find the element by ID of the element
Classname To find the element by Classname of the element
Name To find the element by name of the element
Link text To find the element by text of the link
XPath XPath required for finding the dynamic element and traverse between various elements of the web page
CSS path CSS path also locates elements having no name, class or ID.

Types of X-path

There are two types of XPath:

1) Absolute XPath .

2) Relative XPath .

Absolute XPath :

It is the direct way to find the element, but the disadvantage of the absolute XPath is that if there are any changes made in the path of the element then that XPath gets failed.

The key characteristic of XPath is that it begins with the single forward slash(/) ,which means you can select the element from the root node.

Below is the example of an absolute xpath expression of the element shown in the below screen.

Absolute xpath:

html/body/div[1]/section/div[1]/div/div/div/div[1]/div/div/div/div/div[3]/div[1]/div/h4[1]/b

XPath in Selenium WebDriver: Complete Tutorial

Relative xpath:

For Relative Xpath the path starts from the middle of the HTML DOM structure. It starts with the double forward slash (//), which means it can search the element anywhere at the webpage.

You can starts from the middle of the HTML DOM structure and no need to write long xpath.

Below is the example of a relative XPath expression of the same element shown in the below screen. This is the common format used to find element through a relative XPath.

Relative xpath: //*[@class='featured-box']//*[text()='Testing']

XPath in Selenium WebDriver: Complete Tutorial

What are XPath axes.

XPath axes search different nodes in XML document from current context node. XPath Axes are the methods used to find dynamic elements, which otherwise not possible by normal XPath method having no ID , Classname, Name, etc.

Axes methods are used to find those elements, which dynamically change on refresh or any other operations. There are few axes methods commonly used in Selenium Webdriver like child, parent, ancestor, sibling, preceding, self, etc.

Using XPath Handling complex & Dynamic elements in Selenium

1) Basic XPath:

XPath expression select nodes or list of nodes on the basis of attributes like ID , Name, Classname, etc. from the XML document as illustrated below.

Xpath=//input[@name='uid']

Here is a link to access the page http://demo.guru99.com/v1/

XPath in Selenium WebDriver: Complete Tutorial

Some more basic xpath expressions:

Xpath=//input[@type='text']				
Xpath=	//label[@id='message23']
Xpath=	//input[@value='RESET']
Xpath=//*[@class='barone']
Xpath=//a[@href='http://demo.guru99.com/']
Xpath= //img[@src='//cdn.guru99.com/images/home/java.png']

2) Contains() : Contains() is a method used in XPath expression. It is used when the value of any attribute changes dynamically, for example, login information.

The contain feature has an ability to find the element with partial text as shown in below example.

In this example, we tried to identify the element by just using partial text value of the attribute. In the below XPath expression partial value ‘sub’ is used in place of submit button. It can be observed that the element is found successfully.

Complete value of ‘Type’ is ‘submit’ but using only partial value ‘sub’.

Xpath=//*[contains(@type,'sub')]

Complete value of ‘name’ is ‘btnLogin’ but using only partial value ‘btn’.

Xpath=.//*[contains(@name,'btn')]

In the above expression, we have taken the ‘name’ as an attribute and ‘btn’ as an partial value as shown in the below screenshot. This will find 2 elements (LOGIN & RESET) as their ‘name’ attribute begins with ‘btn’.

XPath in Selenium WebDriver: Complete Tutorial

Similarly, in the below expression, we have taken the ‘id’ as an attribute and ‘message’ as a partial value. This will find 2 elements (‘User-ID must not be blank’ & ‘Password must not be blank’) as its ‘name’ attribute begins with ‘message’.

Xpath=//*[contains(@id,'message')]

XPath in Selenium WebDriver: Complete Tutorial

In the below expression, we have taken the “text” of the link as an attribute and ‘here’ as a partial value as shown in the below screenshot. This will find the link (‘here’) as it displays the text ‘here’.

Xpath=//*[contains(text(),'here')]
Xpath=//*[contains(@href,'guru99.com')]

XPath in Selenium WebDriver: Complete Tutorial

3) Using OR & AND:

In OR expression, two conditions are used, whether 1st condition OR 2nd condition should be true. It is also applicable if any one condition is true or maybe both. Means any one condition should be true to find the element.

In the below XPath expression, it identifies the elements whose single or both conditions are true.

Xpath=//*[@type='submit' OR @name='btnReset']

Highlighting both elements as “LOGIN ” element having attribute ‘type’ and “RESET” element having attribute ‘name’.

XPath in Selenium WebDriver: Complete Tutorial

In AND expression, two conditions are used, both conditions should be true to find the element. It fails to find element if any one condition is false.

Xpath=//input[@type='submit' AND @name='btnLogin']

In below expression, highlighting ‘LOGIN’ element as it having both attribute ‘type’ and ‘name’.

XPath in Selenium WebDriver: Complete Tutorial

4) Start-with function: Start-with function finds the element whose attribute value changes on refresh or any operation on the webpage. In this expression, match the starting text of the attribute is used to find the element whose attribute changes dynamically. You can also find the element whose attribute value is static (not changes).

For example -: Suppose the ID of particular element changes dynamically like:

Id=” message12″

Id=” message345″

Id=” message8769″

and so on.. but the initial text is same. In this case, we use Start-with expression.

In the below expression, there are two elements with an id starting “message”(i.e., ‘User-ID must not be blank’ & ‘Password must not be blank’). In below example, XPath finds those element whose ‘ID’ starting with ‘message’.

Xpath=//label[starts-with(@id,'message')]

XPath in Selenium WebDriver: Complete Tutorial

5) Text(): In this expression, with text function, we find the element with exact text match as shown below. In our case, we find the element with text “UserID”.

Xpath=//td[text()='UserID']

XPath in Selenium WebDriver: Complete Tutorial

6) XPath axes methods: These XPath axes methods are used to find the complex or dynamic elements. Below we will see some of these methods.

For illustrating these XPath axes method, we will use the Guru99 bank demo site.

a) Following: Selects all elements in the document of the current node( ) [ UserID input box is the current node] as shown in the below screen.

Xpath=//*[@type='text']//following::input

XPath in Selenium WebDriver: Complete Tutorial

There are 3 “input” nodes matching by using “following” axis- password, login and reset button. If you want to focus on any particular element then you can use the below XPath method:

Xpath=//*[@type='text']//following::input[1]

You can change the XPath according to the requirement by putting [1],[2]…………and so on.

With the input as ‘1’, the below screen shot finds the particular node that is ‘Password’ input box element.

XPath in Selenium WebDriver: Complete Tutorial

b) Ancestor: The ancestor axis selects all ancestors element (grandparent, parent, etc.) of the current node as shown in the below screen.

In the below expression, we are finding ancestors element of the current node(“ENTERPRISE TESTING” node).

Xpath=//*[text()='Enterprise Testing']//ancestor::div

XPath in Selenium WebDriver: Complete Tutorial

There are 13 “div” nodes matching by using “ancestor” axis. If you want to focus on any particular element then you can use the below XPath, where you change the number 1, 2 as per your requirement:

Xpath=//*[text()='Enterprise Testing']//ancestor::div[1]

You can change the XPath according to the requirement by putting [1], [2]…………and so on.

c) Child : Selects all children elements of the current node (Java) as shown in the below screen.

Xpath=//*[@id='java_technologies']/child::li

XPath in Selenium WebDriver: Complete Tutorial

There are 71 “li” nodes matching by using “child” axis. If you want to focus on any particular element then you can use the below xpath:

Xpath=//*[@id='java_technologies']/child::li[1]

You can change the xpath according to the requirement by putting [1],[2]…………and so on.

d) Preceding: Select all nodes that come before the current node as shown in the below screen.

In the below expression, it identifies all the input elements before “LOGIN” button that is Userid and password input element.

Xpath=//*[@type='submit']//preceding::input

XPath in Selenium WebDriver: Complete Tutorial

There are 2 “input” nodes matching by using “preceding” axis. If you want to focus on any particular element then you can use the below XPath:

Xpath=//*[@type='submit']//preceding::input[1]

You can change the xpath according to the requirement by putting [1],[2]…………and so on.

e) Following-sibling: Select the following siblings of the context node. Siblings are at the same level of the current node as shown in the below screen. It will find the element after the current node.

 xpath=//*[@type='submit']//following-sibling::input

XPath in Selenium WebDriver: Complete Tutorial

One input nodes matching by using “following-sibling” axis.

f) Parent: Selects the parent of the current node as shown in the below screen.

Xpath=//*[@id='rt-feature']//parent::div

XPath in Selenium WebDriver: Complete Tutorial

There are 65 “div” nodes matching by using “parent” axis. If you want to focus on any particular element then you can use the below XPath:

Xpath=//*[@id='rt-feature']//parent::div[1]

You can change the XPath according to the requirement by putting [1],[2]…………and so on.

g) Self: Selects the current node or ‘self’ means it indicates the node itself as shown in the below screen.

XPath in Selenium WebDriver: Complete Tutorial

One node matching by using “self ” axis. It always finds only one node as it represents self-element.

Xpath =//*[@type='password']//self::input

h) Descendant: Selects the descendants of the current node as shown in the below screen.

In the below expression, it identifies all the element descendants to current element ( ‘Main body surround’ frame element) which means down under the node (child node , grandchild node, etc.).

Xpath=//*[@id='rt-feature']//descendant::a

XPath in Selenium WebDriver: Complete Tutorial

There are 12 “link” nodes matching by using “descendant” axis. If you want to focus on any particular element then you can use the below XPath:

Xpath=//*[@id='rt-feature']//descendant::a[1]

You can change the XPath according to the requirement by putting [1],[2]…………and so on.

Summary:

XPath is required to find an element on the web page as to do an operation on that particular element.

  • There are two types of XPath:
    • Absolute XPath
    • Relative XPath
  • XPath Axes are the methods used to find dynamic elements, which otherwise not possible to find by normal XPath method
  • XPath expression select nodes or list of nodes on the basis of attributes like ID , Name, Classname, etc. from the XML document .
Source: http://www.guru99.com/xpath-selenium.html

Selenium Grid Step by Step Guide


Install java jar:

1. Add the PPA.

Open terminal (Ctrl+Alt+T) and run the command:

sudo add-apt-repository ppa:webupd8team/java

Type in your password when it asks and hit Enter.

2. Update and install the installer script:

Run commands to update system package index and install Java installer script:

sudo apt update; sudo apt install oracle-java8-installer

You may replace oracle-java8-installer with oracle-java9-installer to install Java 9.

While the install process, you have to accept Java license to continue downloading & installing Java binaries.

3. Check the Java version

To check the Java version after installing the package, run command:

javac -version

4. Set Java environment variables

The PPA also contains a package to automatically set Java environment variables, just run command:

sudo apt install oracle-java8-set-default

For Java 9, install the package oracle-java9-set-default instead.

Setup Selenium Standalone Server

 1. Download Selenium Selenium Standalone Server:

Go to http://www.seleniumhq.org/download/ and then download Selenium Standalone Server by clicking ‘Download version 3.0.1‘ (version number may vary).

You need to download this for both hub and node PCs

2. Now, start the Hub machine:

Open the terminal, CD to the location where the selenium standalone server file is being kept and type:

java -jar selenium-server-standalone-2.30.0.jar -role hub

It will start the hub.

Another way to verify whether the hub is running is by using a browser. Selenium Grid, by default, uses hub’s port 4444 for its web interface. Simply open up a browser and go to http://localhost:4444/grid/console

Also, you can find if the node can access the hub. For this, open a browser in the node machine and type http://192.168.136.130:4444/grid/console as URL. Here ‘192.168.136.130’ should replace with the node machine’s IP address.

3. Now, the hub is up and running. Let’s setup node:

In the node machine, open a terminal, CD to the location where the selenium standalone jar file is located and type the following command:

java -jar selenium-server-standalone-3.0.1.jar -role webdriver -hub http://192.168.136.130:4444/grid/register -port 5566

Here, 192.168.136.130 should be replaced with the hub machine’s IP address.

We also used port 5566 though you may choose any free port number you desire.

If everything went well, the node will up and show it’s status.

You can also verify if the node is connected with hub properly from the web browser.

Refresh the http://192.168.136.130:4444/grid/console URL and it will show the connected nodes.

4. Run the selenium script:

Now, we will run a selenium remote control script from the hub machine and it will execute to the node machines.

Here is a sample python script we are using:

Please Note: To run this script the node pc must have installed the following things:

  1. Python
  2. Python PIP
  3. Selenium
  4. Latest Chrome driver

Remote Control Script:

# -*- coding: utf-8 -*-
from selenium import selenium
import unittest, time, re

class sample-script(unittest.TestCase):
 def setUp(self):
 self.verificationErrors = []
 self.selenium = selenium("localhost", 4444, "*chrome", "http://jaxara.com/")
 self.selenium.start()
 
 def test_sample-script(self):
 sel = self.selenium
 sel.open("/")
 sel.type("id=edit-search-block-form--4", "test")
 sel.click("xpath=.//*[@value='Search']")
 for i in range(60):
 try:
 if sel.is_element_present("xpath=.//*[@id='block-system-main']/div/h2"): break
 except: pass
 time.sleep(1)
 else: self.fail("time out")
 try: self.failUnless(sel.is_element_present("xpath=.//*[@id='block-system-main']/div/h2"))
 except AssertionError as e: self.verificationErrors.append(str(e))
 
 def tearDown(self):
 self.selenium.stop()
 self.assertEqual([], self.verificationErrors)

if __name__ == "__main__":
 unittest.main()

To verify if the above listed items are already been installed, run this script from the terminal. If the following scripts run properly then everything is installed and ready.

Sample Script:

# -*- coding: utf-8 -*-
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import Select
from selenium.common.exceptions import NoSuchElementException
from selenium.common.exceptions import NoAlertPresentException
import unittest, time, re

class SampleWebScriptPy(unittest.TestCase):
 def setUp(self):
 self.driver = webdriver.Chrome()
 self.driver.implicitly_wait(30)
 self.base_url = "http://jaxara.com/"
 self.verificationErrors = []
 self.accept_next_alert = True
 
 def test_sample_web_script_py(self):
 driver = self.driver
 driver.get(self.base_url + "/")
 driver.find_element_by_id("edit-search-block-form--4").clear()
 driver.find_element_by_id("edit-search-block-form--4").send_keys("test")
 driver.find_element_by_xpath(".//*[@value='Search']").click()
 for i in range(60):
 try:
 if self.is_element_present(By.XPATH, ".//*[@id='block-system-main']/div/h2"): break
 except: pass
 time.sleep(1)
 else: self.fail("time out")
 try: self.assertTrue(self.is_element_present(By.XPATH, ".//*[@id='block-system-main']/div/h2"))
 except AssertionError as e: self.verificationErrors.append(str(e))
 
 def is_element_present(self, how, what):
 try: self.driver.find_element(by=how, value=what)
 except NoSuchElementException as e: return False
 return True
 
 def is_alert_present(self):
 try: self.driver.switch_to_alert()
 except NoAlertPresentException as e: return False
 return True
 
 def close_alert_and_get_its_text(self):
 try:
 alert = self.driver.switch_to_alert()
 alert_text = alert.text
 if self.accept_next_alert:
 alert.accept()
 else:
 alert.dismiss()
 return alert_text
 finally: self.accept_next_alert = True
 
 def tearDown(self):
 self.driver.quit()
 self.assertEqual([], self.verificationErrors)

if __name__ == "__main__":
 unittest.main()

Good luck!

Python Robot Framework Install


To install Robot Framework, you need to pre-installed the following items:

  1. Python 2 or 3
  2. Selenium
  3. PIP
  4. PATH setting in Environment Variables

See How to Install Python, PIP, Selenium, Chrome Driver post if you already have not the above things.

Install Robot:

Open CMD as an administrator user.

Type:

pip install robotframework
pip install robotframework-selenium2library

After completion you can start working on the Robot framework.

You can simply create a .txt file and put the following codes to check the Robot framework is working or not:

*** Settings ***
Library     Selenium2Library
Suite Setup     Go to homepage
Suite Teardown  Close All Browsers

*** Variables ***
${HOMEPAGE}     http://mytestsite/wp-admin
${BROWSER}      chrome
${user}         abc@example.com
${pass}         password

*** Test Cases ***
Open Browser To Login Page
    Input Username    abc@example.com
    Input Password    password
    Submit Credentials

*** Keywords ***
Open Browser To Login Page
    Maximize Browser Window
    Open Browser    ${HOMEPAGE}    ${BROWSER}
    Login Page Should Be Open

Go to homepage
    Open Browser    ${HOMEPAGE}     ${BROWSER}

Input Username
    [Arguments]    ${username}
    Input Text    id=user_login    ${username}

Input Password
    [Arguments]    ${password}
    Input Text    id=user_pass    ${password}

Submit Credentials
    Click Button    xpath=//input[contains(@id, 'wp-submit')]

Save this code in a text file like, demo-robot.txt

Now from CMD or terminal type

pybot demo-robot.txt

It will run the script and generate the detail report, log file and other necessary output.

You can also save the file as robot file like, debo-robot.robot

It that case you need to add “C:\Python27\Lib\site-packages\robot” in your Environment Variable.

Now type the following code to run the robot script:

robot demo-robot.robot

Please Note: If you are using any IDE like Pycharm, some notification will appear after installing Robot framework, which will say that there are some plugins for Robot, do you want to install it or not. In that case you should install it in the IDE.

How to Install Python, PIP, Selenium, Chrome and Firefox Driver


Install Python:

If you are using a Linux machine then you have already installed Python, so only Windows users need to download and install Python. For this, go the following URL, download the latest Python (I am using 2.7.x) and install it:

https://www.python.org/downloads/

Install PIP:

If you already have Python installed in you system, then you have PIP but you need to update it.

To install pip, securely download get-pip.py.

Run the file, it will update PIP.

Make Python Executable via CMD:

Now to make python executable via windows command line, you need to add environment variable, For this go to My Computer Properties > Click Advanced System Settings > click Environment Variables.. > select PATH and click Edit.

Here, add “C:\Python27″ and “C:\Python27\Scripts” by clicking New. If any of them are already exist then no need to add again. Now press OK for everything.

2016-11-20_0-07-242016-11-20_0-08-302016-11-20_0-10-512016-11-20_0-11-152016-11-20_0-13-03

Now close and open the CMD. You can now able to run python files from command prompt by typing ‘python test.py’ where test.py is a python script.

Please Note: Sometimes the PC may need to logoff and then login again to take effect this new installation.

Install Selenium

For installing Selenium first,

Open the CMD.

go to python script directory by typing:

cd C:\Python27\Scripts

Now install Selenium:

pip install -U selenium

It will appear like bellow after successful completion:

2016-11-20_0-28-32

Install Chrome Driver:

To install Chrome driver you need to installed the Chrome browser in your system.

Now, download the latest chrome driver from the official page: https://sites.google.com/a/chromium.org/chromedriver/downloads

To download the latest Firefox (Gecko dirver) download the latest form here: http://www.seleniumhq.org/download/

Unzip it and copy the chromedriver.exe file to “C:\Python27” location.

Please Note: While updating any driver (Chromedriver, Firefox Gecko driver) you need to copy the latest driver.exe file to this same location and replace the old one with new one.

Access Mouse Hover Action in Selenium Webdriver Python


For accessing mouse hover menu we need to use ‘ActionChains’ function.

First import ‘ActionChains’

from selenium.webdriver.common.action_chains import ActionChains

In our example we are going to access Drupal admin menu Content » Add content » Basic page menu item.

Here the xpaths:

Content Menu item:

cls.content_menu_xpath = "//li[contains(@class, 'admin-menu-toolbar-category expandable')]/a[contains(@href, '/admin/content')]"

Add Content:

cls.add_content_menu_xpath = "//li[contains(@class, 'admin-menu-toolbar-category expandable')]/ul[contains(@class, 'dropdown')]/li[contains(@class, 'expandable')]/a[contains(@href, '/node/add')]"

Add Basic Page:

cls.add_basic_page_xpath = "//ul[contains(@id, 'admin-menu-menu')]/li[2]/ul/li[1]/ul/li[2]/a"

Now hover the menu and click on the Add Basic page link:

def admin_hover_menu(self):

    content_menu_hover = self.driver.find_element_by_xpath(self.content_menu_xpath)
    hover_content = ActionChains(self.driver).move_to_element(content_menu_hover)
    hover_content.perform()
    add_content_hover = self.driver.find_element_by_xpath(self.add_content_menu_xpath)
    hover_add_content = ActionChains(self.driver).move_to_element(add_content_hover)
    hover_add_content.perform()

    #Click on hover menu item (Content > Add content > Basic Page)
    self.assertTrue(self.is_element_present(By.XPATH, self.add_basic_page_xpath))
    self.driver.find_element_by_xpath(self.add_basic_page_xpath).click()

    #verifiy create basic page
    self.assertTrue(self.is_element_present(By.XPATH, self.basic_page_title_xpath))

That’s all!

Input into CKEditor in Selenium Python


CKEditor is a WYSIWYG editor. There are other WYSIWYG editors, for example: TinyMCE.

most of the WYSIWYG editor along with CKEditor use <iframe> instead of <textarea> and displays the content inside the <body> element, however, it makes the UI automation process a little bit different.

Automate using native Selenium WebDriver API

Both CKEditor and TinyMCE are JavaScript based, which means they can be automated using Selenium WebDriver’s native API just like any other HTML web applications.

Basic Instructions

In the following example, we have used a Drupal Basic Page content type creation page.

From the Basic page creation page, first, we need to switch into CKEditor iframe:

#Wait for the CKEditor iframe to load and switch to iframe
time.sleep(3)
basic_page_body_xpath = "//div[contains(@id, 'cke_1_contents')]/iframe"

#Locate the iframes
ckeditor_frame = self.driver.find_element_by_xpath(basic_page_body_xpath)

#Switch to iframe
self.driver.switch_to.frame(ckeditor_frame)

Note that, for switching to any iframe we need to wait for the iframe to load.

Here, ‘time.sleep(3)’ do the waiting.

Now, input into the CKEditor:

#Send key to Ckeditor Body
editor_body = self.driver.find_element_by_xpath("//body")
editor_body.send_keys("Test Body")

Now, we need to get our from the CKEditor iframe and switch back to our main site content:

# if driver is already inside ckeditor_frame, switch out first
self.driver.switch_to_default_content()

These are the basic to input data into CKEditor. There are other advance features which are described bellow:

Click toolbar buttons

WYSIWYG editors normally provide native methods to set raw HTML content directly through API, automating the toolbar doesn’t seem to be really necessary. If it’s needed to be done for some reason, it shouldn’t be much of a problem, because toolbar elements are just ordinary web elements, the automating process is fairly straight-forward without any frame switching required.

  1. Find the elements by appropriate locators according to the HTML markup.
  2. Manipulate those elements see if they work or not.

Markup for CKEditor’s toolbar “Numbered List” button:

<a id="cke_39" class="cke_button cke_button__numberedlist" href="javascript:void('Insert/Remove Numbered List')" title="Insert/Remove Numbered List" role="button">
    <span class="cke_button_icon cke_button__numberedlist_icon" >&nbsp;</span>
    <span id="cke_39_label" class="cke_button_label cke_button__numberedlist_label">Insert/Remove Numbered List</span>
</a>

Markup for TinyMCE’s toolbar “Numbered List” button:

id=“mce_11” class=“mce-widget mce-btn” role=“button” aria-label=“Numbered list” aria-pressed=“false”> type=“button”> class=“mce-ico mce-i-numlist”>

Selenium WebDriver Ruby code to click the buttons:

# click CKEditor's 'Numbered List' button
ckeditor_btn_numbered_list = driver.find_element(:class => "cke_button__numberedlist")
ckeditor_btn_numbered_list.click

# click TinyMCE editor's 'Numbered List' button
tinymce_btn_numbered_list = driver.find_element(:css => ".mce-btn[aria-label='Numbered list'] button")
tinymce_btn_numbered_list.click

Clear all input

A quote from Selenium Ruby’s API documentation on clear() method:

If this element is a text entry element, this will clear the value. Has no effect on other elements.

Although clear() method is stated as not available for non-text entry elements, it seems it can actually clear the input iframe without any exceptions.

Apart from clear(), an alternative is to use Selenium’s ActionBuilder to construct an action chain to mimic keyboard shortcut pressing. Ctrl + A will select all, then push Backspace to clear.

# Method 1. Using clear() method
editor_body.clear

# Method 2. Using ActionBuilder
driver.action.click(editor_body)
             .key_down(:control)
             .send_keys("a")
             .key_up(:control)
             .perform
driver.action.send_keys(:backspace).perform

Automate using editors’ built-in JavaScript API

Without worrying about frame switching like using Selenium WebDriver’s native API, it would also be a stable solution to inject JavaScript directly usingdriver.execute_script() to call editors’ built-in JS functions.

Set content

Both editors have built-in methods to set the content of entire input area. CKEditor’s API provides a method called setData(), which replaces editor data with raw input HTML data. Similar method setContent() also exists in TinyMCE editor’s API.

driver.execute_script("CKEDITOR.instances.ckeditor.setData('<h1>Yi Zeng</h1> CKEditor')")
driver.execute_script("tinyMCE.activeEditor.setContent('<h1>Yi Zeng</h1> TinyMCE')")

Clear content

With the same logic, clearing content can be done by injecting JavaScript to set the entire content to empty string.

driver.execute_script("CKEDITOR.instances.ckeditor.setData( '' )")
driver.execute_script("tinyMCE.activeEditor.setContent('')")

Insert content

Instead of setting the entire content, it is also possible to insert some content to the editors. CKEditor’s has a method called insertHTML(), which inserts content at currently selected position, in TinyMCE, it’s called insertContent().

driver.execute_script("CKEDITOR.instances.ckeditor.insertHtml('<p>Christchurch</p>')")
driver.execute_script("tinyMCE.activeEditor.insertContent('<p>Christchurch</p>')")

Examples

Set content using Selenium WebDriver API

# Environment tested
# Linux Mint 16, Selenium 2.41.0, Chromium 33.0, ChromeDriver 2.9
require 'selenium-webdriver'

driver = Selenium::WebDriver.for :chrome
driver.get('http://yizeng.me/2014/01/31/test-wysiwyg-editors-using-selenium-webdriver/')

ckeditor_frame = driver.find_element(:class => 'cke_wysiwyg_frame')
tinymce_frame = driver.find_element(:id => 'tinymce-editor_ifr')

# Using JavaScript injection to set innerHTML, shown as WYSIWYG
driver.switch_to.frame(ckeditor_frame)
ck_editor_body = driver.find_element(:tag_name => 'body')
driver.execute_script("arguments[0].innerHTML = '<h1>CKEditor</h1>Yi Zeng'", ck_editor_body)

driver.switch_to.default_content

# Using native 'send_keys' method, all content are wrapped with <p>
driver.switch_to.frame(tinymce_frame)
tinymce_body = driver.find_element(:css => 'body')
tinymce_body.send_keys('<h1>TInyMCE</h1>Yi Zeng')

Select all content

# Environment tested
# Linux Mint 16, Selenium 2.41.0, Chromium 33.0, ChromeDriver 2.9
require 'selenium-webdriver'

driver = Selenium::WebDriver.for :chrome
driver.get('http://yizeng.me/2014/01/31/test-wysiwyg-editors-using-selenium-webdriver/')

driver.switch_to.frame(driver.find_element(:class => 'cke_wysiwyg_frame'))

ck_editor_body = driver.find_element(:tag_name => 'body')
ck_editor_body.send_keys("Yi Zeng")

driver.action.click(ck_editor_body)
             .key_down(:control)
             .send_keys("a")
             .key_up(:control)
             .perform

Click “Numbered list” from toolbar

# Environment tested
# Linux Mint 16, Selenium 2.41.0, Chromium 33.0, ChromeDriver 2.9
require 'selenium-webdriver'

driver = Selenium::WebDriver.for :chrome
driver.get('http://yizeng.me/2014/01/31/test-wysiwyg-editors-using-selenium-webdriver/')

# click CKEditor's 'Numbered List' button
ckeditor_btn_numbered_list = driver.find_element(:class => "cke_button__numberedlist")
ckeditor_btn_numbered_list.click

# click TinyMCE editor's 'Numbered List' button
tinymce_btn_numbered_list = driver.find_element(:css => ".mce-btn[aria-label='Numbered list'] button")
tinymce_btn_numbered_list.click

Set content using editors’ API

# Environment tested
# Linux Mint 16, Selenium 2.41.0, Chromium 33.0, ChromeDriver 2.9
require 'selenium-webdriver'

driver = Selenium::WebDriver.for :chrome
driver.get('http://yizeng.me/2014/01/31/test-wysiwyg-editors-using-selenium-webdriver/')

driver.execute_script("CKEDITOR.instances.ckeditor.setData('<h1>Yi Zeng</h1> CKEditor')")
driver.execute_script("tinyMCE.activeEditor.setContent('<h1>Yi Zeng</h1> TinyMCE')")

driver.execute_script("CKEDITOR.instances.ckeditor.insertHtml('<p>Christchurch</p>')")
driver.execute_script("tinyMCE.activeEditor.insertContent('<p>Christchurch</p>')")
Reference: http://yizeng.me/2014/01/31/test-wysiwyg-editors-using-selenium-webdriver/

Blog at WordPress.com.

Up ↑