com.robotium.solo.WebUtils Maven / Gradle / Ivy
package com.robotium.solo;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import com.robotium.solo.Solo.Config;
import android.app.Instrumentation;
import android.webkit.WebChromeClient;
import android.webkit.WebView;
import android.widget.TextView;
/**
* Contains web related methods. Examples are:
* enterTextIntoWebElement(), getWebTexts(), getWebElements().
*
* @author Renas Reda, [email protected]
*
*/
class WebUtils {
private ViewFetcher viewFetcher;
private Instrumentation inst;
private ActivityUtils activityUtils;
RobotiumWebClient robotiumWebCLient;
WebElementCreator webElementCreator;
WebChromeClient originalWebChromeClient = null;
private Config config;
/**
* Constructs this object.
*
* @param config the {@code Config} instance
* @param instrumentation the {@code Instrumentation} instance
* @param activityUtils the {@code ActivityUtils} instance
* @param viewFetcher the {@code ViewFetcher} instance
*/
public WebUtils(Config config, Instrumentation instrumentation, ActivityUtils activityUtils, ViewFetcher viewFetcher, Sleeper sleeper){
this.config = config;
this.inst = instrumentation;
this.activityUtils = activityUtils;
this.viewFetcher = viewFetcher;
webElementCreator = new WebElementCreator(sleeper);
robotiumWebCLient = new RobotiumWebClient(instrumentation, webElementCreator);
}
/**
* Returns {@code TextView} objects based on web elements shown in the present WebViews
*
* @param onlyFromVisibleWebViews true if only from visible WebViews
* @return an {@code ArrayList} of {@code TextViews}s created from the present {@code WebView}s
*/
public ArrayList getTextViewsFromWebView(){
boolean javaScriptWasExecuted = executeJavaScriptFunction("allTexts();");
return createAndReturnTextViewsFromWebElements(javaScriptWasExecuted);
}
/**
* Creates and returns TextView objects based on WebElements
*
* @return an ArrayList with TextViews
*/
private ArrayList createAndReturnTextViewsFromWebElements(boolean javaScriptWasExecuted){
ArrayList webElementsAsTextViews = new ArrayList();
if(javaScriptWasExecuted){
for(WebElement webElement : webElementCreator.getWebElementsFromWebViews()){
if(isWebElementSufficientlyShown(webElement)){
RobotiumTextView textView = new RobotiumTextView(inst.getContext(), webElement.getText(), webElement.getLocationX(), webElement.getLocationY());
webElementsAsTextViews.add(textView);
}
}
}
return webElementsAsTextViews;
}
/**
* Returns an ArrayList of WebElements currently shown in the active WebView.
*
* @return an {@code ArrayList} of the {@link WebElement} objects currently shown in the active WebView
*/
public ArrayList getCurrentWebElements(){
boolean javaScriptWasExecuted = executeJavaScriptFunction("allWebElements();");
return getSufficientlyShownWebElements(javaScriptWasExecuted);
}
/**
* Returns an ArrayList of WebElements of the specified By object currently shown in the active WebView.
*
* @param by the By object. Examples are By.id("id") and By.name("name")
* @return an {@code ArrayList} of the {@link WebElement} objects currently shown in the active WebView
*/
public ArrayList getCurrentWebElements(final By by){
boolean javaScriptWasExecuted = executeJavaScript(by, false);
if(config.useJavaScriptToClickWebElements){
if(!javaScriptWasExecuted){
return new ArrayList();
}
return webElementCreator.getWebElementsFromWebViews();
}
return getSufficientlyShownWebElements(javaScriptWasExecuted);
}
/**
* Returns the sufficiently shown WebElements
*
* @return the sufficiently shown WebElements
*/
private ArrayList getSufficientlyShownWebElements(boolean javaScriptWasExecuted){
ArrayList currentWebElements = new ArrayList();
if(javaScriptWasExecuted){
for(WebElement webElement : webElementCreator.getWebElementsFromWebViews()){
if(isWebElementSufficientlyShown(webElement)){
currentWebElements.add(webElement);
}
}
}
return currentWebElements;
}
/**
* Prepares for start of JavaScript execution
*
* @return the JavaScript as a String
*/
private String prepareForStartOfJavascriptExecution(){
webElementCreator.prepareForStart();
WebChromeClient currentWebChromeClient = getCurrentWebChromeClient();
if(currentWebChromeClient != null && !currentWebChromeClient.getClass().isAssignableFrom(RobotiumWebClient.class)){
originalWebChromeClient = getCurrentWebChromeClient();
}
robotiumWebCLient.enableJavascriptAndSetRobotiumWebClient(viewFetcher.getCurrentViews(WebView.class), originalWebChromeClient);
return getJavaScriptAsString();
}
/**
* Returns the current WebChromeClient through reflection
*
* @return the current WebChromeClient
*
*/
private WebChromeClient getCurrentWebChromeClient(){
WebChromeClient currentWebChromeClient = null;
Object currentWebView = viewFetcher.getFreshestView(viewFetcher.getCurrentViews(WebView.class));
if (android.os.Build.VERSION.SDK_INT >= 16) {
try{
currentWebView = new Reflect(currentWebView).field("mProvider").out(Object.class);
}catch(IllegalArgumentException ignored) {}
}
try{
Object mCallbackProxy = new Reflect(currentWebView).field("mCallbackProxy").out(Object.class);
currentWebChromeClient = new Reflect(mCallbackProxy).field("mWebChromeClient").out(WebChromeClient.class);
}catch(Exception ignored){}
return currentWebChromeClient;
}
/**
* Enters text into a web element using the given By method
*
* @param by the By object e.g. By.id("id");
* @param text the text to enter
*/
public void enterTextIntoWebElement(final By by, final String text){
if(by instanceof By.Id){
executeJavaScriptFunction("enterTextById(\""+by.getValue()+"\", \""+text+"\");");
}
else if(by instanceof By.Xpath){
executeJavaScriptFunction("enterTextByXpath(\""+by.getValue()+"\", \""+text+"\");");
}
else if(by instanceof By.CssSelector){
executeJavaScriptFunction("enterTextByCssSelector(\""+by.getValue()+"\", \""+text+"\");");
}
else if(by instanceof By.Name){
executeJavaScriptFunction("enterTextByName(\""+by.getValue()+"\", \""+text+"\");");
}
else if(by instanceof By.ClassName){
executeJavaScriptFunction("enterTextByClassName(\""+by.getValue()+"\", \""+text+"\");");
}
else if(by instanceof By.Text){
executeJavaScriptFunction("enterTextByTextContent(\""+by.getValue()+"\", \""+text+"\");");
}
else if(by instanceof By.TagName){
executeJavaScriptFunction("enterTextByTagName(\""+by.getValue()+"\", \""+text+"\");");
}
}
/**
* Executes JavaScript determined by the given By object
*
* @param by the By object e.g. By.id("id");
* @param shouldClick true if click should be performed
* @return true if JavaScript function was executed
*/
public boolean executeJavaScript(final By by, boolean shouldClick){
if(by instanceof By.Id){
return executeJavaScriptFunction("id(\""+by.getValue()+"\", \"" + String.valueOf(shouldClick) + "\");");
}
else if(by instanceof By.Xpath){
return executeJavaScriptFunction("xpath(\""+by.getValue()+"\", \"" + String.valueOf(shouldClick) + "\");");
}
else if(by instanceof By.CssSelector){
return executeJavaScriptFunction("cssSelector(\""+by.getValue()+"\", \"" + String.valueOf(shouldClick) + "\");");
}
else if(by instanceof By.Name){
return executeJavaScriptFunction("name(\""+by.getValue()+"\", \"" + String.valueOf(shouldClick) + "\");");
}
else if(by instanceof By.ClassName){
return executeJavaScriptFunction("className(\""+by.getValue()+"\", \"" + String.valueOf(shouldClick) + "\");");
}
else if(by instanceof By.Text){
return executeJavaScriptFunction("textContent(\""+by.getValue()+"\", \"" + String.valueOf(shouldClick) + "\");");
}
else if(by instanceof By.TagName){
return executeJavaScriptFunction("tagName(\""+by.getValue()+"\", \"" + String.valueOf(shouldClick) + "\");");
}
return false;
}
/**
* Executes the given JavaScript function
*
* @param function the function as a String
* @return true if JavaScript function was executed
*/
private boolean executeJavaScriptFunction(final String function){
final WebView webView = viewFetcher.getFreshestView(viewFetcher.getCurrentViews(WebView.class));
if(webView == null){
return false;
}
final String javaScript = prepareForStartOfJavascriptExecution();
activityUtils.getCurrentActivity(false).runOnUiThread(new Runnable() {
public void run() {
if(webView != null){
webView.loadUrl("javascript:" + javaScript + function);
}
}
});
return true;
}
/**
* Returns true if the view is sufficiently shown
*
* @param view the view to check
* @return true if the view is sufficiently shown
*/
public final boolean isWebElementSufficientlyShown(WebElement webElement){
final WebView webView = viewFetcher.getFreshestView(viewFetcher.getCurrentViews(WebView.class));
final int[] xyWebView = new int[2];
if(webView != null && webElement != null){
webView.getLocationOnScreen(xyWebView);
if(xyWebView[1] + webView.getHeight() > webElement.getLocationY())
return true;
}
return false;
}
/**
* Splits a name by upper case.
*
* @param name the name to split
* @return a String with the split name
*
*/
public String splitNameByUpperCase(String name) {
String [] texts = name.split("(?=\\p{Upper})");
StringBuilder stringToReturn = new StringBuilder();
for(String string : texts){
if(stringToReturn.length() > 0) {
stringToReturn.append(" " + string.toLowerCase());
}
else {
stringToReturn.append(string.toLowerCase());
}
}
return stringToReturn.toString();
}
/**
* Returns the JavaScript file RobotiumWeb.js as a String
*
* @return the JavaScript file RobotiumWeb.js as a {@code String}
*/
private String getJavaScriptAsString() {
InputStream fis = getClass().getResourceAsStream("RobotiumWeb.js");
StringBuffer javaScript = new StringBuffer();
try {
BufferedReader input = new BufferedReader(new InputStreamReader(fis));
String line = null;
while (( line = input.readLine()) != null){
javaScript.append(line);
javaScript.append("\n");
}
input.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
return javaScript.toString();
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy