Selenium wait for PrimeFaces 4.0 ajax to process

2020-06-28 00:58发布

问题:

My Selenium tests need to wait for ajax requests to process to avoid race conditions. In PrimeFaces 3.5 you could use the following method to wait (copied straight from the PrimeFaces svn repo):

private static final String JQUERY_ACTIVE_CONNECTIONS_QUERY = "return $.active == 0;";
private static final int DEFAULT_SLEEP_TIME_IN_SECONDS = 2;
private static final int DEFAULT_TIMEOUT_IN_SECONDS = 10;

protected void waitUntilAjaxRequestCompletes() {
   new FluentWait<WebDriver>(driver)
      .withTimeout(DEFAULT_TIMEOUT_IN_SECONDS, TimeUnit.SECONDS)
      .pollingEvery(DEFAULT_SLEEP_TIME_IN_SECONDS, TimeUnit.SECONDS)
      .until(new ExpectedCondition<Boolean>() {
         public Boolean apply(WebDriver d) {
            JavascriptExecutor jsExec = (JavascriptExecutor) d;
            return (Boolean) jsExec.executeScript(JQUERY_ACTIVE_CONNECTIONS_QUERY);
         }
   });
}

Unfortunately this code does not work in PrimeFaces 4.0, the jQuery connections never seem to be active.

So the question is: how do I wait for PrimeFaces ajax requests to process in version 4.0?

回答1:

PrimeFaces 4.0 uses its own ajax event handler, you can use the following code:

private static final String JS_JQUERY_DEFINED = "return typeof jQuery != 'undefined';";
private static final String JS_PRIMEFACES_DEFINED = "return typeof PrimeFaces != 'undefined';";
private static final String JS_JQUERY_ACTIVE = "return jQuery.active != 0;";
private static final String JS_PRIMEFACES_QUEUE_NOT_EMPTY = "return !PrimeFaces.ajax.Queue.isEmpty();";

private static final int TIME_OUT_SECONDS=10;
private static final int POLLING_MILLISECONDS=500;

private void waitForJQueryAndPrimeFaces() {
   new FluentWait(driver).withTimeout(TIME_OUT_SECONDS, TimeUnit.SECONDS)
      .pollingEvery(POLLING_MILLISECONDS, TimeUnit.MILLISECONDS)
      .until(new Function < WebDriver, Boolean >() {
         @Override
         public Boolean apply(WebDriver input) {
            boolean ajax = false;
            boolean jQueryDefined = executeBooleanJavascript(input, JS_JQUERY_DEFINED);
            boolean primeFacesDefined = executeBooleanJavascript(input, JS_PRIMEFACES_DEFINED);

            if (jQueryDefined) {
               // jQuery is still active
               ajax |= executeBooleanJavascript(input, JS_JQUERY_ACTIVE);
            }
            if (primeFacesDefined) {
               // PrimeFaces queue isn't empty
               ajax |= executeBooleanJavascript(input, JS_PRIMEFACES_QUEUE_NOT_EMPTY);
            }

            // continue if all ajax request are processed
            return !ajax;
         }
      });
}

private boolean executeBooleanJavascript(WebDriver input, String javascript) {
   return (Boolean) ((JavascriptExecutor) input).executeScript(javascript);
}