Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
9fb1958
First cut for webview recording. Added jquery and recorder js. Able t…
menonvarun Jul 17, 2012
caf9886
Adding the missed webview related files
menonvarun Jul 17, 2012
32805d2
Created resources fodler and moved all the files that needs to be kep…
menonvarun Jul 18, 2012
0c4aa6f
Merge remote-tracking branch 'origin/master' into webview-recording
menonvarun Jul 26, 2012
a83983f
Merge remote-tracking branch 'origin/master' into webview-recording
menonvarun Aug 6, 2012
22c26f5
Adding the working code of webview recording.
menonvarun Aug 21, 2012
1735a65
Merge remote-tracking branch 'origin/master' into webview-recording
menonvarun Aug 21, 2012
bf1f1c5
Adding support for webview runner.
menonvarun Sep 14, 2012
9769466
Modified recorder to store util class as window element.
menonvarun Sep 17, 2012
c19144f
Fixing certain issues
menonvarun Sep 17, 2012
9b55cd9
Updated the dex2jar
menonvarun Nov 1, 2012
888c673
Made changes to execute webview realted code on the Ui thread.
menonvarun Nov 1, 2012
8ba88ad
Adding logic to find and use if an existing WebViewClient if it exists.
menonvarun Nov 9, 2012
d4bac2c
Merge branch 'master' of github.com:Imaginea/bot-bot into webview-rec…
menonvarun Jan 28, 2013
ff0ed42
Support for webview record phonegap as well as hybrid apps
menonvarun Jan 29, 2013
c38d00a
Webview runner support
menonvarun Jan 29, 2013
bc0407e
Fix for removing new line and tabs while getting text. And adding inp…
menonvarun Jan 29, 2013
833fd5d
Modified changes for webview runner
menonvarun Jan 29, 2013
96b67b4
Merge remote-tracking branch 'origin/webview' into webview-runner
menonvarun Jan 29, 2013
e108dcb
Merge branch 'master' of github.com:Imaginea/bot-bot into webview-runner
menonvarun Jan 29, 2013
016b2e0
Doing relaod after adding interface to attache the interface
menonvarun Feb 3, 2013
e1c33bb
Merge branch 'master' of github.com:Imaginea/bot-bot into webview-runner
menonvarun Apr 17, 2013
e74e7c7
Improved the code to relod view and waitfor activity to load.
menonvarun Apr 18, 2013
c16a2d6
Adding info about what each class does
menonvarun Apr 18, 2013
d8e26af
Removing the unused code from WebViewListener and fixing issue with c…
menonvarun Apr 18, 2013
9b2c893
reverting the changes done
menonvarun Apr 18, 2013
1fd6160
Merge pull request #110 from Imaginea/webview-recording
menonvarun Apr 18, 2013
60b6148
Merge pull request #111 from Imaginea/webview-runner
menonvarun Apr 18, 2013
4e27062
Update .gitignore
ajay458 Dec 11, 2013
926f1b5
Working changes for bot-bot
Dec 11, 2013
2f22cc3
Merge branch 'master' of https://github.com/ajay458/bot-bot
Dec 11, 2013
b3715cc
no message
Dec 12, 2013
ad3df3d
Removing unnecessary code
Dec 12, 2013
96a76e5
no message
Dec 13, 2013
e01b49a
Merge pull request #116 from ajay458/master
menonvarun Dec 13, 2013
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/recorder/robo-bin/
/runner/bin1/
/runner/resignapk/
/runner/robo-bin/
/runner/resources/
/runner/staging/
/runner/test-report/
2 changes: 1 addition & 1 deletion build.xml
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
</target>

<target name="server">
<java dir="./server/" fork="true" jar="./server/bot-bot-server-standalone.jar"/>
<java dir="./server/" fork="true" jar="./server/target/bot-bot-server-standalone.jar"/><!-- inserted "target" in to the existing path -->
</target>

<target name="usage">
Expand Down
4 changes: 3 additions & 1 deletion default.properties
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ DEFAULT_ACTIVITY=Dashboard
FRAMEWORK=robotium
TESTCASE_FOLDER=wordpress
TEST_APK_FILENAME=wordpress.apk
ANDROID_VERSION=android-15
ANDROID_VERSION=android-19
VERSION_CODE=19.0.0
SDK_VERSION=4.3

key.store=${user.home}/.android/debug.keystore
key.store.password=android
Expand Down
27 changes: 20 additions & 7 deletions recorder/build.xml
Original file line number Diff line number Diff line change
Expand Up @@ -36,17 +36,26 @@
<os family="unix" />
</condition>

