Web 应用程序中的 Appium:无法在通知弹出窗口中点击允许权限按钮

Posted

技术标签:

【中文标题】Web 应用程序中的 Appium:无法在通知弹出窗口中点击允许权限按钮【英文标题】:Appium in Web app: Unable to tap Allow permission button in notification pop up window 【发布时间】:2018-12-12 23:04:17 【问题描述】:

当我打开网络应用程序时,我会弹出一个窗口。我正在尝试以两种方式点击“允许”按钮:

1) 当我添加权限时:

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

什么都没发生((

2) 当我尝试通过 XPath 找到它时:

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

我收到一个错误:

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

这是我从 UI Automator Viewer 截屏:

我发现了这个帖子:Unable to tap the link after tap on Allow button of permission alert in Appium? 但这对我没有帮助。

【问题讨论】:

您能否通过选择允许按钮将屏幕截图分享给 UIAutomatorViewer。 @AlImran 更新了描述,请看一下 你试过driver.findElement(By.id("android:id/button1")).click();这个吗? @AlImran 它不工作,日志中出现错误:Returned value cannot be converted to WebElement: message=no such element: Unable to locate element: "method":"id","selector":"android:id/button1" 【参考方案1】:

首先:您尝试使用的功能适用于IOS only

在 Android 上,您必须通过 findElement 找到弹出窗口并自己关闭它们

第二:由于您为 Web 应用程序启动 Appium 会话,因此在搜索原生弹出窗口之前,您必须切换上下文

    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();

不要忘记将上下文切换回网络以继续:

    driver.context(webContext);

【讨论】:

谢谢!它帮助了我【参考方案2】:

我也遇到过类似的问题,我是这样解决的:

这是来自我的页面对象的代码的一部分,当点击 useGPS 时,会显示原生 Android 通知以允许或阻止 GPS 的使用,

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

这是一个被覆盖的类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) 

    

忽略屏幕扩展,只需尝试使用现有 Alert 的实现(org.openqa.selenium.Alert 包)。

我知道这不是 1:1 的解决方案,您必须对其进行调整,将其合并到您的代码中,但重点是尝试覆盖 Alert 并等待元素出现,然后与之交互。

希望对你有帮助,

【讨论】:

【参考方案3】:

尝试像这样设置功能:

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

如果没有帮助,请尝试使用此 xPath 找到您的“允许”按钮:

//*[. = 'Allow']

//*[contains(text(), 'Allow')]

//*[contains(text(), 'ALLOW')]

driver.findElement(By.id("com.android.chrome:id/button1")).click();

您也可以尝试通过在浏览器中打开您的应用来找到此按钮,然后在开发工具中找到此按钮的选择器并在 Appium 中使用它。

PS:在您的代码中添加WebDriverWait

new WebDriverWait(driver, 10).until(ExpectedConditions.elementToBeClickable(By.xpath("//*[. = 'Allow']"))).click();

这将等待至少 10 秒,直到元素可点击。有时脚本非常快,此时DOM 不包含您要与之交互的元素。因此,您必须等待一段时间,直到元素位于 DOM 中。这就是为什么在脚本中添加等待非常有用。

对于WebDriverWait,您必须添加一些导入:

import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;

【讨论】:

以上是关于Web 应用程序中的 Appium:无法在通知弹出窗口中点击允许权限按钮的主要内容,如果未能解决你的问题,请参考以下文章

出现“使用当前位置”权限弹出窗口时,Appium 和 Selenium 无法连接

如何从 Appium 打开推送通知并阅读 Android/iOS 设备中的文本?

appium 定位弹出框时报错

APPIUM ANDROID 混合应用程序:在混合应用程序中从本机导航到 Web 视图时,无法将驱动程序上下文获取为“WEBVIEW”

appium 问题四的解决办法(模拟器打开的页面弹出框与脚本打开页面的弹出框不一致)

appium 问题四的解决办法(模拟器打开的页面弹出框与脚本打开页面的弹出框不一致)