From a50c9e2e650a575ce3ce11626743373ba5b7a5a9 Mon Sep 17 00:00:00 2001 From: taefi Date: Fri, 26 Jul 2024 17:55:23 +0300 Subject: [PATCH 1/6] test: add NumberSignal IT --- .../frontend/_views/SharedNumberSignal.tsx | 30 +++++++++++++++++++ .../helper/NumberSignalServiceWrapper.ts | 14 +++++++++ .../spring/react-signals/frontend/routes.tsx | 5 ++++ .../service/NumberSignalProviderService.java | 20 +++++++++++++ .../resources/vaadin-featureflags.properties | 2 ++ .../com/vaadin/hilla/test/NumberSignalIT.java | 29 ++++++++++++++++++ 6 files changed, 100 insertions(+) create mode 100644 packages/java/tests/spring/react-signals/frontend/_views/SharedNumberSignal.tsx create mode 100644 packages/java/tests/spring/react-signals/frontend/helper/NumberSignalServiceWrapper.ts create mode 100644 packages/java/tests/spring/react-signals/src/main/java/com/vaadin/hilla/test/signals/service/NumberSignalProviderService.java create mode 100644 packages/java/tests/spring/react-signals/src/main/resources/vaadin-featureflags.properties create mode 100644 packages/java/tests/spring/react-signals/src/test/java/com/vaadin/hilla/test/NumberSignalIT.java diff --git a/packages/java/tests/spring/react-signals/frontend/_views/SharedNumberSignal.tsx b/packages/java/tests/spring/react-signals/frontend/_views/SharedNumberSignal.tsx new file mode 100644 index 0000000000..6f3f1729e3 --- /dev/null +++ b/packages/java/tests/spring/react-signals/frontend/_views/SharedNumberSignal.tsx @@ -0,0 +1,30 @@ +import { NumberSignalServiceWrapper } from '../helper/NumberSignalServiceWrapper.js'; + +const counter = NumberSignalServiceWrapper.counter(); +const sharedValue = NumberSignalServiceWrapper.sharedValue(); + +export default function SharedNumberSignal() { + return ( +
+ Shared value: {sharedValue} + +
+ Counter value: {counter} + +
+ +
+ ); +} diff --git a/packages/java/tests/spring/react-signals/frontend/helper/NumberSignalServiceWrapper.ts b/packages/java/tests/spring/react-signals/frontend/helper/NumberSignalServiceWrapper.ts new file mode 100644 index 0000000000..49a15d893b --- /dev/null +++ b/packages/java/tests/spring/react-signals/frontend/helper/NumberSignalServiceWrapper.ts @@ -0,0 +1,14 @@ +import { NumberSignalChannel } from '@vaadin/hilla-react-signals'; +import client_1 from 'Frontend/generated/connect-client.default.js'; + +export class NumberSignalServiceWrapper { + static sharedValue() { + const signalChannel = new NumberSignalChannel('NumberSignalProviderService.sharedValue', client_1); + return signalChannel.signal; + } + + static counter() { + const signalChannel = new NumberSignalChannel('NumberSignalProviderService.counter', client_1); + return signalChannel.signal; + } +} diff --git a/packages/java/tests/spring/react-signals/frontend/routes.tsx b/packages/java/tests/spring/react-signals/frontend/routes.tsx index d4a2444244..5b7947cf13 100644 --- a/packages/java/tests/spring/react-signals/frontend/routes.tsx +++ b/packages/java/tests/spring/react-signals/frontend/routes.tsx @@ -1,6 +1,7 @@ import { createBrowserRouter } from 'react-router-dom'; import MainLayout from './MainLayout.js'; import BasicSignalView from './_views/BasicSignalView.js'; +import SharedNumberSignal from './_views/SharedNumberSignal.js'; export const routes = [ { path: '', @@ -10,6 +11,10 @@ export const routes = [ path: '/basic-signal', element: , }, + { + path: '/number-signal', + element: , + }, ], }, ]; diff --git a/packages/java/tests/spring/react-signals/src/main/java/com/vaadin/hilla/test/signals/service/NumberSignalProviderService.java b/packages/java/tests/spring/react-signals/src/main/java/com/vaadin/hilla/test/signals/service/NumberSignalProviderService.java new file mode 100644 index 0000000000..70d6041d61 --- /dev/null +++ b/packages/java/tests/spring/react-signals/src/main/java/com/vaadin/hilla/test/signals/service/NumberSignalProviderService.java @@ -0,0 +1,20 @@ +package com.vaadin.hilla.test.signals.service; + +import com.vaadin.hilla.signals.NumberSignal; +import com.vaadin.flow.server.auth.AnonymousAllowed; +import com.vaadin.hilla.BrowserCallable; + +@AnonymousAllowed +@BrowserCallable +public class NumberSignalProviderService { + private final NumberSignal counter = new NumberSignal(); + private final NumberSignal sharedValue = new NumberSignal(0.5); + + public NumberSignal counter() { + return counter; + } + + public NumberSignal sharedValue() { + return sharedValue; + } +} diff --git a/packages/java/tests/spring/react-signals/src/main/resources/vaadin-featureflags.properties b/packages/java/tests/spring/react-signals/src/main/resources/vaadin-featureflags.properties new file mode 100644 index 0000000000..64ea97e958 --- /dev/null +++ b/packages/java/tests/spring/react-signals/src/main/resources/vaadin-featureflags.properties @@ -0,0 +1,2 @@ +# Experimental feature flags for Vaadin +com.vaadin.experimental.fullstackSignals=true diff --git a/packages/java/tests/spring/react-signals/src/test/java/com/vaadin/hilla/test/NumberSignalIT.java b/packages/java/tests/spring/react-signals/src/test/java/com/vaadin/hilla/test/NumberSignalIT.java new file mode 100644 index 0000000000..b261ef0d0b --- /dev/null +++ b/packages/java/tests/spring/react-signals/src/test/java/com/vaadin/hilla/test/NumberSignalIT.java @@ -0,0 +1,29 @@ +package com.vaadin.hilla.test; + +import com.vaadin.flow.testutil.ChromeBrowserTest; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.openqa.selenium.By; + +public class NumberSignalIT extends ChromeBrowserTest { + + @Override + @Before + public void setup() throws Exception { + super.setup(); + getDriver().get(getRootURL() + "/number-signal"); + waitForPageToLoad(); + } + + private void waitForPageToLoad() { + waitForElementPresent(By.ById.id("sharedValue")); + waitForElementPresent(By.ById.id("counter")); + } + + @Test + public void shouldHaveDefaultValueLoadedFromServer() { + Assert.assertEquals("Shared value: 0.5", $("span").id("sharedValue").getText()); + Assert.assertEquals("Counter value: 0", $("span").id("counter").getText()); + } +} From 8cc93396cbcfd79ef1784c8b77a6aebf113ebcc0 Mon Sep 17 00:00:00 2001 From: taefi Date: Fri, 26 Jul 2024 17:56:13 +0300 Subject: [PATCH 2/6] test: add NumberSignal IT --- .../src/test/java/com/vaadin/hilla/test/NumberSignalIT.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/java/tests/spring/react-signals/src/test/java/com/vaadin/hilla/test/NumberSignalIT.java b/packages/java/tests/spring/react-signals/src/test/java/com/vaadin/hilla/test/NumberSignalIT.java index b261ef0d0b..6ed873dbdb 100644 --- a/packages/java/tests/spring/react-signals/src/test/java/com/vaadin/hilla/test/NumberSignalIT.java +++ b/packages/java/tests/spring/react-signals/src/test/java/com/vaadin/hilla/test/NumberSignalIT.java @@ -23,7 +23,9 @@ private void waitForPageToLoad() { @Test public void shouldHaveDefaultValueLoadedFromServer() { - Assert.assertEquals("Shared value: 0.5", $("span").id("sharedValue").getText()); - Assert.assertEquals("Counter value: 0", $("span").id("counter").getText()); + Assert.assertEquals("Shared value: 0.5", + $("span").id("sharedValue").getText()); + Assert.assertEquals("Counter value: 0", + $("span").id("counter").getText()); } } From d82dc0699dc7ede00342f453c3423d47f21dd9d1 Mon Sep 17 00:00:00 2001 From: taefi Date: Sun, 28 Jul 2024 00:26:00 +0300 Subject: [PATCH 3/6] test: add NumberSignal IT --- .../frontend/_views/SharedNumberSignal.tsx | 42 +++++-- .../service/NumberSignalProviderService.java | 14 +++ .../com/vaadin/hilla/test/NumberSignalIT.java | 106 +++++++++++++++++- 3 files changed, 149 insertions(+), 13 deletions(-) diff --git a/packages/java/tests/spring/react-signals/frontend/_views/SharedNumberSignal.tsx b/packages/java/tests/spring/react-signals/frontend/_views/SharedNumberSignal.tsx index 6f3f1729e3..bc166a7057 100644 --- a/packages/java/tests/spring/react-signals/frontend/_views/SharedNumberSignal.tsx +++ b/packages/java/tests/spring/react-signals/frontend/_views/SharedNumberSignal.tsx @@ -1,22 +1,28 @@ import { NumberSignalServiceWrapper } from '../helper/NumberSignalServiceWrapper.js'; +import { Button } from '@vaadin/react-components'; +import { useSignal } from '@vaadin/hilla-react-signals'; +import { NumberSignalProviderService } from 'Frontend/generated/endpoints.js'; const counter = NumberSignalServiceWrapper.counter(); const sharedValue = NumberSignalServiceWrapper.sharedValue(); export default function SharedNumberSignal() { + const sharedValueFromServer = useSignal(0.0); + const counterValueFromServer = useSignal(0); + return (
- Shared value: {sharedValue} - +
- Counter value: {counter} - +
- + +
+ {sharedValueFromServer} + +
+ {counterValueFromServer} +
); } diff --git a/packages/java/tests/spring/react-signals/src/main/java/com/vaadin/hilla/test/signals/service/NumberSignalProviderService.java b/packages/java/tests/spring/react-signals/src/main/java/com/vaadin/hilla/test/signals/service/NumberSignalProviderService.java index 70d6041d61..9bbe9724f0 100644 --- a/packages/java/tests/spring/react-signals/src/main/java/com/vaadin/hilla/test/signals/service/NumberSignalProviderService.java +++ b/packages/java/tests/spring/react-signals/src/main/java/com/vaadin/hilla/test/signals/service/NumberSignalProviderService.java @@ -3,6 +3,9 @@ import com.vaadin.hilla.signals.NumberSignal; import com.vaadin.flow.server.auth.AnonymousAllowed; import com.vaadin.hilla.BrowserCallable; +import jakarta.validation.constraints.NotNull; + +import java.util.Optional; @AnonymousAllowed @BrowserCallable @@ -17,4 +20,15 @@ public NumberSignal counter() { public NumberSignal sharedValue() { return sharedValue; } + + @NotNull + public Double fetchSharedValue() { + return sharedValue.getValue(); + } + + @NotNull + public Long fetchCounterValue() { + return Optional.ofNullable(counter.getValue()).map(Double::longValue) + .orElse(null); + } } diff --git a/packages/java/tests/spring/react-signals/src/test/java/com/vaadin/hilla/test/NumberSignalIT.java b/packages/java/tests/spring/react-signals/src/test/java/com/vaadin/hilla/test/NumberSignalIT.java index 6ed873dbdb..9e65edab6f 100644 --- a/packages/java/tests/spring/react-signals/src/test/java/com/vaadin/hilla/test/NumberSignalIT.java +++ b/packages/java/tests/spring/react-signals/src/test/java/com/vaadin/hilla/test/NumberSignalIT.java @@ -1,31 +1,127 @@ package com.vaadin.hilla.test; +import com.vaadin.flow.component.button.testbench.ButtonElement; import com.vaadin.flow.testutil.ChromeBrowserTest; + import org.junit.Assert; import org.junit.Before; import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.BlockJUnit4ClassRunner; import org.openqa.selenium.By; +import org.openqa.selenium.WindowType; + +import javax.annotation.concurrent.NotThreadSafe; +@RunWith(BlockJUnit4ClassRunner.class) +@NotThreadSafe public class NumberSignalIT extends ChromeBrowserTest { + private String firstWindowHandle; + @Override @Before public void setup() throws Exception { super.setup(); getDriver().get(getRootURL() + "/number-signal"); + firstWindowHandle = getDriver().getWindowHandle(); waitForPageToLoad(); } private void waitForPageToLoad() { waitForElementPresent(By.ById.id("sharedValue")); waitForElementPresent(By.ById.id("counter")); + waitUntil(driver -> $("span").id("sharedValue").getText() != null); + waitUntil(driver -> $("span").id("counter").getText() != null); + } + + @Test + public void shouldUpdateValue_both_on_browser_and_server() { + for (int i = 0; i < 5; i++) { + var currentSharedValue = getSharedValue(); + clickButton("increaseSharedValue"); + Assert.assertEquals(currentSharedValue + 2, getSharedValue(), 0.0); + Assert.assertEquals(getSharedValue(), fetchSharedValue(), 0.0); + } + + for (int i = 0; i < 5; i++) { + var currentCounterValue = getCounterValue(); + clickButton("incrementCounter"); + Assert.assertEquals(currentCounterValue + 1, getCounterValue()); + Assert.assertEquals(getCounterValue(), fetchCounterValue()); + } } @Test - public void shouldHaveDefaultValueLoadedFromServer() { - Assert.assertEquals("Shared value: 0.5", - $("span").id("sharedValue").getText()); - Assert.assertEquals("Counter value: 0", - $("span").id("counter").getText()); + public void shouldUpdateValue_forOtherClients() { + var currentSharedValue = getSharedValue(); + var currentCounterValue = getCounterValue(); + + var secondWindowDriver = getDriver().switchTo() + .newWindow(WindowType.WINDOW); + try { + var secondWindowHandle = secondWindowDriver.getWindowHandle(); + + Assert.assertNotEquals(firstWindowHandle, secondWindowHandle); + + secondWindowDriver.get(getRootURL() + "/number-signal"); + + var secondWindowSharedValue = Double.parseDouble(secondWindowDriver + .findElement(By.id("sharedValue")).getText()); + Assert.assertEquals(currentSharedValue, secondWindowSharedValue, + 0.0); + + var secondWindowCounterValue = Long.parseLong( + secondWindowDriver.findElement(By.id("counter")).getText()); + Assert.assertEquals(currentCounterValue, secondWindowCounterValue); + + // press reset button on the second window + secondWindowDriver.findElement(By.id("reset")).click(); + + secondWindowSharedValue = Double.parseDouble(secondWindowDriver + .findElement(By.id("sharedValue")).getText()); + Assert.assertEquals(0.5, secondWindowSharedValue, 0.0); + + secondWindowCounterValue = Long.parseLong( + secondWindowDriver.findElement(By.id("counter")).getText()); + Assert.assertEquals(0, secondWindowCounterValue); + + secondWindowDriver.close(); + + // check that the first window is also updated: + getDriver().switchTo().window(firstWindowHandle); + Assert.assertEquals(0.5, getSharedValue(), 0.0); + Assert.assertEquals(0, getCounterValue()); + + } finally { + secondWindowDriver.close(); + } + } + + private double getSharedValue() { + return Double.parseDouble($("span").id("sharedValue").getText()); + } + + private long getCounterValue() { + return Long.parseLong($("span").id("counter").getText()); + } + + private double fetchSharedValue() { + clickButton("fetchSharedValue"); + return Double + .parseDouble($("span").id("sharedValueFromServer").getText()); + } + + private long fetchCounterValue() { + clickButton("fetchCounterValue"); + return Long.parseLong($("span").id("counterValueFromServer").getText()); + } + + private void clickButton(String id) { + $(ButtonElement.class).id(id).click(); + } + + private void resetValues() { + clickButton("reset"); } } From 96c9dda4e5bf915d5688482cd8f8319500aec82d Mon Sep 17 00:00:00 2001 From: taefi Date: Mon, 29 Jul 2024 10:52:40 +0300 Subject: [PATCH 4/6] test: remove unused method --- .../test/java/com/vaadin/hilla/test/NumberSignalIT.java | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/packages/java/tests/spring/react-signals/src/test/java/com/vaadin/hilla/test/NumberSignalIT.java b/packages/java/tests/spring/react-signals/src/test/java/com/vaadin/hilla/test/NumberSignalIT.java index 9e65edab6f..b605e17f6f 100644 --- a/packages/java/tests/spring/react-signals/src/test/java/com/vaadin/hilla/test/NumberSignalIT.java +++ b/packages/java/tests/spring/react-signals/src/test/java/com/vaadin/hilla/test/NumberSignalIT.java @@ -17,14 +17,11 @@ @NotThreadSafe public class NumberSignalIT extends ChromeBrowserTest { - private String firstWindowHandle; - @Override @Before public void setup() throws Exception { super.setup(); getDriver().get(getRootURL() + "/number-signal"); - firstWindowHandle = getDriver().getWindowHandle(); waitForPageToLoad(); } @@ -56,6 +53,7 @@ public void shouldUpdateValue_both_on_browser_and_server() { public void shouldUpdateValue_forOtherClients() { var currentSharedValue = getSharedValue(); var currentCounterValue = getCounterValue(); + var firstWindowHandle = getDriver().getWindowHandle(); var secondWindowDriver = getDriver().switchTo() .newWindow(WindowType.WINDOW); @@ -120,8 +118,4 @@ private long fetchCounterValue() { private void clickButton(String id) { $(ButtonElement.class).id(id).click(); } - - private void resetValues() { - clickButton("reset"); - } } From 720232f6b398dae76c5c6bb311d2359a468029f3 Mon Sep 17 00:00:00 2001 From: taefi Date: Wed, 31 Jul 2024 15:32:07 +0300 Subject: [PATCH 5/6] test: _view to view --- .../spring/react-signals/frontend/App.tsx | 6 --- .../react-signals/frontend/MainLayout.tsx | 34 -------------- .../helper/NumberSignalServiceWrapper.ts | 16 +++---- .../spring/react-signals/frontend/index.ts | 5 -- .../spring/react-signals/frontend/routes.tsx | 23 ---------- .../{_views => views}/BasicSignalView.tsx | 0 .../{_views => views}/SharedNumberSignal.tsx | 2 +- .../spring/react-signals/package-lock.json | 46 +++++++++---------- .../tests/spring/react-signals/package.json | 4 +- 9 files changed, 33 insertions(+), 103 deletions(-) delete mode 100644 packages/java/tests/spring/react-signals/frontend/App.tsx delete mode 100644 packages/java/tests/spring/react-signals/frontend/MainLayout.tsx delete mode 100644 packages/java/tests/spring/react-signals/frontend/index.ts delete mode 100644 packages/java/tests/spring/react-signals/frontend/routes.tsx rename packages/java/tests/spring/react-signals/frontend/{_views => views}/BasicSignalView.tsx (100%) rename packages/java/tests/spring/react-signals/frontend/{_views => views}/SharedNumberSignal.tsx (95%) diff --git a/packages/java/tests/spring/react-signals/frontend/App.tsx b/packages/java/tests/spring/react-signals/frontend/App.tsx deleted file mode 100644 index 6b7546d1ed..0000000000 --- a/packages/java/tests/spring/react-signals/frontend/App.tsx +++ /dev/null @@ -1,6 +0,0 @@ -import router from 'Frontend/routes.js'; -import { RouterProvider } from 'react-router-dom'; - -export default function App() { - return ; -} diff --git a/packages/java/tests/spring/react-signals/frontend/MainLayout.tsx b/packages/java/tests/spring/react-signals/frontend/MainLayout.tsx deleted file mode 100644 index 779dbd23bb..0000000000 --- a/packages/java/tests/spring/react-signals/frontend/MainLayout.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import { AppLayout } from '@vaadin/react-components/AppLayout.js'; -import { DrawerToggle } from '@vaadin/react-components/DrawerToggle.js'; -import { Scroller } from '@vaadin/react-components/Scroller.js'; -import { routes } from 'Frontend/routes.js'; -import { NavLink, Outlet } from 'react-router-dom'; - -export default function MainLayout() { - const menuRoutes = routes[0]!.children; - - return ( - -
-

My App

-
- - - -