<property name="dx" location="${env.ANDROID_HOME}/platform-tools/dx${bat}" />
<condition property="build-tools-folder" value="android-${SDK_VERSION}" else="${VERSION_CODE}">
<available file="${env.ANDROID_HOME}/build-tools/android-${SDK_VERSION}" type="dir" />
</condition>

<property name="build-tools" location="${env.ANDROID_HOME}/build-tools/${build-tools-folder}" />

<property name="dx" location="${build-tools}/dx${bat}" />
<property name="apkbuilder" location="${env.ANDROID_HOME}/tools/apkbuilder${bat}" />
<property name="dex2jar" location="./lib/dex2jar-0.0.9.8/d2j-dex2jar${ext}" />
<property name="asm-verify" location="./lib/dex2jar-0.0.9.8/d2j-asm-verify${ext}" />
<property name="dex2jar" location="./lib/dex2jar-0.0.9.9/d2j-dex2jar${ext}" />
<property name="asm-verify" location="./lib/dex2jar-0.0.9.9/d2j-asm-verify${ext}" />
<property name="dex2jar.decoded.jar" location="${bin.dir}/dex2jar-decoded.jar" />
<property name="dex2jar.decoded.dir" location="${bin.dir}/dex2jar-decoded" />
<property name="android.lib" location="${env.ANDROID_HOME}/platforms/android-10"/>
<property name="out.classes.absolute.dir" location="${dex2jar.decoded.dir}"/>
<property name="recorder.dir" location="."/>
<path id="android.antlibs">
<pathelement path="${env.ANDROID_HOME}/tools/lib/anttasks.jar" />
<pathelement path="${env.ANDROID_HOME}/tools/lib/ant-tasks.jar" />
</path>
<path id="android.sdklibs">
<pathelement path="${env.ANDROID_HOME}/tools/lib/sdklib.jar" />
</path>
<taskdef name="xpath" classname="com.android.ant.XPathTask" classpathref="android.antlibs"/>
<taskdef name="aapt" classname="com.android.ant.AaptExecTask" classpathref="android.antlibs" />
Expand Down Expand Up @@ -103,7 +112,8 @@
<antcall target="dex" />
<delete dir="${staging.dir}/classes.dex" />
<copy file="${dex.file}" todir="${staging.dir}" />
<copy file="${recorder.dir}/recorder.properties" todir="${staging.dir}/assets" />
<!--<copy file="${recorder.dir}/recorder.properties" todir="${staging.dir}/assets" />-->
<copydir src="${recorder.dir}/resources" dest="${staging.dir}/assets" />
<zip destfile="${app.unsigned}" basedir="${staging.dir}" />
<antcall target="-signapp" />
</target>
Expand Down Expand Up @@ -193,14 +203,17 @@


<target name="-apk">
<exec executable="${apkbuilder}" failonerror="yes">
<java classname="com.android.sdklib.build.ApkBuilderMain" failonerror="yes">
<classpath>
<path refid="android.sdklibs"/>
</classpath>
<arg file="${test.app.unsigned}" />
<arg value="-u" />
<arg value="-z" />
<arg file="${test.app.aapt}" />
<arg value="-f" />
<arg file="${dex.file}" />
</exec>
</java>
</target>
<target name ="-signapp" description="Signs the app under test">
<signjar jar="${app.unsigned}" signedjar="${app.signed}" keystore="${key.store}" storepass="${key.store.password}" alias="${key.alias}" keypass="${key.alias.password}" verbose="false" sigalg="MD5withRSA" digestalg="SHA1"/>
Expand Down
4 changes: 4 additions & 0 deletions recorder/resources/jquery1.7.2.js

Large diffs are not rendered by default.

130 changes: 130 additions & 0 deletions recorder/resources/recorder.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@


