Appium - How to Validate if an object exists - android

I'm new to this forum and appium/android automation, I need help on verifying if an object exists on my app before I take the next action.
I tried using the following code below but is not even reaching my second print statement.
#Test
public void addContact() {
System.out.println( "Checking if Contact exists.... 111111 ");
WebElement e = driver.findElement(By.name("John Doe"));
System.out.println( "Checking if Contact exists.... 222222");
boolean contactExists = e.isDisplayed();
System.out.println( contactExists );
if (contactExists == true) {
System.out.println( "Contact exists.... ");
} else {
System.out.println( "Contact DOES NOT exists.... ");
}
}
Running this code here's appium console output... it just keeps looping through this and script fails.
info: [BOOTSTRAP] [info] Got command of type ACTION
info: [BOOTSTRAP] [debug] Got command action: find
info: [BOOTSTRAP] [debug] Finding John Doe using NAME with the contextId:
info: [BOOTSTRAP] [info] Returning result: {"value":"No element found","status":7}
info: Pushing command to appium work queue: ["find",{"strategy":"name","selector":"John Doe","context":"","multiple":false}]
info: [BOOTSTRAP] [info] Got data from client: {"cmd":"action","action":"find","params":{"strategy":"name","selector":"John Doe","context":"","multiple":false}}
is isDisplayed the right approach here or is there a better alternative to do this?
Cheers.... TIA

If you are using Appium 1.0+
By.name locating strategy has been deprecated.Please use some other stuffs like By.xpath etc.

In the newer version of appium you have "accessibility id".Use these instead.
Happy automating

Maybe the following will help you. I have the methods in my TestBase class:
protected static boolean isElementPresent(By by) {
driver.manage().timeouts().implicitlyWait(0, TimeUnit.SECONDS);
List<WebElement> list = driver.findElements(by);
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
if (list.size() == 0) {
return false;
} else {
return list.get(0).isDisplayed();
}
}
public boolean elementIsNotPresent(By by) {
try {
driver.manage().timeouts().implicitlyWait(0, TimeUnit.SECONDS);
return driver.findElements(by).isEmpty();
} finally {
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
}
}
Also, I use the following code to wait until some certain element on the screen:
WebDriverWait wait = new WebDriverWait(driver, 30);
wait.until(ExpectedConditions.elementToBeClickable(By
.xpath("//android.widget.Button[contains(#text, 'Log In')]")));
or:
WebDriverWait wait = new WebDriverWait(driver, 30);
wait.until(ExpectedConditions.presenceOfElementLocated(By
.xpath("//android.widget.TextView[contains(#resource-id, 'action_bar_title')]")));

Related

Error running 01 46, response: ...UNABLETOCONNECT

Getting the data from OBD II simulator to android application via Bluetooth successfully.
Now I am trying get the data from ELM327 device to android application.
I have an ELM327 device connected to my Car. Bluetooth connection happens by ECU connection fails with unable to connect error.
getting below error,
D:NetworkManagementSocketTagger: tagSocket(80) with statsTag=0xffffffff, statsUid=-1
E : Failed to run command. -> Error running 01 46, response: ...UNABLETOCONNECT
Could you please help me to resolve this issue.
i am trying to create an ionic obd-2 application for my university project. i am using "BluetoothSerial" in order to connect with obd simulator i have done all the settings required(that i know of) but i have hit a wall and i dont know what to do next. i connected to the bluetooth device and when is send the "ATZ" commands using bluetoothserial.write(obdcommand) i am getting "OK" can you please share with me how you connected with bluetoothserial or am i missing something...
I will post my code dow below.
obdcommands=['ATD','ATZ','ATE0','ATL0','ATS0','ATH0','ATAT2','ATSP0','0100', '0105\r', '010C'];
constructor(private bluetooth:BluetoothSerial,
private DataSrv:DataSrvService,
private action:ActionSheetController,
private permission:AndroidPermissions,
private alert: AlertController,
private toastctrl:ToastController) {
}
connect(dvc)
{
if(dvc.address=="")
this.showError("No Address");
else{
this.bluetooth.connect(dvc.address).subscribe(success=>
{
this.modal.dismiss(null, 'cancel');
this.presentToast("Connected Successfully");
this.blue=false;
this.deviceConnected();
this.bluetooth.available().then(tr=>{alert(tr)})
},error=>{
alert("Connect Error: "+error);
})
}
}
deviceConnected()
{
this.bluetooth.subscribe('\n').subscribe(success=>{
alert("Subscribed Successfully" +success);
})
}
async searchOBD()
{
for(let k=0;k<this.obdcommands.length;k++)
{
await this.bluetooth.write(this.obdcommands[k]).then( (success) => {
alert('Connected: '+this.obdcommands[k]+'Data: '+success );
},
(error) => {
alert('Reading failed: ' + error );
});
}
}

