How do I handle alerts in an Android web application using Appium server (1.0.1) and the Android SDK?
The below code is not working on android:
driver.switchTo().accept().alert();
Error message:
> -modal window does not get closed
You need to get the Alert before you try and accept it
This is code from some of the Appium Java Client Tests:
wait.until(ExpectedConditions.alertIsPresent());
Alert alert = driver.switchTo().alert();
alert.accept();
This should work most of the time.
If accept() isn't working, replace the driver.switchTo().alert(); and alert.accept(); with code to find the button and then click it.
If it's not finding the button wrap findElementBy(Method) code in a try/retry block, and then click on it.
The best way is to use the appium inspector. Click on the element and copy the resource-id from it. Use this resource id in findElement(By.id()) method.
For me resource-id: android:id/button1
((AndroidDriver) driver).findElement(By.id("android:id/button1")).click();
This is for Android. For regular use you can use
driver.findElement(By.id("android:id/button1")).click();
Some alerts may be native Android's alerts, not generated by a browser. In this case the following code:
Alert alert = driver.switchTo().alert(); alert.accept();
may throw:
WebDriverException: unknown error: unhandled inspector error: {"code":-32603,"message":"No JavaScript dialog to handle"}
To handle such alert, just switch to the native application context, make required actions, and then switch back to the browser:
AppiumDriver<WebElement> appiumDriver = (AppiumDriver<WebElement>) webDriver;
String currentContext = appiumDriver.getContext();
appiumDriver.context("NATIVE_APP");
// actions within the alert
appiumDriver.findElements(By.xpath(OK_BUTTON_LOCATOR)).click(); // put locator instead of OK_BUTTON_LOCATOR
appiumDriver.context(currentContext);
// continue working
WebElement btn = driver.findElement(By.xpath("//android.widget.Button[#content-desc='OK']"));
TouchAction act = new TouchAction(driver);
act.tap(241,320).perform();
(241,320) these are X & Y c ordinates of alert
This work perfectly for me
Appium comes with a default capability to accept, dismiss alerts
capabilities.SetCapability("autoAcceptAlerts", true);
capabilities.SetCapability("autoDismissAlerts", true);
If the alert display on Ui , taking more time to display when we need to wait ..we can use fluent wait instead of this..
So an updated answer on this is this: an AlertDialog is a system level element, so clicking on accept button you should use:
androidDriver.findElementById("android:id/button1").click()
else for cancel do this:
androidDriver.findElementById("android:id/button2").click()
// first check alert is present or not
public boolean isAlertPresent() {
try {
mobDriver.switchTo().alert();
log.info("ALERT IS PRESENT !! ");
return true;
} catch (Exception e) {
log.info("ALERT IS NOT PRESENT !! ");
return false;
}
}
public void mobileAlertHandle() {
if (isAlertPresent()) {
Alert alert = mobDriver.switchTo().alert();
alert.accept();
}
}
if this does not work then inspect your element and try with id or name
ex: mobDriver.findElementById("android:id/button2").click()
Please use the below code, Add some wait before clicking on OK Button.
After that pass the xpath of you OK Button.
synchronized (driver)
{
driver.wait(2000);
}
driver.context(NATIVE_APP);
driver.findElementByXPath{("//android.widget.Button[#resourceid=
‘android:id/button1’]").click();
Related
I'm using webdriver.io to write a suite of Appium tests for a hybrid Cordova App.
"appium": "^1.10.0",
"wdio-appium-service": "^0.2.3",
"wdio-jasmine-framework": "^0.3.8",
"webdriverio": "^4.14.1",
In one of my tests I am trying to programmatically accept the Location Permissions native modal presented on App launch on top of the WebView.
I can easily do so in iOS using browser.alertAccept() but the latter does not seem to work for Android.
I also tried to switch to the native context to dismiss it but had no luck.
function dismissLocationPermissions() {
if (browser.isAndroid) {
new WebView().switchToContext(0);
browser.pause(2000);
const ANDROID_ACCEPT_ALERT_SELECTOR = "//*[#class='android.widget.Button'][2]";
// OR '*//android.widget.Button[#text="ALLOW"]' ?
$(ANDROID_ACCEPT_ALERT_SELECTOR).click();
WebView().switchToContext(1);
} else {
browser.alertAccept();
}
}
How can I dismiss the native alert on Android using wdio?
There is autoGrantPermissions DesiredCapability, if you set it to true - Appium will automatically determine which permissions are required by your application and grant them to the application during the installation procedure.
The capability is set to false by default so you need to explicitly set it like:
DesiredCapabilities dc = new DesiredCapabilities();
dc.setCapability(MobileCapabilityType.NO_RESET, false);
dc.setCapability(AndroidMobileCapabilityType.AUTO_GRANT_PERMISSIONS, true);
driver = new AndroidDriver<>(url, dc);
More information:
Appium Desired Capabilities
Application Setup
The permission dialog is native, so you don't need to switch to the webview to dismiss it.
There is an android id associated with the allow/deny permission button, so you can use that instead of the identifier you have used.
The id for allow button is: com.android.packageinstaller:id/permission_allow_button .
The id for deny button is: com.android.packageinstaller:id/permission_deny_button
I have to click the ALLOW, to give the app permissions on Android 7.0.
I Tried the following xpath
//android.widget.Button[contains(#resource-id,'com.android.packageinstaller:id/permission_allow_button')]
also tried //android.widget.Button[#text='ALLOW']
Getting error :
No Such element exception.
You can try it:
driver.findElement(By.id("com.android.packageinstaller:id/permission_allow_button")).click();
or
driver.findElement(By.Name("Allow")).click();
or
driver.findElement(new By.ByName("Allow")).click();
It's working fine for me.
Since, App requesting for permission. You can allow permission directy using Desired Capabilities.
Try this:
DesiredCapabilities cap = new DesiredCapabilities();
cap.setCapability("autoGrantPermissions", "true");
Check this also.
First of all, you need to locate the alert, whether it is there or not?
So what you can do you is you can create the list, which will check whether alert is present or not? And then if the alert is present, it will click on ALLOW button.
I am using PageObjectFactory Pattern so the following is my code which works fine for me:
#AndroidFindBy(xpath = "//android.widget.Button[#text='ALLOW']")
private List<MobileElement> alert;
#AndroidFindBy(xpath = "//android.widget.Button[#text='ALLOW']")
private MobileElement allowAlert;
if (!alert.isEmpty()) {
try {
// do something
} catch (InterruptedException e) {
e.printStackTrace();
}
waitForElement(appiumDriver, allowAlert).click();
}
I am trying to automate android application using appium when I launch the application and try to login the pop up asks me to have access to Contacts by tapping on "Allow". The pop up have a different appPackage and it is not part of the application package.
Locator for the allow button
addLocator(Locators.ALLOW_CONTACTS, "com.android.packageinstaller:id/permission_allow_button");
method to tap on Allow button
Button allowContactsButton() {
return new Button(getLocator(Locators.ALLOW_CONTACTS));
}
public void dismissAllowContact() {
allowContactsButton().tap();
}
The dismiss function does is able to locate the button but does not tap on it
You can turn on autoAcceptAlerts and grant permissions.
desiredCapabilities.setCapability("autoGrantPermissions", "true");
desiredCapabilities.setCapability("autoAcceptAlerts", "true");
For location service you will have to explicity set authorization using following:
desiredCapabilities.setCapability("locationServicesAuthorized", "true");
You can try similar approach for contacts.
Hoping this helps !
I'm working with the android uiautomtor and I want to confirm Pop-Up-Windows like Bluetooth Requests. The Pop-Up appears when I want to turn on the bluetooth visibility. Then I have to confirm it by pressing the button with the text "YES". I call the method of the uiautomator by using the command line from a PC and it works as well!
I use this Code:
UiObject obj;
boolean success;
obj = new UiObject(new UiSelector().text("YES"));
success = obj.click();
This code is working in a test automation for testing the UI of an android device. So the programm, which calls the method, runs for long time and i want to know if the button was clicked correctly or not. The click()-Method returns true if the ID of the UI-Object was found. I need the return value for analyze the tests.
So here is my question:
Is it possible to return/send the boolean value of the click()-Method from the uiautomator testcase class to the command line?
If you would only want to see the value of "success", you could use:
system.out.println("success = " + success);
It's not clear to me if you want to further use this value in some other parts of your program.
I am writing automated testing code (using ActivityInstrumentationTestCase2) to test an app that involves in-app billing version 2 (subscriptions). I need help on figuring out how to programmatically get my testing code to click on the "Accept and Buy" button that appears inside the "Pay with credit card/Secured by Google Wallet" dialog which is supposedly created by some Google SDK code.
I can get the testing code to click on other buttons that are created by my own code/acitivty, usually by accessing the buttons from its parent activity or view, and then call the .performClick() method on the button. But this "Buy" button is not reachable from any activities as far as I know.
It appears this dialog may be created by com.google.android.finsky.activities.IabActivity based on the logcat output. I used an ActivityMonitor watching this activity, but it was never triggered. If you can help either directly, or point me to the relevant Google SDK source code that's responsible for creating the "Pay with credit card" dialog or the source for the com.google.android.finsky.activities.IabActivity class, I'd be very grateful.
Normally you can't instrument Activities outside of your own package.
You'd have to use the UI Automator framework to click the Buy button.
Thanks to Christopher. I managed to use UI Automation to get the effect I want. I had to write a shell script to call my Instrumentation Test first, which brings up the Buy dialog. Then call
adb shell uiautomator runtest to launch the UI automation code to click on the "Buy" button. Not sure how to sync between them so I just use some sleep code to time the click. Here is the UI automation code:
UiDevice dev = getUiDevice();
// wait for buy button to appear
while (true) {
try {
Thread.sleep(2000l);
UiObject okButton = new UiObject(new UiSelector().text("Accept & buy").className("android.widget.Button"));
okButton.click();
break;
} catch (Exception e) {
}
}
dev.waitForIdle();
Using uiautomator, this is the best I got:
device.findObject(new UiSelector().resourceId("com.android.vending:id/continue_button")).click();
Here are suggestion for making Testcase for Button click in android.
You need to make ActivityInstrumentationTestCase2 for your Activity then do following .
Initialize your button in
protected void setUp() throws Exception {
super.setUp();
mainActivity = getActivity();
btnAcceptBuy= (Button) mainActivity.findViewById(R.id.btnaccept_buy);
}
public void testFragmentKeypad(){
AppLog.showLogE("TEST", "Keypad");
TouchUtils.clickView(this, btnAcceptBuy);
}
By this way you can perform click testing of your button in android.
UiAutomation uiAutomation = new UiAutomation(Looper.getMainLooper(), new UiAutomationConnection());
uiAutomation.setOnAccessibilityEventListener(new UiAutomation.OnAccessibilityEventListener() {
#Override
public void onAccessibilityEvent(AccessibilityEvent event) {
if (event.getEventType() == TYPE_WINDOW_STATE_CHANGED) {
if ("com.google.android.finsky".contentEquals(event.getPackageName())) {
if ("com.google.android.finsky.activities.IabActivity".contentEquals(event.getClassName())) {
final List<AccessibilityNodeInfo> accessibilityNodeInfosByViewId = event.getSource().findAccessibilityNodeInfosByViewId("<package name>:id/<control id>"); // find by layout inspector
if (accessibilityNodeInfosByViewId.size() > 0) {
accessibilityNodeInfosByViewId.get(0).performAction(AccessibilityNodeInfo.ACTION_CLICK);
}
}
}
}
}
});
uiAutomation.connect();
//release when exit
uiAutomation.disconnect();