How to fall-back from WebDriver’s findElementBy() method to the one using native JS getElementBy* methods

Hi All,

If any of you ever encountered problems using WedDriver’s “By.*” selectors (especially in IE7 !!!! ) then you can find this post somehow useful/helpful 🙂

The idea is simple: Use native JavaScript selector’s to find desired element.
I know that this is not a perfect solution, but works for me 🙂

ps. Sorry for a crappy post title 🙂

Cheers,
J

import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.testng.Assert;



/** 
 * Can be used as a fall-back method to find element(s) on page using native JS selector.  
 * VERY USEFUL when buil-in WebDriver's selector doesn't work, especially with IE7 !!!!!!!!!!!!!!!!!!!!!!
 * 
 * Author				: Janusz Kowalczyk
 * Created Date			: 07Jul2011   
 * REVISION HISTORY
 * DATE				CHANGED BY				DESCRIPTION
 * 07Jul2011		Janusz Kowalczyk		Initial Creation  
*/ 
public class JShelper
{
	private JavascriptExecutor jsExec = null;
	private Object o = null;
	private String jsSelector = null;
	
	/**
	 * Class constructor that instantiates JavascriptExecutor 
	*/
	public JShelper(WebDriver webdriver)
	{
		this.jsExec = (JavascriptExecutor) webdriver;
	}
	
	/**
	 * Tends to find HTML element by using three native JavaScript methods:
	 * getElementById(), getElementsByName(), getElementsByTagName().
	 * As a result WebElement is expected.
	 * For more info please refer to docs:   
	 * http://selenium.googlecode.com/svn/trunk/docs/api/java/org/openqa/selenium/JavascriptExecutor.html
	 * 
	 * @param byIdentificator Any unique ID (like: ID, Name, TagName) that gonna be used to find desired element, 
	 * by using one of the native JS methods: 
	 * getElementById(), getElementsByName(), getElementsByTagName()
	 * 
	 * @param foundElementsOffset If you expect to find more than 1 element, 
	 * then explicitly specify which one you want to get. 
	 * 
	*/
	public WebElement getElement(String byIdentificator, int foundElementsOffset)
	{
		String tmpSelector = null;
		
	
		tmpSelector = "document.getElementById('" 
			+ byIdentificator 
			+ "')[" 
			+ foundElementsOffset 
			+ "]";
		o = exec("return " + tmpSelector);
		if (o != null) 
			{ 
				jsSelector = tmpSelector; 
				return (WebElement) o; 
			}
		
		
		tmpSelector = "document.getElementsByName('" 
			+ byIdentificator 
			+ "')[" 
			+ foundElementsOffset 
			+ "]";
		o = exec("return " + tmpSelector);
		if (o != null) 
			{ 
				jsSelector = tmpSelector; 
				return (WebElement) o; 
			}
		
		
		tmpSelector = "document.getElementsByTagName('" 
			+ byIdentificator 
			+ "')[" 
			+ foundElementsOffset 
			+ "]";
		o = exec("return " + tmpSelector);
		if (o != null) 
			{ 
				jsSelector = tmpSelector; 
				return (WebElement) o; 
			}
		
		return (WebElement) o;
	}
	
	
	/**
	 * Retrieves the value of element's attribute
	 * For more information please refer to documentation:
	 * http://selenium.googlecode.com/svn/trunk/docs/api/java/org/openqa/selenium/JavascriptExecutor.html
	 * 
	 * 
	 * @param attribute Any html attribute like: value, class, name, id etc.
	 * 
	 * @return Value of element's attribute
	*/
	public String getAttributeValue(String attribute)
	{
		String tmpCmnd = "return " 
			+ jsSelector 
			+ ".getAttribute('" 
			+ attribute 
			+ "');";
		
		return (String) exec(tmpCmnd);
	}
	
	
	/**
	 * Sets the new value of element's attribute
	 * 
	 * @param attribute Any HTML attribute like: value, class, name, id etc.
	 * @param value Attribute's new value 
	*/
	public void setAttribute(String attribute, String value)
	{
		String tmpCmnd = jsSelector 
		+ ".setAttribute('" 
		+ attribute 
		+ "', '" 
		+ value 
		+ "');";
		
		exec(tmpCmnd);

		assertIsSetTo(attribute, value);
	}
	
	
	/**
	 * Simple assertion to chech is current attribute's value is the same as expected
	 * 
	 * @param attribute Any HTML attribute like: value, class, name, id etc.
	 * @param expValue Expected attribute's value 
	*/
	public void assertIsSetTo(String attribute, String expValue) 
	{
		String currentValue = (String) getAttributeValue(attribute);
		
    	Assert.assertTrue(currentValue != null && currentValue.equals(expValue),
    			"Attribute's new value is different from exptected. Expected value: '" 
    			+ expValue 
    			+ "' Current value: '" 
    			+ currentValue 
    			+ "'");
    }
	
	
	/**
	 * Executes JS
	 * 
	 * @param script Executes JavaScript in the context of the currently selected frame or window. 
	 * For more information please refer to documentation:
	 * http://selenium.googlecode.com/svn/trunk/docs/api/java/org/openqa/selenium/JavascriptExecutor.html
	*/
	private Object exec(String script)
	{
		return jsExec.executeScript(script);
	}
}