Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

waitForVaadin() fails when switching between multiple UIs #869

Open
curo-automation opened this issue Jan 23, 2017 · 3 comments
Open

waitForVaadin() fails when switching between multiple UIs #869

curo-automation opened this issue Jan 23, 2017 · 3 comments

Comments

@curo-automation
Copy link

Vaadin support suggested that we file following issue as a bug.

We use selenium and phantomjs (v2.1.1) alongside testbench.

After navigating to a page, we call waitForVaadin() via the WebDriver in order to wait for Vaadin initialization to complete.

After this, we attempt to find an element like so:

$(TextFieldElement.class).first();

but receive this error:

Vaadin could not find elements with the selector (//com.vaadin.ui.TextField)[0]
For documentation on this error, please visit: http://seleniumhq.org/exceptions/no_such_element.html
Caused by: org.openqa.selenium.WebDriverException:
{"errorMessage":"undefined is not a function (evaluating 'clients[client].getElementsByPath(arguments[0])')" ...}

We receive this error after navigating between UIs.

After close inspection of the "undefined is not a function" error message and TestBenchCommandExecutor.waitForVaadin() method we constructed the following experimental wait method:

private void waitForVaadinInit() {
    StringBuilder commandBuilder = new StringBuilder(500);
    commandBuilder.append("if (window.vaadin == null) { return 4; }");
    commandBuilder.append("var clients = window.vaadin.clients;");
    commandBuilder.append("if (!clients) { return 3; }");
    commandBuilder.append("for (var key in clients) {");
    commandBuilder.append(" var client = clients[key];");
    commandBuilder.append(" if (client.getElementsByPath == undefined) { return 2; }");
    commandBuilder.append(" else if (client.isActive()) { return 1; } }");
    commandBuilder.append("return 0;");
    String command = commandBuilder.toString();
    long startTime = System.currentTimeMillis();
    long maxTime = startTime + 20000;
    JavascriptExecutor js = (JavascriptExecutor) driver;
    long errorCode = -1;
    while (System.currentTimeMillis() < maxTime && errorCode != 0) {
        errorCode = (Long) js.executeScript(command);
    }
    if (errorCode != 0) {
        throw new CurocompAutomationException("Timeout waiting for Vaadin init.");
    }
}

We find that calling this function will properly wait for Vaadin to initialise. We accumulated error codes from cases where the javascript code was retried, and found that it failed with error codes 4, and 2, corresponding to window.vaadin == null and client.getElementsByPath == undefined respectively.

We noticed that TestBenchCommandExecuter.waitForVaadin() does not check for case 2, and will exit early without retrying if it encounters case 4. Whereas the above workaround fixes the issue for us by retrying on these cases.

Thanks in advance!

@Artur-
Copy link
Member

Artur- commented Jan 23, 2017

Hi,

Do you happen to have some kind of test to share, where you encounter this problem? Does it happen when you navigate by clicking a link, opening a new URL or some other means?

When opening a page using the get command, then TestBench should wait for the DOMContentLoaded event before continuing. After this, a waitForVaadin is automatically triggered so after doing driver.get("someUrl") you should always be able to directly do e.g. $(TextFieldElement.class).first();

When the DomContentLoaded event occurs, window.vaadin should always be defined unless the bootstrap JavaScript has failed to load. If we would make TestBench wait when window.vaadin is not defined, we would wait forever if you visit a page where there is no Vaadin app. I don't see when error code "4" would happen so please enlighten me.

@curo-automation
Copy link
Author

curo-automation commented Jan 24, 2017

Hi! Thanks so much for the speedy response.

As to "when does it happen", I should have mentioned this is an intermittent failure.

We have around 300 tests running on CI and every other build we are hit with either situation 2 or 4 above in one of our tests. (Which one seems to be random).

This happens when opening a new URL like so:

driver.navigate().to(url);

and also after clicking links/buttons.

Should we use driver.get(url) instead of driver.navigate().to(url);?

About a test I can share with you, I've shared this thread with our development lead and we'll see what we can do. I'll get back to you on that.

@Artur-
Copy link
Member

Artur- commented Jan 26, 2017

driver.navigate().to(url) is the same as driver.get(url), it's just another way to write it.

I tried running a test which navigates between UIs by either clicking on a link or by using driver.get() but I see no problems so there must be something else involved here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants