Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Appium in Web app: Unable to tap Allow permission button in notification pop up window

When I am opening the web app, I am getting a pop up. I'm trying to click on 'ALLOW' button in two ways:

1) When I add permissions:

caps.setCapability("autoGrantPermissions", true);
caps.setCapability("autoAcceptAlerts", true);
......
driver.switchTo().alert().accept();

nothing happens((

2) When I try to find it by XPath:

driver.findElement(By.xpath("//android.widget.Button[@text='Allow']")).click();

I get an error:

Exception in thread "main" org.openqa.selenium.NoSuchElementException: no such element: Unable to locate element: {"method":"xpath","selector":"//android.widget.Button[@text='Allow']"}

This is my screenshot from UI Automator Viewer :

enter image description here

I found this post:Unable to tap the link after tap on Allow button of permission alert in Appium? but it didn't help me.

like image 977
JohnPix Avatar asked Dec 13 '22 15:12

JohnPix


2 Answers

First: capabilities you were trying to use are for IOS only

On Android you have to find popup via findElement and close them yourself.

Second: since you start Appium session for web application, before searching for native popups you must switch the context:

    String webContext = driver.getContext();
    Set<String> contexts = driver.getContextHandles();
    for (String context: contexts){
        if (context.contains("NATIVE_APP")){
            driver.context(context);
            break;
        }
    }
    driver.findElement(By.id("android:id/button1")).click();

Don't forget to switch context back to web to continue:

    driver.context(webContext);
like image 113
dmle Avatar answered Dec 16 '22 07:12

dmle


I had similar problem like yourself, here is how I solved this:

This is part of code from my page object where when clicking on useGPS, native Android notification is shown to allow or block GPS usage,

public Alert clickButtonUseGPSwithAlert() {
    buttonUseGps.click();
    Validate.action(getSessionInfo(), "click button 'Use a GPS'");
    Alert alert = new Alert(getSessionInfo());
    return alert;
}

and here is an overriden class Alert,

import io.appium.java_client.MobileElement;
import io.appium.java_client.pagefactory.AndroidFindBy;
import io.appium.java_client.pagefactory.AppiumFieldDecorator;
import io.appium.java_client.pagefactory.WithTimeout;
import org.openqa.selenium.support.PageFactory;
import pageObjects.Screen;
import utils.Validate;
import java.util.concurrent.TimeUnit;

public class Alert extends Screen implements org.openqa.selenium.Alert {
    @AndroidFindBy(id = "com.android.packageinstaller:id/dialog_container")
    @WithTimeout(time = 3, unit = TimeUnit.SECONDS)
    public MobileElement alertControl;

    @AndroidFindBy(id = "com.android.packageinstaller:id/permission_message")
    @WithTimeout(time = 3, unit = TimeUnit.SECONDS)
    private MobileElement content;

    @AndroidFindBy(id = "com.android.packageinstaller:id/permission_allow_button")
    @WithTimeout(time = 3, unit = TimeUnit.SECONDS)
    private MobileElement buttonAccept;

    @AndroidFindBy(id = "com.android.packageinstaller:id/permission_deny_button")
    @WithTimeout(time = 3, unit = TimeUnit.SECONDS)
    private MobileElement buttonDismiss;


    public Alert(SessionInfo sessionInfo){
        super(sessionInfo);
        PageFactory.initElements(new AppiumFieldDecorator(sessionInfo.getMobileDriver(), 3, TimeUnit.SECONDS), this);

        WaitUtils.isElementPresent(sessionInfo.getMobileDriver(),alertControl,2);

        if (!Util.areElementsLoaded(alertControl, content, buttonAccept, buttonDismiss)) {
            setLoaded(false);
        } else {
            setLoaded(true);
        }
        Validate.isScreenLoaded(getSessionInfo(), this.isLoaded());

    }

    @Override
    public void dismiss() {
        buttonDismiss.click();
        Validate.action(getSessionInfo(), "ALERT - click button 'Dismiss'");
    }

    @Override
    public void accept() {
        buttonAccept.click();
        Validate.action(getSessionInfo(), "ALERT - click button 'Accept'");
    }

    @Override
    public String getText() {
        String value = content.getText();
        Validate.action(getSessionInfo(), "ALERT - get content");
        return value;
    }

    @Override
    public void sendKeys(String s) {

    }
}

Ignore Screen extending, just try using implementation of existing Alert (org.openqa.selenium.Alert package).

I know this is not solution 1:1 You have to tweak it, to incorporate into Your code, but main point is to try to override Alert and wait for element to appear, and than interact with it.

Hope this would help You,

like image 21
Kovacic Avatar answered Dec 16 '22 06:12

Kovacic