Web UI 自动弹出确认 window
Web UI automation for a pop-up confirmation window
这不是代码问题,而是自动化问题。
有一个由 iframe 组成的桌面网站(在我看来那些是 iframe),它是某种 B2B 商店。所有网站元素都固定在适当的位置,在屏幕之间移动时它们不会移动或改变。
我需要的是自动点击几下按钮,直到我确认,其中一次点击是弹出 window 和 Confirm/Cancel。弹出后,打开下一个屏幕,再点击一个按钮,这对我来说是手动工作。
我曾尝试使用一些 QA 测试软件(例如 Selenium IDE)来实现自动化,但它没有帮助,当我看到那个弹出窗口时它就停止了。在我看来,该软件似乎不知道该弹出窗口覆盖,即使该弹出窗口始终相同。
有谁知道如何解决上述问题?
先谢谢大家了。
重要提示:弹出窗口 window 是网站的一部分。
如果 OS 是 Windows,并且弹出窗口是本机 Windows 对话框 - 而不是 Selenium IDE 可访问的网站的一部分 - 您可以尝试通过调用 Windows API 来解决您的问题。不确定如何使用 selenium.ide 完成此操作,但肯定可以使用使用能够执行本机 Windows 函数的一种受支持编程语言编写的常规 Selenium Webdriver 代码来实现。
例如,这是一个独立的 Java class,它启动 Chrome,导航到一个网站,然后单击本机对话框中显示的“确定”按钮警告”。
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>
这不是代码问题,而是自动化问题。
有一个由 iframe 组成的桌面网站(在我看来那些是 iframe),它是某种 B2B 商店。所有网站元素都固定在适当的位置,在屏幕之间移动时它们不会移动或改变。
我需要的是自动点击几下按钮,直到我确认,其中一次点击是弹出 window 和 Confirm/Cancel。弹出后,打开下一个屏幕,再点击一个按钮,这对我来说是手动工作。
我曾尝试使用一些 QA 测试软件(例如 Selenium IDE)来实现自动化,但它没有帮助,当我看到那个弹出窗口时它就停止了。在我看来,该软件似乎不知道该弹出窗口覆盖,即使该弹出窗口始终相同。
有谁知道如何解决上述问题?
先谢谢大家了。
重要提示:弹出窗口 window 是网站的一部分。
如果 OS 是 Windows,并且弹出窗口是本机 Windows 对话框 - 而不是 Selenium IDE 可访问的网站的一部分 - 您可以尝试通过调用 Windows API 来解决您的问题。不确定如何使用 selenium.ide 完成此操作,但肯定可以使用使用能够执行本机 Windows 函数的一种受支持编程语言编写的常规 Selenium Webdriver 代码来实现。
例如,这是一个独立的 Java class,它启动 Chrome,导航到一个网站,然后单击本机对话框中显示的“确定”按钮警告”。
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>