Setting Capabilities to Use Selenium WebDriver for Mobile Testing

If you visit: http://www.i4info.info

and then: http://www.i4info.info/history

on your mobile phone, you will get a User Agent.

Anytime a mobile device make a request for a webpage, it sends the User Agent in the headers of the HttpGet, HttpPost request. This in turn lets the server know which page to serve. You may allow WebDriver to test the appropriate environment by setting the Capabilities for Selenium WebDriver appropriately. Here is a class that will help with handling the user agent and setting the appropriate capability for the browser you are testing with.


import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxProfile;
import org.openqa.selenium.remote.DesiredCapabilities;

public class UserAgentHandler {
	public void handle(String useragent) {
		if (useragent != null && !useragent.trim().isEmpty()) {
			handleFirefox(useragent);
			handleChrome(useragent);
			handlePhantom(useragent);
		}
	}

	private void handleFirefox(String useragent) {
		try {
			DesiredCapabilities dc = DesiredCapabilities.firefox();
			FirefoxProfile profile = new FirefoxProfile();
			profile.setPreference("general.useragent.override", useragent);
			dc.setCapability(FirefoxDriver.PROFILE, profile);
		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}

	private void handleChrome(String useragent) {
		try {
			DesiredCapabilities dc = DesiredCapabilities.chrome();
			ChromeOptions chromeOptions = new ChromeOptions();
			chromeOptions.addArguments("--user-agent=" + useragent);
			dc.setCapability(ChromeOptions.CAPABILITY, chromeOptions);
		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}

	private void handlePhantom(String useragent) {
		try {
			DesiredCapabilities dc = DesiredCapabilities.phantomjs();
			dc.setJavascriptEnabled(true);
			dc.setCapability("phantomjs.page.settings.userAgent", useragent);
		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}
}

Generating Unique IDs for WebElements via XPATH

Ideally, individual elements would have tags which could be used to generate unique IDs. Typically, this would involve using the tag name, id attribute, name attribute and/or class attribute.

However, when this is not possible, you can parse the xml tree structure to generate unique IDs using the XPATH locator. These can be used in Firefox, Firebug, Firefinder to locate the elements.

As mentioned in stackoverflow.com, this method is not desired because simple changes in the dom can change the xpath id. However, this can allow you some flexibility when analyzing pages.


import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;

public class XPATHDriverWrapper {
	Map xpathIDToWebElementMap = new LinkedHashMap();
	Map webElementToXPATHIDMap = new LinkedHashMap();
	public XPATHDriverWrapper(WebDriver driver){
		WebElement htmlElement = driver.findElement(By.xpath("/html"));
		iterateThroughChildren(htmlElement, "/html");
	}
	
	private void iterateThroughChildren(WebElement parentElement, String parentXPATH) {
		Map siblingCountMap = new LinkedHashMap();

		List childrenElements = parentElement.findElements(By.xpath(parentXPATH+"/*"));
		for(int i=0;i<childrenElements.size(); i++) {
			WebElement childElement = childrenElements.get(i);
			String childTag = childElement.getTagName();
			String childXPATH = constructXPATH(parentXPATH, siblingCountMap, childTag);
			xpathIDToWebElementMap.put(childXPATH, childElement);
			webElementToXPATHIDMap.put(childElement, childXPATH);
			iterateThroughChildren(childElement, childXPATH);
//			System.out.println("childXPATH:"+childXPATH);
		}
	}
	
	public WebElement findWebElementFromXPATHID(String xpathID) {
		return xpathIDToWebElementMap.get(xpathID);
	}
	
	public String findXPATHIDFromWebElement(WebElement webElement) {
		return webElementToXPATHIDMap.get(webElement);
	}
	
	private String constructXPATH(String parentXPATH,
			Map siblingCountMap, String childTag) {
		Integer count = siblingCountMap.get(childTag);
		if(count == null) {
			count = 1;
		} else {
			count = count + 1;
		}
		siblingCountMap.put(childTag, count);
		String childXPATH = parentXPATH + "/" + childTag + "[" + count + "]";
		return childXPATH;
	}
}

import java.util.LinkedHashMap;
import java.util.Map;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class XPATHDocumentWrapper {
	Map xpathIDToNodeMap = new LinkedHashMap();
	Map nodeToXPATHIDMap = new LinkedHashMap();
	public XPATHDocumentWrapper(Document doc) {
		NodeList nList = doc.getElementsByTagName("html");
		Node htmlNode = nList.item(0);
		iterateThroughChildren(htmlNode, "/html");
	}
	
	private void iterateThroughChildren(Node parentNode, String parentXPATH) {
		Map siblingCountMap = new LinkedHashMap();

		NodeList childNodes = parentNode.getChildNodes();
		for(int i=0;i<childNodes.getLength(); i++) {
			Node childNode = childNodes.item(i);
			String childTag = childNode.getNodeName();
			String childXPATH = constructXPATH(parentXPATH, siblingCountMap, childTag);
			xpathIDToNodeMap.put(childXPATH, childNode);
			nodeToXPATHIDMap.put(childNode, childXPATH);
			iterateThroughChildren(childNode, childXPATH);
//			System.out.println("childXPATH:"+childXPATH);
		}
	}
	
	public Node findNodeFromXPATHID(String xpathID) {
		return xpathIDToNodeMap.get(xpathID);
	}
	
	public String findXPATHIDFromNode(Node node) {
		return nodeToXPATHIDMap.get(node);
	}
	
	private String constructXPATH(String parentXPATH,
			Map siblingCountMap, String childTag) {
		Integer count = siblingCountMap.get(childTag);
		if(count == null) {
			count = 1;
		} else {
			count = count + 1;
		}
		siblingCountMap.put(childTag, count);
		String childXPATH = parentXPATH + "/" + childTag + "[" + count + "]";
		return childXPATH;
	}

}