I'm attempting to wait for the WebElement to change from blank,to message 1, then message 2. The problem is I find the first message everytime, but i can't ever seem to wait for the second(it timesout looking for the text)
I've tried having the wait objects separate that didnt work. Ive tried a few of the expected condition methods(textToBePresent*), which after some reading (i found about the refreshed EC) to no avail.
@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
}
The result is testNG fails my test saying:
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.")
Yet I can see the msg2 while the test is running. Does this have to do because I've already initialised the page objects via PageFactory.initElements(driver, this)?
Here is code you can use to check error and success messages sequencenly. Logic:
expectedMessages listexpectedMessages, if so remove first text from expectedMessagesexpectedMessagesWebDriverWait 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;
});
Second solution is to get all messages and after check.
Use code below to get all messages and check what you get from the website:
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);