弹出确认窗口的 Web UI 自动化

Posted

技术标签:

【中文标题】弹出确认窗口的 Web UI 自动化【英文标题】:Web UI automation for a pop-up confirmation window 【发布时间】:2021-12-22 00:02:26 【问题描述】:

这不是代码问题,而是自动化问题。

有一个由 iframe 组成的桌面网站(在我看来,这些都是 iframe),它是某种 B2B 商店。所有网站元素都固定在适当的位置,在屏幕之间移动时它们不会移动或变化。

我需要的是自动点击几下按钮,直到我确认,其中一次点击是一个带有确认/取消的弹出窗口。在此弹出窗口之后,会打开下一个屏幕并单击另一个按钮,这对我来说是手动工作。

我曾尝试使用一些 QA 测试软件(例如 Selenium IDE)来实现自动化,但这并没有帮助,当我遇到那个弹出窗口时它就停止了。在我看来,该软件似乎不知道该弹出式覆盖,即使该弹出式始终相同。

有人知道如何克服上述问题吗?

提前感谢大家。

重要提示:弹出窗口是网站的一部分。

【问题讨论】:

请澄清-您可以使用“某些”工具,直到出现问题按钮,无法处理?这是本机桌面应用程序(可能是电子?)还是带有某种浏览器插件的网站?这是在 Windows 上吗? 这是在 Chrome 中打开的网站。我使用的工具是 Chrome 插件,Selenium IDE。 selenium.dev/selenium-ide 是的,操作系统是 Windows 10。因此,您打开网站,打开 chrome 插件并记录网站上的点击并保存。之后,您可以使用相同的插件来复制步骤。弹出窗口时失败。 弹出窗口是网站的一部分是什么意思?它是一个类似于警报或确认的窗口吗?还是用 html 和 CSS 制作的? 请澄清您的具体问题或提供更多详细信息以准确突出您的需求。正如目前所写的那样,很难准确地说出你在问什么。 【参考方案1】:

如果操作系统是 Windows,并且弹出窗口是本机 Windows 对话框 - 而不是 Selenium IDE 可访问的网站的一部分 - 您可以尝试通过调用 Windows API 来解决您的问题。不确定是否可以使用 selenium.ide 完成此操作,但肯定可以使用常规的 Selenium Webdriver 代码来实现,该代码是用一种能够执行本机 Windows 功能的受支持的编程语言编写的。

例如,这里是一个独立的 Java 类,它启动 Chrome,导航到一个网站,然后单击名为“警告”的本机对话框中显示的 OK 按钮。

package example;

import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.win32.StdCallLibrary;
import com.sun.jna.win32.W32APIOptions;
import org.openqa.selenium.chrome.ChromeDriver;

import java.time.Duration;

public class Main 
    public static void main(String... args) 
        ChromeDriver driver = new ChromeDriver();
        driver.get("https://google.com");

        Pointer dialog = getNativeDialog("Warning");
        Pointer button = getNativeButton(dialog, "OK");
        click(button);
    

    /**
     * Returns a handle to a dialog window by its name
     * @param dialogTitle exact name of the window to find
     */
    public static Pointer getNativeDialog(String dialogTitle) 
        final String DIALOG_CLASS = "#32770";
        return User32.INSTANCE.FindWindowEx(null, null, DIALOG_CLASS, dialogTitle);
    

    /**
     * Returns a handle to the button with specific label within a parentWindow
     * @param parentWindow handle to a window, obtained e.g. with @link #getNativeDialog(String)
     * @param buttonLabel label of the button to search by
     */
    public static Pointer getNativeButton(Pointer parentWindow, String buttonLabel) 
        final String BUTTON_CLASS = "Button";
        return User32.INSTANCE.FindWindowEx(parentWindow, null, BUTTON_CLASS, buttonLabel);
    

    /**
     * Sends BM_CLICK message to a window (or other control) which is equivalent of clicking it
     * with primary mouse button
     * @param target an input handle obtained with e.g. @link #getNativeButton(Pointer, String)
     */
    public static void click(Pointer target) 
        final int BM_CLICK = 0x00F5;
        User32.INSTANCE.SendMessage(target, BM_CLICK, null, null);
        sleep(Duration.ofMillis(500));
    


    private static void sleep(Duration duration) 
        try 
            Thread.sleep(duration.toMillis());
         catch (InterruptedException e) 
            e.printStackTrace();
        
    

    private interface User32 extends StdCallLibrary 
        User32 INSTANCE = (User32) Native.loadLibrary("user32", User32.class, W32APIOptions.DEFAULT_OPTIONS);

        /**
         * Finds window (or other type of control, specified by lpszClass).
         * See https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-findwindowexw
         */
        Pointer FindWindowEx(Pointer hWndParent, Pointer hWndChildAfter, String lpszClass, String lpszWindow);

        /**
         * Sends message to a window (or other type of control). Can be used to simulate user input.
         * Note when the result of sending message triggers modal dialog to show, this method may block indefinitely,
         * unless the dialog is handled in separate thread.
         * See https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-sendmessage
         */
        Pointer SendMessage(Pointer hWnd, int Msg, String wParam, String lParam);
    

这个特定的例子需要这些库

    <dependencies>
        <dependency>
            <groupId>org.seleniumhq.selenium</groupId>
            <artifactId>selenium-java</artifactId>
            <version>3.141.59</version>
        </dependency>
        <dependency>
            <groupId>net.java.dev.jna</groupId>
            <artifactId>jna</artifactId>
            <version>3.4.0</version>
        </dependency>
        <dependency>
            <groupId>net.java.dev.jna</groupId>
            <artifactId>platform</artifactId>
            <version>3.4.0</version>
        </dependency>
    </dependencies>

【讨论】:

嗨,谢谢你的代码好主意,这看起来很棒:) 不幸的是,弹出窗口是网站的一部分 如果弹出窗口是网站的一部分 - 这对您来说应该是个好消息,因为您应该能够找到它并使用普通的 webdriver API 进行交互:driver.findElementBy(...).click()。上述解决方案只有在混合使用 Web 元素和本机操作系统对话框时才有意义。

以上是关于弹出确认窗口的 Web UI 自动化的主要内容,如果未能解决你的问题,请参考以下文章

在提交表单之前显示弹出窗口/模式以进行确认

selenium chrome 驱动程序选择证书弹出确认不起作用

C#的webform中的button弹出确认对话框,该如何处理

(selenium+python)_UI自动化03_定位新开窗口内元素

element-ui MessageBox 弹框,我只想要弹出样式,不想要点击,当做一个弹出提醒,两秒后自动关闭

element-ui MessageBox 弹框,我只想要弹出样式,不想要点击,当做一个弹出提醒,两秒后自动关闭