This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git


The following commit(s) were added to refs/heads/main by this push:
     new 0e8cd2ced57 CAMEL-20943: camel-jbang - Add openapi generate 
integration test (#14744)
0e8cd2ced57 is described below

commit 0e8cd2ced5769434fb2c3484597f1100e85d2082
Author: Marco Carletti <mcarl...@redhat.com>
AuthorDate: Fri Jul 5 16:42:12 2024 +0200

    CAMEL-20943: camel-jbang - Add openapi generate integration test (#14744)
---
 .../apache/camel/dsl/jbang/it/OpenApiITCase.java   | 146 +++++++++++++++++++++
 .../dsl/jbang/it/support/JBangTestSupport.java     |  67 ++++++++++
 2 files changed, 213 insertions(+)

diff --git 
a/dsl/camel-jbang/camel-jbang-it/src/test/java/org/apache/camel/dsl/jbang/it/OpenApiITCase.java
 
b/dsl/camel-jbang/camel-jbang-it/src/test/java/org/apache/camel/dsl/jbang/it/OpenApiITCase.java
new file mode 100644
index 00000000000..a2ba0d2915b
--- /dev/null
+++ 
b/dsl/camel-jbang/camel-jbang-it/src/test/java/org/apache/camel/dsl/jbang/it/OpenApiITCase.java
@@ -0,0 +1,146 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.dsl.jbang.it;
+
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.net.http.HttpClient;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
+import java.time.Duration;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+
+import org.apache.camel.dsl.jbang.it.support.InVersion;
+import org.apache.camel.dsl.jbang.it.support.JBangTestSupport;
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.testcontainers.shaded.com.fasterxml.jackson.databind.ObjectMapper;
+
+public class OpenApiITCase extends JBangTestSupport {
+
+    final HttpClient httpClient = HttpClient.newHttpClient();
+
+    @Test
+    public void runOpenApiOnExistingImplementation() {
+        final String openApiImpl
+                = 
"https://raw.githubusercontent.com/apache/camel-kamelets-examples/main/jbang/open-api/Greetings.java";;
+        final String openApiUrl
+                = 
"https://raw.githubusercontent.com/apache/camel-kamelets-examples/main/jbang/open-api/greetings-api.json";;
+
+        downloadFile(openApiImpl);
+        downloadFile(openApiUrl);
+        executeBackground("run --open-api greetings-api.json Greetings.java");
+        checkLogContains("HTTP endpoints summary");
+        HttpResponse<String> response = 
executeHttpRequest("/camel/greetings/jack", false);
+        Assertions.assertThat(response.statusCode()).isEqualTo(200);
+        Assertions.assertThat(response.body()).isEqualTo("Hello from jack");
+    }
+
+    @Test
+    public void runOpenApiUsingContractFirstApproach() throws IOException {
+        final String openApiUrl
+                = 
"https://raw.githubusercontent.com/apache/camel-kamelets-examples/main/jbang/open-api-contract-first/petstore-v3.json";;
+        final String openApiConfig
+                = 
"https://raw.githubusercontent.com/apache/camel-kamelets-examples/main/jbang/open-api-contract-first/petstore.camel.yaml";;
+
+        downloadFile(openApiUrl);
+        downloadFile(openApiConfig);
+        containerService.executeGenericCommand("mkdir -p camel-mock/pet");
+        downloadFile(
+                
"https://raw.githubusercontent.com/apache/camel-kamelets-examples/main/jbang/open-api-contract-first/camel-mock/pet/123.json";);
+        containerService.executeGenericCommand("mv 123.json camel-mock/pet/");
+        executeBackground("run petstore-v3.json petstore.camel.yaml");
+        checkLogContains("HTTP endpoints summary");
+
+        //verify mock
+        HttpResponse<String> response = executeHttpRequest("/api/v3/pet/123", 
true);
+        Assertions.assertThat(response.statusCode()).isEqualTo(200);
+        Assertions.assertThat(response.body()).contains("donald the dock");
+
+        //verify sample response
+        response = executeHttpRequest("/api/v3/pet/" + new 
Random().nextInt(124, 500), true);
+        Assertions.assertThat(response.statusCode()).isEqualTo(200);
+        Assertions.assertThat(response.body()).contains("jack the cat");
+
+        //verify api-doc
+        response = executeHttpRequest("/api-doc", true);
+        Assertions.assertThat(response.statusCode()).isEqualTo(200);
+        final ObjectMapper objectMapper = new ObjectMapper();
+        Map expectedDoc = objectMapper.readValue(new URL(
+                openApiUrl),
+                Map.class);
+        Map actualDoc = objectMapper.readValue(response.body(), Map.class);
+        Assertions.assertThat(((Map) actualDoc.get("paths")).size())
+                .as("check api doc exposed paths size")
+                .isEqualTo(((Map) expectedDoc.get("paths")).size());
+    }
+
+    @Test
+    public void exportOpenApiUsingContractFirstApproach() {
+        final String openApiUrl
+                = 
"https://raw.githubusercontent.com/apache/camel-kamelets-examples/main/jbang/open-api-contract-first/petstore-v3.json";;
+
+        downloadFile(openApiUrl);
+        final String generatedPath = mountPoint() + "/petstore";
+        generateProperties(Map.of("camel.jbang.runtime", "spring-boot", 
"camel.jbang.gav", "example:petstore:1.0-SNAPSHOT",
+                "camel.jbang.exportDir", generatedPath, "camel.jbang.open-api",
+                DEFAULT_ROUTE_FOLDER + "/petstore-v3.json"));
+        execute("export");
+        assertFileInDataFolderExists("petstore");
+        
assertFileInDataFolderExists("petstore/src/main/resources/petstore-v3.json");
+        
assertFileInDataFolderExists("petstore/src/main/resources/camel/generated-openapi.yaml");
+    }
+
+    @Test
+    @InVersion(from = "4.7.00")
+    public void generateOpenApiWithDtoUsingContractFirstApproach() {
+        final String openApiUrl
+                = 
"https://raw.githubusercontent.com/apache/camel-kamelets-examples/main/jbang/open-api-contract-first/petstore-v3.json";;
+
+        downloadFile(openApiUrl);
+
+        execute("plugin add generate");
+        execute("plugin get");
+        execute("generate rest --dto --input=petstore-v3.json 
--output=rest-dsl.yaml --runtime=spring-boot --routes");
+        List<String> generatedDTO = 
containerService.listDirectory(DEFAULT_ROUTE_FOLDER + "/model").toList();
+        Assertions.assertThat(generatedDTO).as("check generated DTO 
number").hasSize(8);
+        assertFileInContainerExists(DEFAULT_ROUTE_FOLDER + "/rest-dsl.yaml");
+    }
+
+    private HttpResponse<String> executeHttpRequest(final String ctxUrl, 
boolean acceptJson) {
+        try {
+            final HttpRequest.Builder builder = HttpRequest
+                    .newBuilder(
+                            new URI(String.format("http://localhost:%s%s";, 
containerService.getDevConsolePort(), ctxUrl)))
+                    .timeout(Duration.ofSeconds(5))
+                    .GET();
+            if (acceptJson) {
+                builder.headers("Accept", "application/json");
+            }
+            return httpClient.send(builder
+                    .build(),
+                    HttpResponse.BodyHandlers.ofString());
+        } catch (IOException | InterruptedException | URISyntaxException e) {
+            Assertions.fail("unable to execute the request");
+            throw new RuntimeException(e);
+        }
+    }
+}
diff --git 
a/dsl/camel-jbang/camel-jbang-it/src/test/java/org/apache/camel/dsl/jbang/it/support/JBangTestSupport.java
 
b/dsl/camel-jbang/camel-jbang-it/src/test/java/org/apache/camel/dsl/jbang/it/support/JBangTestSupport.java
index 11b5d9e048e..6e6f0164426 100644
--- 
a/dsl/camel-jbang/camel-jbang-it/src/test/java/org/apache/camel/dsl/jbang/it/support/JBangTestSupport.java
+++ 
b/dsl/camel-jbang/camel-jbang-it/src/test/java/org/apache/camel/dsl/jbang/it/support/JBangTestSupport.java
@@ -20,6 +20,13 @@ import java.io.ByteArrayInputStream;
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.Reader;
+import java.io.StringWriter;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.nio.channels.Channels;
+import java.nio.channels.ReadableByteChannel;
+import java.nio.charset.Charset;
 import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
 import java.nio.file.Path;
@@ -28,7 +35,9 @@ import java.nio.file.StandardCopyOption;
 import java.nio.file.attribute.PosixFilePermission;
 import java.time.Duration;
 import java.util.EnumSet;
+import java.util.Map;
 import java.util.Optional;
+import java.util.Properties;
 import java.util.concurrent.TimeUnit;
 
 import org.apache.camel.test.infra.cli.common.CliProperties;
@@ -254,4 +263,62 @@ public abstract class JBangTestSupport {
     protected String makeTheFileWriteable(String containerPath) {
         return containerService.executeGenericCommand("chmod 777 " + 
containerPath);
     }
+
+    protected String downloadNewFileInDataFolder(String downloadUrl) {
+        try {
+            return this.downloadNewFileInDataFolder(new URL(downloadUrl), 
null);
+        } catch (MalformedURLException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    protected String downloadNewFileInDataFolder(URL downloadUrl, String 
fileName) {
+        final String fName = fileName == null ? 
Paths.get(downloadUrl.getPath().toString()).getFileName().toString() : fileName;
+
+        final StringWriter sw = new StringWriter();
+        try (ReadableByteChannel channel = 
Channels.newChannel(downloadUrl.openStream());
+             Reader reader = Channels.newReader(channel, 
Charset.defaultCharset())) {
+            reader.transferTo(sw);
+            sw.flush();
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+        this.newFileInDataFolder(fName, sw.toString());
+        return fName;
+    }
+
+    protected String downloadFile(String downloadUrl) {
+        String fileName = this.downloadNewFileInDataFolder(downloadUrl);
+        containerService.copyFileInternally(mountPoint() + "/" + fileName, 
DEFAULT_ROUTE_FOLDER);
+        return fileName;
+    }
+
+    protected void generateProperties(Map<String, String> properties) {
+        this.generateProperties("application.properties", properties, false);
+    }
+
+    protected void generateProperties(String fileName, Map<String, String> 
properties, boolean inDataFolder) {
+        final Properties prop = new Properties();
+        prop.putAll(properties);
+        final StringWriter contentWriter = new StringWriter();
+        try {
+            prop.store(contentWriter, "");
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+        this.newFileInDataFolder(fileName, contentWriter.toString());
+        if (!inDataFolder) {
+            containerService.executeGenericCommand(
+                    String.format("mv %s/%s %s/%s", mountPoint(), fileName, 
DEFAULT_ROUTE_FOLDER, fileName));
+        }
+    }
+
+    protected void assertFileInContainerExists(String fileAbsolutePath) {
+        String fileName = 
Path.of(fileAbsolutePath).getFileName().toFile().getName();
+        
Assertions.assertThat(containerService.listDirectory(Path.of(fileAbsolutePath).getParent().toAbsolutePath().toString())
+                .anyMatch(child -> fileName.equals(child)))
+                .as("check if file " + fileAbsolutePath + " exists")
+                .isTrue();
+    }
+
 }

Reply via email to