Lea2501
Lea2501

Reputation: 351

Selenium - Wait until returned javascript script value match value

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 }

Upvotes: 1

Views: 6669

Answers (4)

Jorge Quiros
Jorge Quiros

Reputation: 11

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

Upvotes: 0

Lea2501
Lea2501

Reputation: 351

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

Upvotes: 0

Boni García
Boni García

Reputation: 4858

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

Upvotes: 1

cjungel
cjungel

Reputation: 3791

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

Upvotes: 6

Related Questions