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.")); - } - }