Selenium 如何多次等待具有不同文本的同一个 WebElement
Selenium How to wait multiple times for the same WebElement with different text
我试图等待 WebElement 从空白变为消息 1,然后变为消息 2。问题是我每次都能找到第一条消息,但我似乎永远等不到第二条(查找文本超时)
我试过将等待对象分开,但没有用。我尝试了一些预期的条件方法(textToBePresent*),经过一些阅读(我发现刷新的 EC)无济于事。
@FindBy(xpath="//p[@class='statusText']")
WebElement statusMsg
public WebElement statusMsg(){
String msg1="Logging in, please wait."
String msg2="Login successful, please wait."
String msg3="Login attempt exception, error code: "
if(statusMsg.getText().contains(msg3)){
log.error(statusMsg.getText())
log.error("Something happened in the frontend")
Assert.fail(statusMsg.getText())
}else{
log.info(statusMsg.getText())
}
WebDriverWait wait = new WebDriverWait(driver,45)
wait.until(ExpectedConditions.textToBe(By.xpath("//p[@class='statusText']"), msg1))
if(statusMsg.getText().contains(msg3)){
log.error(statusMsg.getText())
log.error("Something happened in the backend")
Assert.fail(statusMsg.getText())
}else{
log.info(statusMsg.getText())
}
wait.until(ExpectedConditions.refreshed(ExpectedConditions.textToBe(By.xpath("//p[@class='statusText']"), msg2)))
log.info("Found: "+msg2)
return statusMsg
}
结果是 testNG 未通过我的测试说:
org.openqa.selenium.TimeoutException: Expected condition failed:
waiting for condition (element found by By.xpath:
//p[@class='statusText'] to have text "Login successful, please
wait.". Current text: "Logging in, please wait.")
然而我可以看到 msg2
而测试是 运行。这是否必须做,因为我已经通过 PageFactory.initElements(driver, this)
初始化了页面对象?
这是您可以用来按顺序检查错误和成功消息的代码。
逻辑:
- 将预期的消息放入
expectedMessages
列表
- 使用 Fluent Wait 检查自定义条件
- 设置每 50 毫秒轮询一次以能够捕获消息
- 检查状态消息元素是否可见,如果可见则获取文本
- 如果实际状态消息为 "error"
,则失败
- 检查实际状态消息是否包含
expectedMessages
中的第一个文本,如果是这样,请从 expectedMessages
中删除第一个文本
- 如果
expectedMessages
,请重复第 6 步,直到没有剩余物品
WebDriverWait wait = new WebDriverWait(driver, 20);
String errorMessage = "Login attempt exception, error code:";
List<String> expectedMessages = Arrays.asList(
"Logging in, please wait.",
"Login successful, please wait.");
wait.pollingEvery(Duration.ofMillis(50))
.withMessage(String.format("Expecting %s login messages", expectedMessages))
.until(d -> {
if (!d.findElement(By.xpath("//p[@class='statusText']")).isDisplayed())
return false;
String actualMessage = d.findElement(By.xpath("//p[@class='statusText']")).getText();
if (actualMessage.contains(errorMessage))
Assert.fail(actualMessage);
String expectedMessage = expectedMessages.get(0);
if (expectedMessage.contains(actualMessage)) {
log.info(String.format("Message \"%s\" found", actualMessage));
expectedMessages.remove(expectedMessage);
}
return expectedMessages.size() == 0;
});
第二种解决方案是获取所有消息并进行检查。
使用下面的代码获取所有消息并检查您从网站获得的内容:
JavascriptExecutor js = (JavascriptExecutor) driver;
List<String> actualMessages = new ArrayList<>();
for (int i = 0; i < 30000; i++) {
actualMessages.addAll(
(ArrayList<String>) js.executeScript("return [...document.querySelectorAll('p.statusText')].map(e=>{return e.textContent})")
);
Thread.sleep(10);
}
// debug here to check message collected
System.out.println(actualMessages);
我试图等待 WebElement 从空白变为消息 1,然后变为消息 2。问题是我每次都能找到第一条消息,但我似乎永远等不到第二条(查找文本超时)
我试过将等待对象分开,但没有用。我尝试了一些预期的条件方法(textToBePresent*),经过一些阅读(我发现刷新的 EC)无济于事。
@FindBy(xpath="//p[@class='statusText']")
WebElement statusMsg
public WebElement statusMsg(){
String msg1="Logging in, please wait."
String msg2="Login successful, please wait."
String msg3="Login attempt exception, error code: "
if(statusMsg.getText().contains(msg3)){
log.error(statusMsg.getText())
log.error("Something happened in the frontend")
Assert.fail(statusMsg.getText())
}else{
log.info(statusMsg.getText())
}
WebDriverWait wait = new WebDriverWait(driver,45)
wait.until(ExpectedConditions.textToBe(By.xpath("//p[@class='statusText']"), msg1))
if(statusMsg.getText().contains(msg3)){
log.error(statusMsg.getText())
log.error("Something happened in the backend")
Assert.fail(statusMsg.getText())
}else{
log.info(statusMsg.getText())
}
wait.until(ExpectedConditions.refreshed(ExpectedConditions.textToBe(By.xpath("//p[@class='statusText']"), msg2)))
log.info("Found: "+msg2)
return statusMsg
}
结果是 testNG 未通过我的测试说:
org.openqa.selenium.TimeoutException: Expected condition failed: waiting for condition (element found by By.xpath: //p[@class='statusText'] to have text "Login successful, please wait.". Current text: "Logging in, please wait.")
然而我可以看到 msg2
而测试是 运行。这是否必须做,因为我已经通过 PageFactory.initElements(driver, this)
初始化了页面对象?
这是您可以用来按顺序检查错误和成功消息的代码。 逻辑:
- 将预期的消息放入
expectedMessages
列表 - 使用 Fluent Wait 检查自定义条件
- 设置每 50 毫秒轮询一次以能够捕获消息
- 检查状态消息元素是否可见,如果可见则获取文本
- 如果实际状态消息为 "error" ,则失败
- 检查实际状态消息是否包含
expectedMessages
中的第一个文本,如果是这样,请从expectedMessages
中删除第一个文本
- 如果
expectedMessages
,请重复第 6 步,直到没有剩余物品
WebDriverWait wait = new WebDriverWait(driver, 20);
String errorMessage = "Login attempt exception, error code:";
List<String> expectedMessages = Arrays.asList(
"Logging in, please wait.",
"Login successful, please wait.");
wait.pollingEvery(Duration.ofMillis(50))
.withMessage(String.format("Expecting %s login messages", expectedMessages))
.until(d -> {
if (!d.findElement(By.xpath("//p[@class='statusText']")).isDisplayed())
return false;
String actualMessage = d.findElement(By.xpath("//p[@class='statusText']")).getText();
if (actualMessage.contains(errorMessage))
Assert.fail(actualMessage);
String expectedMessage = expectedMessages.get(0);
if (expectedMessage.contains(actualMessage)) {
log.info(String.format("Message \"%s\" found", actualMessage));
expectedMessages.remove(expectedMessage);
}
return expectedMessages.size() == 0;
});
第二种解决方案是获取所有消息并进行检查。
使用下面的代码获取所有消息并检查您从网站获得的内容:
JavascriptExecutor js = (JavascriptExecutor) driver;
List<String> actualMessages = new ArrayList<>();
for (int i = 0; i < 30000; i++) {
actualMessages.addAll(
(ArrayList<String>) js.executeScript("return [...document.querySelectorAll('p.statusText')].map(e=>{return e.textContent})")
);
Thread.sleep(10);
}
// debug here to check message collected
System.out.println(actualMessages);