content: /*
   * 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.quarkus.component.velocity.it;
  
  import java.io.File;
  import java.io.IOException;
  import java.nio.charset.StandardCharsets;
  import java.nio.file.Files;
  import java.nio.file.Paths;
  import java.util.Map;
  
  import io.quarkus.test.junit.QuarkusTest;
  import io.restassured.RestAssured;
  import io.restassured.http.ContentType;
  import org.junit.jupiter.api.Test;
  
  import static org.hamcrest.CoreMatchers.containsString;
  import static org.hamcrest.CoreMatchers.equalTo;
  import static org.junit.jupiter.api.Assertions.assertEquals;
  import static org.junit.jupiter.api.Assertions.assertTrue;
  
  @QuarkusTest
  class VelocityTest {
  
      public static final String OLD_BODY = "old_body";
      public static final String BODY = "bar";
      public static final String NEW_BODY = "new_body";
      public static final String MSG = "\nDear Sheldon\n" +
              "\n" +
              "Thanks for the order of Camel in Action.\n" +
              "\n" +
              "Regards Apache Camel Riders Bookstore\n" +
              "PS: Next beer is on me";
  
      @Test
      public void testTemplateViaFile() throws IOException {
          File template = createFile("velocity_test", "Hi ${headers.name}. You have got ${headers.item}. ${body}");
          RestAssured.given()
                  .queryParam("name", "Sheldon")
                  .queryParam("item", "Camel in Action")
                  .queryParam("template", "file://" + template.getPath())
                  .contentType(ContentType.TEXT)
                  .body("PS: Next beer is on me")
                  .post("/velocity/template")
                  .then()
                  .statusCode(201)
                  .body(equalTo("Hi Sheldon. You have got Camel in Action. PS: Next beer is on me"));
      }
  
      @Test
      public void testTemplateViaClasspath() {
          RestAssured.given()
                  .queryParam("name", "Sheldon")
                  .queryParam("item", "Camel in Action")
                  .queryParam("template", "//template/letter.vm")
                  .contentType(ContentType.TEXT)
                  .body("PS: Next beer is on me")
                  .post("/velocity/template")
                  .then()
                  .statusCode(201)
                  .body(equalTo(MSG));
      }
  
      @Test
      public void forEach() {
          RestAssured.given()
                  .queryParam("template", "//template/foreach.vm")
                  .contentType(ContentType.TEXT)
                  .body("Joe,US;Paul,UK")
                  .post("/velocity/list")
                  .then()
                  .statusCode(201)
                  .body(equalTo(
                          """
  
                                  - Person{name='Joe', country='US'}, 0, 1, true
                                  - Person{name='Paul', country='UK'}, 1, 2, false
                                      """));
      }
  
      @Test
      public void testTemplateViaClasspathWithProperties() {
          //class loader is forbidden by properties, response should fail
          RestAssured.given()
                  .queryParam("name", "Sheldon")
                  .queryParam("item", "Camel in Action")
                  .queryParam("template", "//template/template.vm")
                  .queryParam("propertiesFile", "/template/velocity.properties")
                  .queryParam("expectFailure", "true")
                  .contentType(ContentType.TEXT)
                  .body("PS: Next beer is on me")
                  .post("/velocity/template")
                  .then()
                  .statusCode(500)
                  .body(containsString("Exception"));
      }
  
      @Test
      public void testTemplateViaHeader() {
          RestAssured.given()
                  .queryParam("body", "PS: Next beer is on me.")
                  .queryParam("name", "Sheldon")
                  .queryParam("item", "Camel in Action")
                  .contentType(ContentType.TEXT)
                  .body("Hi ${headers.name}. Thanks for ${headers.item}. ${body}")
                  .post("/velocity/templateViaHeader")
                  .then()
                  .statusCode(201)
                  .body(equalTo("Hi Sheldon. Thanks for Camel in Action. PS: Next beer is on me."));
      }
  
      @Test
      public void testSupplementalContext() {
          final String template = "#set( $headers.body = ${body} )\n" + BODY;
          Map result = RestAssured.given()
                  .queryParam("body", OLD_BODY)
                  .queryParam("supplementalBody", NEW_BODY)
                  .contentType(ContentType.TEXT)
                  .body(template)
                  .post("/velocity/supplementalContext")
                  .then()
                  .statusCode(200)
                  .extract().as(Map.class);
  
          assertTrue(result.containsKey("result_value"));
          assertEquals(BODY, result.get("result_value"));
          assertTrue(result.containsKey("body"));
          assertEquals(NEW_BODY, result.get("body"));
      }
  
      @Test
      public void testBodyAsDomainObject() {
          RestAssured.given()
                  .queryParam("name", "Sheldon")
                  .queryParam("country", "Earth 1")
                  .contentType(ContentType.JSON)
                  .body(new Person("Sheldon", "Earth 2"))
                  .post("/velocity/bodyAsDomainObject")
                  .then()
                  .statusCode(201)
                  .body(equalTo("\nHi Sheldon from Earth 2"));
      }
  
      @Test
      public void testVelocityContext() {
          Map result = RestAssured.given()
                  .queryParam("name", "Sheldon")
                  .queryParam("name2", "Leonard")
                  .queryParam("item", "Earth 1")
                  .contentType(ContentType.JSON)
                  .body("Hello!")
                  .post("/velocity/velocityContext")
                  .then()
                  .statusCode(201)
                  .extract().as(Map.class);
  
          assertTrue(result.containsKey("headers.name"));
          assertEquals("Leonard", result.get("headers.name"));
          assertTrue(result.containsKey("result"));
          assertEquals("\nDear Sheldon. You ordered item Earth 1 on Monday.", result.get("result"));
      }
  
      @Test
      public void testDynamicTemplates() {
          RestAssured.given()
                  .queryParam("body", "Monaday")
                  .queryParam("name", "Sheldon")
                  .queryParam("item", "Camel in Action")
                  .contentType(ContentType.TEXT)
                  .body("template/dynamicTemplate.vm")
                  .post("/velocity/dynamicTemplate")
                  .then()
                  .statusCode(201)
                  .body(equalTo("\n" +
                          "Dear Sheldon. You ordered item Camel in Action on Monaday."));
      }
  
      @Test
      public void testContentCacheFalse() throws Exception {
          testContentCache(false);
      }
  
      @Test
      public void testContentCacheTrue() throws Exception {
          testContentCache(true);
      }
  
      private void testContentCache(boolean useContentCache) throws Exception {
          File template = createFile("velocity_test", "Hi ${body}");
  
          RestAssured.given()
                  .queryParam("template", "file://" + template.getPath())
                  .queryParam("contentCache", useContentCache)
                  .contentType(ContentType.TEXT)
                  .body("Sheldon")
                  .post("/velocity/template")
                  .then()
                  .statusCode(201)
                  .body(equalTo("Hi Sheldon"));
  
          //override file
          Files.write(Paths.get(template.getPath()), "Bye ${body}".getBytes(StandardCharsets.UTF_8));
  
          RestAssured.given()
                  .queryParam("template", "file://" + template.getPath())
                  .queryParam("contentCache", useContentCache)
                  .contentType(ContentType.TEXT)
                  .body("Sheldon")
                  .post("/velocity/template")
                  .then()
  
                  .statusCode(201)
                  .body(equalTo(useContentCache ? "Hi Sheldon" : "Bye Sheldon"));
      }
  
      private File createFile(String fileName, String body) throws IOException {
          File tmpFile = File.createTempFile(fileName, ".vm");
  
          Files.write(tmpFile.toPath(), body.getBytes(StandardCharsets.UTF_8));
  
          tmpFile.deleteOnExit();
          return tmpFile;
      }
  }
  