From 61ac25428f64cfee6ce351b2d5271f9bbf75e57b Mon Sep 17 00:00:00 2001 From: Tomi Virtanen Date: Fri, 15 Dec 2023 14:34:13 +0200 Subject: [PATCH] test: add tests for waitForVaadin (#1707) Adds a new hook in waitForVaadin while loop for tests. New tests verifies that waiting stops properly after client flag `devServerIsNotLoaded` is changed or client's `isActive()` return value changes. Co-authored-by: Mikhail Shabarov <61410877+mshabarov@users.noreply.github.com> --- .../com/vaadin/tests/WaitForVaadinIT.java | 69 ++++++++++++++++++- .../com/vaadin/tests/WaitForVaadinIT.java | 67 ++++++++++++++++++ .../commands/TestBenchCommandExecutor.java | 6 ++ 3 files changed, 141 insertions(+), 1 deletion(-) diff --git a/vaadin-testbench-integration-tests-junit5/src/test/java/com/vaadin/tests/WaitForVaadinIT.java b/vaadin-testbench-integration-tests-junit5/src/test/java/com/vaadin/tests/WaitForVaadinIT.java index 2605e02e8..926fe8d78 100644 --- a/vaadin-testbench-integration-tests-junit5/src/test/java/com/vaadin/tests/WaitForVaadinIT.java +++ b/vaadin-testbench-integration-tests-junit5/src/test/java/com/vaadin/tests/WaitForVaadinIT.java @@ -8,7 +8,10 @@ */ package com.vaadin.tests; +import java.lang.reflect.Field; + import org.junit.jupiter.api.Assertions; +import org.openqa.selenium.JavascriptExecutor; import com.vaadin.flow.component.Component; import com.vaadin.testUI.PageObjectView; @@ -38,6 +41,18 @@ public void waitForVaadin_activeConnector_waits() { assertExecutionBlocked(() -> getCommandExecutor().waitForVaadin()); } + @BrowserTest + public void waitForVaadin_activeConnector_waitsUtilReady() { + openTestURL(); + assertDevServerIsNotLoaded(); + getCommandExecutor().executeScript( + "window.Vaadin.Flow.clients[\"blocker\"] = {isActive: () => true};"); + setWaitForVaadinLoopHook(500, + "window.Vaadin.Flow.clients[\"blocker\"] = {isActive: () => false};"); + getCommandExecutor().waitForVaadin(); + assertClientIsActive(); + } + @BrowserTest public void waitForVaadin_noConnectors_returnsImmediately() { openTestURL(); @@ -57,12 +72,39 @@ public void waitForVaadin_noFlow_returnsImmediately() { @BrowserTest public void waitForVaadin_devModeNotReady_waits() { openTestURL(); - getCommandExecutor().executeScript( "window.Vaadin = {Flow: {devServerIsNotLoaded: true}};"); assertExecutionBlocked(() -> getCommandExecutor().waitForVaadin()); } + @BrowserTest + public void waitForVaadin_devModeNotReady_waitsUntilReady() { + openTestURL(); + assertDevServerIsNotLoaded(); + getCommandExecutor().executeScript( + "window.Vaadin = {Flow: {devServerIsNotLoaded: true}};"); + setWaitForVaadinLoopHook(500, + "window.Vaadin.Flow.devServerIsNotLoaded = false;"); + getCommandExecutor().waitForVaadin(); + assertDevServerIsNotLoaded(); + } + + private void assertDevServerIsNotLoaded() { + Object devServerIsNotLoaded = executeScript( + "return window.Vaadin.Flow.devServerIsNotLoaded;"); + Assertions.assertTrue( + devServerIsNotLoaded == null + || devServerIsNotLoaded == Boolean.FALSE, + "devServerIsNotLoaded should be null or false"); + } + + private void assertClientIsActive() { + Object active = executeScript( + "return window.Vaadin.Flow.clients[\"blocker\"].isActive();"); + Assertions.assertSame(active, Boolean.FALSE, + "clients[\"blocker\"].isActive() should return false"); + } + private void assertExecutionNoLonger(Runnable command) { long before = System.currentTimeMillis(); command.run(); @@ -80,4 +122,29 @@ private void assertExecutionBlocked(Runnable command) { Assertions.assertTrue(timeout >= BLOCKING_EXECUTION_TIMEOUT, "Unexpected execution time, waiting time = " + timeout); } + + private void setWaitForVaadinLoopHook(long timeout, + String scriptToRunAfterTimeout) { + long systemCurrentTimeMillis = System.currentTimeMillis(); + setWaitForVaadinLoopHook(() -> { + if (System.currentTimeMillis() + - systemCurrentTimeMillis > timeout) { + ((JavascriptExecutor) getCommandExecutor().getDriver() + .getWrappedDriver()) + .executeScript(scriptToRunAfterTimeout); + setWaitForVaadinLoopHook(null); + } + }); + } + + private void setWaitForVaadinLoopHook(Runnable action) { + try { + Field field = getCommandExecutor().getClass() + .getDeclaredField("waitForVaadinLoopHook"); + field.setAccessible(true); + field.set(getCommandExecutor(), action); + } catch (NoSuchFieldException | IllegalAccessException e) { + throw new RuntimeException(e); + } + } } diff --git a/vaadin-testbench-integration-tests/src/test/java/com/vaadin/tests/WaitForVaadinIT.java b/vaadin-testbench-integration-tests/src/test/java/com/vaadin/tests/WaitForVaadinIT.java index 9df44ba39..f11602188 100644 --- a/vaadin-testbench-integration-tests/src/test/java/com/vaadin/tests/WaitForVaadinIT.java +++ b/vaadin-testbench-integration-tests/src/test/java/com/vaadin/tests/WaitForVaadinIT.java @@ -8,8 +8,11 @@ */ package com.vaadin.tests; +import java.lang.reflect.Field; + import org.junit.Assert; import org.junit.Test; +import org.openqa.selenium.JavascriptExecutor; import com.vaadin.flow.component.Component; import com.vaadin.testUI.PageObjectView; @@ -38,6 +41,18 @@ public void waitForVaadin_activeConnector_waits() { assertExecutionBlocked(() -> getCommandExecutor().waitForVaadin()); } + @Test + public void waitForVaadin_activeConnector_waitsUtilReady() { + openTestURL(); + assertDevServerIsNotLoaded(); + getCommandExecutor().executeScript( + "window.Vaadin.Flow.clients[\"blocker\"] = {isActive: () => true};"); + setWaitForVaadinLoopHook(500, + "window.Vaadin.Flow.clients[\"blocker\"] = {isActive: () => false};"); + getCommandExecutor().waitForVaadin(); + assertClientIsActive(); + } + @Test public void waitForVaadin_noConnectors_returnsImmediately() { openTestURL(); @@ -63,6 +78,33 @@ public void waitForVaadin_devModeNotReady_waits() { assertExecutionBlocked(() -> getCommandExecutor().waitForVaadin()); } + @Test + public void waitForVaadin_devModeNotReady_waitsUntilReady() { + openTestURL(); + assertDevServerIsNotLoaded(); + getCommandExecutor().executeScript( + "window.Vaadin = {Flow: {devServerIsNotLoaded: true}};"); + setWaitForVaadinLoopHook(500, + "window.Vaadin.Flow.devServerIsNotLoaded = false;"); + getCommandExecutor().waitForVaadin(); + assertDevServerIsNotLoaded(); + } + + private void assertDevServerIsNotLoaded() { + Object devServerIsNotLoaded = executeScript( + "return window.Vaadin.Flow.devServerIsNotLoaded;"); + Assert.assertTrue("devServerIsNotLoaded should be null or false", + devServerIsNotLoaded == null + || devServerIsNotLoaded == Boolean.FALSE); + } + + private void assertClientIsActive() { + Object active = executeScript( + "return window.Vaadin.Flow.clients[\"blocker\"].isActive();"); + Assert.assertSame("clients[\"blocker\"].isActive() should return false", + Boolean.FALSE, active); + } + private void assertExecutionNoLonger(Runnable command) { long before = System.currentTimeMillis(); command.run(); @@ -82,4 +124,29 @@ private void assertExecutionBlocked(Runnable command) { "Unexpected blocked execution time, waiting time = " + timeout, timeout >= BLOCKING_EXECUTION_TIMEOUT); } + + private void setWaitForVaadinLoopHook(long timeout, + String scriptToRunAfterTimeout) { + long systemCurrentTimeMillis = System.currentTimeMillis(); + setWaitForVaadinLoopHook(() -> { + if (System.currentTimeMillis() + - systemCurrentTimeMillis > timeout) { + ((JavascriptExecutor) getCommandExecutor().getDriver() + .getWrappedDriver()) + .executeScript(scriptToRunAfterTimeout); + setWaitForVaadinLoopHook(null); + } + }); + } + + private void setWaitForVaadinLoopHook(Runnable action) { + try { + Field field = getCommandExecutor().getClass() + .getDeclaredField("waitForVaadinLoopHook"); + field.setAccessible(true); + field.set(getCommandExecutor(), action); + } catch (NoSuchFieldException | IllegalAccessException e) { + throw new RuntimeException(e); + } + } } diff --git a/vaadin-testbench-shared/src/main/java/com/vaadin/testbench/commands/TestBenchCommandExecutor.java b/vaadin-testbench-shared/src/main/java/com/vaadin/testbench/commands/TestBenchCommandExecutor.java index f00c64798..5716b846d 100644 --- a/vaadin-testbench-shared/src/main/java/com/vaadin/testbench/commands/TestBenchCommandExecutor.java +++ b/vaadin-testbench-shared/src/main/java/com/vaadin/testbench/commands/TestBenchCommandExecutor.java @@ -64,6 +64,9 @@ private static Logger getLogger() { + "}"; // @formatter:on + // A hook for testing purposes + private Runnable waitForVaadinLoopHook; + public TestBenchCommandExecutor(ImageComparison imageComparison, ReferenceNameGenerator referenceNameGenerator) { this.imageComparison = imageComparison; @@ -113,6 +116,9 @@ public void waitForVaadin() { long timeoutTime = System.currentTimeMillis() + 40000; Boolean finished = false; while (System.currentTimeMillis() < timeoutTime && !finished) { + if (waitForVaadinLoopHook != null) { + waitForVaadinLoopHook.run(); + } // Must use the wrapped driver here to avoid calling waitForVaadin // again finished = (Boolean) ((JavascriptExecutor) getDriver()