This is an automated email from the ASF dual-hosted git repository.
jamesnetherton pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-quarkus.git
The following commit(s) were added to refs/heads/main by this push:
new 1aa650f Add additional test coverage for REST DSL methods
1aa650f is described below
commit 1aa650f3677032499af8640cca2fc5e9062b2c9a
Author: James Netherton <[email protected]>
AuthorDate: Wed Sep 1 07:12:00 2021 +0100
Add additional test coverage for REST DSL methods
Fixes #3036
---
.../component/openapijava/it/OpenApiRoutes.java | 116 +++++++++++++++++-
.../component/openapijava/it/OpenApiTest.java | 130 +++++++++++++++++++++
.../quarkus/component/rest/it/RestRoutes.java | 72 ++++++++++--
.../camel/quarkus/component/rest/it/RestTest.java | 76 +++++++++---
4 files changed, 365 insertions(+), 29 deletions(-)
diff --git
a/integration-tests/openapi-java/src/main/java/org/apache/camel/quarkus/component/openapijava/it/OpenApiRoutes.java
b/integration-tests/openapi-java/src/main/java/org/apache/camel/quarkus/component/openapijava/it/OpenApiRoutes.java
index beb1dc7..ee15121 100644
---
a/integration-tests/openapi-java/src/main/java/org/apache/camel/quarkus/component/openapijava/it/OpenApiRoutes.java
+++
b/integration-tests/openapi-java/src/main/java/org/apache/camel/quarkus/component/openapijava/it/OpenApiRoutes.java
@@ -23,21 +23,127 @@ import java.util.Set;
import javax.ws.rs.core.MediaType;
import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.model.rest.CollectionFormat;
+import org.apache.camel.model.rest.RestParamType;
import org.apache.camel.quarkus.component.openapijava.it.model.Fruit;
public class OpenApiRoutes extends RouteBuilder {
@Override
public void configure() throws Exception {
- Set<Fruit> fruits =
Collections.newSetFromMap(Collections.synchronizedMap(new LinkedHashMap<>()));
- fruits.add(new Fruit("Apple", "Winter fruit"));
- fruits.add(new Fruit("Pineapple", "Tropical fruit"));
rest()
.get("/fruits/list")
.id("list")
.produces(MediaType.APPLICATION_JSON)
.route()
- .setBody().constant(fruits)
- .marshal().json();
+ .setBody().constant(getFruits())
+ .marshal().json()
+ .endRest()
+
+ .get("/operation/spec")
+ .param()
+ .type(RestParamType.header)
+ .name("header_number")
+ .dataType("integer")
+ .required(true)
+ .allowableValues("1", "2", "3")
+ .defaultValue("1")
+ .description("Header Param Number")
+ .endParam()
+ .param()
+ .type(RestParamType.query)
+ .name("query_letter")
+ .dataType("string")
+ .required(false)
+ .allowableValues("A", "B", "C")
+ .defaultValue("B")
+ .description("Query Param Letter")
+ .collectionFormat(CollectionFormat.multi)
+ .endParam()
+ .responseMessage()
+ .code(418)
+ .message("I am a teapot")
+ .responseModel(Integer.class)
+ .header("rate")
+ .description("API Rate Limit")
+ .dataType("integer")
+ .endHeader()
+ .endResponseMessage()
+ .responseMessage()
+ .code("error")
+ .message("Response Error")
+ .endResponseMessage()
+ .route()
+ .setBody().constant("GET: /operation/spec")
+ .endRest()
+
+ .get("/security/scopes")
+ .security("OAuth2", "scope1,scope2,scope3")
+ .route()
+ .setBody().constant("GET: /security/scopes")
+ .endRest()
+
+ .get("/security/api/key")
+ .route()
+ .setBody().constant("GET: /security/api/key/header")
+ .endRest()
+ .securityDefinitions()
+ .apiKey("X-API-Key", "The API key")
+ .withHeader("X-API-KEY")
+ .end()
+ .end()
+
+ .get("/security/basic/auth")
+ .route()
+ .setBody().constant("/security/basic/auth")
+ .endRest()
+ .securityDefinitions()
+ .basicAuth("basicAuth", "Basic Authentication")
+ .end()
+
+ .get("/security/bearer/token")
+ .route()
+ .setBody().constant("/security/bearer/token")
+ .endRest()
+ .securityDefinitions()
+ .bearerToken("bearerAuth", "Bearer Token Authentication")
+ .end()
+
+ .get("/security/mutual/tls")
+ .route()
+ .setBody().constant("/security/mutual/tls")
+ .endRest()
+ .securityDefinitions()
+ .mutualTLS("mutualTLS")
+ .end()
+
+ .get("/security/oauth2")
+ .route()
+ .setBody().constant("/security/oauth2")
+ .endRest()
+ .securityDefinitions()
+ .oauth2("oauth2", "OAuth2 Authentication")
+ .flow("implicit")
+
.authorizationUrl("https://secure.apache.org/fake/oauth2/authorize")
+ .withScope("scope1", "Scope 1")
+ .withScope("scope2", "Scope 2")
+ .withScope("scope3", "Scope 3")
+ .end()
+ .end()
+
+ .get("/security/openid")
+ .route()
+ .setBody().constant("/security/openid")
+ .endRest()
+ .securityDefinitions()
+ .openIdConnect("openId",
"https://secure.apache.org/fake/openid-configuration")
+ .end();
+ }
+
+ private Set<Fruit> getFruits() {
+ Set<Fruit> fruits =
Collections.newSetFromMap(Collections.synchronizedMap(new LinkedHashMap<>()));
+ fruits.add(new Fruit("Apple", "Winter fruit"));
+ fruits.add(new Fruit("Pineapple", "Tropical fruit"));
+ return fruits;
}
}
diff --git
a/integration-tests/openapi-java/src/test/java/org/apache/camel/quarkus/component/openapijava/it/OpenApiTest.java
b/integration-tests/openapi-java/src/test/java/org/apache/camel/quarkus/component/openapijava/it/OpenApiTest.java
index 7da09f1..205f176 100644
---
a/integration-tests/openapi-java/src/test/java/org/apache/camel/quarkus/component/openapijava/it/OpenApiTest.java
+++
b/integration-tests/openapi-java/src/test/java/org/apache/camel/quarkus/component/openapijava/it/OpenApiTest.java
@@ -21,6 +21,7 @@ import io.restassured.RestAssured;
import io.restassured.http.ContentType;
import org.junit.jupiter.api.Test;
+import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.hasKey;
import static org.hamcrest.Matchers.is;
@@ -51,4 +52,133 @@ class OpenApiTest {
"paths.'/fruits/list'.get.operationId", is("list"));
}
+ @Test
+ public void openApiEndpointSecurity() {
+ RestAssured.given()
+ .get("/openapi.json")
+ .then()
+ .contentType(ContentType.JSON)
+ .statusCode(200)
+ .body(
+ "paths.'/security/scopes'", hasKey("get"),
+ "paths.'/security/scopes'.get.security[0].OAuth2",
contains("scope1", "scope2", "scope3"));
+
+ }
+
+ @Test
+ public void openApiKeySecurityDefinition() {
+ RestAssured.given()
+ .get("/openapi.json")
+ .then()
+ .contentType(ContentType.JSON)
+ .statusCode(200)
+ .body(
+ "components.securitySchemes", hasKey("X-API-Key"),
+ "components.securitySchemes.X-API-Key.type",
is("apiKey"),
+ "components.securitySchemes.X-API-Key.description",
is("The API key"),
+ "components.securitySchemes.X-API-Key.name",
is("X-API-KEY"),
+ "components.securitySchemes.X-API-Key.in",
is("header"));
+
+ }
+
+ @Test
+ public void openApiBasicAuthSecurityDefinition() {
+ RestAssured.given()
+ .get("/openapi.json")
+ .then()
+ .contentType(ContentType.JSON)
+ .statusCode(200)
+ .body(
+ "components.securitySchemes", hasKey("basicAuth"),
+ "components.securitySchemes.basicAuth.scheme",
is("basic"),
+ "components.securitySchemes.basicAuth.type",
is("http"),
+ "components.securitySchemes.basicAuth.description",
is("Basic Authentication"));
+
+ }
+
+ @Test
+ public void openApiBearerAuthSecurityDefinition() {
+ RestAssured.given()
+ .get("/openapi.json")
+ .then()
+ .contentType(ContentType.JSON)
+ .statusCode(200)
+ .body(
+ "components.securitySchemes", hasKey("bearerAuth"),
+ "components.securitySchemes.bearerAuth.scheme",
is("bearer"),
+ "components.securitySchemes.bearerAuth.type",
is("http"),
+ "components.securitySchemes.bearerAuth.bearerFormat",
is("Bearer Token Authentication"));
+ }
+
+ @Test
+ public void openApiMutualTlsSecurityDefinition() {
+ RestAssured.given()
+ .get("/openapi.json")
+ .then()
+ .contentType(ContentType.JSON)
+ .statusCode(200)
+ .body(
+ "components.securitySchemes", hasKey("mutualTLS"),
+ "components.securitySchemes.mutualTLS.type",
is("mutualTLS"));
+ }
+
+ @Test
+ public void openApiOauth2SecurityDefinition() {
+ RestAssured.given()
+ .get("/openapi.json")
+ .then()
+ .contentType(ContentType.JSON)
+ .statusCode(200)
+ .body(
+ "components.securitySchemes", hasKey("oauth2"),
+
"components.securitySchemes.oauth2.flows.implicit.authorizationUrl",
+ is("https://secure.apache.org/fake/oauth2/authorize"),
+
"components.securitySchemes.oauth2.flows.implicit.scopes.scope1", is("Scope 1"),
+
"components.securitySchemes.oauth2.flows.implicit.scopes.scope2", is("Scope 2"),
+
"components.securitySchemes.oauth2.flows.implicit.scopes.scope3", is("Scope
3"));
+ }
+
+ @Test
+ public void openApiOpenIdSecurityDefinition() {
+ RestAssured.given()
+ .get("/openapi.json")
+ .then()
+ .contentType(ContentType.JSON)
+ .statusCode(200)
+ .body(
+ "components.securitySchemes", hasKey("openId"),
+ "components.securitySchemes.openId.openIdConnectUrl",
+
is("https://secure.apache.org/fake/openid-configuration"),
+ "components.securitySchemes.openId.type",
is("openIdConnect"));
+ }
+
+ @Test
+ public void openApiOperationSpecification() {
+ RestAssured.given()
+ .get("/openapi.json")
+ .then()
+ .contentType(ContentType.JSON)
+ .statusCode(200)
+ .body(
+ "paths.'/operation/spec'", hasKey("get"),
+ "paths.'/operation/spec'.get.parameters[0].name",
is("header_number"),
+
"paths.'/operation/spec'.get.parameters[0].description", is("Header Param
Number"),
+
"paths.'/operation/spec'.get.parameters[0].schema.default", is("1"),
+
"paths.'/operation/spec'.get.parameters[0].schema.enum", contains("1", "2",
"3"),
+
"paths.'/operation/spec'.get.parameters[0].schema.type", is("integer"),
+ "paths.'/operation/spec'.get.parameters[0].in",
is("header"),
+ "paths.'/operation/spec'.get.parameters[0].required",
is(true),
+ "paths.'/operation/spec'.get.parameters[1].style",
is("multi"),
+ "paths.'/operation/spec'.get.parameters[1].name",
is("query_letter"),
+
"paths.'/operation/spec'.get.parameters[1].description", is("Query Param
Letter"),
+
"paths.'/operation/spec'.get.parameters[1].schema.default", is("B"),
+
"paths.'/operation/spec'.get.parameters[1].schema.enum", contains("A", "B",
"C"),
+
"paths.'/operation/spec'.get.parameters[1].schema.type", is("string"),
+ "paths.'/operation/spec'.get.parameters[1].in",
is("query"),
+ "paths.'/operation/spec'.get.parameters[1].required",
is(false),
+
"paths.'/operation/spec'.get.responses.418.headers.rate.schema.type",
is("integer"),
+
"paths.'/operation/spec'.get.responses.418.headers.rate.description", is("API
Rate Limit"),
+
"paths.'/operation/spec'.get.responses.418.description", is("I am a teapot"),
+
"paths.'/operation/spec'.get.responses.error.description", is("Response
Error"));
+ }
}
diff --git
a/integration-tests/rest/src/main/java/org/apache/camel/quarkus/component/rest/it/RestRoutes.java
b/integration-tests/rest/src/main/java/org/apache/camel/quarkus/component/rest/it/RestRoutes.java
index 88189f2..5342994 100644
---
a/integration-tests/rest/src/main/java/org/apache/camel/quarkus/component/rest/it/RestRoutes.java
+++
b/integration-tests/rest/src/main/java/org/apache/camel/quarkus/component/rest/it/RestRoutes.java
@@ -16,34 +16,67 @@
*/
package org.apache.camel.quarkus.component.rest.it;
+import java.util.Map;
+
+import javax.activation.DataHandler;
import javax.ws.rs.core.MediaType;
import org.apache.camel.Exchange;
+import org.apache.camel.attachment.AttachmentMessage;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.model.rest.RestBindingMode;
import org.apache.camel.model.rest.RestParamType;
public class RestRoutes extends RouteBuilder {
+ private static final String PERSON_JSON = "{\"firstName\": \"John\",
\"lastName\": \"Doe\", \"age\": 64}";
+ private static final String PERSON_XML = "<person firstName=\"John\"
lastName=\"Doe\" age=\"64\"/>";
+
@Override
public void configure() {
- final String personJson = "{\"firstName\": \"John\", \"lastName\":
\"Doe\", \"age\": 64}";
- final String personXml = "<person firstName=\"John\" lastName=\"Doe\"
age=\"64\"/>";
restConfiguration()
.enableCORS(true)
.corsAllowCredentials(true)
- .corsHeaderProperty("Access-Control-Allow-Methods", "GET,
POST");
+ .corsHeaderProperty("Access-Control-Allow-Methods", "GET,
POST")
+ .endpointProperty("fileNameExtWhitelist", ".txt");
rest("/rest")
- .get("/get")
+ .delete()
+ .produces("text/plain")
+ .route()
+ .setBody(constant("DELETE: /rest"))
+ .endRest()
+
+ .get()
+ .produces("text/plain")
+ .route()
+ .setBody(constant("GET: /rest"))
+ .endRest()
+
+ .head()
+ .route()
+ .setHeader(Exchange.CONTENT_TYPE).constant("text/plain")
+ .endRest()
+
+ .patch()
+ .consumes("text/plain")
+ .produces("text/plain")
.route()
- .setBody(constant("GET: /rest/get"))
+ .setBody(simple("${body}: /rest"))
.endRest()
- .post("/post")
- .consumes("text/plain").produces("text/plain")
+ .post()
+ .consumes("text/plain")
+ .produces("text/plain")
.route()
- .setBody(constant("POST: /rest/post"))
+ .setBody(simple("${body}: /rest"))
+ .endRest()
+
+ .put()
+ .consumes("text/plain")
+ .produces("text/plain")
+ .route()
+ .setBody(simple("${body}: /rest"))
.endRest()
.post("/validation")
@@ -72,7 +105,7 @@ public class RestRoutes extends RouteBuilder {
.get("/binding/json/producer")
.route()
- .setBody(constant(personJson))
+ .setBody(constant(PERSON_JSON))
.endRest()
.post("/pojo/binding/xml")
@@ -86,12 +119,31 @@ public class RestRoutes extends RouteBuilder {
.get("/binding/xml/producer")
.route()
- .setBody(constant(personXml))
+ .setBody(constant(PERSON_XML))
.endRest()
.post("/log")
.route()
.log("Hello ${body}")
+ .endRest()
+
+ .verb("head", "/custom/verb")
+ .route()
+ .setHeader(Exchange.CONTENT_TYPE, constant("text/plain"))
+ .endRest()
+
+ .post("/multipart/upload")
+ .route()
+ .process(exchange -> {
+ AttachmentMessage attachmentMessage =
exchange.getMessage(AttachmentMessage.class);
+ Map<String, DataHandler> attachments =
attachmentMessage.getAttachments();
+ if (attachments != null) {
+ int size = attachments.size();
+ exchange.getMessage().setBody(String.valueOf(size));
+ } else {
+ exchange.getMessage().setBody("0");
+ }
+ })
.endRest();
}
}
diff --git
a/integration-tests/rest/src/test/java/org/apache/camel/quarkus/component/rest/it/RestTest.java
b/integration-tests/rest/src/test/java/org/apache/camel/quarkus/component/rest/it/RestTest.java
index be25dca..7f9d59e 100644
---
a/integration-tests/rest/src/test/java/org/apache/camel/quarkus/component/rest/it/RestTest.java
+++
b/integration-tests/rest/src/test/java/org/apache/camel/quarkus/component/rest/it/RestTest.java
@@ -16,11 +16,18 @@
*/
package org.apache.camel.quarkus.component.rest.it;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
import io.quarkus.test.junit.QuarkusTest;
import io.restassured.RestAssured;
import io.restassured.http.ContentType;
+import io.restassured.response.ValidatableResponse;
import org.apache.camel.component.platform.http.PlatformHttpConstants;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.Matchers.is;
@@ -40,21 +47,27 @@ class RestTest {
.body("component",
is(PlatformHttpConstants.PLATFORM_HTTP_COMPONENT_NAME));
}
- @Test
- public void rest() {
- RestAssured.get("/rest/get")
+ @ParameterizedTest
+ @ValueSource(strings = { "DELETE", "GET", "HEAD", "PATCH", "POST", "PUT" })
+ public void rest(String method) {
+ String body = method.matches("PATCH|POST|PUT") ? method : "";
+
+ ValidatableResponse response = RestAssured.given()
+ .body(body)
+ .request(method, "/rest")
.then()
.header("Access-Control-Allow-Headers",
matchesPattern(".*Access-Control.*"))
.header("Access-Control-Allow-Methods", matchesPattern("GET,
POST"))
- .header("Access-Control-Allow-Credentials", equalTo("true"))
- .body(equalTo("GET: /rest/get"));
-
- RestAssured.given()
- .contentType(ContentType.TEXT)
- .post("/rest/post")
- .then()
- .statusCode(200)
- .body(equalTo("POST: /rest/post"));
+ .header("Access-Control-Allow-Credentials", equalTo("true"));
+
+ if (method.equals("HEAD")) {
+ // Response body is ignored for HEAD so verify response headers
+ response.statusCode(204);
+ response.header("Content-Type", ContentType.TEXT.toString());
+ } else {
+ response.statusCode(200);
+ response.body(is(method + ": /rest"));
+ }
}
@Test
@@ -178,7 +191,7 @@ class RestTest {
}
@Test
- public void lightweight() throws Throwable {
+ public void lightweight() {
RestAssured.when()
.get("/rest/inspect/camel-context/lightweight")
.then()
@@ -187,7 +200,7 @@ class RestTest {
}
@Test
- public void restLog() throws Throwable {
+ public void restLog() {
String message = "Camel Quarkus Platform HTTP";
RestAssured.given()
.contentType(ContentType.TEXT)
@@ -198,4 +211,39 @@ class RestTest {
.statusCode(200)
.body(is(message));
}
+
+ @Test
+ public void customVerb() {
+ RestAssured.given()
+ .head("/rest/custom/verb")
+ .then()
+ .statusCode(204)
+ .header("Content-Type", is(ContentType.TEXT.toString()));
+ }
+
+ @Test
+ public void multiPartUpload() throws IOException {
+ Path txtFile = Files.createTempFile("multipartUpload", ".txt");
+ Path csvFile = Files.createTempFile("multipartUpload", ".csv");
+
+ try {
+ RestAssured.given()
+ .multiPart(txtFile.toFile())
+ .post("/rest/multipart/upload")
+ .then()
+ .statusCode(200)
+ .body(is("1"));
+
+ // fileNameExtWhitelist config will only allow the txt file
extension
+ RestAssured.given()
+ .multiPart(csvFile.toFile())
+ .post("/rest/multipart/upload")
+ .then()
+ .statusCode(200)
+ .body(is("0"));
+ } finally {
+ Files.deleteIfExists(txtFile);
+ Files.deleteIfExists(csvFile);
+ }
+ }
}