function botbotutil() {
this.attrLoc = ['id', 'class', 'name', 'href'];
this.typeLoc = ['input', 'img', 'a', 'select'];
this.attrvalue = {};
this.data = {};

this.getCollectedElementInfo = function (ele) {
var aValues = [];
this.getAllLocatorValues(ele);
var temp =this.attrvalue;
this.attrvalue={};
return temp;
};

this.getLocator = function () {
var tag = !this.attrvalue['tag'] ? '' : this.attrvalue['tag'];
var id = !this.attrvalue['id'] ? '' : this.attrvalue['id'];
var name = !this.attrvalue['name'] ? '' : this.attrvalue['name'];
var cls = !this.attrvalue['class'] ? '' : this.attrvalue['class'].replace(/\s/g, '.');
if (cls != '') this.attrvalue['class'] = cls;

var locator = tag + (!cls ? '' : "." + cls) + (!id ? '' : "#" + id) + (!name ? '' : '[name=\'' + name + '\']');

return locator;
};

this.getIndex = function (locator, ele) {
var elements = $(locator);
for (i in elements) {
if (elements[i] === $(ele)[0]) {
return i;
}
}
return null;
};

this.getTextValue = function (ele) {
var text = '';
if ($(ele).val() != '') {
text = $(ele).val();
}
return text;
};

this.getAllLocatorValues = function (ele) {

for (typ in this.typeLoc) {
if (this.typeLoc[typ] == $(ele)[0].nodeName.toLowerCase()) {
temp = ele;
this.attrvalue['tag'] = $(ele)[0].nodeName.toLowerCase();
break;
}
}
for (att in this.attrLoc) {
if ($(ele).attr(this.attrLoc[att])) {
this.attrvalue[this.attrLoc[att]] = $(ele).attr(this.attrLoc[att]);
}
}
if (this.attrvalue.length != 0 && (temp === null)) {
temp = ele;
this.attrvalue['tag'] = $(ele)[0].nodeName.toLowerCase();
}
if ($(ele).text() != '') {
var text = $(ele).text();
text=text.replace(/[\n\r\t]/g, "");
this.attrvalue['text'] = text;
}

var locator = this.getLocator();
if (locator != '') {
this.attrvalue['locator'] = locator;
}
var index = this.getIndex(locator, ele);
if (index != null) {
this.attrvalue['index'] = index;
}
};
}

var botbot = {

addListener:function () {
if (window._botbotEventInitialized) {
return;
}
window._botbotEventInitialized = true;
window._botbotutil=new botbotutil();
document.getElementsByTagName('body')[0].addEventListener('click', function () {
var ele = event.target;
var aValues = [];
var util = window._botbotutil;
var data = {};
var attrvalue = util.getCollectedElementInfo(ele);
for (key in attrvalue) {
aValues.push('"' + key + '=' + attrvalue[key] + '"');
}
data['command'] = 'clickwebelement';
data['args[0]'] = !attrvalue['locator'] ? '' : attrvalue['locator'];
if (attrvalue['index'] > 0) data['args[1]'] = attrvalue['index'];
data['args[0]-data'] = aValues;
window.irecorder.record(JSON.stringify(data));
}, true);

$('input[type="text"],input[type="textbox"], input[type="password"]').on('change', function (e) {
var ele = e.target;
var util = window._botbotutil;
var attrvalue = util.getCollectedElementInfo(ele);
var data = {};

var aValues = [];
data['command'] = 'enterwebtext';
data['args[0]'] = !attrvalue['locator'] ? '' : attrvalue['locator'];
if (attrvalue['index'] > 0) {
data['args[1]'] = attrvalue['index'];
data['args[2]'] = util.getTextValue(ele);
} else {
data['args[1]'] = util.getTextValue(ele);
}
for (key in attrvalue) {
aValues.push('"' + key + '=' + attrvalue[key] + '"');
}
data['args[0]-data'] = aValues;
window.irecorder.record(JSON.stringify(data));
});

console.log("Added bot-bot liteners");
}
};
File renamed without changes.
89 changes: 64 additions & 25 deletions recorder/src/org/imaginea/botbot/Command.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,28 @@
import java.util.Arrays;
import java.util.List;

import org.json.JSONException;
import org.json.JSONObject;

import android.content.res.Resources.NotFoundException;
import android.util.Log;
import android.view.MenuItem;
import android.view.View;

public class Command {
ViewClasses vc = new ViewClasses();

public Command() {

}

String userAction;
JSONObject json=new JSONObject();
String userAction="";
Object view;
List<Object> arguments;
int id = 0;
String viewClassName = "";
String commandData = "";

public Command() {

}

public void add(String command, Object view, Object... args) {
this.userAction = command;
this.view = view;
Expand All @@ -37,7 +42,16 @@ public void add(String command, Object view, Object... args) {
arguments.add(0, (String)view);
this.userAction="clicktext";
}

}

public void add(String command, String... args) {
this.userAction = command;
if(args.length==1 && args[0].equals("")){
this.arguments= new ArrayList<Object>();
}
else{
this.arguments = new ArrayList<Object>(Arrays.asList(args));
}
}

public void add(String command, View view, Object... args) {
Expand Down Expand Up @@ -67,6 +81,7 @@ public void add(String command, View view, Object... args) {
if (command.contentEquals("click")) {
this.userAction = "clickbyid";
}

} catch (NotFoundException e) {
//Escaping in case the rid resource is not found
}
Expand All @@ -90,39 +105,63 @@ private String getStringIdFromResource(View view, int id)
}
return rid;
}

