1

I need to wait until the result of a javascript match a string or a boolean value.

With this javascript:

document.getElementById('video_html5').seeking;

I get a "false" / "true" value, and i need to wait until the value is "false", so I'm sure that the video is not seeking, but I only found the way to wait for a javascript command value and not the way to check that the value matches some text.

new WebDriverWait(driver, 30)
    .until(ExpectedConditions.jsReturnsValue("return document.getElementById('video_html5').seeking;"));

Because in some cases I get a string other than boolean and need to compare those strings.

I have found how to do it in Ruby but not in Java:

wait_element = @wait.until { @driver.execute_script("return document.getElementById('vid1_html5_api_Shaka_api').seeking;").eql? false }
1
  • Would this work? jsReturnsValue("document.getElementById('video_html5').seeking === 'false' ? 'true' : undefined;") It'll compare the value directly in the JavaScript, returning undefined if seeking is true. Commented Jan 9, 2017 at 18:54

4 Answers 4

6

You can write your own custom expected conditions.

public class MyCustomConditions {

  public static ExpectedCondition<Boolean> myCustomCondition() {
    return new ExpectedCondition<Boolean>() {
      @Override
      public Boolean apply(WebDriver driver) {
        return (Boolean) ((JavascriptExecutor) driver)
          .executeScript("return document.getElementById('video_html5').seeking === 'string_value' || ... ");
      }
    };
  }
}

And then in your tests you can use the condition as follows.

WebDriverWait wait = new WebDriverWait(driver, 30);
wait.until(MyCustomConditions.myCustomCondition());
Sign up to request clarification or add additional context in comments.

2 Comments

The thing is that I prefer some sort of universal way to do it, because i need to make many comparisons of strings with the javascript results, so i would prefer to not having to add a customCondition for every comparison, if possible.
Perhaps you can create a single condition with generic logic and then pass specific parameters as needed.
1

A generic way to do it (where command is the JavaScript you want to run with webdriver in timeout seconds):

public Object executeScriptAndWaitOutput(WebDriver driver, long timeout, final String command) {
  WebDriverWait wait = new WebDriverWait(driver, timeout);
  wait.withMessage("Timeout executing script: " + command);

  final Object[] out = new Object[1];
  wait.until(new ExpectedCondition<Boolean>() {
    @Override
    public Boolean apply(WebDriver d) {
      try {
        out[0] = executeScript(command);
      } catch (WebDriverException we) {
        log.warn("Exception executing script", we);
        out[0] = null;
      }
      return out[0] != null;
    }
  });
  return out[0];
}

Comments

0

Finally i did the following and worked, getting ideas from different answers:

public Boolean checkStateSeeking() throws InterruptedException {
        JavascriptExecutor js = (JavascriptExecutor) driver;
        Boolean seekingState = (Boolean) js
                .executeScript("return document.getElementById('vid1_html5').seeking;");

        while (seekingState) {
            // System.out.println(seekingState);
            seekingState = (Boolean) js
                    .executeScript("return document.getElementById('vid1_html5').seeking;");
        }

        return seekingState;
    }

Comments

0

Getting ideas for all the answers I create a function to wait for an element to change each and waiting N seconds, using the xpath of the element and the expected value.

 public static String checkValueChanged(WebDriver driver, String expectedValue, String path, int waitTime) throws InterruptedException {
    JavascriptExecutor js = (JavascriptExecutor) driver;
    String elementValue = (String) js
            .executeScript("return document.evaluate(\""+path+"\", document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue.value;");

    while (!(elementValue.equals(expectedValue)) && (waitTime>0)) {
        Thread.sleep(1000);
        waitTime--;
        elementValue = (String) js
                .executeScript("return document.evaluate(\""+path+"\", document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue.value;");
    }
    return elementValue;
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.