diff --git a/vaadin-testbench-unit-junit5/src/test/java/com/vaadin/testbench/unit/SignalsTest.java b/vaadin-testbench-unit-junit5/src/test/java/com/vaadin/testbench/unit/SignalsTest.java index 4683fddcb..246b8d312 100644 --- a/vaadin-testbench-unit-junit5/src/test/java/com/vaadin/testbench/unit/SignalsTest.java +++ b/vaadin-testbench-unit-junit5/src/test/java/com/vaadin/testbench/unit/SignalsTest.java @@ -9,6 +9,7 @@ package com.vaadin.testbench.unit; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import com.example.base.signals.SignalsView; @@ -16,6 +17,8 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Timeout; +import com.vaadin.flow.signals.SignalEnvironment; + @ViewPackages(packages = "com.example.base.signals") @Timeout(10) public class SignalsTest extends UIUnitTest { @@ -67,6 +70,30 @@ void attachedComponent_triggerSignalFromNonUIThreadThroughComponentEffect_effect Assertions.assertEquals("Counter: 10", counterTester.getText()); } + @Test + void effectDispatcher_routesToTestQueue_notServiceThreadPool() + throws InterruptedException { + // On the test thread, both VaadinServiceEnvironment (from + // MockVaadin) and TestSignalEnvironment are active. The default + // effect dispatcher must resolve to TestSignalEnvironment's queue + // (via registerFirst) so that runPendingSignalsTasks() can drive + // effect execution deterministically. Without registerFirst, + // VaadinServiceEnvironment's thread pool would be used instead, + // making effects run asynchronously outside the test's control. + navigate(SignalsView.class); + + var latch = new CountDownLatch(1); + SignalEnvironment.getDefaultEffectDispatcher() + .execute(latch::countDown); + + Assertions.assertFalse(latch.await(50, TimeUnit.MILLISECONDS), + "Task should be queued, not executed immediately on a " + + "thread pool"); + runPendingSignalsTasks(); + Assertions.assertTrue(latch.await(0, TimeUnit.MILLISECONDS), + "Task should have executed after draining the test queue"); + } + @Test void attachedComponent_slowEffect_effectEvaluatedAsynchronously() { var view = navigate(SignalsView.class); diff --git a/vaadin-testbench-unit-shared/src/main/java/com/vaadin/testbench/unit/TestSignalEnvironment.java b/vaadin-testbench-unit-shared/src/main/java/com/vaadin/testbench/unit/TestSignalEnvironment.java index 960a63536..aca04ba59 100644 --- a/vaadin-testbench-unit-shared/src/main/java/com/vaadin/testbench/unit/TestSignalEnvironment.java +++ b/vaadin-testbench-unit-shared/src/main/java/com/vaadin/testbench/unit/TestSignalEnvironment.java @@ -25,8 +25,10 @@ *

* How it works: *