private void createCommandData(){
try {
json.put("command", this.userAction);

public String getData() {
String data = "";
data = data.concat("\"command\":\"" + this.userAction + "\"");
data = data.concat(",\"viewClassName\":\"" + this.viewClassName + "\"");
int i=0;
for (Object args:arguments) {
data = data.concat(",\"args[" + i + "]\":\"" + args + "\"");
i++;
json.put("viewClassName", this.viewClassName);
for (int i = 0; i < arguments.size(); i++) {
json.put("args[" + i + "]", arguments.get(i));
}
commandData=json.toString();
commandData = commandData.replace("\"", "\\\"");

Log.i("bot-bot","command data is:"+commandData);
} catch (JSONException e) {
Log.i("bot-bot", "unable to generate the JSON data in command.");
Log.i("bot-bot", e.getMessage());
}
}

data = data.replace("\"", "\\\"");
data = "{".concat(data).concat("}");
return data;
public String getData() {
if(commandData.contentEquals("")) createCommandData();
return commandData;
}

public void add(String command) {
this.userAction = command;
this.arguments= new ArrayList<Object>();
public void add(String data) {
try{
JSONObject testJson= new JSONObject(data);
this.commandData=data;
}catch(JSONException jse){
json=new JSONObject();
try{
json.put("command", data);
}catch(JSONException e){
Log.i("bot-bot", "unable to generate the JSON data in command.");
Log.i("bot-bot", e.getMessage());
}
this.commandData=json.toString();
}
Log.i("bot-bot","Web Command data is:"+commandData);
this.commandData = this.commandData.replace("\\\"", "");
this.commandData = this.commandData.replace("\"", "\\\"");
}

@Override
public String toString() {
String retText;
try {
retText = "command =" + this.userAction + "; view=" + view.toString()
+ "; viewClassName=" + this.viewClassName + "; id=" + id
retText = "command =" + this.userAction + ";";
if(view!=null) retText=retText+"view=" + view.toString();
retText=retText+ "; viewClassName=" + this.viewClassName + "; id=" + id
+ "; args[0]=" + arguments.get(0).toString()
+ "; args[1]=" + arguments.get(1).toString()
+ "; args[2]=" + arguments.get(2).toString();
} catch (IndexOutOfBoundsException e) {
retText = "command =" + this.userAction + "; view=" + view.toString()
+ "; viewClassName=" + this.viewClassName + "; id=" + id
retText = "command =" + this.userAction + ";";
if(view!=null) retText=retText+"view=" + view.toString();
retText=retText + "; viewClassName=" + this.viewClassName + "; id=" + id
+ "; args=" + arguments.toString();
}
return retText;
Expand Down
19 changes: 16 additions & 3 deletions recorder/src/org/imaginea/botbot/CommandTransmitter.java
Original file line number Diff line number Diff line change
Expand Up @@ -195,10 +195,17 @@ String getSession(){
sb.append(line);
}
rd.close();
String status="";
String result = sb.toString();
String status = result.substring(
result.indexOf("<status>") + 8,
result.indexOf("</status>"));
//if(result.indexOf("<status>")>0 && result.indexOf("</status>")>0){

status = result.substring(
result.indexOf("<status>") + 8,
result.indexOf("</status>"));


//}

if (status.contentEquals("stopped")) {
recordID=1;
prevRecord=0;
Expand All @@ -212,6 +219,12 @@ String getSession(){
"Unable to get status of the record. Application will continue without recording");
Log.i("bot-bot","Url is : "+ sUrl + "/api/recordsessions/"+CommandTransmitter.sessionID);
Log.i("bot-bot", "Error is: "+e.toString());
}catch (Exception e) {
Log.i("bot-bot",
"Unable to get status of the record. Application will continue without recording");
Log.i("bot-bot","Url is : "+ sUrl + "/api/recordsessions/"+CommandTransmitter.sessionID);
Log.i("bot-bot", "Error is: "+e.toString());
session = CommandTransmitter.sessionID;
}
}
return session;
Expand Down
Loading