diff --git a/bom/application/pom.xml b/bom/application/pom.xml
index a9ae775c7c7fe..17f46829327a4 100644
--- a/bom/application/pom.xml
+++ b/bom/application/pom.xml
@@ -1863,6 +1863,11 @@
quarkus-vertx-http-dev-ui-spi
${project.version}
+
+ io.quarkus
+ quarkus-vertx-http-dev-ui-tests
+ ${project.version}
+
io.quarkus
quarkus-vertx-http-dev-ui-resources
diff --git a/extensions/hibernate-orm/deployment/pom.xml b/extensions/hibernate-orm/deployment/pom.xml
index 8d828fe785924..d1b1770d2f167 100644
--- a/extensions/hibernate-orm/deployment/pom.xml
+++ b/extensions/hibernate-orm/deployment/pom.xml
@@ -53,6 +53,11 @@
io.quarkus
quarkus-vertx-http-dev-ui-spi
+
+ io.quarkus
+ quarkus-vertx-http-dev-ui-tests
+ test
+
io.quarkus
quarkus-junit5-internal
diff --git a/extensions/hibernate-orm/deployment/src/test/java/io/quarkus/hibernate/orm/devui/DevUIHibernateOrmActiveFalseAndNamedPuActiveTrueTest.java b/extensions/hibernate-orm/deployment/src/test/java/io/quarkus/hibernate/orm/devui/DevUIHibernateOrmActiveFalseAndNamedPuActiveTrueTest.java
new file mode 100644
index 0000000000000..20843c98b3e41
--- /dev/null
+++ b/extensions/hibernate-orm/deployment/src/test/java/io/quarkus/hibernate/orm/devui/DevUIHibernateOrmActiveFalseAndNamedPuActiveTrueTest.java
@@ -0,0 +1,33 @@
+package io.quarkus.hibernate.orm.devui;
+
+import org.jboss.shrinkwrap.api.asset.StringAsset;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+import io.quarkus.hibernate.orm.devui.namedpu.MyNamedPuEntity;
+import io.quarkus.test.QuarkusDevModeTest;
+
+public class DevUIHibernateOrmActiveFalseAndNamedPuActiveTrueTest extends DevUIHibernateOrmTest {
+
+ @RegisterExtension
+ static final QuarkusDevModeTest test = new QuarkusDevModeTest()
+ .withApplicationRoot((jar) -> jar.addAsResource(
+ new StringAsset("quarkus.datasource.db-kind=h2\n"
+ + "quarkus.datasource.jdbc.url=jdbc:h2:mem:test\n"
+ + "quarkus.datasource.\"nameddatasource\".db-kind=h2\n"
+ + "quarkus.datasource.\"nameddatasource\".jdbc.url=jdbc:h2:mem:test2\n"
+ // Hibernate ORM is inactive for the default PU
+ + "quarkus.hibernate-orm.active=false\n"
+ + "quarkus.hibernate-orm.datasource=\n"
+ + "quarkus.hibernate-orm.packages=io.quarkus.test.devconsole\n"
+ // ... but it's (implicitly) active for a named PU
+ + "quarkus.hibernate-orm.\"namedpu\".datasource=nameddatasource\n"
+ + "quarkus.hibernate-orm.\"namedpu\".packages=io.quarkus.hibernate.orm.devui.namedpu\n"),
+ "application.properties")
+ .addClasses(MyEntity.class)
+ .addClasses(MyNamedPuEntity.class));
+
+ public DevUIHibernateOrmActiveFalseAndNamedPuActiveTrueTest() {
+ super("namedpu", "MyNamedPuEntity", "io.quarkus.hibernate.orm.devui.namedpu.MyNamedPuEntity");
+ }
+
+}
diff --git a/extensions/hibernate-orm/deployment/src/test/java/io/quarkus/hibernate/orm/devui/DevUIHibernateOrmActiveFalseTest.java b/extensions/hibernate-orm/deployment/src/test/java/io/quarkus/hibernate/orm/devui/DevUIHibernateOrmActiveFalseTest.java
new file mode 100644
index 0000000000000..f5ac6f4970d50
--- /dev/null
+++ b/extensions/hibernate-orm/deployment/src/test/java/io/quarkus/hibernate/orm/devui/DevUIHibernateOrmActiveFalseTest.java
@@ -0,0 +1,24 @@
+package io.quarkus.hibernate.orm.devui;
+
+import org.jboss.shrinkwrap.api.asset.StringAsset;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+import io.quarkus.test.QuarkusDevModeTest;
+
+public class DevUIHibernateOrmActiveFalseTest extends DevUIHibernateOrmTest {
+
+ @RegisterExtension
+ static final QuarkusDevModeTest test = new QuarkusDevModeTest()
+ .withApplicationRoot((jar) -> jar.addAsResource(
+ new StringAsset("quarkus.datasource.db-kind=h2\n"
+ + "quarkus.datasource.jdbc.url=jdbc:h2:mem:test\n"
+ // Hibernate ORM is inactive: the dev console should be empty.
+ + "quarkus.hibernate-orm.active=false\n"),
+ "application.properties")
+ .addClasses(MyEntity.class));
+
+ public DevUIHibernateOrmActiveFalseTest() {
+ super(0, 0);
+ }
+
+}
diff --git a/extensions/hibernate-orm/deployment/src/test/java/io/quarkus/hibernate/orm/devui/DevUIHibernateOrmSmokeTest.java b/extensions/hibernate-orm/deployment/src/test/java/io/quarkus/hibernate/orm/devui/DevUIHibernateOrmSmokeTest.java
new file mode 100644
index 0000000000000..2af06838e358a
--- /dev/null
+++ b/extensions/hibernate-orm/deployment/src/test/java/io/quarkus/hibernate/orm/devui/DevUIHibernateOrmSmokeTest.java
@@ -0,0 +1,21 @@
+package io.quarkus.hibernate.orm.devui;
+
+import org.jboss.shrinkwrap.api.asset.StringAsset;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+import io.quarkus.test.QuarkusDevModeTest;
+
+public class DevUIHibernateOrmSmokeTest extends DevUIHibernateOrmTest {
+
+ @RegisterExtension
+ static final QuarkusDevModeTest test = new QuarkusDevModeTest()
+ .withApplicationRoot((jar) -> jar.addAsResource(
+ new StringAsset("quarkus.datasource.db-kind=h2\n"
+ + "quarkus.datasource.jdbc.url=jdbc:h2:mem:test\n"),
+ "application.properties")
+ .addClasses(MyEntity.class));
+
+ public DevUIHibernateOrmSmokeTest() {
+ super("", "MyEntity", "io.quarkus.hibernate.orm.devui.MyEntity");
+ }
+}
diff --git a/extensions/hibernate-orm/deployment/src/test/java/io/quarkus/hibernate/orm/devui/DevUIHibernateOrmTest.java b/extensions/hibernate-orm/deployment/src/test/java/io/quarkus/hibernate/orm/devui/DevUIHibernateOrmTest.java
new file mode 100644
index 0000000000000..837a038adb240
--- /dev/null
+++ b/extensions/hibernate-orm/deployment/src/test/java/io/quarkus/hibernate/orm/devui/DevUIHibernateOrmTest.java
@@ -0,0 +1,105 @@
+package io.quarkus.hibernate.orm.devui;
+
+import java.util.Iterator;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import com.fasterxml.jackson.databind.JsonNode;
+
+import io.quarkus.devui.tests.DevUIJsonRPCTest;
+
+/**
+ * All tests test the same api call, with different configuration and different expected results
+ * This abstract class reduce the code in each test
+ */
+public abstract class DevUIHibernateOrmTest extends DevUIJsonRPCTest {
+
+ private String expectedPersistenceUnitName = null;
+ private String expectedTableName = null;
+ private String expectedClassName = null;
+ private int expectedNumberOfEntityTypes = 1;
+ private int expectedNumberOfPersistenceUnits = 1;
+
+ public DevUIHibernateOrmTest(String expectedPersistenceUnitName, String expectedTableName, String expectedClassName) {
+ super("io.quarkus.quarkus-hibernate-orm");
+ this.expectedPersistenceUnitName = expectedPersistenceUnitName;
+ this.expectedTableName = expectedTableName;
+ this.expectedClassName = expectedClassName;
+ }
+
+ public DevUIHibernateOrmTest(int expectedNumberOfEntityTypes,
+ int expectedNumberOfPersistenceUnits) {
+ super("io.quarkus.quarkus-hibernate-orm");
+ this.expectedNumberOfEntityTypes = expectedNumberOfEntityTypes;
+ this.expectedNumberOfPersistenceUnits = expectedNumberOfPersistenceUnits;
+ }
+
+ @Test
+ public void testGetInfo() throws Exception {
+ JsonNode getInfoResponse = super.executeJsonRPCMethod("getInfo");
+ Assertions.assertNotNull(getInfoResponse);
+
+ JsonNode persistenceUnits = getInfoResponse.get("persistenceUnits");
+ Assertions.assertNotNull(persistenceUnits);
+ Assertions.assertTrue(persistenceUnits.isArray());
+
+ if (expectedPersistenceUnitName == null) {
+ Assertions.assertEquals(0, persistenceUnits.size());
+ } else {
+ Assertions.assertEquals(1, persistenceUnits.size());
+ Iterator persistenceUnitsIterator = persistenceUnits.elements();
+ while (persistenceUnitsIterator.hasNext()) {
+ JsonNode defaultPersistenceUnit = persistenceUnitsIterator.next();
+ JsonNode name = defaultPersistenceUnit.get("name");
+ Assertions.assertEquals(expectedPersistenceUnitName, name.asText());
+
+ JsonNode managedEntities = defaultPersistenceUnit.get("managedEntities");
+ Assertions.assertNotNull(managedEntities);
+ Assertions.assertTrue(managedEntities.isArray());
+
+ Iterator managedEntitiesIterator = managedEntities.elements();
+ while (managedEntitiesIterator.hasNext()) {
+ JsonNode myEntity = managedEntitiesIterator.next();
+ Assertions.assertEquals(expectedNumberOfPersistenceUnits, persistenceUnits.size());
+
+ String tableName = myEntity.get("tableName").asText();
+ Assertions.assertEquals(expectedTableName, tableName);
+
+ String className = myEntity.get("className").asText();
+ Assertions.assertEquals(expectedClassName, className);
+
+ }
+
+ JsonNode namedQueries = defaultPersistenceUnit.get("namedQueries");
+ Assertions.assertNotNull(namedQueries);
+ Assertions.assertTrue(namedQueries.isArray());
+
+ }
+ }
+ }
+
+ @Test
+ public void testGetNumberOfPersistenceUnits() throws Exception {
+ JsonNode getNumberOfPersistenceUnitsResponse = super.executeJsonRPCMethod("getNumberOfPersistenceUnits");
+ Assertions.assertNotNull(getNumberOfPersistenceUnitsResponse);
+ Assertions.assertTrue(getNumberOfPersistenceUnitsResponse.isInt());
+ Assertions.assertEquals(expectedNumberOfPersistenceUnits, getNumberOfPersistenceUnitsResponse.asInt());
+ }
+
+ @Test
+ public void testGetNumberOfEntityTypes() throws Exception {
+ JsonNode getNumberOfEntityTypesResponse = super.executeJsonRPCMethod("getNumberOfEntityTypes");
+ Assertions.assertNotNull(getNumberOfEntityTypesResponse);
+ Assertions.assertTrue(getNumberOfEntityTypesResponse.isInt());
+ Assertions.assertEquals(expectedNumberOfEntityTypes, getNumberOfEntityTypesResponse.asInt());
+ }
+
+ @Test
+ public void testGetNumberOfNamedQueries() throws Exception {
+ JsonNode getNumberOfNamedQueriesResponse = super.executeJsonRPCMethod("getNumberOfNamedQueries");
+ Assertions.assertNotNull(getNumberOfNamedQueriesResponse);
+ Assertions.assertTrue(getNumberOfNamedQueriesResponse.isInt());
+ Assertions.assertEquals(0, getNumberOfNamedQueriesResponse.asInt());
+ }
+}
diff --git a/extensions/hibernate-orm/deployment/src/test/java/io/quarkus/hibernate/orm/devui/MyEntity.java b/extensions/hibernate-orm/deployment/src/test/java/io/quarkus/hibernate/orm/devui/MyEntity.java
new file mode 100644
index 0000000000000..622bdfa97927e
--- /dev/null
+++ b/extensions/hibernate-orm/deployment/src/test/java/io/quarkus/hibernate/orm/devui/MyEntity.java
@@ -0,0 +1,16 @@
+package io.quarkus.hibernate.orm.devui;
+
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.Id;
+
+@Entity
+public class MyEntity {
+
+ @Id
+ Long id;
+
+ @Column
+ String field;
+
+}
diff --git a/extensions/hibernate-orm/deployment/src/test/java/io/quarkus/hibernate/orm/devui/namedpu/MyNamedPuEntity.java b/extensions/hibernate-orm/deployment/src/test/java/io/quarkus/hibernate/orm/devui/namedpu/MyNamedPuEntity.java
new file mode 100644
index 0000000000000..d7b4d6087b840
--- /dev/null
+++ b/extensions/hibernate-orm/deployment/src/test/java/io/quarkus/hibernate/orm/devui/namedpu/MyNamedPuEntity.java
@@ -0,0 +1,14 @@
+package io.quarkus.hibernate.orm.devui.namedpu;
+
+import jakarta.persistence.Entity;
+import jakarta.persistence.Id;
+
+@Entity
+public class MyNamedPuEntity {
+
+ @Id
+ Long id;
+
+ String field;
+
+}
diff --git a/extensions/vertx-http/deployment/pom.xml b/extensions/vertx-http/deployment/pom.xml
index 444f15fd3dbd1..1c718f24ae0ed 100644
--- a/extensions/vertx-http/deployment/pom.xml
+++ b/extensions/vertx-http/deployment/pom.xml
@@ -115,6 +115,11 @@
+
+ io.quarkus
+ quarkus-vertx-http-dev-ui-tests
+ test
+
io.quarkus
quarkus-security-deployment
diff --git a/extensions/vertx-http/deployment/src/test/java/io/quarkus/devui/BuildMetricsTest.java b/extensions/vertx-http/deployment/src/test/java/io/quarkus/devui/BuildMetricsTest.java
new file mode 100644
index 0000000000000..cf8adc6920ba7
--- /dev/null
+++ b/extensions/vertx-http/deployment/src/test/java/io/quarkus/devui/BuildMetricsTest.java
@@ -0,0 +1,33 @@
+package io.quarkus.devui;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+import com.fasterxml.jackson.databind.JsonNode;
+
+import io.quarkus.devui.tests.DevUIJsonRPCTest;
+import io.quarkus.test.QuarkusDevModeTest;
+
+public class BuildMetricsTest extends DevUIJsonRPCTest {
+
+ @RegisterExtension
+ static final QuarkusDevModeTest config = new QuarkusDevModeTest().withEmptyApplication();
+
+ public BuildMetricsTest() {
+ super("devui-build-metrics");
+ }
+
+ @Test
+ public void testGetBuildStepsMetrics() throws Exception {
+ JsonNode buildStepsMetricsResponse = super.executeJsonRPCMethod("getBuildStepsMetrics");
+ Assertions.assertNotNull(buildStepsMetricsResponse);
+
+ int duration = buildStepsMetricsResponse.get("duration").asInt();
+ Assertions.assertTrue(duration > 0);
+
+ boolean dependencyGraphsIncluded = buildStepsMetricsResponse.get("dependencyGraphs").isObject();
+ Assertions.assertTrue(dependencyGraphsIncluded);
+
+ }
+}
diff --git a/extensions/vertx-http/deployment/src/test/java/io/quarkus/devui/ConfigurationTest.java b/extensions/vertx-http/deployment/src/test/java/io/quarkus/devui/ConfigurationTest.java
new file mode 100644
index 0000000000000..6468be25f62ad
--- /dev/null
+++ b/extensions/vertx-http/deployment/src/test/java/io/quarkus/devui/ConfigurationTest.java
@@ -0,0 +1,38 @@
+package io.quarkus.devui;
+
+import java.util.Map;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+import com.fasterxml.jackson.databind.JsonNode;
+
+import io.quarkus.devui.tests.DevUIJsonRPCTest;
+import io.quarkus.test.QuarkusDevModeTest;
+
+public class ConfigurationTest extends DevUIJsonRPCTest {
+
+ @RegisterExtension
+ static final QuarkusDevModeTest config = new QuarkusDevModeTest()
+ .withEmptyApplication();
+
+ public ConfigurationTest() {
+ super("devui-configuration");
+ }
+
+ @Test
+ public void testLogstreamHistory() throws Exception {
+
+ JsonNode updatePropertyResponse = super.executeJsonRPCMethod("updateProperty",
+ Map.of(
+ "name", "quarkus.application.name",
+ "value", "changedByTest"));
+ Assertions.assertTrue(updatePropertyResponse.asBoolean());
+
+ // Get the properties to make sure it is changed
+ JsonNode allPropertiesResponse = super.executeJsonRPCMethod("getAllValues");
+ String applicationName = allPropertiesResponse.get("quarkus.application.name").asText();
+ Assertions.assertEquals("changedByTest", applicationName);
+ }
+}
diff --git a/extensions/vertx-http/deployment/src/test/java/io/quarkus/devui/ExtensionsTest.java b/extensions/vertx-http/deployment/src/test/java/io/quarkus/devui/ExtensionsTest.java
new file mode 100644
index 0000000000000..61f49d7e9dc25
--- /dev/null
+++ b/extensions/vertx-http/deployment/src/test/java/io/quarkus/devui/ExtensionsTest.java
@@ -0,0 +1,38 @@
+package io.quarkus.devui;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+import com.fasterxml.jackson.databind.JsonNode;
+
+import io.quarkus.devui.tests.DevUIBuildTimeDataTest;
+import io.quarkus.test.QuarkusDevModeTest;
+
+public class ExtensionsTest extends DevUIBuildTimeDataTest {
+
+ @RegisterExtension
+ static final QuarkusDevModeTest config = new QuarkusDevModeTest().withEmptyApplication();
+
+ public ExtensionsTest() {
+ super("devui");
+ }
+
+ @Test
+ public void testGetExtensions() throws Exception {
+ JsonNode extensionsResponse = super.getBuildTimeData("extensions");
+ Assertions.assertNotNull(extensionsResponse);
+
+ JsonNode activeExtensions = extensionsResponse.get("active");
+ Assertions.assertNotNull(activeExtensions);
+ Assertions.assertTrue(activeExtensions.isArray());
+
+ JsonNode inactiveExtensions = extensionsResponse.get("inactive");
+ Assertions.assertNotNull(inactiveExtensions);
+ Assertions.assertTrue(inactiveExtensions.isArray());
+
+ log.info(extensionsResponse.toPrettyString());
+
+ }
+
+}
diff --git a/extensions/vertx-http/deployment/src/test/java/io/quarkus/devui/LogstreamTest.java b/extensions/vertx-http/deployment/src/test/java/io/quarkus/devui/LogstreamTest.java
new file mode 100644
index 0000000000000..41c7649c9e44f
--- /dev/null
+++ b/extensions/vertx-http/deployment/src/test/java/io/quarkus/devui/LogstreamTest.java
@@ -0,0 +1,66 @@
+package io.quarkus.devui;
+
+import java.util.Iterator;
+import java.util.Map;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+import com.fasterxml.jackson.databind.JsonNode;
+
+import io.quarkus.devui.tests.DevUIJsonRPCTest;
+import io.quarkus.test.QuarkusDevModeTest;
+
+public class LogstreamTest extends DevUIJsonRPCTest {
+
+ @RegisterExtension
+ static final QuarkusDevModeTest config = new QuarkusDevModeTest()
+ .withEmptyApplication();
+
+ public LogstreamTest() {
+ super("devui-logstream");
+ }
+
+ @Test
+ public void testHistory() throws Exception {
+ JsonNode historyResponse = super.executeJsonRPCMethod("history");
+ Assertions.assertNotNull(historyResponse);
+ Assertions.assertTrue(historyResponse.isArray());
+ Assertions.assertTrue(hasStartedLine(historyResponse.elements()));
+ }
+
+ @Test
+ public void testGetLoggers() throws Exception {
+ JsonNode getLoggersResponse = super.executeJsonRPCMethod("getLoggers");
+ Assertions.assertNotNull(getLoggersResponse);
+ Assertions.assertTrue(getLoggersResponse.isArray());
+ }
+
+ @Test
+ public void testUpdateLoggers() throws Exception {
+ // Get the level before
+ JsonNode getLoggerResponse = super.executeJsonRPCMethod("getLogger", Map.of("loggerName", "io.quarkus"));
+ Assertions.assertNotNull(getLoggerResponse);
+ Assertions.assertEquals("INFO", getLoggerResponse.get("effectiveLevel").asText());
+
+ // Update the level
+ JsonNode updateLogLevelResponse = super.executeJsonRPCMethod("updateLogLevel",
+ Map.of("loggerName", "io.quarkus",
+ "levelValue", "DEBUG"));
+ Assertions.assertNotNull(updateLogLevelResponse);
+ Assertions.assertEquals("DEBUG", updateLogLevelResponse.get("effectiveLevel").asText());
+ }
+
+ private boolean hasStartedLine(Iterator elements) {
+ while (elements.hasNext()) {
+ JsonNode next = elements.next();
+ String line = next.get("formattedMessage").asText();
+
+ if (line.contains("powered by Quarkus") && line.contains(" started in ")) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/extensions/vertx-http/dev-ui-tests/pom.xml b/extensions/vertx-http/dev-ui-tests/pom.xml
new file mode 100644
index 0000000000000..4904a56d79ce3
--- /dev/null
+++ b/extensions/vertx-http/dev-ui-tests/pom.xml
@@ -0,0 +1,26 @@
+
+
+ 4.0.0
+
+ quarkus-vertx-http-parent
+ io.quarkus
+ 999-SNAPSHOT
+ ../
+
+
+ quarkus-vertx-http-dev-ui-tests
+ Quarkus - Vert.x - HTTP - Dev UI Tests
+
+
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+
+
+ io.quarkus
+ quarkus-websockets-client-deployment
+
+
+
+
diff --git a/extensions/vertx-http/dev-ui-tests/src/main/java/io/quarkus/devui/tests/DevUIBuildTimeDataTest.java b/extensions/vertx-http/dev-ui-tests/src/main/java/io/quarkus/devui/tests/DevUIBuildTimeDataTest.java
new file mode 100644
index 0000000000000..ec774880ec7bf
--- /dev/null
+++ b/extensions/vertx-http/dev-ui-tests/src/main/java/io/quarkus/devui/tests/DevUIBuildTimeDataTest.java
@@ -0,0 +1,73 @@
+package io.quarkus.devui.tests;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.nio.charset.StandardCharsets;
+import java.util.Scanner;
+
+import org.eclipse.microprofile.config.ConfigProvider;
+import org.jboss.logging.Logger;
+
+import com.fasterxml.jackson.core.JsonFactory;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+public abstract class DevUIBuildTimeDataTest {
+
+ protected static final Logger log = Logger.getLogger(DevUIBuildTimeDataTest.class);
+
+ protected URI uri;
+
+ private final ObjectMapper mapper = new ObjectMapper();
+ private final JsonFactory factory = mapper.getFactory();
+
+ public DevUIBuildTimeDataTest(String namespace) {
+ String testUrl = ConfigProvider.getConfig().getValue("test.url", String.class);
+ String nonApplicationRoot = ConfigProvider.getConfig()
+ .getOptionalValue("quarkus.http.non-application-root-path", String.class).orElse("q");
+ if (!nonApplicationRoot.startsWith("/")) {
+ nonApplicationRoot = "/" + nonApplicationRoot;
+ }
+ this.uri = URI.create(testUrl + nonApplicationRoot + "/dev-ui/" + namespace + "-data.js");
+ }
+
+ public JsonNode getBuildTimeData(String key) throws Exception {
+
+ String data = readDataFromUrl();
+ String[] kvs = data.split(CONST);
+
+ for (String kv : kvs) {
+ if (kv.startsWith(key + SPACE + EQUALS + SPACE + OPEN_CURLY_BRACKET)) {
+ String json = kv.substring(kv.indexOf(EQUALS) + 1).trim();
+ log.debug("json = " + json);
+ return toJsonNode(json);
+ }
+ }
+
+ return null;
+ }
+
+ protected JsonNode toJsonNode(String json) {
+ try {
+ JsonParser parser = factory.createParser(json);
+ return mapper.readTree(parser);
+ } catch (IOException ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ private String readDataFromUrl() throws MalformedURLException, IOException {
+ try (Scanner scanner = new Scanner(uri.toURL().openStream(),
+ StandardCharsets.UTF_8.toString())) {
+ scanner.useDelimiter("\\A");
+ return scanner.hasNext() ? scanner.next() : null;
+ }
+ }
+
+ private static final String CONST = "export const ";
+ private static final String SPACE = " ";
+ private static final String EQUALS = "=";
+ private static final String OPEN_CURLY_BRACKET = "{";
+}
diff --git a/extensions/vertx-http/dev-ui-tests/src/main/java/io/quarkus/devui/tests/DevUIJsonRPCTest.java b/extensions/vertx-http/dev-ui-tests/src/main/java/io/quarkus/devui/tests/DevUIJsonRPCTest.java
new file mode 100644
index 0000000000000..3e7d0cb3a960d
--- /dev/null
+++ b/extensions/vertx-http/dev-ui-tests/src/main/java/io/quarkus/devui/tests/DevUIJsonRPCTest.java
@@ -0,0 +1,131 @@
+package io.quarkus.devui.tests;
+
+import java.io.IOException;
+import java.net.URI;
+import java.util.Map;
+import java.util.Random;
+import java.util.concurrent.LinkedBlockingDeque;
+import java.util.concurrent.TimeUnit;
+
+import jakarta.websocket.ClientEndpoint;
+import jakarta.websocket.ContainerProvider;
+import jakarta.websocket.OnMessage;
+import jakarta.websocket.OnOpen;
+import jakarta.websocket.Session;
+
+import org.eclipse.microprofile.config.ConfigProvider;
+import org.jboss.logging.Logger;
+import org.junit.jupiter.api.Assertions;
+
+import com.fasterxml.jackson.core.JsonFactory;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+public abstract class DevUIJsonRPCTest {
+
+ protected static final Logger log = Logger.getLogger(DevUIJsonRPCTest.class);
+
+ protected URI uri;
+
+ private final ObjectMapper mapper = new ObjectMapper();
+ private final JsonFactory factory = mapper.getFactory();
+ private final Random random = new Random();
+
+ private final String namespace;
+
+ public DevUIJsonRPCTest(String namespace) {
+ this.namespace = namespace;
+ String testUrl = ConfigProvider.getConfig().getValue("test.url", String.class);
+ String nonApplicationRoot = ConfigProvider.getConfig()
+ .getOptionalValue("quarkus.http.non-application-root-path", String.class).orElse("q");
+ if (!nonApplicationRoot.startsWith("/")) {
+ nonApplicationRoot = "/" + nonApplicationRoot;
+ }
+ this.uri = URI.create(testUrl + nonApplicationRoot + "/dev-ui/json-rpc-ws");
+ }
+
+ public JsonNode executeJsonRPCMethod(String methodName) throws Exception {
+ return executeJsonRPCMethod(methodName, null);
+ }
+
+ public JsonNode executeJsonRPCMethod(String methodName, Map params) throws Exception {
+ try (Session session = ContainerProvider.getWebSocketContainer().connectToServer(Client.class, uri)) {
+ Assertions.assertEquals("CONNECT", MESSAGES.poll(10, TimeUnit.SECONDS));
+
+ int id = random.nextInt(Integer.MAX_VALUE);
+
+ String request = createJsonRPCRequest(id, methodName, params);
+ log.debug("request = " + request);
+ session.getAsyncRemote().sendText(request);
+
+ JsonNode response = parseJsonRPCResponse(id);
+ log.debug("response = " + response.toPrettyString());
+
+ return response;
+ }
+ }
+
+ protected JsonNode toJsonNode(String json) {
+ try {
+ JsonParser parser = factory.createParser(json);
+ return mapper.readTree(parser);
+ } catch (IOException ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ private JsonNode parseJsonRPCResponse(int id) throws InterruptedException, IOException {
+ return parseJsonRPCResponse(id, 0);
+ }
+
+ private JsonNode parseJsonRPCResponse(int id, int loopCount) throws InterruptedException, IOException {
+ String response = MESSAGES.poll(10, TimeUnit.SECONDS);
+ JsonNode jsonResponse = toJsonNode(response);
+ if (jsonResponse.isObject()) {
+ int responseId = jsonResponse.get("id").asInt();
+ if (responseId == id) {
+ return jsonResponse.get("result").get("object");
+ }
+ }
+
+ if (loopCount > 10)
+ throw new RuntimeException("Too many recursions, message not returned for id [" + id + "]");
+ return parseJsonRPCResponse(id, loopCount + 1);
+ }
+
+ private String createJsonRPCRequest(int id, String methodName, Map params) throws IOException {
+
+ ObjectNode request = mapper.createObjectNode();
+
+ request.put("jsonrpc", "2.0");
+ request.put("id", id);
+ request.put("method", this.namespace + "." + methodName);
+ ObjectNode jsonParams = mapper.createObjectNode();
+ if (params != null && !params.isEmpty()) {
+ for (Map.Entry p : params.entrySet()) {
+ jsonParams.put(p.getKey(), p.getValue());
+ }
+ }
+ request.set("params", jsonParams);
+ return mapper.writerWithDefaultPrettyPrinter().writeValueAsString(request);
+ }
+
+ private static final LinkedBlockingDeque MESSAGES = new LinkedBlockingDeque<>();
+
+ @ClientEndpoint
+ public static class Client {
+
+ @OnOpen
+ public void open(Session session) {
+ MESSAGES.add("CONNECT");
+ }
+
+ @OnMessage
+ public void message(String msg) {
+ MESSAGES.add(msg);
+ }
+ }
+
+}
diff --git a/extensions/vertx-http/pom.xml b/extensions/vertx-http/pom.xml
index 794f5f2c19d59..f370261e6feee 100644
--- a/extensions/vertx-http/pom.xml
+++ b/extensions/vertx-http/pom.xml
@@ -21,5 +21,6 @@
deployment-spi
dev-ui-spi
dev-ui-resources
+ dev-ui-tests
diff --git a/integration-tests/devmode/pom.xml b/integration-tests/devmode/pom.xml
index 6a6c2b5ce8521..f149a3b7510d3 100644
--- a/integration-tests/devmode/pom.xml
+++ b/integration-tests/devmode/pom.xml
@@ -14,6 +14,11 @@
+
+ io.quarkus
+ quarkus-vertx-http-dev-ui-tests
+ test
+
io.quarkus
quarkus-resteasy-reactive-deployment
diff --git a/integration-tests/devmode/src/test/java/io/quarkus/test/devconsole/DevConsoleHibernateOrmActiveFalseAndNamedPuActiveTrueTest.java b/integration-tests/devmode/src/test/java/io/quarkus/test/devconsole/DevConsoleHibernateOrmActiveFalseAndNamedPuActiveTrueTest.java
index 7849ff7cb7bd3..65fc963124c9d 100644
--- a/integration-tests/devmode/src/test/java/io/quarkus/test/devconsole/DevConsoleHibernateOrmActiveFalseAndNamedPuActiveTrueTest.java
+++ b/integration-tests/devmode/src/test/java/io/quarkus/test/devconsole/DevConsoleHibernateOrmActiveFalseAndNamedPuActiveTrueTest.java
@@ -52,27 +52,4 @@ public void testLegacyPages() {
.statusCode(200)
.body(Matchers.containsString("No named queries were found."));
}
-
- @Test
- public void testPages() {
- // TODO #31970 restore tests of the page's content as we used to do for the old Dev UI
-
- RestAssured.get("q/dev-v1/io.quarkus.quarkus-hibernate-orm/persistence-units")
- .then()
- .statusCode(200);
- // .body(Matchers.not(Matchers.containsString("<default>")))
- // .body(Matchers.containsString("namedpu"));
-
- RestAssured.get("q/dev-v1/io.quarkus.quarkus-hibernate-orm/managed-entities")
- .then()
- .statusCode(200);
- // .body(Matchers.not(Matchers.containsString(MyEntity.class.getName())))
- // .body(Matchers.containsString(MyNamedPuEntity.class.getName()));
-
- RestAssured.get("q/dev-v1/io.quarkus.quarkus-hibernate-orm/named-queries")
- .then()
- .statusCode(200);
- // .body(Matchers.containsString("No named queries were found."));
- }
-
}
diff --git a/integration-tests/devmode/src/test/java/io/quarkus/test/devconsole/DevConsoleHibernateOrmActiveFalseTest.java b/integration-tests/devmode/src/test/java/io/quarkus/test/devconsole/DevConsoleHibernateOrmActiveFalseTest.java
index 7d834bb7290e8..c7636abd64a5b 100644
--- a/integration-tests/devmode/src/test/java/io/quarkus/test/devconsole/DevConsoleHibernateOrmActiveFalseTest.java
+++ b/integration-tests/devmode/src/test/java/io/quarkus/test/devconsole/DevConsoleHibernateOrmActiveFalseTest.java
@@ -41,25 +41,4 @@ public void testLegacyPages() {
.statusCode(200)
.body(Matchers.containsString("No persistence units were found"));
}
-
- @Test
- public void testPages() {
- // TODO #31970 restore tests of the page's content as we used to do for the old Dev UI
-
- RestAssured.get("q/dev-ui/hibernate-orm/persistence-units")
- .then()
- .statusCode(200);
- // .body(Matchers.containsString("No persistence units were found"));
-
- RestAssured.get("q/dev-ui/hibernate-orm/entity-types")
- .then()
- .statusCode(200);
- // .body(Matchers.containsString("No persistence units were found"));
-
- RestAssured.get("q/dev-ui/hibernate-orm/named-queries")
- .then()
- .statusCode(200);
- // .body(Matchers.containsString("No persistence units were found"));
- }
-
}
diff --git a/integration-tests/devmode/src/test/java/io/quarkus/test/devconsole/DevConsoleHibernateOrmSmokeTest.java b/integration-tests/devmode/src/test/java/io/quarkus/test/devconsole/DevConsoleHibernateOrmSmokeTest.java
index 58a8ef4b09512..542c8f0c461fd 100644
--- a/integration-tests/devmode/src/test/java/io/quarkus/test/devconsole/DevConsoleHibernateOrmSmokeTest.java
+++ b/integration-tests/devmode/src/test/java/io/quarkus/test/devconsole/DevConsoleHibernateOrmSmokeTest.java
@@ -39,25 +39,4 @@ public void testLegacyPages() {
.statusCode(200)
.body(Matchers.containsString("No named queries were found."));
}
-
- @Test
- public void testPages() {
- // TODO #31970 restore tests of the page's content as we used to do for the old Dev UI
-
- RestAssured.get("q/dev-ui/hibernate-orm/persistence-units")
- .then()
- .statusCode(200);
- // .body(Matchers.containsString("<default>"));
-
- RestAssured.get("q/dev-ui/hibernate-orm/entity-types")
- .then()
- .statusCode(200);
- // .body(Matchers.containsString("io.quarkus.test.devconsole.MyEntity"));
-
- RestAssured.get("q/dev-ui/hibernate-orm/named-queries")
- .then()
- .statusCode(200);
- // .body(Matchers.containsString("No named queries were found."));
- }
-
}