简体   繁体   中英

How to test a polling javascript ajax call with Selenium Java WebDriver

I have a page with JavaScript code that polls an API every second and replaces and element in the HTML page with the response. I would like to test this page using Selenium WebDriver. I have WebDriver setup in my Junit Test but I don't know how to deal with the polling Java Script.

RemoteWebDriver driver = chrome.getWebDriver();
driver.get("http://localhost:8080");

The JavaScript code configures a timer to call the getMessage() is setup like so.

 <body>
    <h1 id="message"> Loading ... </h1>
</body>
<script>
    function getMessage()
    {
        $.ajax({
            url : '/message',
            type: 'GET',
            success: function(data){
                $('#message').text(data.message);
            },
            error: function (data) {
                $('#message').text("Error Response");
            }
        });
    }

    $(document).ready(function() {
        window.setInterval(getMessage, 1000);
    });
</script>

I want to test the H1 message value changed to something every second or so for 30 seconds, so I am expecting to see 25 changes in 30 second run of the test. How can I do this with Selenium WebDriver?

Below is one of the hacky way of printing the message every two seconds

We can write our own function and pass that function to Until method of FluentWait. It will call this method every 2 second & Timeout is set to 30 seconds. We are using counter Once count > 10 . It should come out of until . May need some refactoring as per your needs.

Function<WebDriver, Boolean> function = new Function<WebDriver, Boolean>()
 {
    int count = 1;
    public Boolean apply(WebDriver arg0) {
    count++;
    WebElement element = arg0.findElement(By.id("message"));
    String text= element.getText(); 
    System.out.println("Message " + text); // your logic
    if(count > 10))
    {
       return true;
    }
    return false;
    }
 }

Example use . Assuming driver paths etc. are set properly

public static void main(String[] args) throws InterruptedException {
 
 WebDriver driver = new FirefoxDriver();
 driver.get("http://localhost:8080");
 
 FluentWait<WebDriver> wait = new FluentWait<WebDriver>(driver);
 wait.pollingEvery(Duration.ofSeconds(2));
 wait.withTimeout(Duration.ofSeconds(30));
 wait.ignoring(NoSuchElementException.class);
 
 Function<WebDriver, Boolean> function = new Function<WebDriver, Boolean>()
 {
   int count = 1;
   public Boolean apply(WebDriver arg0) {
   count++;
   WebElement element = arg0.findElement(By.id("message"));
   String text= element.getText(); 
   System.out.println("Message " + text); // your logic
   if(count > 10))
   {
      System.out.println(count + "++++++++++++++++++");
      return true;
   }
   return false;
  }
  };
 
 wait.until(function);// You can handle timeout exception using try-catch as per your 
 //use case
}

Here is another approach:

private boolean testElementFor1SecChange(SearchContext searchContext, By locator, Duration testDuration){
    String baseElementText = searchContext.findElement(locator).getText();
    for(int i = 0; i < testDuration.get(ChronoUnit.SECONDS); i++){
        try {
            Thread.sleep(1000);
            String nextElementText = searchContext.findElement(locator).getText();
            if(baseElementText == null || baseElementText.equals(nextElementText)){
                return false;
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
            return false;
        }
    }
    return true;
}

So the test would look like:

@Test
public void testChanges(){
    driver.get("http://localhost:8080");
    Assert.assertTrue(
            testElementFor1SecChange(driver, By.id("message"), Duration.ofSeconds(30))
    );
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM