Misty mountains

Wait for Vaadin in Selenium

Our web project uses the Vaadin framework. Because the pages are not loaded in one time, we have to wait a certain time. For that purpose we have to wait for Vaadin in our selenium scripts.

Wait for Vaadin in selenium

At first we created a VaadinIsLoaded method. This function is waits until Vaadin is completely loaded.

We create at first the following code. The code executes some Javascript code and returns if the Javascript returns OK. It keeps waiting until the code returns OK or until a timeout occurs.

public void waitForVaadin(Webdriver driver){
  long start = System.currentTimeMillis();
  // Javascript checks vaadin isActive flag for all Vaadin Window objects
  StringBuilder script = new StringBuilder();
  script.append("if(window.vaadin==null||window.vaadin.clients==null) return false;");
  script.append("var isWaiting=false;");
  script.append("for(i in window.vaadin.clients) isWaiting|=window.vaadin.clients[i].isActive();");
  script.append("return isWaiting?'Wait':'Ok';");
  for (;;) {
    // Query server side
    Object result = ((JavascriptExecutor) driver).executeScript(script.toString());
    if ("Ok".equals(result)) return;
    // More than 10 seconds is too slow
    long now = System.currentTimeMillis();
    if (now - start > 20 * 1000)
      throw new IllegalStateException("Too slow");
    // Sleep a bit, releasing the CPU to Vaadin
    try {
      Thread.sleep(50);
    } catch (InterruptedException e) {
      throw new IllegalStateException(e);
    }
  }
}

Selenium provides functionalities to wait for certain conditions until a defined task is complete. That is an ExpectedCondition.

I was not very happy with the previous code. It contains a check and a loop to wait. When the check is successful, it exits. When the check is not successful, the functions checks again until a period of time. After that time, the method throws an error. Selenium has many patterns like this. It is done via so called Expected Conditions. I tried to create one for this method.

First, I extracted the validation out the method and created a new ExpectedCondition object. In this case I can use the same logic as other Expected Conditions in selenium.

To create an ExpectedCondition class, I override the apply method. The toString method is used to have a decent output when printing the class.

public static ExpectedCondition<Boolean> VaadinIsLoaded() {
  return new ExpectedCondition<Boolean>() {
    private Boolean loaded = false;
    
    @Override
    public Boolean apply(WebDriver driver) {
      StringBuilder script = new StringBuilder();        
      script.append("if(window.vaadin==null||window.vaadin.clients==null) return false;");
      script.append("var isWaiting=false;");
      script.append("for(i in window.vaadin.clients) isWaiting|=window.vaadin.clients[i].isActive();");
      script.append("return isWaiting?'Wait':'Ok';");

      Object result = ((JavascriptExecutor) driver).executeScript(script.toString());
      loaded = result.equals("Ok");
      return loaded;
    }

    @Override
    public String toString() {
      return String.format("Vaadin to be loaded. Vaadin Loaded on page: \"%s\"", loaded);
    }
  };
}

You can call the VaadinIsLoaded function like any other Expected Condition with a WebDriverWait object.

public void waitForVaadin(WebDriver driver) {
  WebDriverWait wait = new WebDriverWait(driver, 20);
  wait.until(ExpectedConditionsCm.VaadinIsLoaded());
}

Now I do have a simple way to wait until the page is loaded. In this way I wait for Vaadin in Selenium scripts.

About the author

I currently work as a Test Automation Consultant at b.ignited. Here I work for different clients in different industries to help them start and speed up their testing cycles

I’ve been testing software since 2000 when I became involved in testing telephone applications and hardware. Since then, I’ve been able to expand my experience by testing a variety of embedded, web, mobile and desktop applications. I have used various development methodologies from waterfall to agile.

I consider myself to be a lifelong learner.