0

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)?

Sers
  • 12,047
  • 2
  • 12
  • 31
imp
  • 435
  • 6
  • 20
  • Share your HTML code. `Login attempt exception, error code:` should come after wrong credentials attempt. – cruisepandey Oct 09 '19 at 04:52
  • Not sure what HTML you are referring to? The login exemption strings arent the issue in question it is the line `wait.until(ExpectedConditions.refreshed(ExpectedConditions.textToBe(By.xpath("//p[@class='statusText']"), msg2)))` – imp Oct 09 '19 at 04:58
  • Maybe the message `Login successful` is on your page but you have wrong xpath to search it. – daggett Oct 09 '19 at 05:37
  • I did think of that but I do find it if i disable the first wait. That portion of the test actually passes but i need to be able to report on the first message as well as the second. So if i do instead of what is written above `wait.until(ExpectedConditions.textToBe(By.xpath("//p[@class='statusText']"),msg2))` it works when `wait.until(ExpectedConditions.textToBe(By.xpath("//p[@class='statusText']"), msg1))` is commented out – imp Oct 09 '19 at 05:51

1 Answers1

0

Here is code you can use to check error and success messages sequencenly. Logic:

  1. Put expected messages to the expectedMessages list
  2. Use Fluent Wait to check for custom conditions
  3. Set polling every 50 milliseconds to able to catch messages
  4. Check if status message element is visible, if so get text
  5. Fail if actual status message is "error"
  6. Check actual status message contains first text in the expectedMessages, if so remove first text from expectedMessages
  7. Repeat step 6 until there's no items left if expectedMessages


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

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);
Sers
  • 12,047
  • 2
  • 12
  • 31
  • @MistaWizard If this answer or any other one solved your issue, you can upvote answer and mark it as accepted, [how to accept the answer](https://stackoverflow.com/help/someone-answers) – Sers Oct 10 '19 at 12:37
  • Thank you, I've tried this fluent wait method and unfortunately its not working in my case. Again i only pickup the first message. At first i thought it might be the poll so i set that to 1 millisecond... I can visually see the change in the field (with the aid of chrome devtools i see its still the right element) – imp Oct 10 '19 at 12:44
  • its taken a little while to test (i'm trying in both groovy 2.5 and 3.0 and java 8/11) – imp Oct 10 '19 at 12:45
  • There's probably one more solution can be tried. I'll share code in the answer shortly. Can you explain what exactly not worked with fluent wait? – Sers Oct 10 '19 at 12:47
  • @MistaWizard try new code in the answer to collect all messages – Sers Oct 10 '19 at 13:17
  • Thanks, Ive just done something simpler(added the method into a while and kept calling said method until list was zero) it mustve logged hundreds of the first message, but never the second message. @Sers, I'm going to try out your way tonight. Thank you – imp Oct 10 '19 at 13:33