vaadin / testbench

Vaadin TestBench is a tool for automated user interface testing of Vaadin applications.
https://vaadin.com/testbench
Other
20 stars 22 forks source link

Upload TestBenchElement sometimes fails to upload and times out #1802

Open jorgheymans opened 3 weeks ago

jorgheymans commented 3 weeks ago

Using the UploadElement.class, we're seeing that it fails seemingly randomly.

      $(UploadElement.class)
          .id("id")
          .upload(new File("src/test/resources/attachments/test.pdf").getAbsoluteFile()); 

When it fails, it's because of org.openqa.selenium.ScriptTimeoutException: script timeout.

    at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:518)
    at org.openqa.selenium.remote.RemoteWebDriver.executeAsyncScript(RemoteWebDriver.java:471)
    at com.vaadin.testbench.TestBenchDriverProxy.executeAsyncScript(TestBenchDriverProxy.java:196)
    at com.vaadin.testbench.TestBenchDriverProxy_$$_jvstdb6_0._d7executeAsyncScript(TestBenchDriverProxy_$$_jvstdb6_0.java)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:568)
    at com.vaadin.testbench.DriverInvocationHandler.invoke(DriverInvocationHandler.java:47)
    at com.vaadin.testbench.TestBenchDriverProxy_$$_jvstdb6_0.executeAsyncScript(TestBenchDriverProxy_$$_jvstdb6_0.java)
    at com.vaadin.flow.component.upload.testbench.UploadElement.waitForUploads(UploadElement.java:147)
    at com.vaadin.flow.component.upload.testbench.UploadElement.upload(UploadElement.java:94)
    at com.vaadin.flow.component.upload.testbench.UploadElement.upload(UploadElement.java:54)

The timeout originates in this method:

    private void waitForUploads(int maxSeconds) {
        Timeouts timeouts = getDriver().manage().timeouts();
        timeouts.setScriptTimeout(maxSeconds, TimeUnit.SECONDS);

        String script = "var callback = arguments[arguments.length - 1];"
                + "var upload = arguments[0];"
                + "window.setTimeout(function() {"
                + "  var inProgress = upload.files.filter(function(file) { return file.uploading;}).length >0;"
                + "  if (!inProgress) callback();" //
                + "}, 500);";
        getCommandExecutor().getDriver().executeAsyncScript(script, this);

    }

AI overlord says that above code has a potential bug in it: one logical issue is usage of setTimeout. It only checks for in-progress uploads once after 500ms. If upload takes longer, your callback won't be executed. Use a polling technique instead

and then proposes this:

String script = "var callback = arguments[arguments.length - 1];"
                + "var upload = arguments[0];"
                + "(function poll() {"
                + "   var inProgress = upload.files.filter(function(file) { return file.uploading;}).length > 0;"
                + "   if (!inProgress) callback();"
                + "   else setTimeout(poll, 500);"
                + "})()";

Does this make any sense at all, or should the source of timeout be investigated somewhere else?