A piece of typescript is working as intended on my emulator but fails on Android

The error that I receive in my Chrome: Inspect log is as below:
"Error: Uncaught (in promise): TypeError: undefined is not a function↵TypeError: undefined is not a function↵ at file:///android_asset/www/build/main.js:101314:24↵ at t.invoke (file:///android_asset/www/build/polyfills.js:3:11562)↵ at Object.inner.inner.fork.onInvoke (file:///android_asset/www/build/main.js:4403:37)↵ at t.invoke (file:///android_asset/www/build/polyfills.js:3:11532)↵ at n.run (file:///android_asset/www/build/polyfills.js:3:6468)↵ at file:///android_asset/www/build/polyfills.js:3:3767↵ at t.invokeTask (file:///android_asset/www/build/polyfills.js:3:12256)↵ at Object.inner.inner.fork.onInvokeTask (file:///android_asset/www/build/main.js:4394:37)↵ at t.invokeTask (file:///android_asset/www/build/polyfills.js:3:12215)↵ at n.runTask (file:///android_asset/www/build/polyfills.js:3:7153)↵ at a (file:///android_asset/www/build/polyfills.js:3:2312)↵ at XMLHttpRequest.invoke (file:///android_asset/www/build/polyfills.js:3:13253)↵ at new Error (native)↵ at Error.d (file:///android_asset/www/build/polyfills.js:3:3991)↵ at l (file:///android_asset/www/build/polyfills.js:3:3244)↵ at file:///android_asset/www/build/polyfills.js:3:3798↵ at t.invokeTask (file:///android_asset/www/build/polyfills.js:3:12256)↵ at Object.inner.inner.fork.onInvokeTask (file:///android_asset/www/build/main.js:4394:37)↵ at t.invokeTask (file:///android_asset/www/build/polyfills.js:3:12215)↵ at n.runTask (file:///android_asset/www/build/polyfills.js:3:7153)↵ at a (file:///android_asset/www/build/polyfills.js:3:2312)↵ at XMLHttpRequest.invoke (file:///android_asset/www/build/polyfills.js:3:13253)"
This happens when I try to run the following
(res) => {
console.log(res);
if (res.receiver) {
///Check if msisdn exists
///If it does, select that item
var found = false;
(<any>Object).values(this.approvedBenifs).forEach(element => {
if (element.msisdn == res.receiver.FlashMsisdn) {
this.selectedBenif = this.approvedBenifs.indexOf(element);
found = true;
}
});
}
However, running this code in Chrome through my Ionic emulator works fine.
The line that seems fishy to me is obviously the one involving (<any>Object). Is the (<any>Object).values() method the problem here, and if so, what strategy can I use to get a collection of values from a specified array?
Edit
I've rewritten the code to be less weird, and it works:
var found = false;
for (let element of this.approvedBenifs) {
if (element.msisdn == res.receiver.FlashMsisdn) {
this.selectedBenif = this.approvedBenifs.indexOf(element);
found = true;
}
}
However, I'd still be interested to know why the (<any>Object).values() method seems to fail on Android.
Perhaps you could try removing the
(<any>Object).values
(I'm asssuming this.approvedBenifs is an array) and just directly iterate through the array.
this.approvedBenifs.forEach(element => {
if (element.msisdn == res.receiver.FlashMsisdn) {
this.selectedBenif = this.approvedBenifs.indexOf(element);
found = true;
}
});
To get a collection of keys just use Object.keys(ARRAY_NAME) which will return an array of keys on the array or object. You're currently fetching the values.

How to write test case for displaying of application page using appium?

i want to automate android application based on jquery mobile. now i am using the appium framework for testing. i have setup successfully and can open the application on mobile using the appium. now i want to write test cases to check the current page. but i am unable to find the selector element. i have tried various solutions but failed. here is my script.
"use strict";
require("./helpers/setup");
var wd = require("wd"),
_ = require('underscore'),
serverConfigs = require('./helpers/appium-servers');
describe("android simple", function () {
this.timeout(300000);
var driver;
var allPassed = true;
before(function () {
var serverConfig = process.env.npm_package_config_sauce ?
serverConfigs.sauce : serverConfigs.local;
driver = wd.promiseChainRemote(serverConfig);
require("./helpers/logging").configure(driver);
var desired = process.env.npm_package_config_sauce ?
_.clone(require("./helpers/caps").android18) :
_.clone(require("./helpers/caps").android19);
desired.app = require("./helpers/apps").androidApiCsm;
if (process.env.npm_package_config_sauce) {
desired.name = 'android - simple';
desired.tags = ['sample'];
}
return driver
.init(desired)
.setImplicitWaitTimeout(5000)
.contexts().then(function (contexts) { // get list of available views. Returns array: ["NATIVE_APP","WEBVIEW_1"]
driver.context(contexts[1]); // choose the webview context
});
});
after(function () {
return driver
.quit()
.finally(function () {
if (process.env.npm_package_config_sauce) {
return driver.sauceJobStatus(allPassed);
}
});
});
afterEach(function () {
allPassed = allPassed && this.currentTest.state === 'passed';
});
it("should find an elment and click on the button ",function(){
return driver.getCurrentActivity(
function(err,element){
console.log("using xpath err: ", err);
console.log("using xpath element: ", element);
});
return driver.elementByAccessibilityId('LoginForm',
function(err,element){
console.log("using xpath err: ", err);
console.log("using xpath element: ", element);
});
});
});
Here is the result.
npm run android-csm
android simple
> CALL init({"browserName":"","appium-version":"1.3","platformName":"Android","platformVersion":"4.4.2","deviceName":"Android Emulator","app":"http://localhost/mobileandroid-debug.apk"})
> POST /session {"desiredCapabilities":{"browserName":"","appium-version":"1.3","platformName":"Android","platformVersion":"4.4.2","deviceName":"Android Emulator","app":"http://localhost/mobileandroid-debug.apk"}}
Driving the web on session: 9bc4f487-6c3c-4896-b530-e61583e972bc
> RESPONSE setImplicitWaitTimeout(5000)
> CALL contexts()
> GET /session/:sessionID/contexts
> RESPONSE contexts() ["NATIVE_APP","WEBVIEW_com....."]
> CALL context("WEBVIEW_com.....")
> POST /session/:sessionID/context {"name":"WEBVIEW_com....."}
✓ should able to context switch
> CALL elementByAccessibilityId("LoginForm")
> POST /session/:sessionID/element {"using":"accessibility id","value":"LoginForm"}
> RESPONSE context("WEBVIEW_com....")
using xpath err: {"message":"[elementByAccessibilityId(\"LoginForm\")] Error response status: 7, , NoSuchElement - An element could not be located on the page using the given search parameters. Selenium error: An element could not be located on the page using the given search parameters.","status":7,"cause":{"status":7,"value":{"message":"An element could not be located on the page using the given search parameters."},"sessionId":"9bc4f487-6c3c-4896-b530-e61583e972bc"},"jsonwire-error":{"status":7,"summary":"NoS...
using xpath element: undefined
1) should find an elment and click on the button
1 failing
1) android simple should find an elment and click on the button :
Error: [elementByAccessibilityId("LoginForm")] Error response status: 7, , NoSuchElement - An element could not be located on the page using the given search parameters. Selenium error: An element could not be located on the page using the given search parameters.
at exports.newError (node_modules/wd/lib/utils.js:139:13)
at node_modules/wd/lib/callbacks.js:75:19
at node_modules/wd/lib/webdriver.js:174:5
at Request._callback (node_modules/wd/lib/http-utils.js:87:7)
at Request.self.callback (node_modules/request/request.js:368:22)
at Request.<anonymous> (node_modules/request/request.js:1219:14)
at IncomingMessage.<anonymous> (node_modules/request/request.js:1167:12)
at endReadableNT (_stream_readable.js:926:12)
at _combinedTickCallback (internal/process/next_tick.js:74:11)
at process._tickCallback (internal/process/next_tick.js:98:9)

Error: Could not get the Java version. Is Java installed?

I run Appium server:
➜ ~ appium
info: Welcome to Appium v1.3.5 (REV a124a15677e26b33db16e81c4b3b34d9c6b8cac9)
info: Appium REST http interface listener started on 0.0.0.0:4723
info: Console LogLevel: debug
info: --> POST /wd/hub/session {"desiredCapabilities":{"appPackage":"com.grindrapp.android","appActivity":".activity.SplashActivity","platformVersion":"4.4.2","browserName":"","platformName":"Android","deviceName":"10.0.0.9:5555"}}
info: Client User-Agent string: Apache-HttpClient/4.3.4 (java 1.5)
info: [debug] Didn't get app but did get Android package, will attempt to launch it on the device
info: [debug] Creating new appium session 090abe0c-36d9-4f9b-987a-f3b665045928
info: Starting android appium
info: [debug] Getting Java version
info: [debug] Cleaning up android objects
info: [debug] Cleaning up appium session
error: Failed to start an Appium session, err was: Error: Could not get the Java version. Is Java installed?
info: [debug] Error: Could not get the Java version. Is Java installed?
at /usr/local/lib/node_modules/appium/lib/devices/android/android-common.js:1040:17
at ChildProcess.exithandler (child_process.js:735:7)
at ChildProcess.emit (events.js:110:17)
at maybeClose (child_process.js:1008:16)
at Socket.<anonymous> (child_process.js:1176:11)
at Socket.emit (events.js:107:17)
at Pipe.close (net.js:476:12)
info: [debug] Responding to client with error: {"status":33,"value":{"message":"A new session could not be created. (Original error: Could not get the Java version. Is Java installed?)","origValue":"Could not get the Java version. Is Java installed?"},"sessionId":null}
info: <-- POST /wd/hub/session 500 316.738 ms - 222
^C
➜ ~ echo $JAVA_HOME
/Library/Java/JavaVirtualMachines/jdk1.7.0_76.jdk/Contents/Home
I try to run this code to post to Appium server:
public class AndroidTest {
private AppiumDriver driver;
#Before
public void setUp() throws Exception {
// File classpathRoot = new File(System.getProperty("user.dir"));
// File appDir = new File(classpathRoot, "../../../data/app/");
// File app = new File(appDir, "Facebook.apk");
DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setCapability(CapabilityType.BROWSER_NAME, "");
capabilities.setCapability("deviceName","10.0.0.9:5555");
capabilities.setCapability("platformVersion", "4.4.2");
capabilities.setCapability("platformName","Android");
//capabilities.setCapability("app", app.getCanonicalPath());
capabilities.setCapability("appPackage", "com.grindrapp.android");
capabilities.setCapability("appActivity", ".activity.SplashActivity");
driver = new AndroidDriver(new URL("http://127.0.0.1:4723/wd/hub"), capabilities);
}
but as you can see I get this error:
info: [debug] Error: Could not get the Java version. Is Java installed?
how can I fix this?
I'm trying to automatically open an app which i downloaded from the google play and I don't have its apk.
I think this is the final solution for your problem.
As always, make a backup copy of the file before editing.
Edit the file /usr/local/lib/node_modules/appium/lib/devices/android/android-common.js
In the else if(stderr) branch around line 1034:
else if (stderr) {
var firstLine = stderr.split("\n")[0];
if (new RegExp("java version").test(firstLine)) {
javaVersion = firstLine.split(" ")[2].replace(/"/g, '');
}
}
replace the code to read:
else if (stderr){
if(new RegExp("java version").test(stderr)){
var regex = "java version \"[0-9]+\.[0-9]+\.[0-9]+";
var stderrstring = '' + stderr + '';
var regmatch = stderrstring.match(regex);
javaVersion = '' + regmatch + '' //convert object to string
javaVersion.replace(/"/g,'');
}
}
The code should work with a regular java version response message plus the one that you are receiving.
The file is located here:
/usr/local/lib/node_modules/appium/lib/devices/android/android-common.js
The code we are concerned with starting at line 1029 is:
androidCommon.getJavaVersion = function (cb) {
exec("java -version", function (err, stdout, stderr) {
var javaVersion = null;
if (err) {
return cb(new Error("'java -version' failed. " + err));
} else if (stderr) {
var firstLine = stderr.split("\n")[0];
if (new RegExp("java version").test(firstLine)) {
javaVersion = firstLine.split(" ")[2].replace(/"/g, '');
}
}
if (javaVersion === null) {
return cb(new Error("Could not get the Java version. Is Java installed?"));
}
return cb(null, javaVersion);
});
};
I am unable to test this on my system, but I think that a successful execution of java -version would return its response on stdout and not stderr. I would change the code to provide more information as to what is happening and help debug it.
You are getting the JavaVersion = null message at the end of the listing which means that there is nothing returned in err and parsing of stderr is not setting JavaVersion. It does not tell you if there is anything in stderr nor does it even look at stdout.
Here is a revised code listing. If the output is indeed returned on stderr, the code will now at least print it out so you can see what is returned. I added the same code branch for stdout as it was not checked at all.
androidCommon.getJavaVersion = function (cb) {
exec("java -version", function (err, stdout, stderr) {
var javaVersion = null;
var firstLine = null;
if (err) {
return cb(new Error("'java -version' failed. " + err));
} else if (stderr) {
firstLine = stderr.split("\n")[0];
if (new RegExp("java version").test(firstLine)) {
javaVersion = firstLine.split(" ")[2].replace(/"/g, '');
}else{
return cb(new Error("Java version stderr string parse error: " + stderr));
}
} else if(stdout){
firstLine = stdout.split("\n")[0];
if (new RegExp("java version").test(firstLine)) {
javaVersion = firstLine.split(" ")[2].replace(/"/g, '');
}else{
return cb(new Error("Java version stdout string parse error: " + stdout));
}
}
if (javaVersion === null) {
return cb(new Error("Could not get the Java version. Is Java installed?"));
}
return cb(null, javaVersion);
});
}
So:
make a backup copy of android-commons.js
make the code change and give it a try.
This might work as written or the error messages will tell you what is being returned.
The code in android-common.js is looking for the java version number on the first line.
I had the similar issue, but my java -version returns result as
[~]$ java -version
Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF8
java version "1.7.0_76"
Java(TM) SE Runtime Environment (build 1.7.0_76-b13)
Java HotSpot(TM) 64-Bit Server VM (build 24.76-b04, mixed mode)
So I simply changed the code in android-common.js to split second line instead of first line
firstLine = stderr.split("\n")[0]; -> firstLine = stderr.split("\n")[1]

unable to connect to JSON service in android application of Titanium studio

i am trying to do login application which takes id and password..when i click on logi button then it will connect to our local server by JSON..with the specified URL..the code is..
var loginReq = Titanium.Network.createHTTPClient();
loginReq.onload = function()
{
var json = this.responseText; alert(json);
var response = JSON.parse(json);
if (response.data.status == "success")
{ alert("Welcome ");
}
else
{ alert(response.data.status);
}
};
loginReq.onerror = function(event)
{
alert(event.toSource());
//alert("Network error");
};
loginBtn.addEventListener('click',function(e)
{ if (username.value != '' && password.value != '')
{
var url = 'our local url action=login&id='+username.value+'&pwd='+password.value;
loginReq.open("POST",url);
loginReq.send();
}
else
{
alert("Username/Password are required");
}
});
Here it is not connecting our URl..so it is entering into loginReq.onerror function...instead of loginReq.onload function..why it is throwing run time error.. The same code working fine with Iphone..
The Run Time Error is..
TypeError:Cannot call property toSource in object{'source':[Ti.Network.HttpClient],specified url} is not a function,it is a object.
This is wat the error..please let me Know...
Apparently the toSource() function does not exist in android, as it is an object. Try debugging and see what the object event contains.
You could do that by adding a line above the alert line, and adding a debug line to it.
Look in debug mode and see all variables
"toSource()" is not a documented function for either platform, and I also do not see it in the source for Titanium Mobile. If you aren't getting the error on iOS, I'm guessing it is because the error handler isn't getting called. Perhaps your emulator or device does not have internet access, whereas your iOS simulator or device does?
Regardless, error handling in the HTTPClient normally looks something like this:
loginReq.onerror = function(e)
{
Ti.API.info("ERROR " + e.error);
alert(e.error);
};

Categories

Resources