I am using Appium 1.22.3 and webdriverIO5 for Android mobile automation
The DOM for the element I am trying to click on is as below:
<android.widget.Button content-desc="Sign in">
I have used different combinations of locators as below:
await $('android.widget.Button');
driver.elementsByAccessibilityId('Sign in');
$('Sign in');
$('id=Sign in')
findElementByAccessibilityId("Sign in");
dr.findElementByAccessibilityId("Sign in")
However none of these xpaths work and I get error as below:
2022-09-04 12:35:01:866 - [HTTP] {"using":"class name","value":"android.widget.Button"}
2022-09-04 12:35:01:869 - [debug] [W3C (b124862d)] Calling AppiumDriver.findElement() with args: ["class name","android.widget.Button","b124862d-91b8-4b4a-9d50-bba5b9b912f4"]
2022-09-04 12:35:01:869 - [debug] [BaseDriver] Valid locator strategies for this request: xpath, id, class name, accessibility id, css selector, -android uiautomator
2022-09-04 12:35:01:869 - [debug] [BaseDriver] Waiting up to 0 ms for condition
2022-09-04 12:35:01:869 - [debug] [WD Proxy] Matched '/element' to command name 'findElement'
2022-09-04 12:35:01:869 - [debug] [WD Proxy] Proxying [POST /element] to [POST http://127.0.0.1:8200/wd/hub/session/0900bfc4-1ae4-4c76-895d-3203dca78bcc/element] with body: {"strategy":"class name","selector":"android.widget.Button","context":"","multiple":false}
2022-09-04 12:35:02:441 - [WD Proxy] Got response with status 404: {"sessionId":"0900bfc4-1ae4-4c76-895d-3203dca78bcc","value":{"error":"no such element","message":"An element could not be located on the page using the given search parameters","stacktrace":"io.appium.uiautomator2.common.exceptions.ElementNotFoundException: An element could not be located on the page using the given search parameters\n\tat io.appium.uiautomator2.handler.FindElement.safeHandle(FindElement.java:70)\n\tat io.appium.uiautomator2.handler.request.SafeRequestHandler.handle(SafeRequestHandler.java:59)\n\tat io.appium.uiautomator2.server.AppiumServlet.handleRequest(AppiumServlet.java:266)\n\tat io.appium.uiautomator2.server.AppiumServlet.handleHttpRequest(AppiumServlet.java:260)\n\tat io.appium.uiautomator2.http.ServerHandler.channelRead(ServerHandler.java:68)\n\tat io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:366)\n\tat io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:352)\n\tat io.netty.chann...
2022-09-04 12:35:02:441 - [debug] [W3C] Matched W3C error code 'no such element' to NoSuchElementError
2022-09-04 12:35:02:454 - [debug] [W3C (b124862d)] Encountered internal error running command: NoSuchElementError: An element could not be located on the page using the given search parameters.
Appreciate any help on how to identify the correct locator here
Thanks. I was able to use let el = await $('//android.widget.Button[#content-desc="Sign in"]'); successfully finally!
Related
I starting to test a React Native app with Appium and Weddriver.io via the XCIUTest driver (documented here and here), initially on iOS targeting a simulator. It's early days: I've got the framework installed and running and set up an initial test - in which I want to click a T&C checkbox and then click a submit button on the initial welcome screen of my app. However neither the "click" nor the "touchAction" commands do anything - they don't trigger the onPress action callback or check the checkbox.
The component selectors are working OK, as I can query the "label" of the elements selected and they are correct (and if I purposefully break the accessibility id I get errors). I can also write to an field which I added for testing and I can change the text value to another string from the test, so I know I've got it generally set up and communicating with my app in the simulator OK.
I am targeting the BundleId of an already installed app (rather than a Zip to install which is another method).
So why might the click or touch actions not be triggering their behaviour?
Are there pitfalls around permissions, capabilities or security issues in Appium?
Should I be using "click" or "touch" in a React Native tests?
I am using React Native Base but I have replaced those UI components with simpler ones from React Native to remove that complication.
There is debug logging in the onPress callback, so if I click the button manually I see the logs, but commands from the Mocha tests don't log the attempt nor perform any actions.
Relevant package.json dependency versions:
dependencies:
"native-base": "~3.4",
"react": "17.0.2",
"react-native": "0.67.4",
dev-dependencies:
"#babel/core": "^7.17.10",
"#babel/preset-env": "^7.17.10",
"#babel/register": "^7.17.10",
"#babel/runtime": "^7.17.10",
"chai": "^4.1.2",
"mocha": "^8.0.1",
"webdriverio": "^7.20.9"
I have Appium v8.5.5 installed globally, running in a terminal.
node: v16.15.0, npm: v8.5.5
I have tried many things, like waitForDisplayed, clicking the button before and/or after the successful input field text-entry, adding a and clicking or touching that. I don't see any errors or warnings.
e.g. in my component (the checkbox and button are real, the input and link were added just for testing)
async function onClickAgree() {
console.log('HelpScreen.onClickAgree')
}
...
<Checkbox accessibilityLabel={ 'help_agree_checkbox' }
accessible={true}
isChecked={agree}
onChange={onChangeAgreeCheckbox}
value="agree"
label="Accept terms and conditions"
marginX="30"/>
<Button accessibilityLabel={ 'help_agree_submit_button' }
accessible={true}
width={300}
onPress={() => onClickAgree()}
title="Get Started"
>
Get Started
</Button>
<Link
accessibilityLabel="help_agree_test_link"
accessible={true}
onPress={onClickAgree}>
Test link
</Link>
<Input accessibilityLabel={ 'help_agree_test_input' }
accessible={true}
value={testInputContent} onChangeText={setTestInputContent} minWidth={200}></Input>
and in the test case:
import { remote } from 'webdriverio';
const opts = {
path: '/wd/hub',
port: 4723,
capabilities: {
automationName: "XCUITest",
platformName: "iOS",
deviceName: "iPad Pro (12.9-inch) (3rd generation)",
platformVersion: "13.2",
appPackage: "com.mydomain.myapp", // my app's bundleId
}
}
describe('Initial test...', function (){
let client;
beforeEach(async function () {
client = await remote(opts);
});
after(async function () {
await client.deleteSession()
})
it('should do a test', async function () {
const button = await client.$("~help_agree_submit_button")
// await button.click() // doesn't work!
await button.touchAction('tap') // doesn't work!
await client.$("~help_agree_submit_button").click()// doesn't work!
//
// TODO: why don't any of the Tap/Clicks work??
const link = await client.$("~help_agree_test_link")
await link.click() // doesn't work!
await link.touchAction('tap') // doesn't work!
//
const input = await client.$("~help_agree_test_input")
await input.setValue('QA testing injection content') // works
//
await link.click() // doesn't work!
await link.touchAction('tap') // doesn't work!
//
await input.setValue('QA2 testing injection content') // works!
//
await button.click() // doesn't work!
await button.touchAction('tap')// doesn't work!
//
const field = await client.$("~help_agree_checkbox")
// await field.waitForClickable({ timeout: 3000 }) // no such method, webdriverio docs: not supported in native!
await field.waitForDisplayed({ timeout: 3000 })
// const field = await client.$("Checkbox");
// const field = await client.$("ForwardRef(Checkbox)") // invalid but this is the name from the inspector
await field.click() // doesn't work
await field.touchAction('tap') // doesn't work...
...
The logs from the test runner show the Click and Touch commands being sent, and they seem similar to the successful POST for the input which works, so I can't see anything failing there.
2022-08-14T10:17:56.761Z INFO webdriver: COMMAND elementClick("05010000-0000-0000-8992-000000000000")
2022-08-14T10:17:56.761Z INFO webdriver: [POST] http://127.0.0.1:4723/wd/hub/session/11d60dce-5632-4800-a836-ca34623af0c1/element/05010000-0000-0000-8992-000000000000/click
2022-08-14T10:17:56.935Z INFO webdriver: COMMAND findElement("accessibility id", "help_agree_test_link")
2022-08-14T10:17:56.935Z INFO webdriver: [POST] http://127.0.0.1:4723/wd/hub/session/11d60dce-5632-4800-a836-ca34623af0c1/element
2022-08-14T10:17:56.935Z INFO webdriver: DATA { using: 'accessibility id', value: 'help_agree_test_link' }
2022-08-14T10:17:57.033Z INFO webdriver: RESULT {
'element-6066-11e4-a52e-4f735466cecf': '06010000-0000-0000-8992-000000000000',
ELEMENT: '06010000-0000-0000-8992-000000000000'
}
2022-08-14T10:17:57.036Z INFO webdriver: COMMAND elementClick("06010000-0000-0000-8992-000000000000")
2022-08-14T10:17:57.036Z INFO webdriver: [POST] http://127.0.0.1:4723/wd/hub/session/11d60dce-5632-4800-a836-ca34623af0c1/element/06010000-0000-0000-8992-000000000000/click
2022-08-14T10:17:57.287Z INFO webdriver: COMMAND touchPerform(<object>)
2022-08-14T10:17:57.287Z INFO webdriver: [POST] http://127.0.0.1:4723/wd/hub/session/11d60dce-5632-4800-a836-ca34623af0c1/touch/perform
2022-08-14T10:17:57.287Z INFO webdriver: DATA { actions: [ { action: 'tap', options: [Object] } ] }
2022-08-14T10:17:58.007Z INFO webdriver: COMMAND findElement("accessibility id", "help_agree_test_input")
2022-08-14T10:17:58.007Z INFO webdriver: [POST] http://127.0.0.1:4723/wd/hub/session/11d60dce-5632-4800-a836-ca34623af0c1/element
2022-08-14T10:17:58.007Z INFO webdriver: DATA { using: 'accessibility id', value: 'help_agree_test_input' }
2022-08-14T10:17:58.180Z INFO webdriver: RESULT {
'element-6066-11e4-a52e-4f735466cecf': '07010000-0000-0000-8992-000000000000',
ELEMENT: '07010000-0000-0000-8992-000000000000'
}
2022-08-14T10:17:58.184Z INFO webdriver: COMMAND elementClear("07010000-0000-0000-8992-000000000000")
2022-08-14T10:17:58.184Z INFO webdriver: [POST] http://127.0.0.1:4723/wd/hub/session/11d60dce-5632-4800-a836-ca34623af0c1/element/07010000-0000-0000-8992-000000000000/clear
2022-08-14T10:17:58.283Z INFO webdriver: COMMAND elementSendKeys("07010000-0000-0000-8992-000000000000", "QA testing injection content")
2022-08-14T10:17:58.284Z INFO webdriver: [POST] http://127.0.0.1:4723/wd/hub/session/11d60dce-5632-4800-a836-ca34623af0c1/element/07010000-0000-0000-8992-000000000000/value
2022-08-14T10:17:58.284Z INFO webdriver: DATA { text: 'QA testing injection content' }
2022-08-14T10:17:58.886Z INFO webdriver: COMMAND elementClick("06010000-0000-0000-8992-000000000000")
2022-08-14T10:17:58.886Z INFO webdriver: [POST] http://127.0.0.1:4723/wd/hub/session/11d60dce-5632-4800-a836-ca34623af0c1/element/06010000-0000-0000-8992-000000000000/click
2022-08-14T10:18:01.500Z INFO webdriver: COMMAND touchPerform(<object>)
2022-08-14T10:18:01.501Z INFO webdriver: [POST] http://127.0.0.1:4723/wd/hub/session/11d60dce-5632-4800-a836-ca34623af0c1/touch/perform
2022-08-14T10:18:01.501Z INFO webdriver: DATA { actions: [ { action: 'tap', options: [Object] } ] }
2022-08-14T10:18:01.823Z INFO webdriver: COMMAND elementClear("07010000-0000-0000-8992-000000000000")
2022-08-14T10:18:01.823Z INFO webdriver: [POST] http://127.0.0.1:4723/wd/hub/session/11d60dce-5632-4800-a836-ca34623af0c1/element/07010000-0000-0000-8992-000000000000/clear
2022-08-14T10:18:01.908Z INFO webdriver: COMMAND elementSendKeys("07010000-0000-0000-8992-000000000000", "QA2 testing injection content")
2022-08-14T10:18:01.909Z INFO webdriver: [POST] http://127.0.0.1:4723/wd/hub/session/11d60dce-5632-4800-a836-ca34623af0c1/element/07010000-0000-0000-8992-000000000000/value
2022-08-14T10:18:01.909Z INFO webdriver: DATA { text: 'QA2 testing injection content' }
2022-08-14T10:18:02.506Z INFO webdriver: COMMAND elementClick("05010000-0000-0000-8992-000000000000")
2022-08-14T10:18:02.507Z INFO webdriver: [POST] http://127.0.0.1:4723/wd/hub/session/11d60dce-5632-4800-a836-ca34623af0c1/element/05010000-0000-0000-8992-000000000000/click
2022-08-14T10:18:05.278Z INFO webdriver: COMMAND touchPerform(<object>)
2022-08-14T10:18:05.278Z INFO webdriver: [POST] http://127.0.0.1:4723/wd/hub/session/11d60dce-5632-4800-a836-ca34623af0c1/touch/perform
2022-08-14T10:18:05.278Z INFO webdriver: DATA { actions: [ { action: 'tap', options: [Object] } ] }
2022-08-14T10:18:05.552Z INFO webdriver: COMMAND findElement("accessibility id", "help_agree_checkbox")
2022-08-14T10:18:05.552Z INFO webdriver: [POST] http://127.0.0.1:4723/wd/hub/session/11d60dce-5632-4800-a836-ca34623af0c1/element
2022-08-14T10:18:05.552Z INFO webdriver: DATA { using: 'accessibility id', value: 'help_agree_checkbox' }
2022-08-14T10:18:05.645Z INFO webdriver: RESULT {
'element-6066-11e4-a52e-4f735466cecf': '03010000-0000-0000-8992-000000000000',
ELEMENT: '03010000-0000-0000-8992-000000000000'
}
2022-08-14T10:18:05.649Z INFO webdriver: COMMAND isElementDisplayed("03010000-0000-0000-8992-000000000000")
2022-08-14T10:18:05.649Z INFO webdriver: [GET] http://127.0.0.1:4723/wd/hub/session/11d60dce-5632-4800-a836-ca34623af0c1/element/03010000-0000-0000-8992-000000000000/displayed
2022-08-14T10:18:05.701Z INFO webdriver: RESULT true
2022-08-14T10:18:05.703Z INFO webdriver: COMMAND elementClick("03010000-0000-0000-8992-000000000000")
2022-08-14T10:18:05.703Z INFO webdriver: [POST] http://127.0.0.1:4723/wd/hub/session/11d60dce-5632-4800-a836-ca34623af0c1/element/03010000-0000-0000-8992-000000000000/click
2022-08-14T10:18:05.874Z INFO webdriver: COMMAND touchPerform(<object>)
2022-08-14T10:18:05.874Z INFO webdriver: [POST] http://127.0.0.1:4723/wd/hub/session/11d60dce-5632-4800-a836-ca34623af0c1/touch/perform
2022-08-14T10:18:05.874Z INFO webdriver: DATA { actions: [ { action: 'tap', options: [Object] } ] }
2022-08-14T10:18:06.154Z INFO webdriver: COMMAND getElementAttribute("03010000-0000-0000-8992-000000000000", "label")
2022-08-14T10:18:06.154Z INFO webdriver: [GET] http://127.0.0.1:4723/wd/hub/session/11d60dce-5632-4800-a836-ca34623af0c1/element/03010000-0000-0000-8992-000000000000/attribute/label
2022-08-14T10:18:06.196Z INFO webdriver: RESULT help_agree_checkbox
label is help_agree_checkbox
2022-08-14T10:18:06.197Z INFO webdriver: COMMAND isElementSelected("03010000-0000-0000-8992-000000000000")
2022-08-14T10:18:06.197Z INFO webdriver: [GET] http://127.0.0.1:4723/wd/hub/session/11d60dce-5632-4800-a836-ca34623af0c1/element/03010000-0000-0000-8992-000000000000/selected
2022-08-14T10:18:06.244Z INFO webdriver: RESULT false
The logs from the Appium server show similar POST traffic for both the click/touch and the successful input-edit, so I can't see an obvious failure point there. e.g."
[HTTP] {"text":"QA2 testing injection content"}
[debug] [W3C (11d60dce)] Calling AppiumDriver.setValue() with args: ["QA2 testing injection content","07010000-0000-0000-8992-000000000000","11d60dce-5632-4800-a836-ca34623af0c1"]
[debug] [XCUITest] Executing command 'setValue'
[debug] [WD Proxy] Matched '/element/07010000-0000-0000-8992-000000000000/value' to command name 'setValue'
[debug] [Protocol Converter] Added 'text' property "QA2 testing injection content" to 'setValue' request body
[debug] [WD Proxy] Proxying [POST /element/07010000-0000-0000-8992-000000000000/value] to [POST http://127.0.0.1:8100/session/3D972CDD-B64A-4B57-ADCC-F2057E0C4DA3/element/07010000-0000-0000-8992-000000000000/value] with body: {"value":["Q","A","2"," ","t","e","s","t","i","n","g"," ","i","n","j","e","c","t","i","o","n"," ","c","o","n","t","e","n","t"],"text":"QA2 testing injection content"}
[debug] [WD Proxy] Got response with status 200: {"value":null,"sessionId":"3D972CDD-B64A-4B57-ADCC-F2057E0C4DA3"}
[debug] [W3C (11d60dce)] Responding to client with driver.setValue() result: null
[HTTP] <-- POST /wd/hub/session/11d60dce-5632-4800-a836-ca34623af0c1/element/07010000-0000-0000-8992-000000000000/value 200 595 ms - 14
[HTTP]
[HTTP] --> POST /wd/hub/session/11d60dce-5632-4800-a836-ca34623af0c1/element/05010000-0000-0000-8992-000000000000/click
[HTTP] {}
[W3C (11d60dce)] Driver proxy active, passing request on via HTTP proxy
[debug] [XCUITest] Executing command 'proxyReqRes'
[debug] [WD Proxy] Matched '/wd/hub/session/11d60dce-5632-4800-a836-ca34623af0c1/element/05010000-0000-0000-8992-000000000000/click' to command name 'click'
[debug] [WD Proxy] Proxying [POST /wd/hub/session/11d60dce-5632-4800-a836-ca34623af0c1/element/05010000-0000-0000-8992-000000000000/click] to [POST http://127.0.0.1:8100/session/3D972CDD-B64A-4B57-ADCC-F2057E0C4DA3/element/05010000-0000-0000-8992-000000000000/click] with body: {}
[debug] [WD Proxy] Got response with status 200: {"value":null,"sessionId":"3D972CDD-B64A-4B57-ADCC-F2057E0C4DA3"}
[WD Proxy] Replacing sessionId 3D972CDD-B64A-4B57-ADCC-F2057E0C4DA3 with 11d60dce-5632-4800-a836-ca34623af0c1
[HTTP] <-- POST /wd/hub/session/11d60dce-5632-4800-a836-ca34623af0c1/element/05010000-0000-0000-8992-000000000000/click 200 2768 ms - 65
[HTTP]
[HTTP] --> POST /wd/hub/session/11d60dce-5632-4800-a836-ca34623af0c1/touch/perform
[HTTP] {"actions":[{"action":"tap","options":{"element":"05010000-0000-0000-8992-000000000000"}}]}
[debug] [W3C (11d60dce)] Calling AppiumDriver.performTouch() with args: [[{"action":"tap","options":{"element":"05010000-0000-0000-8992-000000000000"}}],"11d60dce-5632-4800-a836-ca34623af0c1"]
[debug] [XCUITest] Executing command 'performTouch'
[debug] [XCUITest] Received the following touch action: tap(options={"element":"05010000-0000-0000-8992-000000000000"})
[debug] [WD Proxy] Proxying [POST /wda/touch/perform] to [POST http://127.0.0.1:8100/session/3D972CDD-B64A-4B57-ADCC-F2057E0C4DA3/wda/touch/perform] with body: {"actions":[{"action":"tap","options":{"element":"05010000-0000-0000-8992-000000000000"}}]}
[debug] [WD Proxy] Got response with status 200: {"value":null,"sessionId":"3D972CDD-B64A-4B57-ADCC-F2057E0C4DA3"}
[debug] [W3C (11d60dce)] Responding to client with driver.performTouch() result: null
[HTTP] <-- POST /wd/hub/session/11d60dce-5632-4800-a836-ca34623af0c1/touch/perform 200 271 ms - 14
[HTTP]
It turns out the automation is clicking at the wrong co-ordinates.
I found there are additional logs you can enable to help debug.
capabilities.showIOSLog streams iOS simulator debugging output,
which goes into the Appium server logs.
logLevel:debug sets Webdriver to emit lower level logging which turns up in the Mocha test logs as additional "DEBUG" entries.
With these enabled I noticed a difference between the x,y position returned by the Appium/Webdriver Get Element Rect() or Location() commands and the iOS XCSynthesizedEventRecord activity which is triggered by the Click command.
Appium logs:
[IOSSimulatorLog] [IOS_SYSLOG_ROW] <XCSynthesizedEventRecord 'tap'>
[IOSSimulatorLog] [IOS_SYSLOG_ROW] Path 1:
[IOSSimulatorLog] [IOS_SYSLOG_ROW] Touch down at 542.5, 613.8, offset=0.00s
Mocha output:
/2E000000-0000-0000-67C7-000000000000/rect
2022-08-19T02:52:53.698Z INFO webdriver: RESULT { y: 595, x: 487, width: 111, height: 38 }
Considering where the x,y is registered "X axis position of the top-left corner of the web element " - W3C
So the button rect is [595, 487] to [706,525]
So 542.5, 613.8 would miss it.
I finally got the click to register using this minimum offset. Interestingly clicking right on the x,y doesn't trigger it.
client.touchPerform([
{ action: 'press', options: { x: rect.x+1, y: rect.y+1 }},
{ action: 'release' }
]);
Finally in my app console debug logs:
LOG HelpScreen.onClickAgree !!!!
So I still have the remaining problem of why or who is getting the coordinates wrong (e.g. XCUITest, iOS, React Native, React Native Base or my app layout), but at least I know what the problem is - and it's nothing to do with security, permissions or the test platform setup.
I have this HTML file, test_xpath.htm:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
</head>
<body>
<h1>Hello World!</h1>
<div>
Click me!
</div>
</body>
</html>
In the folder of this file, I run PHP CLI > 5.4 as a server like this:
php -S localhost:8080
... so the HTML page is available at http://localhost:8080/test_xpath.htm.
Then I run this SlimerJS code:
// run with:
// SLIMERJSLAUNCHER=/usr/bin/firefox46 /home/USERNAME/.nvm/versions/node/v4.0.0/lib/node_modules/casperjs/bin/casperjs --engine=slimerjs test_xpath.js
var casper = require('casper').create({
verbose: true,
logLevel: 'debug',
userAgent: 'Mozilla/5.0 (X11; Linux i686; rv:43.0) Gecko/20100101 Firefox/43.0',
viewportSize: {width: 1024, height: 768},
pageSettings: {
loadImages: false,//The script is much faster when this field is set to false
loadPlugins: false,
}
});
casper.on("url.changed", function(){
this.then(function(){
this.echo("URL changed " + this.getCurrentUrl()); //getTitle());
});
});
casper.on('remote.message', function(message) {
this.echo('remote message caught: ' + message);
});
casper.start().thenOpen("http://localhost:8080/test_xpath.htm", function() {
console.log("website opened");
});
// set this to true to run - causes "[error] [remote] findAll(): invalid selector provided "//*[text()="Click me!"]":SyntaxError: An invalid or illegal string was specified"
if (false) {
casper.waitForSelector('//*[text()="Click me!"]', function() {
this.echo("I'm sure //*[text()='Click me!'] is available in the DOM");
});
}
casper.then(function(){
this.evaluate(function(){
var aelem = __utils__.getElementByXPath('//*[text()="Click me!"]');
aelem.click();
});
});
casper.then(function(){
casper.capture('TestCapture.png');
});
casper.run();
If I run the JS code as is - that is, the waitForSelector part is disabled by if(false) - then everything runs fine.
However, if I enable that part by changing the if(false) to if(true), I get this:
$ SLIMERJSLAUNCHER=/usr/bin/firefox46 /home/USERNAME/.nvm/versions/node/v4.0.0/lib/node_modules/casperjs/bin/casperjs --engine=slimerjs test_xpath.js
[info] [phantom] Starting...
[info] [phantom] Running suite: 5 steps
[debug] [phantom] opening url: http://localhost:8080/test_xpath.htm, HTTP GET
[debug] [phantom] Navigation requested: url=http://localhost:8080/test_xpath.htm, type=Undefined, willNavigate=true, isMainFrame=true
[debug] [phantom] url changed to "http://localhost:8080/test_xpath.htm"
[debug] [phantom] Successfully injected Casper client-side utilities
[info] [phantom] Step anonymous 2/6 http://localhost:8080/test_xpath.htm (HTTP 200)
URL changed http://localhost:8080/test_xpath.htm
[info] [phantom] Step anonymous 2/6: done in 235ms.
[info] [phantom] Step anonymous 3/6 http://localhost:8080/test_xpath.htm (HTTP 200)
website opened
[info] [phantom] Step anonymous 3/6: done in 258ms.
[info] [phantom] Step _step 4/6 http://localhost:8080/test_xpath.htm (HTTP 200)
[info] [phantom] Step _step 4/6: done in 276ms.
[error] [remote] findAll(): invalid selector provided "//*[text()="Click me!"]":SyntaxError: An invalid or illegal string was specified
[error] [remote] findAll(): invalid selector provided "//*[text()="Click me!"]":SyntaxError: An invalid or illegal string was specified
[error] [remote] findAll(): invalid selector provided "//*[text()="Click me!"]":SyntaxError: An invalid or illegal string was specified
[error] [remote] findAll(): invalid selector provided "//*[text()="Click me!"]":SyntaxError: An invalid or illegal string was specified
[error] [remote] findAll(): invalid selector provided "//*[text()="Click me!"]":SyntaxError: An invalid or illegal string was specified
....
I truly don't understand this, because http://docs.casperjs.org/en/latest/modules/casper.html#waitforselector says:
Waits until an element matching the provided selector expression exists in remote DOM to process any next step
... where http://docs.casperjs.org/en/latest/selectors.html says:
CasperJS makes a heavy use of selectors in order to work with the DOM, and can transparently use either CSS3 or XPath expressions.
So, XPath should be OK - what's more, I'm using THE EXACT SAME XPATH in:
var aelem = __utils__.getElementByXPath('//*[text()="Click me!"]');
... and there it works, but it fails in:
casper.waitForSelector('//*[text()="Click me!"]', function() { ....
Why does this happen - where am I going wrong? And how can I use this XPath in waitForSelector, if it's possible?
If you pass a string into the waitForSelector() function, it would be interpreted as a CSS selector. To have it work with an XPath expression pass in an object explicitly specifying the selector type:
selectorObject = {
type: 'xpath',
path: '//*[text()="Click me!"]'
}
casper.waitForSelector(selectorObject, function() {
// ...
});
You can solve it with waitForText() as well, sample here.
I'm trying to mimic browser behavior on a site built with ASP, which seems to use a lot of javascript based links and UI using CasperJS. I'm pretty stuck, and not sure how what to do next.
I'm using:casperjs1.1.0-beta3,phantomjs1.9.8, and the site url is https://icsid.worldbank.org/apps/ICSIDWEB/cases/Pages/AdvancedSearch.aspx
This is the HTML link I want to click on:
<td>
3
</td>
The site has some SSL configuration problems, so CasperJS is run with some additional flags to work: casperjs --ignore-ssl-errors=true --ssl-protocol=tlsv1 icsid.js
icsid.js just tries to open the site and click on a link to get to the next page of results. I want to check all results.
var casper = require('casper').create({
clientScripts: ["./jquery.min.js"],
verbose: true,
logLevel: 'debug',
pageSettings: {
loadImages: false,
loadPlugins: false,
userAgent: 'Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.2 Safari/537.36',
}
});
casper.start('https://icsid.worldbank.org/apps/ICSIDWEB/cases/Pages/AdvancedSearch.aspx', function(){});
casper.then(function() {
this.wait(5000);
this.capture('screenshot0.png');
casper.then(function(){
var text = this.evaluate(function(){
return jQuery('.gdcol a')[0].text;
});
console.log('text: ' + text);
this.evaluate(function(){
// try to go to second page
return jQuery('a').filter(function(index) { return $(this).text() === "2"; })[0].click();
});
});
casper.then(function(){
this.wait(5000);
var size = this.evaluate(function(){
return jQuery('.gdcol a').size();
});
console.log('size: ' + size);
// if successfully clicked and changed url, the link text will change
var text = this.evaluate(function(){
return jQuery('.gdcol a')[0].text;
});
console.log('text: ' + text);
// if it's still on the first page, this will be null
var page = this.evaluate(function(){
return jQuery('a').filter(function(index) { return $(this).text() === "1"; })[0].text;
});
console.log('page: ' + page);
// if it's on the second page, this will be null
var page = this.evaluate(function(){
return jQuery('a').filter(function(index) { return $(this).text() === "2"; })[0].text;
});
console.log('page: ' + page);
this.capture('screenshot1.png');
});
});
casper.run();
This is the resulting log:
[info] [phantom] Starting...
[info] [phantom] Running suite: 3 steps
[debug] [phantom] opening url: https://icsid.worldbank.org/apps/ICSIDWEB/cases/Pages/AdvancedSearch.aspx, HTTP GET
[debug] [phantom] Navigation requested: url=https://icsid.worldbank.org/apps/ICSIDWEB/cases/Pages/AdvancedSearch.aspx, type=Other, willNavigate=true, isMainFrame=true
[debug] [phantom] url changed to "https://icsid.worldbank.org/apps/ICSIDWEB/cases/Pages/AdvancedSearch.aspx"
2015-07-23 11:48:31.255 phantomjs[10699:d13] CoreText performance note: Client called CTFontCreateWithName() using name "Arial" and got font with PostScript name "ArialMT". For best performance, only use PostScript names when calling this API.
2015-07-23 11:48:31.256 phantomjs[10699:d13] CoreText performance note: Set a breakpoint on CTFontLogSuboptimalRequest to debug.
2015-07-23 11:48:31.278 phantomjs[10699:d13] CoreText performance note: Client called CTFontCreateWithName() using name "Arial" and got font with PostScript name "ArialMT". For best performance, only use PostScript names when calling this API.
2015-07-23 11:48:31.279 phantomjs[10699:d13] CoreText performance note: Client called CTFontCreateWithName() using name "Arial" and got font with PostScript name "ArialMT". For best performance, only use PostScript names when calling this API.
2015-07-23 11:48:31.280 phantomjs[10699:d13] CoreText performance note: Client called CTFontCreateWithName() using name "Arial" and got font with PostScript name "ArialMT". For best performance, only use PostScript names when calling this API.
2015-07-23 11:48:31.280 phantomjs[10699:d13] CoreText performance note: Client called CTFontCreateWithName() using name "Arial" and got font with PostScript name "ArialMT". For best performance, only use PostScript names when calling this API.
2015-07-23 11:48:31.479 phantomjs[10699:d13] CoreText performance note: Client called CTFontCreateWithName() using name "Arial" and got font with PostScript name "ArialMT". For best performance, only use PostScript names when calling this API.
2015-07-23 11:48:31.480 phantomjs[10699:d13] CoreText performance note: Client called CTFontCreateWithName() using name "Arial" and got font with PostScript name "ArialMT". For best performance, only use PostScript names when calling this API.
[debug] [phantom] Automatically injected ./jquery.min.js client side
[debug] [phantom] Successfully injected Casper client-side utilities
[info] [phantom] Step anonymous 2/3 https://icsid.worldbank.org/apps/ICSIDWEB/cases/Pages/AdvancedSearch.aspx (HTTP 200)
[info] [phantom] Step anonymous 2/3: done in 1886ms.
[info] [phantom] Step anonymous 3/3 https://icsid.worldbank.org/apps/ICSIDWEB/cases/Pages/AdvancedSearch.aspx (HTTP 200)
[debug] [phantom] Capturing page to /Users/yubrew/app/lib/tasks/screenshot0.png
[info] [phantom] Capture saved to /Users/yubrew/app/lib/tasks/screenshot0.png
[info] [phantom] Step anonymous 3/3: done in 2347ms.
[info] [phantom] Step _step 4/6 https://icsid.worldbank.org/apps/ICSIDWEB/cases/Pages/AdvancedSearch.aspx (HTTP 200)
[info] [phantom] Step _step 4/6: done in 2351ms.
[info] [phantom] wait() finished waiting for 5000ms.
[info] [phantom] Step anonymous 5/6 https://icsid.worldbank.org/apps/ICSIDWEB/cases/Pages/AdvancedSearch.aspx (HTTP 200)
text: ARB/15/30
[info] [phantom] Step anonymous 5/6: done in 7377ms.
[info] [phantom] Step anonymous 6/6 https://icsid.worldbank.org/apps/ICSIDWEB/cases/Pages/AdvancedSearch.aspx (HTTP 200)
size: 50
text: ARB/15/30
page: null
page: 2
[debug] [phantom] Capturing page to /Users/yubrew/app/lib/tasks/screenshot1.png
[info] [phantom] Capture saved to /Users/yubrew/app/lib/tasks/screenshot1.png
[info] [phantom] Step anonymous 6/6: done in 7491ms.
[info] [phantom] Step _step 7/7 https://icsid.worldbank.org/apps/ICSIDWEB/cases/Pages/AdvancedSearch.aspx (HTTP 200)
[info] [phantom] Step _step 7/7: done in 7493ms.
[info] [phantom] wait() finished waiting for 5000ms.
[info] [phantom] Done 7 steps in 12493ms
Note that the screenshots and console log indicate that the page contents has not changed.
You shouldn't use Element.click(), because it doesn't do anything in PhantomJS most of the time. Use CasperJS' click() function that tries many thing to properly click an element.
Since CSS selectors don't support matches based on text, you can use XPath to solve this:
var x = require('casper').selectXPath;
...
casper.click(x("//a[text()='2']"));
Your other misconception is that casper.wait() actually does something. All then*() and wait*() functions are asynchronous step functions. When you call them, you're only scheduling a step that should be executed at the end of the current step.
For example, if you call this:
this.wait(5000);
this.capture('screenshot0.png');
this.then(function(){...
it is executed like this:
this.capture('screenshot0.png');
this.wait(5000);
this.then(function(){...
If you can, you should wrap synchronous function calls in a casper.then().
I am doing iOS Mobile Application Testing using Selenium. I am using respectives
Appium version 1.3.7
Node JS version 2.7.5
ios webkit debug proxy
iPhone 5c
Xcode version 6.1
I am using a shell script which is helping me to check the ios_webkit_debug_proxy is available or not. If not exists, within 2 seconds, it will start the ios_webkit_debug_proxy.
My testing is working well. But still facing some problem in appium that Appium is stopped certainly giving an uncaught exception: Cannot read property 'executeAtom' of null
I have tried to solve in various ways.
Restart Appium and run again.
Update the appium version to stable latest version 1.4.0. But the
error is still remaining.
Update the Node JS.
Xcode is always opened in run execution time.
Nullify the implicitly wait before every WebDriverWait happens.
Link: http://chon.techliminal.com/ajax_wait/#/intro
Using java uncaught exception handler in every related class. Link:
https://bharatonjava.wordpress.com/2012/09/04/uncaughtexceptionhandler-in-java/
But still error is remaining. Would you please suggest me how I can solve this problem??
For your better understanding I am attaching the log file below.
info: [debug] [REMOTE] Sending javascript command
info: [debug] [REMOTE] Remote debugger data sent [{"method":"Runtime.evaluate","params":{"objectGroup":"console","includeCommandLineAPI":true,"doNotPauseOnExceptionsAndMuteConsole":true,"expression":"(function(){return function(){function h(a){return...]
Debugger web socket received data : {"result":{"result":{"type":"string","value":"{\"status\":0,\"value\":[]}"},"wasThrown":false},"id":57}
info: [debug] Waited for 7659ms so far
info: --> POST /wd/hub/session/d102c79f-f695-4fbb-a020-45caf2af7b05/context {"name":"NATIVE_APP"}
info: [debug] Attempting to set context to 'NATIVE_APP'
info: [debug] Responding to client with success: {"status":0,"value":"","sessionId":"d102c79f-f695-4fbb-a020-45caf2af7b05"}
info: POST /wd/hub/session/d102c79f-f695-4fbb-a020-45caf2af7b05/context {"name":"NATIVE_APP"}
info: [debug] Attempting to set context to 'NATIVE_APP'
info: [debug] Responding to client with success: {"status":0,"value":"","sessionId":"d102c79f-f695-4fbb-a020-45caf2af7b05"}
info: POST /wd/hub/session/d102c79f-f695-4fbb-a020-45caf2af7b05/context 200 0.862 ms - 74 {"status":0,"value":"","sessionId":"d102c79f-f695-4fbb-a020-45caf2af7b05"}
error: uncaughtException: Cannot read property 'executeAtom' of null date=Fri May 22 2015 11:40:38 GMT+0600 (BDT), pid=9153, uid=501, gid=20, cwd=/Applications/Appium.app/Contents/Resources/node_modules/appium, execPath=/Applications/Appium.app/Contents/Resources/node/bin/node, version=v0.12.1, argv=[/Applications/Appium.app/Contents/Resources/node/bin/node, /Applications/Appium.app/Contents/Resources/node_modules/appium/lib/server/main.js, --command-timeout, 7200, --platform-version, 7.1, --platform-name, iOS, --app, com.bjitgroup.putter, --udid, 0b72ccc692943f83fa2f83e78e8b3030a760fa5f, --device-name, iPhone 5], rss=218198016, heapTotal=187542272, heapUsed=76792360, loadavg=[1.51611328125, 1.689453125, 1.67431640625], uptime=71672, trace=[column=14, file=/Applications/Appium.app/Contents/Resources/node_modules/appium/lib/devices/ios/ios-controller.js,
function=iOSController.executeAtom, line=647, method=executeAtom, native=false, column=10, file=/Applications/Appium.app/Contents/Resources/node_modules/appium/lib/devices/ios/ios-controller.js,
function=, line=311, method=null, native=false, column=13, file=/Applications/Appium.app/Contents/Resources/node_modules/appium/lib/devices/common.js,
function=, line=90, method=null, native=false, column=5, file=/Applications/Appium.app/Contents/Resources/node_modules/appium/lib/devices/common.js,
function=, line=66, method=null, native=false, column=15, file=timers.js, function=Timer.listOnTimeout, line=110, method=listOnTimeout, native=false],
stack=[TypeError: Cannot read property 'executeAtom' of null,
at iOSController.executeAtom (/Applications/Appium.app/Contents/Resources/node_modules/appium/lib/devices/ios/ios-controller.js:647:14),
at null. (/Applications/Appium.app/Contents/Resources/node_modules/appium/lib/devices/ios/ios-controller.js:311:10),
at null. (/Applications/Appium.app/Contents/Resources/node_modules/appium/lib/devices/common.js:90:13),
at null. (/Applications/Appium.app/Contents/Resources/node_modules/appium/lib/devices/common.js:66:5),
at Timer.listOnTimeout (timers.js:110:15)]
please follow this link in github. I have got a solution that is happening because of async error.
https://github.com/appium/appium/issues/5177
describe('The feature', function() {
beforeEach(function () {
browser.executeScript('localStorage.setItem("key","value");');
});
it('should do this', function() {
});
});
but i get this error when the test is run against selenium with chromedriver 2.10 and chrome 37
Executing: [execute script: window.localStorage.setItem("key","value");, []])
15:31:29.747 WARN - Exception thrown
org.openqa.selenium.WebDriverException: <unknown>: Failed to read the 'localStorage'
property from 'Window': Storage is disabled inside 'data:' URLs.
(Session info: chrome=37.0.2062.120)
(Driver info: chromedriver=2.10.267518,platform=Linux 3.11.0-26-generic x86_64) (WARNING:
The server did not provide any stacktrace information)
Any idea where the problem cam from ?
According to one of the answers at Remove an item from localStorage in a protractor test, this happens when you try to access localStorage without hitting the browser (say, browser.get) first when you are using the Chrome driver. The solution seems to be to hit the browser first (maybe your root page) to get a page loaded in Chrome so that you can manipulate the localStorage. That at least is what I have been doing for our project. Hope this helps!