diff --git a/.github/project.yml b/.github/project.yml index b218c2a8e2..bd84b11398 100644 --- a/.github/project.yml +++ b/.github/project.yml @@ -1,4 +1,4 @@ name: Citrus Framework release: - current-version: 4.2.0 + current-version: 4.2.1 next-version: 4.3.0-SNAPSHOT diff --git a/connectors/citrus-docker/src/main/resources/META-INF/spring.schemas b/connectors/citrus-docker/src/main/resources/META-INF/spring.schemas index a84ad964d8..708da1e242 100644 --- a/connectors/citrus-docker/src/main/resources/META-INF/spring.schemas +++ b/connectors/citrus-docker/src/main/resources/META-INF/spring.schemas @@ -35,8 +35,9 @@ http\://www.citrusframework.org/schema/docker/config/citrus-docker-config-4.0.1. http\://www.citrusframework.org/schema/docker/config/citrus-docker-config-4.0.2.xsd=org/citrusframework/schema/citrus-docker-config-4.0.2.xsd http\://www.citrusframework.org/schema/docker/config/citrus-docker-config-4.1.0.xsd=org/citrusframework/schema/citrus-docker-config-4.1.0.xsd http\://www.citrusframework.org/schema/docker/config/citrus-docker-config-4.1.1.xsd=org/citrusframework/schema/citrus-docker-config-4.1.1.xsd -http\://www.citrusframework.org/schema/docker/config/citrus-docker-config-4.3.0-SNAPSHOT.xsd=org/citrusframework/schema/citrus-docker-config-4.3.0-SNAPSHOT.xsd http\://www.citrusframework.org/schema/docker/config/citrus-docker-config-4.2.0.xsd=org/citrusframework/schema/citrus-docker-config-4.2.0.xsd +http\://www.citrusframework.org/schema/docker/config/citrus-docker-config-4.2.1.xsd=org/citrusframework/schema/citrus-docker-config-4.2.1.xsd +http\://www.citrusframework.org/schema/docker/config/citrus-docker-config-4.3.0-SNAPSHOT.xsd=org/citrusframework/schema/citrus-docker-config-4.3.0-SNAPSHOT.xsd http\://www.citrusframework.org/schema/docker/config/citrus-docker-config.xsd=org/citrusframework/schema/citrus-docker-config.xsd http\://www.citrusframework.org/schema/docker/testcase/citrus-docker-testcase-2.3.xsd=com/consol/citrus/schema/citrus-docker-testcase-2.3.xsd http\://www.citrusframework.org/schema/docker/testcase/citrus-docker-testcase-2.4.xsd=com/consol/citrus/schema/citrus-docker-testcase-2.4.xsd @@ -75,6 +76,7 @@ http\://www.citrusframework.org/schema/docker/testcase/citrus-docker-testcase-4. http\://www.citrusframework.org/schema/docker/testcase/citrus-docker-testcase-4.0.2.xsd=org/citrusframework/schema/citrus-docker-testcase-4.0.2.xsd http\://www.citrusframework.org/schema/docker/testcase/citrus-docker-testcase-4.1.0.xsd=org/citrusframework/schema/citrus-docker-testcase-4.1.0.xsd http\://www.citrusframework.org/schema/docker/testcase/citrus-docker-testcase-4.1.1.xsd=org/citrusframework/schema/citrus-docker-testcase-4.1.1.xsd -http\://www.citrusframework.org/schema/docker/testcase/citrus-docker-testcase-4.3.0-SNAPSHOT.xsd=org/citrusframework/schema/citrus-docker-testcase-4.3.0-SNAPSHOT.xsd http\://www.citrusframework.org/schema/docker/testcase/citrus-docker-testcase-4.2.0.xsd=org/citrusframework/schema/citrus-docker-testcase-4.2.0.xsd +http\://www.citrusframework.org/schema/docker/testcase/citrus-docker-testcase-4.2.1.xsd=org/citrusframework/schema/citrus-docker-testcase-4.2.1.xsd +http\://www.citrusframework.org/schema/docker/testcase/citrus-docker-testcase-4.3.0-SNAPSHOT.xsd=org/citrusframework/schema/citrus-docker-testcase-4.3.0-SNAPSHOT.xsd http\://www.citrusframework.org/schema/docker/testcase/citrus-docker-testcase.xsd=org/citrusframework/schema/citrus-docker-testcase.xsd diff --git a/connectors/citrus-kubernetes/src/main/resources/META-INF/spring.schemas b/connectors/citrus-kubernetes/src/main/resources/META-INF/spring.schemas index bbf8aaa47c..8811abdcf8 100644 --- a/connectors/citrus-kubernetes/src/main/resources/META-INF/spring.schemas +++ b/connectors/citrus-kubernetes/src/main/resources/META-INF/spring.schemas @@ -27,8 +27,9 @@ http\://www.citrusframework.org/schema/kubernetes/config/citrus-kubernetes-confi http\://www.citrusframework.org/schema/kubernetes/config/citrus-kubernetes-config-4.0.2.xsd=org/citrusframework/schema/citrus-kubernetes-config-4.0.2.xsd http\://www.citrusframework.org/schema/kubernetes/config/citrus-kubernetes-config-4.1.0.xsd=org/citrusframework/schema/citrus-kubernetes-config-4.1.0.xsd http\://www.citrusframework.org/schema/kubernetes/config/citrus-kubernetes-config-4.1.1.xsd=org/citrusframework/schema/citrus-kubernetes-config-4.1.1.xsd -http\://www.citrusframework.org/schema/kubernetes/config/citrus-kubernetes-config-4.3.0-SNAPSHOT.xsd=org/citrusframework/schema/citrus-kubernetes-config-4.3.0-SNAPSHOT.xsd http\://www.citrusframework.org/schema/kubernetes/config/citrus-kubernetes-config-4.2.0.xsd=org/citrusframework/schema/citrus-kubernetes-config-4.2.0.xsd +http\://www.citrusframework.org/schema/kubernetes/config/citrus-kubernetes-config-4.2.1.xsd=org/citrusframework/schema/citrus-kubernetes-config-4.2.1.xsd +http\://www.citrusframework.org/schema/kubernetes/config/citrus-kubernetes-config-4.3.0-SNAPSHOT.xsd=org/citrusframework/schema/citrus-kubernetes-config-4.3.0-SNAPSHOT.xsd http\://www.citrusframework.org/schema/kubernetes/config/citrus-kubernetes-config.xsd=org/citrusframework/schema/citrus-kubernetes-config.xsd http\://www.citrusframework.org/schema/kubernetes/testcase/citrus-kubernetes-testcase-2.7.1.xsd=com/consol/citrus/schema/citrus-kubernetes-testcase-2.7.1.xsd http\://www.citrusframework.org/schema/kubernetes/testcase/citrus-kubernetes-testcase-2.7.2.xsd=com/consol/citrus/schema/citrus-kubernetes-testcase-2.7.2.xsd @@ -59,6 +60,7 @@ http\://www.citrusframework.org/schema/kubernetes/testcase/citrus-kubernetes-tes http\://www.citrusframework.org/schema/kubernetes/testcase/citrus-kubernetes-testcase-4.0.2.xsd=org/citrusframework/schema/citrus-kubernetes-testcase-4.0.2.xsd http\://www.citrusframework.org/schema/kubernetes/testcase/citrus-kubernetes-testcase-4.1.0.xsd=org/citrusframework/schema/citrus-kubernetes-testcase-4.1.0.xsd http\://www.citrusframework.org/schema/kubernetes/testcase/citrus-kubernetes-testcase-4.1.1.xsd=org/citrusframework/schema/citrus-kubernetes-testcase-4.1.1.xsd -http\://www.citrusframework.org/schema/kubernetes/testcase/citrus-kubernetes-testcase-4.3.0-SNAPSHOT.xsd=org/citrusframework/schema/citrus-kubernetes-testcase-4.3.0-SNAPSHOT.xsd http\://www.citrusframework.org/schema/kubernetes/testcase/citrus-kubernetes-testcase-4.2.0.xsd=org/citrusframework/schema/citrus-kubernetes-testcase-4.2.0.xsd +http\://www.citrusframework.org/schema/kubernetes/testcase/citrus-kubernetes-testcase-4.2.1.xsd=org/citrusframework/schema/citrus-kubernetes-testcase-4.2.1.xsd +http\://www.citrusframework.org/schema/kubernetes/testcase/citrus-kubernetes-testcase-4.3.0-SNAPSHOT.xsd=org/citrusframework/schema/citrus-kubernetes-testcase-4.3.0-SNAPSHOT.xsd http\://www.citrusframework.org/schema/kubernetes/testcase/citrus-kubernetes-testcase.xsd=org/citrusframework/schema/citrus-kubernetes-testcase.xsd diff --git a/connectors/citrus-kubernetes/src/test/resources/org/citrusframework/kubernetes/integration/KubernetesExecuteIT.xml b/connectors/citrus-kubernetes/src/test/resources/org/citrusframework/kubernetes/integration/KubernetesExecuteIT.xml index 0bbcdcd7fa..4b73e20fdc 100644 --- a/connectors/citrus-kubernetes/src/test/resources/org/citrusframework/kubernetes/integration/KubernetesExecuteIT.xml +++ b/connectors/citrus-kubernetes/src/test/resources/org/citrusframework/kubernetes/integration/KubernetesExecuteIT.xml @@ -38,7 +38,7 @@ { "result": { - "clientVersion": "6.12.0", + "clientVersion": "6.13.0", "apiVersion": "${apiVersion}", "kind":"Info", "masterUrl": "@matches('http://(kubernetes\\.docker\\.internal|localhost):[0-9]+/')@", diff --git a/connectors/citrus-kubernetes/src/test/resources/org/citrusframework/kubernetes/integration/KubernetesSendReceiveIT.xml b/connectors/citrus-kubernetes/src/test/resources/org/citrusframework/kubernetes/integration/KubernetesSendReceiveIT.xml index b5305c0834..e4a7d90a28 100644 --- a/connectors/citrus-kubernetes/src/test/resources/org/citrusframework/kubernetes/integration/KubernetesSendReceiveIT.xml +++ b/connectors/citrus-kubernetes/src/test/resources/org/citrusframework/kubernetes/integration/KubernetesSendReceiveIT.xml @@ -46,7 +46,7 @@ { "command": "info", "result": { - "clientVersion": "6.12.0", + "clientVersion": "6.13.0", "apiVersion": "${apiVersion}", "kind":"Info", "masterUrl": "@matches('http://(kubernetes\\.docker\\.internal|localhost):[0-9]+/')@", diff --git a/connectors/citrus-openapi/src/main/java/org/citrusframework/openapi/OpenApiTestDataGenerator.java b/connectors/citrus-openapi/src/main/java/org/citrusframework/openapi/OpenApiTestDataGenerator.java index e5dc360ed4..6b31655892 100644 --- a/connectors/citrus-openapi/src/main/java/org/citrusframework/openapi/OpenApiTestDataGenerator.java +++ b/connectors/citrus-openapi/src/main/java/org/citrusframework/openapi/OpenApiTestDataGenerator.java @@ -187,7 +187,7 @@ public static String createRandomValueExpression( } if (schema.format != null && schema.format.equals("date")) { - payload.append("citrus:currentDate()"); + payload.append("citrus:currentDate('yyyy-MM-dd')"); } else if (schema.format != null && schema.format.equals("date-time")) { payload.append("citrus:currentDate('yyyy-MM-dd'T'hh:mm:ss')"); } else if (StringUtils.hasText(schema.pattern)) { diff --git a/connectors/citrus-openapi/src/main/java/org/citrusframework/openapi/model/v3/Oas30ModelHelper.java b/connectors/citrus-openapi/src/main/java/org/citrusframework/openapi/model/v3/Oas30ModelHelper.java index 614b2de512..39bdd2486e 100644 --- a/connectors/citrus-openapi/src/main/java/org/citrusframework/openapi/model/v3/Oas30ModelHelper.java +++ b/connectors/citrus-openapi/src/main/java/org/citrusframework/openapi/model/v3/Oas30ModelHelper.java @@ -219,7 +219,7 @@ public static Map getRequiredHeaders(Oas30Response response) return response.headers.entrySet() .stream() - .filter(entry -> entry.getValue().required) + .filter(entry -> Boolean.TRUE.equals(entry.getValue().required)) .collect(Collectors.toMap(Map.Entry::getKey, entry -> entry.getValue().schema)); } diff --git a/connectors/citrus-openapi/src/test/java/org/citrusframework/openapi/actions/OpenApiClientRequestMessageBuilderTest.java b/connectors/citrus-openapi/src/test/java/org/citrusframework/openapi/actions/OpenApiClientRequestMessageBuilderTest.java new file mode 100644 index 0000000000..17b2159a60 --- /dev/null +++ b/connectors/citrus-openapi/src/test/java/org/citrusframework/openapi/actions/OpenApiClientRequestMessageBuilderTest.java @@ -0,0 +1,63 @@ +package org.citrusframework.openapi.actions; + +import org.citrusframework.context.TestContext; +import org.citrusframework.http.message.HttpMessage; +import org.citrusframework.message.Message; +import org.citrusframework.openapi.OpenApiSpecification; +import org.citrusframework.spi.Resources; +import org.testng.Assert; +import org.testng.annotations.Test; + +import static org.citrusframework.openapi.actions.OpenApiActionBuilder.openapi; + +public class OpenApiClientRequestMessageBuilderTest { + + private final OpenApiSpecification petstoreSpec = OpenApiSpecification.from( + Resources.create("classpath:org/citrusframework/openapi/petstore/petstore-derivation-for-message-builder-test.json")); + + + @Test + public void shouldAddRandomDataForOperation() { + Message message = openapi() + .specification(petstoreSpec) + .client() + .send("addPet") // operationId + .build() + .getMessageBuilder() + .build(new TestContext(), ""); + Assert.assertTrue(message instanceof HttpMessage); + HttpMessage httpMessage = (HttpMessage) message; + // test payload + Object payload = httpMessage.getPayload(); + Assert.assertNotNull(payload); + Assert.assertTrue(payload instanceof String); + // test header + Object header = httpMessage.getHeader("X-SAMPLE-HEADER"); + Assert.assertNotNull(header); + } + + @Test + public void shouldAddCustomDataForOperation() { + String body = "{\"a\":\"b\"}"; + String sampleHeader = "X-SAMPLE-HEADER-VALUE"; + Message message = openapi() + .specification(petstoreSpec) + .client() + .send("addPet") // operationId + .message() + .body(body) + .header("X-SAMPLE-HEADER", sampleHeader) + .build() + .getMessageBuilder() + .build(new TestContext(), ""); + Assert.assertTrue(message instanceof HttpMessage); + HttpMessage httpMessage = (HttpMessage) message; + // test payload + Object payload = httpMessage.getPayload(); + Assert.assertEquals(payload, body); + // test header + Object header = httpMessage.getHeader("X-SAMPLE-HEADER"); + Assert.assertEquals(header, sampleHeader); + } + +} \ No newline at end of file diff --git a/connectors/citrus-openapi/src/test/java/org/citrusframework/openapi/model/v3/Oas30ModelHelperTest.java b/connectors/citrus-openapi/src/test/java/org/citrusframework/openapi/model/v3/Oas30ModelHelperTest.java new file mode 100644 index 0000000000..38d8b13fde --- /dev/null +++ b/connectors/citrus-openapi/src/test/java/org/citrusframework/openapi/model/v3/Oas30ModelHelperTest.java @@ -0,0 +1,54 @@ +package org.citrusframework.openapi.model.v3; + +import io.apicurio.datamodels.openapi.models.OasSchema; +import io.apicurio.datamodels.openapi.v3.models.Oas30Header; +import io.apicurio.datamodels.openapi.v3.models.Oas30Response; +import io.apicurio.datamodels.openapi.v3.models.Oas30Schema; +import org.testng.Assert; +import org.testng.annotations.Test; + +import java.util.Map; + +public class Oas30ModelHelperTest { + + @Test + public void shouldNotFindRequiredHeadersWithoutRequiredAttribute() { + var header = new Oas30Header("X-TEST"); + header.schema = new Oas30Schema(); + header.required = null; // explicitely assigned because this is test case + var response = new Oas30Response("200"); + response.headers.put(header.getName(), header); + + Map result = Oas30ModelHelper.getRequiredHeaders(response); + + Assert.assertEquals(result.size(), 0); + } + + @Test + public void shouldFindRequiredHeaders() { + var header = new Oas30Header("X-TEST"); + header.schema = new Oas30Schema(); + header.required = Boolean.TRUE; // explicitely assigned because this is test case + var response = new Oas30Response("200"); + response.headers.put(header.getName(), header); + + Map result = Oas30ModelHelper.getRequiredHeaders(response); + + Assert.assertEquals(result.size(), 1); + Assert.assertSame(result.get(header.getName()), header.schema); + } + + @Test + public void shouldNotFindOptionalHeaders() { + var header = new Oas30Header("X-TEST"); + header.schema = new Oas30Schema(); + header.required = Boolean.FALSE; // explicitely assigned because this is test case + var response = new Oas30Response("200"); + response.headers.put(header.getName(), header); + + Map result = Oas30ModelHelper.getRequiredHeaders(response); + + Assert.assertEquals(result.size(), 0); + } + +} \ No newline at end of file diff --git a/connectors/citrus-openapi/src/test/resources/org/citrusframework/openapi/petstore/petstore-derivation-for-message-builder-test.json b/connectors/citrus-openapi/src/test/resources/org/citrusframework/openapi/petstore/petstore-derivation-for-message-builder-test.json new file mode 100644 index 0000000000..a3d3953ce1 --- /dev/null +++ b/connectors/citrus-openapi/src/test/resources/org/citrusframework/openapi/petstore/petstore-derivation-for-message-builder-test.json @@ -0,0 +1,164 @@ +{ + "openapi": "3.0.2", + "info": { + "title": "Swagger Petstore", + "version": "1.0.1", + "description": "This is a sample server Petstore server.", + "license": { + "name": "Apache 2.0", + "url": "http://www.apache.org/licenses/LICENSE-2.0.html" + } + }, + "servers": [ + { + "url": "http://localhost/petstore/v3" + } + ], + "paths": { + "/pet": { + "post": { + "requestBody": { + "description": "Pet object that needs to be added to the store", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + }, + "required": true + }, + "parameters": [ + { + "name": "X-SAMPLE-HEADER", + "required": true, + "in": "header", + "schema": { + "type": "string" + } + }, + { + "name": "sample-param", + "required": true, + "in": "query", + "schema": { + "type": "string" + } + } + ], + "tags": [ + "pet" + ], + "responses": { + "201": { + "description": "Created" + }, + "405": { + "description": "Invalid input" + } + }, + "operationId": "addPet", + "summary": "Add a new pet to the store", + "description": "" + } + } + }, + "components": { + "schemas": { + "Category": { + "type": "object", + "properties": { + "id": { + "format": "int64", + "type": "integer" + }, + "name": { + "type": "string" + } + }, + "xml": { + "name": "Category" + } + }, + "Tag": { + "type": "object", + "properties": { + "id": { + "format": "int64", + "type": "integer" + }, + "name": { + "type": "string" + } + }, + "xml": { + "name": "Tag" + } + }, + "Pet": { + "required": [ + "category", + "name", + "status" + ], + "type": "object", + "properties": { + "id": { + "format": "int64", + "type": "integer" + }, + "category": { + "$ref": "#/components/schemas/Category" + }, + "name": { + "type": "string", + "example": "doggie" + }, + "photoUrls": { + "type": "array", + "items": { + "type": "string" + }, + "xml": { + "name": "photoUrl", + "wrapped": true + } + }, + "tags": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Tag" + }, + "xml": { + "name": "tag", + "wrapped": true + } + }, + "status": { + "description": "pet status in the store", + "enum": [ + "available", + "pending", + "sold" + ], + "type": "string" + } + }, + "xml": { + "name": "Pet" + } + } + } + }, + "tags": [ + { + "name": "pet", + "description": "Everything about your Pets" + } + ] +} diff --git a/connectors/citrus-selenium/src/main/resources/META-INF/spring.schemas b/connectors/citrus-selenium/src/main/resources/META-INF/spring.schemas index fb0bf312b2..fdd9bb9e69 100644 --- a/connectors/citrus-selenium/src/main/resources/META-INF/spring.schemas +++ b/connectors/citrus-selenium/src/main/resources/META-INF/spring.schemas @@ -27,8 +27,9 @@ http\://www.citrusframework.org/schema/selenium/config/citrus-selenium-config-4. http\://www.citrusframework.org/schema/selenium/config/citrus-selenium-config-4.0.2.xsd=org/citrusframework/schema/citrus-selenium-config-4.0.2.xsd http\://www.citrusframework.org/schema/selenium/config/citrus-selenium-config-4.1.0.xsd=org/citrusframework/schema/citrus-selenium-config-4.1.0.xsd http\://www.citrusframework.org/schema/selenium/config/citrus-selenium-config-4.1.1.xsd=org/citrusframework/schema/citrus-selenium-config-4.1.1.xsd -http\://www.citrusframework.org/schema/selenium/config/citrus-selenium-config-4.3.0-SNAPSHOT.xsd=org/citrusframework/schema/citrus-selenium-config-4.3.0-SNAPSHOT.xsd http\://www.citrusframework.org/schema/selenium/config/citrus-selenium-config-4.2.0.xsd=org/citrusframework/schema/citrus-selenium-config-4.2.0.xsd +http\://www.citrusframework.org/schema/selenium/config/citrus-selenium-config-4.2.1.xsd=org/citrusframework/schema/citrus-selenium-config-4.2.1.xsd +http\://www.citrusframework.org/schema/selenium/config/citrus-selenium-config-4.3.0-SNAPSHOT.xsd=org/citrusframework/schema/citrus-selenium-config-4.3.0-SNAPSHOT.xsd http\://www.citrusframework.org/schema/selenium/config/citrus-selenium-config.xsd=org/citrusframework/schema/citrus-selenium-config.xsd http\://www.citrusframework.org/schema/selenium/testcase/citrus-selenium-testcase-2.7.1.xsd=com/consol/citrus/schema/citrus-selenium-testcase-2.7.1.xsd http\://www.citrusframework.org/schema/selenium/testcase/citrus-selenium-testcase-2.7.2.xsd=com/consol/citrus/schema/citrus-selenium-testcase-2.7.2.xsd @@ -59,6 +60,7 @@ http\://www.citrusframework.org/schema/selenium/testcase/citrus-selenium-testcas http\://www.citrusframework.org/schema/selenium/testcase/citrus-selenium-testcase-4.0.2.xsd=org/citrusframework/schema/citrus-selenium-testcase-4.0.2.xsd http\://www.citrusframework.org/schema/selenium/testcase/citrus-selenium-testcase-4.1.0.xsd=org/citrusframework/schema/citrus-selenium-testcase-4.1.0.xsd http\://www.citrusframework.org/schema/selenium/testcase/citrus-selenium-testcase-4.1.1.xsd=org/citrusframework/schema/citrus-selenium-testcase-4.1.1.xsd -http\://www.citrusframework.org/schema/selenium/testcase/citrus-selenium-testcase-4.3.0-SNAPSHOT.xsd=org/citrusframework/schema/citrus-selenium-testcase-4.3.0-SNAPSHOT.xsd http\://www.citrusframework.org/schema/selenium/testcase/citrus-selenium-testcase-4.2.0.xsd=org/citrusframework/schema/citrus-selenium-testcase-4.2.0.xsd +http\://www.citrusframework.org/schema/selenium/testcase/citrus-selenium-testcase-4.2.1.xsd=org/citrusframework/schema/citrus-selenium-testcase-4.2.1.xsd +http\://www.citrusframework.org/schema/selenium/testcase/citrus-selenium-testcase-4.3.0-SNAPSHOT.xsd=org/citrusframework/schema/citrus-selenium-testcase-4.3.0-SNAPSHOT.xsd http\://www.citrusframework.org/schema/selenium/testcase/citrus-selenium-testcase.xsd=org/citrusframework/schema/citrus-selenium-testcase.xsd diff --git a/core/citrus-api/src/main/java/org/citrusframework/TestResult.java b/core/citrus-api/src/main/java/org/citrusframework/TestResult.java index 7ba17d260a..beeb39aa79 100644 --- a/core/citrus-api/src/main/java/org/citrusframework/TestResult.java +++ b/core/citrus-api/src/main/java/org/citrusframework/TestResult.java @@ -132,7 +132,7 @@ public static TestResult failed(String name, String className, @Nonnull String e /** * Create new test result with parameters for failed execution. */ - public static TestResult failed(String name, String className, @Nonnull Map parameters, @Nullable Throwable cause) { + public static TestResult failed(String name, String className, @Nullable Throwable cause, @Nonnull Map parameters) { return new TestResult(FAILURE, name, className) .withParameters(parameters) .withCause(cause) @@ -196,6 +196,11 @@ public String getFailureType() { return failureType; } + public TestResult withFailureType(String failureType) { + this.failureType = failureType; + return this; + } + @Nullable public Duration getDuration() { return duration; diff --git a/core/citrus-api/src/main/java/org/citrusframework/TestResultInstanceProvider.java b/core/citrus-api/src/main/java/org/citrusframework/TestResultInstanceProvider.java new file mode 100644 index 0000000000..ed5930531e --- /dev/null +++ b/core/citrus-api/src/main/java/org/citrusframework/TestResultInstanceProvider.java @@ -0,0 +1,13 @@ +package org.citrusframework; + +/** + * Provides methods to create instances of {@link TestResult} for different outcomes of a test case. + * Implementors may decide to create TestResults with specific parameters derived from the {@link TestCase}. + */ +public interface TestResultInstanceProvider { + + TestResult createSuccess(TestCase testCase); + TestResult createFailed(TestCase testCase, Throwable throwable); + TestResult createSkipped(TestCase testCase); + +} diff --git a/core/citrus-base/src/main/java/org/citrusframework/DefaultTestCase.java b/core/citrus-base/src/main/java/org/citrusframework/DefaultTestCase.java index 7ab2da958b..236ad4efde 100644 --- a/core/citrus-base/src/main/java/org/citrusframework/DefaultTestCase.java +++ b/core/citrus-base/src/main/java/org/citrusframework/DefaultTestCase.java @@ -16,6 +16,20 @@ package org.citrusframework; +import static java.lang.String.format; +import static java.util.Objects.isNull; +import static java.util.Objects.nonNull; +import static org.citrusframework.TestResult.failed; +import static org.citrusframework.TestResult.skipped; +import static org.citrusframework.TestResult.success; +import static org.citrusframework.util.TestUtils.waitForCompletion; + +import java.time.Duration; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; import org.apache.commons.lang3.time.StopWatch; import org.citrusframework.container.AbstractActionContainer; import org.citrusframework.container.AfterTest; @@ -23,24 +37,10 @@ import org.citrusframework.context.TestContext; import org.citrusframework.exceptions.CitrusRuntimeException; import org.citrusframework.exceptions.TestCaseFailedException; +import org.citrusframework.spi.ReferenceResolver; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.time.Duration; -import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -import static java.lang.String.format; -import static java.util.Objects.isNull; -import static java.util.Objects.nonNull; -import static org.citrusframework.TestResult.failed; -import static org.citrusframework.TestResult.skipped; -import static org.citrusframework.TestResult.success; -import static org.citrusframework.util.TestUtils.waitForCompletion; - /** * Default test case implementation holding a list of test actions to execute. Test case also holds variable definitions and * performs the test lifecycle such as start, finish, before and after test. @@ -51,6 +51,8 @@ public class DefaultTestCase extends AbstractActionContainer implements TestCase private static final Logger logger = LoggerFactory.getLogger(DefaultTestCase.class); + private static final TestResultInstanceProvider DEFAULT_TEST_RESULT_INSTANCE_PROVIDER = new DefaultTestResultInstanceProvider(); + /** * Further chain of test actions to be executed in any case (success, error) * Usually used to clean up database in any case of test result @@ -114,16 +116,16 @@ public void doExecute(final TestContext context) { executeAction(actionBuilder.build(), context); } - testResult = success(getName(), testClass.getName()); + testResult = getTestResultInstanceProvider(context).createSuccess(this); } catch (final TestCaseFailedException e) { gracefullyStopTimer(); throw e; } catch (final Exception | AssertionError e) { - testResult = failed(getName(), testClass.getName(), e); + testResult = getTestResultInstanceProvider(context).createFailed(this, e); throw new TestCaseFailedException(e); } } else { - testResult = skipped(getName(), testClass.getName()); + testResult = getTestResultInstanceProvider(context).createSkipped(this); context.getTestListeners().onTestSkipped(this); } } @@ -142,7 +144,7 @@ public void start(final TestContext context) { beforeTest(context); } catch (final Exception | AssertionError e) { - testResult = failed(getName(), testClass.getName(), e); + testResult = getTestResultInstanceProvider(context).createFailed(this, e); throw new TestCaseFailedException(e); } } @@ -193,7 +195,7 @@ public void executeAction(final TestAction action, final TestContext context) { context.getTestActionListeners().onTestActionSkipped(this, action); } } catch (final Exception | AssertionError e) { - testResult = failed(getName(), testClass.getName(), e); + testResult = getTestResultInstanceProvider(context).createFailed(this, e); throw new TestCaseFailedException(e); } finally { setExecutedAction(action); @@ -219,9 +221,9 @@ public void finish(final TestContext context) { if (isNull(testResult)) { if (context.hasExceptions()) { contextException = context.getExceptions().remove(0); - testResult = failed(getName(), testClass.getName(), contextException); + testResult = getTestResultInstanceProvider(context).createFailed(this, contextException); } else { - testResult = success(getName(), testClass.getName()); + testResult = getTestResultInstanceProvider(context).createSuccess(this); } } @@ -238,7 +240,7 @@ public void finish(final TestContext context) { } catch (final TestCaseFailedException e) { throw e; } catch (final Exception | AssertionError e) { - testResult = failed(getName(), testClass.getName(), e); + testResult = getTestResultInstanceProvider(context).createFailed(this, e); throw new TestCaseFailedException(e); } finally { if (testResult != null) { @@ -298,7 +300,7 @@ private void executeFinalActions(TestContext context) { if (testResult.isSuccess() && context.hasExceptions()) { CitrusRuntimeException contextException = context.getExceptions().remove(0); - testResult = failed(getName(), testClass.getName(), contextException); + testResult = getTestResultInstanceProvider(context).createFailed(this, contextException); throw new TestCaseFailedException(contextException); } } @@ -381,6 +383,16 @@ public void setFinalActions(final List finalActions) { this.finalActions = finalActions.stream().map(action -> (TestActionBuilder) () -> action).collect(Collectors.toList()); } + private TestResultInstanceProvider getTestResultInstanceProvider(TestContext context) { + + ReferenceResolver referenceResolver = context.getReferenceResolver(); + if (referenceResolver != null && referenceResolver.isResolvable(TestResultInstanceProvider.class)) { + return referenceResolver.resolve(TestResultInstanceProvider.class); + } + + return DEFAULT_TEST_RESULT_INSTANCE_PROVIDER; + } + @Override public String toString() { final StringBuilder stringBuilder = new StringBuilder(); @@ -527,4 +539,26 @@ public void setTimeout(final long timeout) { public long getTimeout() { return timeout; } + + /** + * Default implementation of {@link TestResultInstanceProvider} that provides simple TestResults + * without any parameters. + */ + private static final class DefaultTestResultInstanceProvider implements TestResultInstanceProvider { + + @Override + public TestResult createSuccess(TestCase testCase) { + return success(testCase.getName(), testCase.getTestClass().getName()); + } + + @Override + public TestResult createFailed(TestCase testCase, Throwable throwable) { + return failed(testCase.getName(), testCase.getTestClass().getName(), throwable); + } + + @Override + public TestResult createSkipped(TestCase testCase) { + return skipped(testCase.getName(), testCase.getTestClass().getName()); + } + } } diff --git a/core/citrus-base/src/main/java/org/citrusframework/report/LoggingReporter.java b/core/citrus-base/src/main/java/org/citrusframework/report/LoggingReporter.java index 7c7371c6b8..a73fc1fd4e 100644 --- a/core/citrus-base/src/main/java/org/citrusframework/report/LoggingReporter.java +++ b/core/citrus-base/src/main/java/org/citrusframework/report/LoggingReporter.java @@ -16,9 +16,11 @@ package org.citrusframework.report; +import org.apache.commons.lang3.exception.ExceptionUtils; import org.citrusframework.CitrusVersion; import org.citrusframework.TestAction; import org.citrusframework.TestCase; +import org.citrusframework.TestResult; import org.citrusframework.common.Described; import org.citrusframework.container.TestActionContainer; import org.citrusframework.context.TestContext; @@ -30,6 +32,7 @@ import java.util.Optional; import static java.lang.String.format; +import static java.time.Duration.ZERO; import static java.util.Objects.nonNull; import static org.citrusframework.util.StringUtils.hasText; @@ -83,34 +86,37 @@ public class LoggingReporter extends AbstractTestReporter implements MessageList */ private static final Logger noOpLogger = new NOPLoggerFactory().getLogger(LoggingReporter.class.getName()); + private static boolean isInitialized = false; + private static String formatDurationString(TestCase test) { return nonNull(test.getTestResult()) && nonNull(test.getTestResult().getDuration()) ? " (" + test.getTestResult().getDuration().toString() + ") " : ""; } @Override public void generate(TestResults testResults) { - separator(); newLine(); info("CITRUS TEST RESULTS"); newLine(); testResults.doWithResults(testResult -> { - info(testResult.toString()); + info(toFormattedTestResult(testResult)); if (testResult.isFailed()) { - info(Optional.ofNullable(testResult.getCause()) - .filter(cause -> hasText(cause.getMessage())) - .map(cause -> " FAILURE: Caused by: " + cause.getClass().getSimpleName() + ": " + cause.getMessage()) - .orElse(" FAILURE: Caused by: " + Optional.ofNullable(testResult.getErrorMessage()).orElse("Unknown error"))); + info( + Optional.ofNullable(testResult.getCause()) + .filter(cause -> hasText(cause.getMessage())) + .map(ExceptionUtils::getRootCause) + .map(cause -> "\tCaused by: " + cause.getClass().getSimpleName() + ": " + cause.getMessage()) + .orElse("\tCaused by: " + Optional.ofNullable(testResult.getErrorMessage()).orElse("Unknown error"))); } }); newLine(); - info(format("TOTAL:\t\t\t%s", testResults.getFailed() + testResults.getSuccess())); - info(format("SUCCESS:\t\t%s (%s%%)", testResults.getSuccess(), testResults.getSuccessPercentage())); - info(format("FAILED:\t\t%s (%s%%)", testResults.getFailed(), testResults.getFailedPercentage())); - debug(format("SKIPPED:\t\t%s (%s%%)", testResults.getSkipped(), testResults.getSkippedPercentage())); + info(format("TOTAL:\t\t%s", testResults.getFailed() + testResults.getSuccess())); + info(format("SUCCESS:\t\t%s (%s%%)", testResults.getSuccess(), testResults.getSuccessPercentageFormatted())); + info(format("FAILED:\t\t%s (%s%%)", testResults.getFailed(), testResults.getFailedPercentageFormatted())); + debug(format("SKIPPED:\t\t%s (%s%%)", testResults.getSkipped(), testResults.getSkippedPercentageFormatted())); info(format("PERFORMANCE:\t%s ms", testResults.getTotalDuration().toMillis())); newLine(); @@ -118,6 +124,13 @@ public void generate(TestResults testResults) { separator(); } + private String toFormattedTestResult(TestResult testResult) { + return format("%s (%6d ms) %s", + testResult.getResult(), + Optional.ofNullable(testResult.getDuration()).orElse(ZERO).toMillis(), + testResult.getTestName()); + } + @Override public void onTestFailure(TestCase testCase, Throwable cause) { newLine(); @@ -135,7 +148,6 @@ public void onTestSkipped(TestCase test) { newLine(); separator(); debug("SKIPPING TEST: " + test.getName()); - separator(); newLine(); } } @@ -168,16 +180,31 @@ public void onTestSuccess(TestCase test) { @Override public void onFinish() { - newLine(); - separator(); - debug("AFTER TEST SUITE"); - newLine(); + if (isDebugEnabled()) { + newLine(); + separator(); + debug("AFTER TEST SUITE"); + newLine(); + } } @Override public void onStart() { - newLine(); + if (!isInitialized) { + printBanner(); + + isInitialized = true; + } + separator(); + + if (isDebugEnabled()) { + debug("BEFORE TEST SUITE"); + newLine(); + } + } + + private void printBanner() { info(" .__ __ "); info(" ____ |__|/ |________ __ __ ______"); info("_/ ___\\| \\ __\\_ __ \\ | \\/ ___/"); @@ -188,42 +215,42 @@ public void onStart() { newLine(); info("C I T R U S T E S T S " + CitrusVersion.version()); newLine(); - - separator(); - debug("BEFORE TEST SUITE"); - newLine(); } @Override public void onFinishFailure(Throwable cause) { newLine(); - info("AFTER TEST SUITE: FAILED"); + error("AFTER TEST SUITE: FAILED"); separator(); newLine(); } @Override public void onFinishSuccess() { - newLine(); - info("AFTER TEST SUITE: SUCCESS"); - separator(); - newLine(); + if (isDebugEnabled()) { + newLine(); + debug("AFTER TEST SUITE: SUCCESS"); + separator(); + newLine(); + } } @Override public void onStartFailure(Throwable cause) { newLine(); - info("BEFORE TEST SUITE: FAILED"); + error("BEFORE TEST SUITE: FAILED"); separator(); newLine(); } @Override public void onStartSuccess() { - newLine(); - info("BEFORE TEST SUITE: SUCCESS"); - separator(); - newLine(); + if (isDebugEnabled()) { + newLine(); + debug("BEFORE TEST SUITE: SUCCESS"); + separator(); + newLine(); + } } @Override @@ -308,6 +335,15 @@ protected void info(String line) { logger.info(line); } + /** + * Write error level output. + * + * @param line + */ + protected void error(String line) { + logger.error(line); + } + /** * Write error level output. * diff --git a/core/citrus-base/src/test/java/org/citrusframework/report/LoggingReporterTest.java b/core/citrus-base/src/test/java/org/citrusframework/report/LoggingReporterTest.java index 9e365acbd3..a9394ef037 100644 --- a/core/citrus-base/src/test/java/org/citrusframework/report/LoggingReporterTest.java +++ b/core/citrus-base/src/test/java/org/citrusframework/report/LoggingReporterTest.java @@ -16,9 +16,6 @@ package org.citrusframework.report; -import java.time.Duration; -import java.util.Locale; - import org.citrusframework.DefaultTestCase; import org.citrusframework.actions.EchoAction; import org.citrusframework.exceptions.CitrusRuntimeException; @@ -28,12 +25,18 @@ import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; +import java.time.Duration; +import java.util.Locale; + import static java.lang.String.format; import static org.citrusframework.TestResult.failed; import static org.citrusframework.TestResult.skipped; import static org.citrusframework.TestResult.success; import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.argThat; +import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.MockitoAnnotations.openMocks; import static org.springframework.test.util.ReflectionTestUtils.setField; @@ -72,6 +75,20 @@ public void beforeMethod() { setField(fixture, "logger", logger, Logger.class); } + @Test + void onStartPrintsBannerExactlyOnce() { + // Print citrus information on startup + fixture.onStart(); + + verify(logger).info(argThat(a -> a.startsWith("C I T R U S T E S T S"))); + + // Do not print it continuously + clearInvocations(logger); + fixture.onStart(); + + verify(logger, never()).info(argThat(a -> a.startsWith("C I T R U S T E S T S"))); + } + @Test public void testLoggingReporterSuccess() { fixture.onStart(); @@ -92,8 +109,8 @@ public void testLoggingReporterSuccess() { fixture.generate(testResults); - verify(logger).info("TestResult[testName=testLoggingReporterSuccess-1, result=SUCCESS, durationMs=111]"); - verify(logger).info("TestResult[testName=testLoggingReporterSuccess-2, result=SUCCESS, durationMs=222]"); + verify(logger).info("SUCCESS ( 111 ms) testLoggingReporterSuccess-1"); + verify(logger).info("SUCCESS ( 222 ms) testLoggingReporterSuccess-2"); verifyResultSummaryLog(2, 2, 0, 333); @@ -102,7 +119,8 @@ public void testLoggingReporterSuccess() { @Test public void testLoggingReporterFailed() { - var cause = new CitrusRuntimeException("Failed!"); + var nestedException = new CitrusRuntimeException("I am the final boss."); + var cause = new CitrusRuntimeException("Failed!", nestedException); fixture.onStart(); fixture.onStartSuccess(); @@ -117,30 +135,34 @@ public void testLoggingReporterFailed() { TestResults testResults = new TestResults(); testResults.addResult(failed("testLoggingReporterFailed-1", getClass().getSimpleName(), cause).withDuration(Duration.ofMillis(1234))); - testResults.addResult(failed("testLoggingReporterFailed-2", getClass().getSimpleName(), cause).withDuration(Duration.ofMillis(2345))); + testResults.addResult(failed("testLoggingReporterFailed-2", getClass().getSimpleName(), nestedException).withDuration(Duration.ofMillis(2345))); + var customErrorMessage = "custom error message"; + testResults.addResult(failed("testLoggingReporterFailed-3", getClass().getSimpleName(), customErrorMessage).withDuration(Duration.ofMillis(3456))); fixture.generate(testResults); - verify(logger).info("TestResult[testName=testLoggingReporterFailed-1, result=FAILURE, durationMs=1234]"); - verify(logger).info("TestResult[testName=testLoggingReporterFailed-2, result=FAILURE, durationMs=2345]"); + verify(logger).info("FAILURE ( 1234 ms) testLoggingReporterFailed-1"); + verify(logger).info("FAILURE ( 2345 ms) testLoggingReporterFailed-2"); + verify(logger, times(2)).info("\tCaused by: %s: %s".formatted(nestedException.getClass().getSimpleName(), nestedException.getMessage())); + verify(logger).info("FAILURE ( 3456 ms) testLoggingReporterFailed-3"); + verify(logger).info("\tCaused by: %s".formatted(customErrorMessage)); - verifyResultSummaryLog(2, 0, 2, 3579); + verifyResultSummaryLog(3, 0, 3, 7035); verify(logger, never()).debug(anyString()); } @Test public void testLoggingReporterMiscellaneous() { - var cause = new CitrusRuntimeException("Failed!"); - TestResults testResults = new TestResults(); testResults.addResult(success("testLoggingReporterMiscellaneous-1", getClass().getSimpleName()).withDuration(Duration.ofSeconds(1))); - testResults.addResult(failed("testLoggingReporterMiscellaneous-2", getClass().getSimpleName(), cause).withDuration(Duration.ofNanos(22848329))); + testResults.addResult(failed("testLoggingReporterMiscellaneous-2", getClass().getSimpleName(), (String) null).withDuration(Duration.ofNanos(22848329))); fixture.generate(testResults); - verify(logger).info("TestResult[testName=testLoggingReporterMiscellaneous-1, result=SUCCESS, durationMs=1000]"); - verify(logger).info("TestResult[testName=testLoggingReporterMiscellaneous-2, result=FAILURE, durationMs=22]"); + verify(logger).info("SUCCESS ( 1000 ms) testLoggingReporterMiscellaneous-1"); + verify(logger).info("FAILURE ( 22 ms) testLoggingReporterMiscellaneous-2"); + verify(logger).info("\tCaused by: Unknown error"); verifyResultSummaryLog(2, 1, 1, 1022); @@ -163,7 +185,7 @@ public void testLoggingReporterSkipped() { fixture.generate(testResults); - verify(logger).info("TestResult[testName=testLoggingReporterSkipped, result=SKIP]"); + verify(logger).info("SKIP ( 0 ms) testLoggingReporterSkipped"); verifyResultSummaryLog(0, 0, 0, 0); @@ -203,7 +225,7 @@ void afterMethodTeardown() throws Exception { } private void verifyResultSummaryLog(int total, int success, int failed, long performance) { - verify(logger).info("TOTAL:\t\t\t" + total); + verify(logger).info("TOTAL:\t\t" + total); verify(logger).info("SUCCESS:\t\t" + success + " (" + calculatePercentage(total, success) + "%)"); verify(logger).info("FAILED:\t\t" + failed + " (" + calculatePercentage(total, failed) + "%)"); verify(logger).info("PERFORMANCE:\t" + performance + " ms"); @@ -215,6 +237,6 @@ private String calculatePercentage(int total, int success) { } double percentage = (double) success / total * 100; - return format(Locale.US,"%3.1f", percentage); + return format(Locale.US, "%3.1f", percentage); } } diff --git a/core/citrus-spring/src/main/resources/META-INF/spring.schemas b/core/citrus-spring/src/main/resources/META-INF/spring.schemas index cca313d8a3..f121cc9f98 100644 --- a/core/citrus-spring/src/main/resources/META-INF/spring.schemas +++ b/core/citrus-spring/src/main/resources/META-INF/spring.schemas @@ -45,8 +45,9 @@ http\://www.citrusframework.org/schema/config/citrus-config-4.0.1.xsd=org/citrus http\://www.citrusframework.org/schema/config/citrus-config-4.0.2.xsd=org/citrusframework/schema/citrus-config-4.0.2.xsd http\://www.citrusframework.org/schema/config/citrus-config-4.1.0.xsd=org/citrusframework/schema/citrus-config-4.1.0.xsd http\://www.citrusframework.org/schema/config/citrus-config-4.1.1.xsd=org/citrusframework/schema/citrus-config-4.1.1.xsd -http\://www.citrusframework.org/schema/config/citrus-config-4.3.0-SNAPSHOT.xsd=org/citrusframework/schema/citrus-config-4.3.0-SNAPSHOT.xsd http\://www.citrusframework.org/schema/config/citrus-config-4.2.0.xsd=org/citrusframework/schema/citrus-config-4.2.0.xsd +http\://www.citrusframework.org/schema/config/citrus-config-4.2.1.xsd=org/citrusframework/schema/citrus-config-4.2.1.xsd +http\://www.citrusframework.org/schema/config/citrus-config-4.3.0-SNAPSHOT.xsd=org/citrusframework/schema/citrus-config-4.3.0-SNAPSHOT.xsd http\://www.citrusframework.org/schema/config/citrus-config.xsd=org/citrusframework/schema/citrus-config.xsd http\://www.citrusframework.org/schema/testcase/citrus-testcase-1.0.xsd=com/consol/citrus/schema/citrus-testcase-1.0.xsd http\://www.citrusframework.org/schema/testcase/citrus-testcase-1.1.xsd=com/consol/citrus/schema/citrus-testcase-1.1.xsd @@ -95,6 +96,7 @@ http\://www.citrusframework.org/schema/testcase/citrus-testcase-4.0.1.xsd=org/ci http\://www.citrusframework.org/schema/testcase/citrus-testcase-4.0.2.xsd=org/citrusframework/schema/citrus-testcase-4.0.2.xsd http\://www.citrusframework.org/schema/testcase/citrus-testcase-4.1.0.xsd=org/citrusframework/schema/citrus-testcase-4.1.0.xsd http\://www.citrusframework.org/schema/testcase/citrus-testcase-4.1.1.xsd=org/citrusframework/schema/citrus-testcase-4.1.1.xsd -http\://www.citrusframework.org/schema/testcase/citrus-testcase-4.3.0-SNAPSHOT.xsd=org/citrusframework/schema/citrus-testcase-4.3.0-SNAPSHOT.xsd http\://www.citrusframework.org/schema/testcase/citrus-testcase-4.2.0.xsd=org/citrusframework/schema/citrus-testcase-4.2.0.xsd +http\://www.citrusframework.org/schema/testcase/citrus-testcase-4.2.1.xsd=org/citrusframework/schema/citrus-testcase-4.2.1.xsd +http\://www.citrusframework.org/schema/testcase/citrus-testcase-4.3.0-SNAPSHOT.xsd=org/citrusframework/schema/citrus-testcase-4.3.0-SNAPSHOT.xsd http\://www.citrusframework.org/schema/testcase/citrus-testcase.xsd=org/citrusframework/schema/citrus-testcase.xsd diff --git a/endpoints/citrus-camel/src/main/resources/META-INF/spring.schemas b/endpoints/citrus-camel/src/main/resources/META-INF/spring.schemas index 09da408c78..e4b4ef1e9d 100644 --- a/endpoints/citrus-camel/src/main/resources/META-INF/spring.schemas +++ b/endpoints/citrus-camel/src/main/resources/META-INF/spring.schemas @@ -40,8 +40,9 @@ http\://www.citrusframework.org/schema/camel/config/citrus-camel-config-4.0.1.xs http\://www.citrusframework.org/schema/camel/config/citrus-camel-config-4.0.2.xsd=org/citrusframework/schema/citrus-camel-config-4.0.2.xsd http\://www.citrusframework.org/schema/camel/config/citrus-camel-config-4.1.0.xsd=org/citrusframework/schema/citrus-camel-config-4.1.0.xsd http\://www.citrusframework.org/schema/camel/config/citrus-camel-config-4.1.1.xsd=org/citrusframework/schema/citrus-camel-config-4.1.1.xsd -http\://www.citrusframework.org/schema/camel/config/citrus-camel-config-4.3.0-SNAPSHOT.xsd=org/citrusframework/schema/citrus-camel-config-4.3.0-SNAPSHOT.xsd http\://www.citrusframework.org/schema/camel/config/citrus-camel-config-4.2.0.xsd=org/citrusframework/schema/citrus-camel-config-4.2.0.xsd +http\://www.citrusframework.org/schema/camel/config/citrus-camel-config-4.2.1.xsd=org/citrusframework/schema/citrus-camel-config-4.2.1.xsd +http\://www.citrusframework.org/schema/camel/config/citrus-camel-config-4.3.0-SNAPSHOT.xsd=org/citrusframework/schema/citrus-camel-config-4.3.0-SNAPSHOT.xsd http\://www.citrusframework.org/schema/camel/config/citrus-camel-config.xsd=org/citrusframework/schema/citrus-camel-config.xsd http\://www.citrusframework.org/schema/camel/testcase/citrus-camel-testcase-2.3.xsd=com/consol/citrus/schema/citrus-camel-testcase-2.3.xsd http\://www.citrusframework.org/schema/camel/testcase/citrus-camel-testcase-2.4.xsd=com/consol/citrus/schema/citrus-camel-testcase-2.4.xsd @@ -80,6 +81,7 @@ http\://www.citrusframework.org/schema/camel/testcase/citrus-camel-testcase-4.0. http\://www.citrusframework.org/schema/camel/testcase/citrus-camel-testcase-4.0.2.xsd=org/citrusframework/schema/citrus-camel-testcase-4.0.2.xsd http\://www.citrusframework.org/schema/camel/testcase/citrus-camel-testcase-4.1.0.xsd=org/citrusframework/schema/citrus-camel-testcase-4.1.0.xsd http\://www.citrusframework.org/schema/camel/testcase/citrus-camel-testcase-4.1.1.xsd=org/citrusframework/schema/citrus-camel-testcase-4.1.1.xsd -http\://www.citrusframework.org/schema/camel/testcase/citrus-camel-testcase-4.3.0-SNAPSHOT.xsd=org/citrusframework/schema/citrus-camel-testcase-4.3.0-SNAPSHOT.xsd http\://www.citrusframework.org/schema/camel/testcase/citrus-camel-testcase-4.2.0.xsd=org/citrusframework/schema/citrus-camel-testcase-4.2.0.xsd +http\://www.citrusframework.org/schema/camel/testcase/citrus-camel-testcase-4.2.1.xsd=org/citrusframework/schema/citrus-camel-testcase-4.2.1.xsd +http\://www.citrusframework.org/schema/camel/testcase/citrus-camel-testcase-4.3.0-SNAPSHOT.xsd=org/citrusframework/schema/citrus-camel-testcase-4.3.0-SNAPSHOT.xsd http\://www.citrusframework.org/schema/camel/testcase/citrus-camel-testcase.xsd=org/citrusframework/schema/citrus-camel-testcase.xsd diff --git a/endpoints/citrus-ftp/src/main/resources/META-INF/spring.schemas b/endpoints/citrus-ftp/src/main/resources/META-INF/spring.schemas index eafd2a0f54..2200d3cc49 100644 --- a/endpoints/citrus-ftp/src/main/resources/META-INF/spring.schemas +++ b/endpoints/citrus-ftp/src/main/resources/META-INF/spring.schemas @@ -38,8 +38,9 @@ http\://www.citrusframework.org/schema/ftp/config/citrus-ftp-config-4.0.1.xsd=or http\://www.citrusframework.org/schema/ftp/config/citrus-ftp-config-4.0.2.xsd=org/citrusframework/schema/citrus-ftp-config-4.0.2.xsd http\://www.citrusframework.org/schema/ftp/config/citrus-ftp-config-4.1.0.xsd=org/citrusframework/schema/citrus-ftp-config-4.1.0.xsd http\://www.citrusframework.org/schema/ftp/config/citrus-ftp-config-4.1.1.xsd=org/citrusframework/schema/citrus-ftp-config-4.1.1.xsd -http\://www.citrusframework.org/schema/ftp/config/citrus-ftp-config-4.3.0-SNAPSHOT.xsd=org/citrusframework/schema/citrus-ftp-config-4.3.0-SNAPSHOT.xsd http\://www.citrusframework.org/schema/ftp/config/citrus-ftp-config-4.2.0.xsd=org/citrusframework/schema/citrus-ftp-config-4.2.0.xsd +http\://www.citrusframework.org/schema/ftp/config/citrus-ftp-config-4.2.1.xsd=org/citrusframework/schema/citrus-ftp-config-4.2.1.xsd +http\://www.citrusframework.org/schema/ftp/config/citrus-ftp-config-4.3.0-SNAPSHOT.xsd=org/citrusframework/schema/citrus-ftp-config-4.3.0-SNAPSHOT.xsd http\://www.citrusframework.org/schema/ftp/config/citrus-ftp-config.xsd=org/citrusframework/schema/citrus-ftp-config.xsd http\://www.citrusframework.org/schema/scp/config/citrus-scp-config-2.7.6.xsd=com/consol/citrus/schema/citrus-scp-config-2.7.6.xsd http\://www.citrusframework.org/schema/scp/config/citrus-scp-config-2.7.7.xsd=com/consol/citrus/schema/citrus-scp-config-2.7.7.xsd @@ -64,8 +65,9 @@ http\://www.citrusframework.org/schema/scp/config/citrus-scp-config-4.0.1.xsd=or http\://www.citrusframework.org/schema/scp/config/citrus-scp-config-4.0.2.xsd=org/citrusframework/schema/citrus-scp-config-4.0.2.xsd http\://www.citrusframework.org/schema/scp/config/citrus-scp-config-4.1.0.xsd=org/citrusframework/schema/citrus-scp-config-4.1.0.xsd http\://www.citrusframework.org/schema/scp/config/citrus-scp-config-4.1.1.xsd=org/citrusframework/schema/citrus-scp-config-4.1.1.xsd -http\://www.citrusframework.org/schema/scp/config/citrus-scp-config-4.3.0-SNAPSHOT.xsd=org/citrusframework/schema/citrus-scp-config-4.3.0-SNAPSHOT.xsd http\://www.citrusframework.org/schema/scp/config/citrus-scp-config-4.2.0.xsd=org/citrusframework/schema/citrus-scp-config-4.2.0.xsd +http\://www.citrusframework.org/schema/scp/config/citrus-scp-config-4.2.1.xsd=org/citrusframework/schema/citrus-scp-config-4.2.1.xsd +http\://www.citrusframework.org/schema/scp/config/citrus-scp-config-4.3.0-SNAPSHOT.xsd=org/citrusframework/schema/citrus-scp-config-4.3.0-SNAPSHOT.xsd http\://www.citrusframework.org/schema/scp/config/citrus-scp-config.xsd=org/citrusframework/schema/citrus-scp-config.xsd http\://www.citrusframework.org/schema/sftp/config/citrus-sftp-config-2.7.5.xsd=com/consol/citrus/schema/citrus-sftp-config-2.7.5.xsd http\://www.citrusframework.org/schema/sftp/config/citrus-sftp-config-2.7.6.xsd=com/consol/citrus/schema/citrus-sftp-config-2.7.6.xsd @@ -88,6 +90,7 @@ http\://www.citrusframework.org/schema/sftp/config/citrus-sftp-config-4.0.1.xsd= http\://www.citrusframework.org/schema/sftp/config/citrus-sftp-config-4.0.2.xsd=org/citrusframework/schema/citrus-sftp-config-4.0.2.xsd http\://www.citrusframework.org/schema/sftp/config/citrus-sftp-config-4.1.0.xsd=org/citrusframework/schema/citrus-sftp-config-4.1.0.xsd http\://www.citrusframework.org/schema/sftp/config/citrus-sftp-config-4.1.1.xsd=org/citrusframework/schema/citrus-sftp-config-4.1.1.xsd -http\://www.citrusframework.org/schema/sftp/config/citrus-sftp-config-4.3.0-SNAPSHOT.xsd=org/citrusframework/schema/citrus-sftp-config-4.3.0-SNAPSHOT.xsd http\://www.citrusframework.org/schema/sftp/config/citrus-sftp-config-4.2.0.xsd=org/citrusframework/schema/citrus-sftp-config-4.2.0.xsd +http\://www.citrusframework.org/schema/sftp/config/citrus-sftp-config-4.2.1.xsd=org/citrusframework/schema/citrus-sftp-config-4.2.1.xsd +http\://www.citrusframework.org/schema/sftp/config/citrus-sftp-config-4.3.0-SNAPSHOT.xsd=org/citrusframework/schema/citrus-sftp-config-4.3.0-SNAPSHOT.xsd http\://www.citrusframework.org/schema/sftp/config/citrus-sftp-config.xsd=org/citrusframework/schema/citrus-sftp-config.xsd diff --git a/endpoints/citrus-http/src/main/java/org/citrusframework/http/actions/HttpClientActionBuilder.java b/endpoints/citrus-http/src/main/java/org/citrusframework/http/actions/HttpClientActionBuilder.java index 16494006b0..0d41b1767d 100644 --- a/endpoints/citrus-http/src/main/java/org/citrusframework/http/actions/HttpClientActionBuilder.java +++ b/endpoints/citrus-http/src/main/java/org/citrusframework/http/actions/HttpClientActionBuilder.java @@ -24,7 +24,7 @@ import org.citrusframework.util.ObjectHelper; import org.citrusframework.util.StringUtils; import org.springframework.http.HttpMethod; -import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; /** * Action executes http client operations such as sending requests and receiving responses. @@ -250,7 +250,7 @@ public HttpClientResponseActionBuilder response() { * Generic response builder for expecting response messages on client with response status code. * @return */ - public HttpClientResponseActionBuilder response(HttpStatus status) { + public HttpClientResponseActionBuilder response(HttpStatusCode status) { HttpClientResponseActionBuilder builder = new HttpClientResponseActionBuilder(); if (httpClient != null) { builder.endpoint(httpClient); diff --git a/endpoints/citrus-http/src/main/java/org/citrusframework/http/actions/HttpClientResponseActionBuilder.java b/endpoints/citrus-http/src/main/java/org/citrusframework/http/actions/HttpClientResponseActionBuilder.java index d5031c3ee7..959af70245 100644 --- a/endpoints/citrus-http/src/main/java/org/citrusframework/http/actions/HttpClientResponseActionBuilder.java +++ b/endpoints/citrus-http/src/main/java/org/citrusframework/http/actions/HttpClientResponseActionBuilder.java @@ -16,8 +16,6 @@ package org.citrusframework.http.actions; -import java.util.Optional; - import jakarta.servlet.http.Cookie; import org.citrusframework.actions.ReceiveMessageAction; import org.citrusframework.http.message.HttpMessage; @@ -26,9 +24,10 @@ import org.citrusframework.message.Message; import org.citrusframework.message.MessageBuilder; import org.citrusframework.message.builder.ReceiveMessageBuilderSupport; -import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatusCode; +import java.util.Optional; + /** * @author Christoph Deppisch * @since 2.4 @@ -98,7 +97,7 @@ public HttpMessageBuilderSupport from(Message controlMessage) { * @param status * @return */ - public HttpMessageBuilderSupport status(HttpStatus status) { + public HttpMessageBuilderSupport status(HttpStatusCode status) { httpMessage.status(status); return this; } diff --git a/endpoints/citrus-http/src/main/resources/META-INF/spring.schemas b/endpoints/citrus-http/src/main/resources/META-INF/spring.schemas index f175f6cca9..0a72ff05f0 100644 --- a/endpoints/citrus-http/src/main/resources/META-INF/spring.schemas +++ b/endpoints/citrus-http/src/main/resources/META-INF/spring.schemas @@ -45,8 +45,9 @@ http\://www.citrusframework.org/schema/http/config/citrus-http-config-4.0.1.xsd= http\://www.citrusframework.org/schema/http/config/citrus-http-config-4.0.2.xsd=org/citrusframework/schema/citrus-http-config-4.0.2.xsd http\://www.citrusframework.org/schema/http/config/citrus-http-config-4.1.0.xsd=org/citrusframework/schema/citrus-http-config-4.1.0.xsd http\://www.citrusframework.org/schema/http/config/citrus-http-config-4.1.1.xsd=org/citrusframework/schema/citrus-http-config-4.1.1.xsd -http\://www.citrusframework.org/schema/http/config/citrus-http-config-4.3.0-SNAPSHOT.xsd=org/citrusframework/schema/citrus-http-config-4.3.0-SNAPSHOT.xsd http\://www.citrusframework.org/schema/http/config/citrus-http-config-4.2.0.xsd=org/citrusframework/schema/citrus-http-config-4.2.0.xsd +http\://www.citrusframework.org/schema/http/config/citrus-http-config-4.2.1.xsd=org/citrusframework/schema/citrus-http-config-4.2.1.xsd +http\://www.citrusframework.org/schema/http/config/citrus-http-config-4.3.0-SNAPSHOT.xsd=org/citrusframework/schema/citrus-http-config-4.3.0-SNAPSHOT.xsd http\://www.citrusframework.org/schema/http/config/citrus-http-config.xsd=org/citrusframework/schema/citrus-http-config.xsd http\://www.citrusframework.org/schema/http/testcase/citrus-http-testcase-2.3.xsd=com/consol/citrus/schema/citrus-http-testcase-2.3.xsd http\://www.citrusframework.org/schema/http/testcase/citrus-http-testcase-2.4.xsd=com/consol/citrus/schema/citrus-http-testcase-2.4.xsd @@ -85,6 +86,7 @@ http\://www.citrusframework.org/schema/http/testcase/citrus-http-testcase-4.0.1. http\://www.citrusframework.org/schema/http/testcase/citrus-http-testcase-4.0.2.xsd=org/citrusframework/schema/citrus-http-testcase-4.0.2.xsd http\://www.citrusframework.org/schema/http/testcase/citrus-http-testcase-4.1.0.xsd=org/citrusframework/schema/citrus-http-testcase-4.1.0.xsd http\://www.citrusframework.org/schema/http/testcase/citrus-http-testcase-4.1.1.xsd=org/citrusframework/schema/citrus-http-testcase-4.1.1.xsd -http\://www.citrusframework.org/schema/http/testcase/citrus-http-testcase-4.3.0-SNAPSHOT.xsd=org/citrusframework/schema/citrus-http-testcase-4.3.0-SNAPSHOT.xsd http\://www.citrusframework.org/schema/http/testcase/citrus-http-testcase-4.2.0.xsd=org/citrusframework/schema/citrus-http-testcase-4.2.0.xsd +http\://www.citrusframework.org/schema/http/testcase/citrus-http-testcase-4.2.1.xsd=org/citrusframework/schema/citrus-http-testcase-4.2.1.xsd +http\://www.citrusframework.org/schema/http/testcase/citrus-http-testcase-4.3.0-SNAPSHOT.xsd=org/citrusframework/schema/citrus-http-testcase-4.3.0-SNAPSHOT.xsd http\://www.citrusframework.org/schema/http/testcase/citrus-http-testcase.xsd=org/citrusframework/schema/citrus-http-testcase.xsd diff --git a/endpoints/citrus-http/src/test/java/org/citrusframework/http/actions/HttpClientActionBuilderTest.java b/endpoints/citrus-http/src/test/java/org/citrusframework/http/actions/HttpClientActionBuilderTest.java new file mode 100644 index 0000000000..ffa59bd0ac --- /dev/null +++ b/endpoints/citrus-http/src/test/java/org/citrusframework/http/actions/HttpClientActionBuilderTest.java @@ -0,0 +1,58 @@ +package org.citrusframework.http.actions; + +import org.citrusframework.http.client.HttpClient; +import org.citrusframework.http.message.HttpMessage; +import org.springframework.http.HttpStatusCode; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import static org.citrusframework.http.message.HttpMessageHeaders.HTTP_REASON_PHRASE; +import static org.citrusframework.http.message.HttpMessageHeaders.HTTP_STATUS_CODE; +import static org.mockito.Mockito.mock; +import static org.springframework.http.HttpStatus.OK; +import static org.springframework.test.util.ReflectionTestUtils.getField; +import static org.testng.AssertJUnit.assertEquals; +import static org.testng.AssertJUnit.assertFalse; +import static org.testng.AssertJUnit.assertNotNull; + +public class HttpClientActionBuilderTest { + + private HttpClient httpClientMock; + + @BeforeMethod + void beforeMethodSetup() { + httpClientMock = mock(HttpClient.class); + } + + @Test + public void responseWithHttpStatus() { + var fixture = new HttpClientActionBuilder(httpClientMock) + .receive() + .response(OK) // Method under test + .message(); + + var httpMessage = (HttpMessage) getField(fixture, HttpClientResponseActionBuilder.HttpMessageBuilderSupport.class, "httpMessage"); + assertNotNull(httpMessage); + + var headers = httpMessage.getHeaders(); + assertEquals(OK.value(), headers.get(HTTP_STATUS_CODE)); + assertEquals(OK.name(), headers.get(HTTP_REASON_PHRASE)); + } + + @Test + public void responseWithHttpStatusCode() { + var code = 123; + + var fixture = new HttpClientActionBuilder(httpClientMock) + .receive() + .response(HttpStatusCode.valueOf(code)) // Method under test + .message(); + + var httpMessage = (HttpMessage) getField(fixture, HttpClientResponseActionBuilder.HttpMessageBuilderSupport.class, "httpMessage"); + assertNotNull(httpMessage); + + var headers = httpMessage.getHeaders(); + assertEquals(code, headers.get(HTTP_STATUS_CODE)); + assertFalse(headers.containsKey(HTTP_REASON_PHRASE)); + } +} diff --git a/endpoints/citrus-http/src/test/java/org/citrusframework/http/actions/HttpClientResponseActionBuilderTest.java b/endpoints/citrus-http/src/test/java/org/citrusframework/http/actions/HttpClientResponseActionBuilderTest.java new file mode 100644 index 0000000000..e276347d1d --- /dev/null +++ b/endpoints/citrus-http/src/test/java/org/citrusframework/http/actions/HttpClientResponseActionBuilderTest.java @@ -0,0 +1,43 @@ +package org.citrusframework.http.actions; + +import org.citrusframework.http.message.HttpMessage; +import org.citrusframework.message.MessageBuilder; +import org.springframework.http.HttpStatusCode; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.springframework.http.HttpStatus.OK; + +public class HttpClientResponseActionBuilderTest { + + private HttpMessage httpMessageMock; + private MessageBuilder messageBuilderMock; + + @BeforeMethod + void beforeMethodSetup() { + httpMessageMock = mock(HttpMessage.class); + messageBuilderMock = mock(MessageBuilder.class); + } + + @Test + public void statusFromHttpStatus() { + new HttpClientResponseActionBuilder(messageBuilderMock, httpMessageMock) + .message() + .status(OK); // Method under test + + verify(httpMessageMock).status(OK); + } + + @Test + public void statusFromHttpStatusCode() { + var httpStatusCode = HttpStatusCode.valueOf(123); + + new HttpClientResponseActionBuilder(messageBuilderMock, httpMessageMock) + .message() + .status(httpStatusCode); // Method under test + + verify(httpMessageMock).status(httpStatusCode); + } +} diff --git a/endpoints/citrus-jms/src/main/resources/META-INF/spring.schemas b/endpoints/citrus-jms/src/main/resources/META-INF/spring.schemas index a6e42fb68e..9f1b78600c 100644 --- a/endpoints/citrus-jms/src/main/resources/META-INF/spring.schemas +++ b/endpoints/citrus-jms/src/main/resources/META-INF/spring.schemas @@ -38,8 +38,9 @@ http\://www.citrusframework.org/schema/jms/config/citrus-jms-config-4.0.1.xsd=or http\://www.citrusframework.org/schema/jms/config/citrus-jms-config-4.0.2.xsd=org/citrusframework/schema/citrus-jms-config-4.0.2.xsd http\://www.citrusframework.org/schema/jms/config/citrus-jms-config-4.1.0.xsd=org/citrusframework/schema/citrus-jms-config-4.1.0.xsd http\://www.citrusframework.org/schema/jms/config/citrus-jms-config-4.1.1.xsd=org/citrusframework/schema/citrus-jms-config-4.1.1.xsd -http\://www.citrusframework.org/schema/jms/config/citrus-jms-config-4.3.0-SNAPSHOT.xsd=org/citrusframework/schema/citrus-jms-config-4.3.0-SNAPSHOT.xsd http\://www.citrusframework.org/schema/jms/config/citrus-jms-config-4.2.0.xsd=org/citrusframework/schema/citrus-jms-config-4.2.0.xsd +http\://www.citrusframework.org/schema/jms/config/citrus-jms-config-4.2.1.xsd=org/citrusframework/schema/citrus-jms-config-4.2.1.xsd +http\://www.citrusframework.org/schema/jms/config/citrus-jms-config-4.3.0-SNAPSHOT.xsd=org/citrusframework/schema/citrus-jms-config-4.3.0-SNAPSHOT.xsd http\://www.citrusframework.org/schema/jms/config/citrus-jms-config.xsd=org/citrusframework/schema/citrus-jms-config.xsd http\://www.citrusframework.org/schema/jms/testcase/citrus-jms-testcase-2.0.xsd=com/consol/citrus/schema/citrus-jms-testcase-2.0.xsd http\://www.citrusframework.org/schema/jms/testcase/citrus-jms-testcase-2.1.xsd=com/consol/citrus/schema/citrus-jms-testcase-2.1.xsd @@ -81,6 +82,7 @@ http\://www.citrusframework.org/schema/jms/testcase/citrus-jms-testcase-4.0.1.xs http\://www.citrusframework.org/schema/jms/testcase/citrus-jms-testcase-4.0.2.xsd=org/citrusframework/schema/citrus-jms-testcase-4.0.2.xsd http\://www.citrusframework.org/schema/jms/testcase/citrus-jms-testcase-4.1.0.xsd=org/citrusframework/schema/citrus-jms-testcase-4.1.0.xsd http\://www.citrusframework.org/schema/jms/testcase/citrus-jms-testcase-4.1.1.xsd=org/citrusframework/schema/citrus-jms-testcase-4.1.1.xsd -http\://www.citrusframework.org/schema/jms/testcase/citrus-jms-testcase-4.3.0-SNAPSHOT.xsd=org/citrusframework/schema/citrus-jms-testcase-4.3.0-SNAPSHOT.xsd http\://www.citrusframework.org/schema/jms/testcase/citrus-jms-testcase-4.2.0.xsd=org/citrusframework/schema/citrus-jms-testcase-4.2.0.xsd +http\://www.citrusframework.org/schema/jms/testcase/citrus-jms-testcase-4.2.1.xsd=org/citrusframework/schema/citrus-jms-testcase-4.2.1.xsd +http\://www.citrusframework.org/schema/jms/testcase/citrus-jms-testcase-4.3.0-SNAPSHOT.xsd=org/citrusframework/schema/citrus-jms-testcase-4.3.0-SNAPSHOT.xsd http\://www.citrusframework.org/schema/jms/testcase/citrus-jms-testcase.xsd=org/citrusframework/schema/citrus-jms-testcase.xsd diff --git a/endpoints/citrus-jmx/src/main/resources/META-INF/spring.schemas b/endpoints/citrus-jmx/src/main/resources/META-INF/spring.schemas index d559be3ae6..4e7a4dc114 100644 --- a/endpoints/citrus-jmx/src/main/resources/META-INF/spring.schemas +++ b/endpoints/citrus-jmx/src/main/resources/META-INF/spring.schemas @@ -33,8 +33,9 @@ http\://www.citrusframework.org/schema/jmx/config/citrus-jmx-config-4.0.1.xsd=or http\://www.citrusframework.org/schema/jmx/config/citrus-jmx-config-4.0.2.xsd=org/citrusframework/schema/citrus-jmx-config-4.0.2.xsd http\://www.citrusframework.org/schema/jmx/config/citrus-jmx-config-4.1.0.xsd=org/citrusframework/schema/citrus-jmx-config-4.1.0.xsd http\://www.citrusframework.org/schema/jmx/config/citrus-jmx-config-4.1.1.xsd=org/citrusframework/schema/citrus-jmx-config-4.1.1.xsd -http\://www.citrusframework.org/schema/jmx/config/citrus-jmx-config-4.3.0-SNAPSHOT.xsd=org/citrusframework/schema/citrus-jmx-config-4.3.0-SNAPSHOT.xsd http\://www.citrusframework.org/schema/jmx/config/citrus-jmx-config-4.2.0.xsd=org/citrusframework/schema/citrus-jmx-config-4.2.0.xsd +http\://www.citrusframework.org/schema/jmx/config/citrus-jmx-config-4.2.1.xsd=org/citrusframework/schema/citrus-jmx-config-4.2.1.xsd +http\://www.citrusframework.org/schema/jmx/config/citrus-jmx-config-4.3.0-SNAPSHOT.xsd=org/citrusframework/schema/citrus-jmx-config-4.3.0-SNAPSHOT.xsd http\://www.citrusframework.org/schema/jmx/config/citrus-jmx-config.xsd=org/citrusframework/schema/citrus-jmx-config.xsd http\://www.citrusframework.org/schema/jmx/testcase/citrus-jmx-testcase-2.5.1.xsd=com/consol/citrus/schema/citrus-jmx-testcase-2.5.1.xsd http\://www.citrusframework.org/schema/jmx/testcase/citrus-jmx-testcase-2.5.2.xsd=com/consol/citrus/schema/citrus-jmx-testcase-2.5.2.xsd @@ -71,6 +72,7 @@ http\://www.citrusframework.org/schema/jmx/testcase/citrus-jmx-testcase-4.0.1.xs http\://www.citrusframework.org/schema/jmx/testcase/citrus-jmx-testcase-4.0.2.xsd=org/citrusframework/schema/citrus-jmx-testcase-4.0.2.xsd http\://www.citrusframework.org/schema/jmx/testcase/citrus-jmx-testcase-4.1.0.xsd=org/citrusframework/schema/citrus-jmx-testcase-4.1.0.xsd http\://www.citrusframework.org/schema/jmx/testcase/citrus-jmx-testcase-4.1.1.xsd=org/citrusframework/schema/citrus-jmx-testcase-4.1.1.xsd -http\://www.citrusframework.org/schema/jmx/testcase/citrus-jmx-testcase-4.3.0-SNAPSHOT.xsd=org/citrusframework/schema/citrus-jmx-testcase-4.3.0-SNAPSHOT.xsd http\://www.citrusframework.org/schema/jmx/testcase/citrus-jmx-testcase-4.2.0.xsd=org/citrusframework/schema/citrus-jmx-testcase-4.2.0.xsd +http\://www.citrusframework.org/schema/jmx/testcase/citrus-jmx-testcase-4.2.1.xsd=org/citrusframework/schema/citrus-jmx-testcase-4.2.1.xsd +http\://www.citrusframework.org/schema/jmx/testcase/citrus-jmx-testcase-4.3.0-SNAPSHOT.xsd=org/citrusframework/schema/citrus-jmx-testcase-4.3.0-SNAPSHOT.xsd http\://www.citrusframework.org/schema/jmx/testcase/citrus-jmx-testcase.xsd=org/citrusframework/schema/citrus-jmx-testcase.xsd diff --git a/endpoints/citrus-kafka/src/main/resources/META-INF/spring.schemas b/endpoints/citrus-kafka/src/main/resources/META-INF/spring.schemas index dee5749f78..ea8db3adff 100644 --- a/endpoints/citrus-kafka/src/main/resources/META-INF/spring.schemas +++ b/endpoints/citrus-kafka/src/main/resources/META-INF/spring.schemas @@ -34,8 +34,9 @@ http\://www.citrusframework.org/schema/kafka/config/citrus-kafka-config-4.0.1.xs http\://www.citrusframework.org/schema/kafka/config/citrus-kafka-config-4.0.2.xsd=org/citrusframework/schema/citrus-kafka-config-4.0.2.xsd http\://www.citrusframework.org/schema/kafka/config/citrus-kafka-config-4.1.0.xsd=org/citrusframework/schema/citrus-kafka-config-4.1.0.xsd http\://www.citrusframework.org/schema/kafka/config/citrus-kafka-config-4.1.1.xsd=org/citrusframework/schema/citrus-kafka-config-4.1.1.xsd -http\://www.citrusframework.org/schema/kafka/config/citrus-kafka-config-4.3.0-SNAPSHOT.xsd=org/citrusframework/schema/citrus-kafka-config-4.3.0-SNAPSHOT.xsd http\://www.citrusframework.org/schema/kafka/config/citrus-kafka-config-4.2.0.xsd=org/citrusframework/schema/citrus-kafka-config-4.2.0.xsd +http\://www.citrusframework.org/schema/kafka/config/citrus-kafka-config-4.2.1.xsd=org/citrusframework/schema/citrus-kafka-config-4.2.1.xsd +http\://www.citrusframework.org/schema/kafka/config/citrus-kafka-config-4.3.0-SNAPSHOT.xsd=org/citrusframework/schema/citrus-kafka-config-4.3.0-SNAPSHOT.xsd http\://www.citrusframework.org/schema/kafka/config/citrus-kafka-config.xsd=org/citrusframework/schema/citrus-kafka-config.xsd http\://www.citrusframework.org/schema/kafka/testcase/citrus-kafka-testcase-2.8.0.xsd=com/consol/citrus/schema/citrus-kafka-testcase-2.8.0.xsd http\://www.citrusframework.org/schema/kafka/testcase/citrus-kafka-testcase-3.0.0-M1.xsd=com/consol/citrus/schema/citrus-kafka-testcase-3.0.0-M1.xsd @@ -57,6 +58,7 @@ http\://www.citrusframework.org/schema/kafka/testcase/citrus-kafka-testcase-4.0. http\://www.citrusframework.org/schema/kafka/testcase/citrus-kafka-testcase-4.0.2.xsd=org/citrusframework/schema/citrus-kafka-testcase-4.0.2.xsd http\://www.citrusframework.org/schema/kafka/testcase/citrus-kafka-testcase-4.1.0.xsd=org/citrusframework/schema/citrus-kafka-testcase-4.1.0.xsd http\://www.citrusframework.org/schema/kafka/testcase/citrus-kafka-testcase-4.1.1.xsd=org/citrusframework/schema/citrus-kafka-testcase-4.1.1.xsd -http\://www.citrusframework.org/schema/kafka/testcase/citrus-kafka-testcase-4.3.0-SNAPSHOT.xsd=org/citrusframework/schema/citrus-kafka-testcase-4.3.0-SNAPSHOT.xsd http\://www.citrusframework.org/schema/kafka/testcase/citrus-kafka-testcase-4.2.0.xsd=org/citrusframework/schema/citrus-kafka-testcase-4.2.0.xsd +http\://www.citrusframework.org/schema/kafka/testcase/citrus-kafka-testcase-4.2.1.xsd=org/citrusframework/schema/citrus-kafka-testcase-4.2.1.xsd +http\://www.citrusframework.org/schema/kafka/testcase/citrus-kafka-testcase-4.3.0-SNAPSHOT.xsd=org/citrusframework/schema/citrus-kafka-testcase-4.3.0-SNAPSHOT.xsd http\://www.citrusframework.org/schema/kafka/testcase/citrus-kafka-testcase.xsd=org/citrusframework/schema/citrus-kafka-testcase.xsd diff --git a/endpoints/citrus-mail/src/main/resources/META-INF/spring.schemas b/endpoints/citrus-mail/src/main/resources/META-INF/spring.schemas index b69c79d048..d5424d9380 100644 --- a/endpoints/citrus-mail/src/main/resources/META-INF/spring.schemas +++ b/endpoints/citrus-mail/src/main/resources/META-INF/spring.schemas @@ -40,6 +40,7 @@ http\://www.citrusframework.org/schema/mail/config/citrus-mail-config-4.0.1.xsd= http\://www.citrusframework.org/schema/mail/config/citrus-mail-config-4.0.2.xsd=org/citrusframework/schema/citrus-mail-config-4.0.2.xsd http\://www.citrusframework.org/schema/mail/config/citrus-mail-config-4.1.0.xsd=org/citrusframework/schema/citrus-mail-config-4.1.0.xsd http\://www.citrusframework.org/schema/mail/config/citrus-mail-config-4.1.1.xsd=org/citrusframework/schema/citrus-mail-config-4.1.1.xsd -http\://www.citrusframework.org/schema/mail/config/citrus-mail-config-4.3.0-SNAPSHOT.xsd=org/citrusframework/schema/citrus-mail-config-4.3.0-SNAPSHOT.xsd http\://www.citrusframework.org/schema/mail/config/citrus-mail-config-4.2.0.xsd=org/citrusframework/schema/citrus-mail-config-4.2.0.xsd +http\://www.citrusframework.org/schema/mail/config/citrus-mail-config-4.2.1.xsd=org/citrusframework/schema/citrus-mail-config-4.2.1.xsd +http\://www.citrusframework.org/schema/mail/config/citrus-mail-config-4.3.0-SNAPSHOT.xsd=org/citrusframework/schema/citrus-mail-config-4.3.0-SNAPSHOT.xsd http\://www.citrusframework.org/schema/mail/config/citrus-mail-config.xsd=org/citrusframework/schema/citrus-mail-config.xsd diff --git a/endpoints/citrus-rmi/src/main/resources/META-INF/spring.schemas b/endpoints/citrus-rmi/src/main/resources/META-INF/spring.schemas index 426147e56f..b9e50f7a02 100644 --- a/endpoints/citrus-rmi/src/main/resources/META-INF/spring.schemas +++ b/endpoints/citrus-rmi/src/main/resources/META-INF/spring.schemas @@ -33,6 +33,7 @@ http\://www.citrusframework.org/schema/rmi/config/citrus-rmi-config-4.0.1.xsd=or http\://www.citrusframework.org/schema/rmi/config/citrus-rmi-config-4.0.2.xsd=org/citrusframework/schema/citrus-rmi-config-4.0.2.xsd http\://www.citrusframework.org/schema/rmi/config/citrus-rmi-config-4.1.0.xsd=org/citrusframework/schema/citrus-rmi-config-4.1.0.xsd http\://www.citrusframework.org/schema/rmi/config/citrus-rmi-config-4.1.1.xsd=org/citrusframework/schema/citrus-rmi-config-4.1.1.xsd -http\://www.citrusframework.org/schema/rmi/config/citrus-rmi-config-4.3.0-SNAPSHOT.xsd=org/citrusframework/schema/citrus-rmi-config-4.3.0-SNAPSHOT.xsd http\://www.citrusframework.org/schema/rmi/config/citrus-rmi-config-4.2.0.xsd=org/citrusframework/schema/citrus-rmi-config-4.2.0.xsd +http\://www.citrusframework.org/schema/rmi/config/citrus-rmi-config-4.2.1.xsd=org/citrusframework/schema/citrus-rmi-config-4.2.1.xsd +http\://www.citrusframework.org/schema/rmi/config/citrus-rmi-config-4.3.0-SNAPSHOT.xsd=org/citrusframework/schema/citrus-rmi-config-4.3.0-SNAPSHOT.xsd http\://www.citrusframework.org/schema/rmi/config/citrus-rmi-config.xsd=org/citrusframework/schema/citrus-rmi-config.xsd diff --git a/endpoints/citrus-spring-integration/src/main/resources/META-INF/spring.schemas b/endpoints/citrus-spring-integration/src/main/resources/META-INF/spring.schemas index 3bc1038461..3e725ba070 100644 --- a/endpoints/citrus-spring-integration/src/main/resources/META-INF/spring.schemas +++ b/endpoints/citrus-spring-integration/src/main/resources/META-INF/spring.schemas @@ -17,8 +17,9 @@ http\://www.citrusframework.org/schema/spring-integration/config/citrus-spring-i http\://www.citrusframework.org/schema/spring-integration/config/citrus-spring-integration-config-4.0.2.xsd=org/citrusframework/schema/citrus-spring-integration-config-4.0.2.xsd http\://www.citrusframework.org/schema/spring-integration/config/citrus-spring-integration-config-4.1.0.xsd=org/citrusframework/schema/citrus-spring-integration-config-4.1.0.xsd http\://www.citrusframework.org/schema/spring-integration/config/citrus-spring-integration-config-4.1.1.xsd=org/citrusframework/schema/citrus-spring-integration-config-4.1.1.xsd -http\://www.citrusframework.org/schema/spring-integration/config/citrus-spring-integration-config-4.3.0-SNAPSHOT.xsd=org/citrusframework/schema/citrus-spring-integration-config-4.3.0-SNAPSHOT.xsd http\://www.citrusframework.org/schema/spring-integration/config/citrus-spring-integration-config-4.2.0.xsd=org/citrusframework/schema/citrus-spring-integration-config-4.2.0.xsd +http\://www.citrusframework.org/schema/spring-integration/config/citrus-spring-integration-config-4.2.1.xsd=org/citrusframework/schema/citrus-spring-integration-config-4.2.1.xsd +http\://www.citrusframework.org/schema/spring-integration/config/citrus-spring-integration-config-4.3.0-SNAPSHOT.xsd=org/citrusframework/schema/citrus-spring-integration-config-4.3.0-SNAPSHOT.xsd http\://www.citrusframework.org/schema/spring-integration/config/citrus-spring-integration-config.xsd=org/citrusframework/schema/citrus-spring-integration-config.xsd http\://www.citrusframework.org/schema/spring-integration/testcase/citrus-spring-integration-testcase-3.0.0-M1.xsd=com/consol/citrus/schema/citrus-spring-integration-testcase-3.0.0-M1.xsd http\://www.citrusframework.org/schema/spring-integration/testcase/citrus-spring-integration-testcase-3.0.0-M2.xsd=com/consol/citrus/schema/citrus-spring-integration-testcase-3.0.0-M2.xsd @@ -39,6 +40,7 @@ http\://www.citrusframework.org/schema/spring-integration/testcase/citrus-spring http\://www.citrusframework.org/schema/spring-integration/testcase/citrus-spring-integration-testcase-4.0.2.xsd=org/citrusframework/schema/citrus-spring-integration-testcase-4.0.2.xsd http\://www.citrusframework.org/schema/spring-integration/testcase/citrus-spring-integration-testcase-4.1.0.xsd=org/citrusframework/schema/citrus-spring-integration-testcase-4.1.0.xsd http\://www.citrusframework.org/schema/spring-integration/testcase/citrus-spring-integration-testcase-4.1.1.xsd=org/citrusframework/schema/citrus-spring-integration-testcase-4.1.1.xsd -http\://www.citrusframework.org/schema/spring-integration/testcase/citrus-spring-integration-testcase-4.3.0-SNAPSHOT.xsd=org/citrusframework/schema/citrus-spring-integration-testcase-4.3.0-SNAPSHOT.xsd http\://www.citrusframework.org/schema/spring-integration/testcase/citrus-spring-integration-testcase-4.2.0.xsd=org/citrusframework/schema/citrus-spring-integration-testcase-4.2.0.xsd +http\://www.citrusframework.org/schema/spring-integration/testcase/citrus-spring-integration-testcase-4.2.1.xsd=org/citrusframework/schema/citrus-spring-integration-testcase-4.2.1.xsd +http\://www.citrusframework.org/schema/spring-integration/testcase/citrus-spring-integration-testcase-4.3.0-SNAPSHOT.xsd=org/citrusframework/schema/citrus-spring-integration-testcase-4.3.0-SNAPSHOT.xsd http\://www.citrusframework.org/schema/spring-integration/testcase/citrus-spring-integration-testcase.xsd=org/citrusframework/schema/citrus-spring-integration-testcase.xsd diff --git a/endpoints/citrus-ssh/src/main/resources/META-INF/spring.schemas b/endpoints/citrus-ssh/src/main/resources/META-INF/spring.schemas index fc8d09da88..4a80c8c406 100644 --- a/endpoints/citrus-ssh/src/main/resources/META-INF/spring.schemas +++ b/endpoints/citrus-ssh/src/main/resources/META-INF/spring.schemas @@ -42,6 +42,7 @@ http\://www.citrusframework.org/schema/ssh/config/citrus-ssh-config-4.0.1.xsd=or http\://www.citrusframework.org/schema/ssh/config/citrus-ssh-config-4.0.2.xsd=org/citrusframework/schema/citrus-ssh-config-4.0.2.xsd http\://www.citrusframework.org/schema/ssh/config/citrus-ssh-config-4.1.0.xsd=org/citrusframework/schema/citrus-ssh-config-4.1.0.xsd http\://www.citrusframework.org/schema/ssh/config/citrus-ssh-config-4.1.1.xsd=org/citrusframework/schema/citrus-ssh-config-4.1.1.xsd -http\://www.citrusframework.org/schema/ssh/config/citrus-ssh-config-4.3.0-SNAPSHOT.xsd=org/citrusframework/schema/citrus-ssh-config-4.3.0-SNAPSHOT.xsd http\://www.citrusframework.org/schema/ssh/config/citrus-ssh-config-4.2.0.xsd=org/citrusframework/schema/citrus-ssh-config-4.2.0.xsd +http\://www.citrusframework.org/schema/ssh/config/citrus-ssh-config-4.2.1.xsd=org/citrusframework/schema/citrus-ssh-config-4.2.1.xsd +http\://www.citrusframework.org/schema/ssh/config/citrus-ssh-config-4.3.0-SNAPSHOT.xsd=org/citrusframework/schema/citrus-ssh-config-4.3.0-SNAPSHOT.xsd http\://www.citrusframework.org/schema/ssh/config/citrus-ssh-config.xsd=org/citrusframework/schema/citrus-ssh-config.xsd diff --git a/endpoints/citrus-vertx/src/main/resources/META-INF/spring.schemas b/endpoints/citrus-vertx/src/main/resources/META-INF/spring.schemas index 9ef6f1c759..72203d5ee6 100644 --- a/endpoints/citrus-vertx/src/main/resources/META-INF/spring.schemas +++ b/endpoints/citrus-vertx/src/main/resources/META-INF/spring.schemas @@ -40,6 +40,7 @@ http\://www.citrusframework.org/schema/vertx/config/citrus-vertx-config-4.0.1.xs http\://www.citrusframework.org/schema/vertx/config/citrus-vertx-config-4.0.2.xsd=org/citrusframework/schema/citrus-vertx-config-4.0.2.xsd http\://www.citrusframework.org/schema/vertx/config/citrus-vertx-config-4.1.0.xsd=org/citrusframework/schema/citrus-vertx-config-4.1.0.xsd http\://www.citrusframework.org/schema/vertx/config/citrus-vertx-config-4.1.1.xsd=org/citrusframework/schema/citrus-vertx-config-4.1.1.xsd -http\://www.citrusframework.org/schema/vertx/config/citrus-vertx-config-4.3.0-SNAPSHOT.xsd=org/citrusframework/schema/citrus-vertx-config-4.3.0-SNAPSHOT.xsd http\://www.citrusframework.org/schema/vertx/config/citrus-vertx-config-4.2.0.xsd=org/citrusframework/schema/citrus-vertx-config-4.2.0.xsd +http\://www.citrusframework.org/schema/vertx/config/citrus-vertx-config-4.2.1.xsd=org/citrusframework/schema/citrus-vertx-config-4.2.1.xsd +http\://www.citrusframework.org/schema/vertx/config/citrus-vertx-config-4.3.0-SNAPSHOT.xsd=org/citrusframework/schema/citrus-vertx-config-4.3.0-SNAPSHOT.xsd http\://www.citrusframework.org/schema/vertx/config/citrus-vertx-config.xsd=org/citrusframework/schema/citrus-vertx-config.xsd diff --git a/endpoints/citrus-websocket/src/main/resources/META-INF/spring.schemas b/endpoints/citrus-websocket/src/main/resources/META-INF/spring.schemas index 0655a62afa..8c5142d6d1 100644 --- a/endpoints/citrus-websocket/src/main/resources/META-INF/spring.schemas +++ b/endpoints/citrus-websocket/src/main/resources/META-INF/spring.schemas @@ -35,6 +35,7 @@ http\://www.citrusframework.org/schema/websocket/config/citrus-websocket-config- http\://www.citrusframework.org/schema/websocket/config/citrus-websocket-config-4.0.2.xsd=org/citrusframework/schema/citrus-websocket-config-4.0.2.xsd http\://www.citrusframework.org/schema/websocket/config/citrus-websocket-config-4.1.0.xsd=org/citrusframework/schema/citrus-websocket-config-4.1.0.xsd http\://www.citrusframework.org/schema/websocket/config/citrus-websocket-config-4.1.1.xsd=org/citrusframework/schema/citrus-websocket-config-4.1.1.xsd -http\://www.citrusframework.org/schema/websocket/config/citrus-websocket-config-4.3.0-SNAPSHOT.xsd=org/citrusframework/schema/citrus-websocket-config-4.3.0-SNAPSHOT.xsd http\://www.citrusframework.org/schema/websocket/config/citrus-websocket-config-4.2.0.xsd=org/citrusframework/schema/citrus-websocket-config-4.2.0.xsd +http\://www.citrusframework.org/schema/websocket/config/citrus-websocket-config-4.2.1.xsd=org/citrusframework/schema/citrus-websocket-config-4.2.1.xsd +http\://www.citrusframework.org/schema/websocket/config/citrus-websocket-config-4.3.0-SNAPSHOT.xsd=org/citrusframework/schema/citrus-websocket-config-4.3.0-SNAPSHOT.xsd http\://www.citrusframework.org/schema/websocket/config/citrus-websocket-config.xsd=org/citrusframework/schema/citrus-websocket-config.xsd diff --git a/endpoints/citrus-ws/src/main/resources/META-INF/spring.schemas b/endpoints/citrus-ws/src/main/resources/META-INF/spring.schemas index f0a304bd57..0434b1bdb2 100644 --- a/endpoints/citrus-ws/src/main/resources/META-INF/spring.schemas +++ b/endpoints/citrus-ws/src/main/resources/META-INF/spring.schemas @@ -45,8 +45,9 @@ http\://www.citrusframework.org/schema/ws/config/citrus-ws-config-4.0.1.xsd=org/ http\://www.citrusframework.org/schema/ws/config/citrus-ws-config-4.0.2.xsd=org/citrusframework/schema/citrus-ws-config-4.0.2.xsd http\://www.citrusframework.org/schema/ws/config/citrus-ws-config-4.1.0.xsd=org/citrusframework/schema/citrus-ws-config-4.1.0.xsd http\://www.citrusframework.org/schema/ws/config/citrus-ws-config-4.1.1.xsd=org/citrusframework/schema/citrus-ws-config-4.1.1.xsd -http\://www.citrusframework.org/schema/ws/config/citrus-ws-config-4.3.0-SNAPSHOT.xsd=org/citrusframework/schema/citrus-ws-config-4.3.0-SNAPSHOT.xsd http\://www.citrusframework.org/schema/ws/config/citrus-ws-config-4.2.0.xsd=org/citrusframework/schema/citrus-ws-config-4.2.0.xsd +http\://www.citrusframework.org/schema/ws/config/citrus-ws-config-4.2.1.xsd=org/citrusframework/schema/citrus-ws-config-4.2.1.xsd +http\://www.citrusframework.org/schema/ws/config/citrus-ws-config-4.3.0-SNAPSHOT.xsd=org/citrusframework/schema/citrus-ws-config-4.3.0-SNAPSHOT.xsd http\://www.citrusframework.org/schema/ws/config/citrus-ws-config.xsd=org/citrusframework/schema/citrus-ws-config.xsd http\://www.citrusframework.org/schema/ws/testcase/citrus-ws-testcase-1.1.xsd=com/consol/citrus/schema/citrus-ws-testcase-1.1.xsd http\://www.citrusframework.org/schema/ws/testcase/citrus-ws-testcase-1.2.xsd=com/consol/citrus/schema/citrus-ws-testcase-1.2.xsd @@ -94,6 +95,7 @@ http\://www.citrusframework.org/schema/ws/testcase/citrus-ws-testcase-4.0.1.xsd= http\://www.citrusframework.org/schema/ws/testcase/citrus-ws-testcase-4.0.2.xsd=org/citrusframework/schema/citrus-ws-testcase-4.0.2.xsd http\://www.citrusframework.org/schema/ws/testcase/citrus-ws-testcase-4.1.0.xsd=org/citrusframework/schema/citrus-ws-testcase-4.1.0.xsd http\://www.citrusframework.org/schema/ws/testcase/citrus-ws-testcase-4.1.1.xsd=org/citrusframework/schema/citrus-ws-testcase-4.1.1.xsd -http\://www.citrusframework.org/schema/ws/testcase/citrus-ws-testcase-4.3.0-SNAPSHOT.xsd=org/citrusframework/schema/citrus-ws-testcase-4.3.0-SNAPSHOT.xsd http\://www.citrusframework.org/schema/ws/testcase/citrus-ws-testcase-4.2.0.xsd=org/citrusframework/schema/citrus-ws-testcase-4.2.0.xsd +http\://www.citrusframework.org/schema/ws/testcase/citrus-ws-testcase-4.2.1.xsd=org/citrusframework/schema/citrus-ws-testcase-4.2.1.xsd +http\://www.citrusframework.org/schema/ws/testcase/citrus-ws-testcase-4.3.0-SNAPSHOT.xsd=org/citrusframework/schema/citrus-ws-testcase-4.3.0-SNAPSHOT.xsd http\://www.citrusframework.org/schema/ws/testcase/citrus-ws-testcase.xsd=org/citrusframework/schema/citrus-ws-testcase.xsd diff --git a/endpoints/citrus-zookeeper/src/main/resources/META-INF/spring.schemas b/endpoints/citrus-zookeeper/src/main/resources/META-INF/spring.schemas index baf1e75588..bc1aa89523 100644 --- a/endpoints/citrus-zookeeper/src/main/resources/META-INF/spring.schemas +++ b/endpoints/citrus-zookeeper/src/main/resources/META-INF/spring.schemas @@ -30,8 +30,9 @@ http\://www.citrusframework.org/schema/zookeeper/config/citrus-zookeeper-config- http\://www.citrusframework.org/schema/zookeeper/config/citrus-zookeeper-config-4.0.2.xsd=org/citrusframework/schema/citrus-zookeeper-config-4.0.2.xsd http\://www.citrusframework.org/schema/zookeeper/config/citrus-zookeeper-config-4.1.0.xsd=org/citrusframework/schema/citrus-zookeeper-config-4.1.0.xsd http\://www.citrusframework.org/schema/zookeeper/config/citrus-zookeeper-config-4.1.1.xsd=org/citrusframework/schema/citrus-zookeeper-config-4.1.1.xsd -http\://www.citrusframework.org/schema/zookeeper/config/citrus-zookeeper-config-4.3.0-SNAPSHOT.xsd=org/citrusframework/schema/citrus-zookeeper-config-4.3.0-SNAPSHOT.xsd http\://www.citrusframework.org/schema/zookeeper/config/citrus-zookeeper-config-4.2.0.xsd=org/citrusframework/schema/citrus-zookeeper-config-4.2.0.xsd +http\://www.citrusframework.org/schema/zookeeper/config/citrus-zookeeper-config-4.2.1.xsd=org/citrusframework/schema/citrus-zookeeper-config-4.2.1.xsd +http\://www.citrusframework.org/schema/zookeeper/config/citrus-zookeeper-config-4.3.0-SNAPSHOT.xsd=org/citrusframework/schema/citrus-zookeeper-config-4.3.0-SNAPSHOT.xsd http\://www.citrusframework.org/schema/zookeeper/config/citrus-zookeeper-config.xsd=org/citrusframework/schema/citrus-zookeeper-config.xsd http\://www.citrusframework.org/schema/zookeeper/testcase/citrus-zookeeper-testcase-2.6.1.xsd=com/consol/citrus/schema/citrus-zookeeper-testcase-2.6.1.xsd http\://www.citrusframework.org/schema/zookeeper/testcase/citrus-zookeeper-testcase-2.6.2.xsd=com/consol/citrus/schema/citrus-zookeeper-testcase-2.6.2.xsd @@ -65,6 +66,7 @@ http\://www.citrusframework.org/schema/zookeeper/testcase/citrus-zookeeper-testc http\://www.citrusframework.org/schema/zookeeper/testcase/citrus-zookeeper-testcase-4.0.2.xsd=org/citrusframework/schema/citrus-zookeeper-testcase-4.0.2.xsd http\://www.citrusframework.org/schema/zookeeper/testcase/citrus-zookeeper-testcase-4.1.0.xsd=org/citrusframework/schema/citrus-zookeeper-testcase-4.1.0.xsd http\://www.citrusframework.org/schema/zookeeper/testcase/citrus-zookeeper-testcase-4.1.1.xsd=org/citrusframework/schema/citrus-zookeeper-testcase-4.1.1.xsd -http\://www.citrusframework.org/schema/zookeeper/testcase/citrus-zookeeper-testcase-4.3.0-SNAPSHOT.xsd=org/citrusframework/schema/citrus-zookeeper-testcase-4.3.0-SNAPSHOT.xsd http\://www.citrusframework.org/schema/zookeeper/testcase/citrus-zookeeper-testcase-4.2.0.xsd=org/citrusframework/schema/citrus-zookeeper-testcase-4.2.0.xsd +http\://www.citrusframework.org/schema/zookeeper/testcase/citrus-zookeeper-testcase-4.2.1.xsd=org/citrusframework/schema/citrus-zookeeper-testcase-4.2.1.xsd +http\://www.citrusframework.org/schema/zookeeper/testcase/citrus-zookeeper-testcase-4.3.0-SNAPSHOT.xsd=org/citrusframework/schema/citrus-zookeeper-testcase-4.3.0-SNAPSHOT.xsd http\://www.citrusframework.org/schema/zookeeper/testcase/citrus-zookeeper-testcase.xsd=org/citrusframework/schema/citrus-zookeeper-testcase.xsd diff --git a/pom.xml b/pom.xml index f60de64b62..c368aabc72 100644 --- a/pom.xml +++ b/pom.xml @@ -50,14 +50,15 @@ + catalog + connectors core - utils - runtime - validation endpoints - connectors + runtime + test-api-generator tools - catalog + utils + validation @@ -174,7 +175,7 @@ 3.5.0 1.6.13 3.9.0 - 3.12.0 + 3.13.1 3.3.0 3.0.1 3.3.1 @@ -188,48 +189,47 @@ 2.2.4 3.1.0 - 2.33.0 + 2.34.0 2.0.2 1.10.14 - 4.5.0 + 4.6.0 1.1.27 1.8.0 3.25.1 - 1.78 - 1.14.13 - 0.1.4 + 1.78.1 + 1.14.17 2.12.0 - 1.6.0 - 1.16.1 + 1.8.0 + 1.17.0 2.16.1 3.14.0 - 1.3.1 - 3.10.0 - 7.16.1 + 1.3.2 + 3.11.1 + 7.18.0 3.3.6 - 4.2.25 + 4.2.26 1.2.0 3.0.21 2.0.1 2.2 4.13.0 5.3.1 - 2.7.2 - 2.17.0 + 2.7.3 + 2.17.1 2.1.3 2.0.1 3.0.0 3.1.0 2.0.3 6.0.0 - 3.0.2 - 2.1.1 + 3.1.0 + 2.2.0 4.0.2 - 3.0.1 + 3.0.2 2.4.1 1.13.0 4.0.5 - 12.0.8 + 12.0.10 2.0.0 0.1.55 2.9.0 @@ -240,34 +240,35 @@ 1.10.2 4.13.2 2.9.1 - 6.12.0 - 6.12.0 + 6.13.0 + 6.13.0 3.7.0 2.22.1 - 5.11.0 - 3.1.0 + 5.12.0 + 3.2.0 4.1.105.Final 4.12.0 - 7.5.0 - 4.7.5 - 3.0.3 - 4.19.1 + 7.5.0 + 4.7.6 + 3.0.4 + 4.21.0 2.0.11 1.1.10.5 2.2 3.2.5 - 6.1.6 - 4.0.10 - 6.2.4 + 6.1.8 + 3.3.1 + 4.0.11 + 6.3.0 3.0.1 2.12.1 1.6.9 2.1.21 - 7.10.1 - 4.5.7 + 7.10.2 + 4.5.8 1.6.3 - 4.24 - 3.0.0 + 4.25 + 5.2.0 2.6.0 2.12.2 1.4.20 @@ -518,7 +519,7 @@ org.openapitools openapi-generator - ${openapi-generator-maven-plugin} + ${org.openapitools.version} provided diff --git a/runtime/citrus-cucumber/src/main/resources/META-INF/spring.schemas b/runtime/citrus-cucumber/src/main/resources/META-INF/spring.schemas index 6f8b9b6481..9e66c0372f 100644 --- a/runtime/citrus-cucumber/src/main/resources/META-INF/spring.schemas +++ b/runtime/citrus-cucumber/src/main/resources/META-INF/spring.schemas @@ -30,6 +30,7 @@ http\://www.citrusframework.org/schema/cucumber/testcase/citrus-cucumber-testcas http\://www.citrusframework.org/schema/cucumber/testcase/citrus-cucumber-testcase-4.0.2.xsd=org/citrusframework/schema/citrus-cucumber-testcase-4.0.2.xsd http\://www.citrusframework.org/schema/cucumber/testcase/citrus-cucumber-testcase-4.1.0.xsd=org/citrusframework/schema/citrus-cucumber-testcase-4.1.0.xsd http\://www.citrusframework.org/schema/cucumber/testcase/citrus-cucumber-testcase-4.1.1.xsd=org/citrusframework/schema/citrus-cucumber-testcase-4.1.1.xsd -http\://www.citrusframework.org/schema/cucumber/testcase/citrus-cucumber-testcase-4.3.0-SNAPSHOT.xsd=org/citrusframework/schema/citrus-cucumber-testcase-4.3.0-SNAPSHOT.xsd http\://www.citrusframework.org/schema/cucumber/testcase/citrus-cucumber-testcase-4.2.0.xsd=org/citrusframework/schema/citrus-cucumber-testcase-4.2.0.xsd +http\://www.citrusframework.org/schema/cucumber/testcase/citrus-cucumber-testcase-4.2.1.xsd=org/citrusframework/schema/citrus-cucumber-testcase-4.2.1.xsd +http\://www.citrusframework.org/schema/cucumber/testcase/citrus-cucumber-testcase-4.3.0-SNAPSHOT.xsd=org/citrusframework/schema/citrus-cucumber-testcase-4.3.0-SNAPSHOT.xsd http\://www.citrusframework.org/schema/cucumber/testcase/citrus-cucumber-testcase.xsd=org/citrusframework/schema/citrus-cucumber-testcase.xsd diff --git a/runtime/citrus-groovy/src/test/java/org/citrusframework/groovy/dsl/container/WaitForTest.java b/runtime/citrus-groovy/src/test/java/org/citrusframework/groovy/dsl/container/WaitForTest.java index 93c89386ca..9ca4d439b3 100644 --- a/runtime/citrus-groovy/src/test/java/org/citrusframework/groovy/dsl/container/WaitForTest.java +++ b/runtime/citrus-groovy/src/test/java/org/citrusframework/groovy/dsl/container/WaitForTest.java @@ -31,11 +31,13 @@ import org.citrusframework.message.DefaultMessageStore; import org.citrusframework.message.MessageStore; import org.testng.Assert; +import org.testng.annotations.Ignore; import org.testng.annotations.Test; /** * @author Christoph Deppisch */ +@Ignore public class WaitForTest extends AbstractGroovyActionDslTest { private static final String DEFAULT_WAIT_TIME = "5000"; diff --git a/runtime/citrus-quarkus/pom.xml b/runtime/citrus-quarkus/pom.xml index 84badea16a..22b89975ae 100644 --- a/runtime/citrus-quarkus/pom.xml +++ b/runtime/citrus-quarkus/pom.xml @@ -15,7 +15,7 @@ pom - 3.8.0 + 3.10.0 diff --git a/runtime/citrus-xml/src/test/java/org/citrusframework/xml/container/WaitForTest.java b/runtime/citrus-xml/src/test/java/org/citrusframework/xml/container/WaitForTest.java index 4962540015..21175d2148 100644 --- a/runtime/citrus-xml/src/test/java/org/citrusframework/xml/container/WaitForTest.java +++ b/runtime/citrus-xml/src/test/java/org/citrusframework/xml/container/WaitForTest.java @@ -31,11 +31,13 @@ import org.citrusframework.xml.XmlTestLoader; import org.citrusframework.xml.actions.AbstractXmlActionTest; import org.testng.Assert; +import org.testng.annotations.Ignore; import org.testng.annotations.Test; /** * @author Christoph Deppisch */ +@Ignore public class WaitForTest extends AbstractXmlActionTest { private static final String DEFAULT_WAIT_TIME = "5000"; diff --git a/runtime/citrus-yaml/src/test/java/org/citrusframework/yaml/container/WaitForTest.java b/runtime/citrus-yaml/src/test/java/org/citrusframework/yaml/container/WaitForTest.java index 898ad27b29..ec398e709e 100644 --- a/runtime/citrus-yaml/src/test/java/org/citrusframework/yaml/container/WaitForTest.java +++ b/runtime/citrus-yaml/src/test/java/org/citrusframework/yaml/container/WaitForTest.java @@ -31,11 +31,13 @@ import org.citrusframework.yaml.YamlTestLoader; import org.citrusframework.yaml.actions.AbstractYamlActionTest; import org.testng.Assert; +import org.testng.annotations.Ignore; import org.testng.annotations.Test; /** * @author Christoph Deppisch */ +@Ignore public class WaitForTest extends AbstractYamlActionTest { private static final String DEFAULT_WAIT_TIME = "5000"; diff --git a/src/manual/connector-openapi.adoc b/src/manual/connector-openapi.adoc index f3f9220ada..382d0c65e8 100644 --- a/src/manual/connector-openapi.adoc +++ b/src/manual/connector-openapi.adoc @@ -334,11 +334,11 @@ The generator provides the following features: * generation of a Test API ** from OpenAPI Specification ** [TODO #1163] from WSDL via an intermediate step that generates a "light" OpenApi specification from a WSDL -* integration into Citrus XML test cases +* integration into <> ** integration into XML editors via generated XSD *** schema validation *** auto completion -* integration into Citrus Java test cases via Java DSL [TODO #1161] +* integration into <> via Java DSL [TODO #1161] The following directory structure/table specifies the files, which are generated by the generator. Note that the `Prefix` is a configuration parameter which should uniquely identify a generated API. @@ -387,9 +387,9 @@ target/ ==== Configuration of Test API generation Code generation is typically performed during the build process. -For the Citrus Test API Generator, it is carried out by a Maven plugin. +For the Citrus Test API Generator, it is carried out by a Maven or Gradle plugin. While the standard generator plugin, `org.openapitools:openapi-generator-maven-plugin`, can be employed for this purpose, configuring it can be cumbersome, especially when dealing with multiple APIs. -To address this challenge, Citrus offers its adaptation of this standard generator Maven plugin. +To address this challenge, Citrus offers its adaptation of this standard generator plugin. This `Citrus OpenAPI Generator Plugin` simplifies the configuration of test API generation by providing predefined defaults and supporting the generation of multiple APIs. Additionally, it enhances support for generating Spring integration files (`spring.handlers` and `spring.schemas`), thereby facilitating the integration of generated APIs into Spring-based applications. Consequently, utilizing the Citrus Generator Plugin is recommended in most scenarios. @@ -535,27 +535,26 @@ The following shows the configuration of test api generation for different scena These are the primary elements you can configure in the `` section: |=== -| Configuration element | Maven Property | Description | Default Value +| Configuration element | Maven Property | Description | Default Value | `schemaFolder` | `citrus.test.api.generator.schema.folder` | Location for the generated XSD schemas | `schema/xsd/%VERSION%` | `resourceFolder` | `citrus.test.api.generator.resource.folder` | Location to which resources are generated | `generated-resources` | `sourceFolder` | `citrus.test.api.generator.source.folder` | Location to which sources are generated | `generated-sources` | `metaInfFolder` | `citrus.test.api.generator.meta.inf.folder` | Location to which spring meta files are generated/updated | `target/generated-test-resources/META-INF` | `generateSpringIntegrationFiles` | `citrus.test.api.generator.generate.spring.integration.files` | Specifies whether spring integration files should be generated | `true` -| Nested api element | | | +| Nested `` element | | | | `prefix` | `citrus.test.api.generator.prefix` | Specifies the prefix used for the test API, typically an acronym | (no default, required) | `source` | `citrus.test.api.generator.source` | Specifies the source of the test API | (no default, required) | `version` | `citrus.test.api.generator.version` | Specifies the version of the API, may be null | (none) | `endpoint` | `citrus.test.api.generator.endpoint` | Specifies the endpoint of the test API | `applicationServiceClient` | `type` | `citrus.test.api.generator.type` | Specifies the type of the test API | `REST`, other option is `SOAP` | `useTags` | `citrus.test.api.generator.use.tags` | Specifies whether tags should be used by the generator | `true` -| `invokerPackage` | `citrus.test.api.generator.invoker.package` | Package for the test API classes | `org.citrusframework.automation.%PREFIX%.%VERSION%` +| `invokerPackage` | `citrus.test.api.generator.invoker.package` | Package for the test API classes | `org.citrusframework.automation.%PREFIX%.%VERSION%` | `apiPackage` | `citrus.test.api.generator.api.package` | Package for the test API interface classes | `org.citrusframework.automation.%PREFIX%.%VERSION%.api` | `modelPackage` | `citrus.test.api.generator.model.package` | Package for the test API model classes | `org.citrusframework.automation.%PREFIX%.%VERSION%.model` -| `targetXmlnsNamespace` | `citrus.test.api.generator.namespace` | XML namespace used by the API | `http://www.citrusframework.org/schema/%VERSION%/%PREFIX%-api` +| `targetXmlnsNamespace` | `citrus.test.api.generator.namespace` | XML namespace used by the API | `http://www.citrusframework.org/schema/%VERSION%/%PREFIX%-api` |=== - Note: `%PREFIX%` and `%VERSION%` are placeholders that will be replaced by their specific values as configured. The plugin performs a conversion to lowercase for `PREFIX` used in package names and in `targetXmlnsNamespace`. @@ -568,7 +567,6 @@ To run the generator, execute the following command in your project directory: mvn citrus-test-api-generator-maven-plugin:create-test-api ---- - This command will generate the classes and XSD files as configured for your APIs in the specified locations. ==== Spring meta file generation @@ -683,7 +681,7 @@ Further examples can be found here `org.citrusframework.openapi.generator.Genera ---- To utilize the test API in Java, it's necessary to import the API configuration, that provides the respective request actions. -The request to test can then be autowired, configured and autowired, as illustrated in the sample below. +The request to test can then be configured and autowired, as illustrated in the sample below. Further examples can be found here `org.citrusframework.openapi.generator.GetPetByIdIT`. .Java DSL diff --git a/src/manual/overview.adoc b/src/manual/overview.adoc index 1d0dc63045..da4adca006 100644 --- a/src/manual/overview.adoc +++ b/src/manual/overview.adoc @@ -15,6 +15,7 @@ hesitate to contact us. Find below the reference documentation for the latest Ci |Latest |link:/citrus/reference/html/index.html[HTML] |link:/citrus/reference/pdf/citrus-reference.pdf[PDF] |4.3.0-SNAPSHOT |link:/citrus/reference/4.3.0-SNAPSHOT/html/index.html[HTML] |link:/citrus/reference/4.3.0-SNAPSHOT/pdf/citrus-reference-4.3.0-SNAPSHOT.pdf[PDF] +|4.2.1 |link:/citrus/reference/4.2.1/html/index.html[HTML] |link:/citrus/reference/4.2.1/pdf/citrus-reference-4.2.1.pdf[PDF] |4.2.0 |link:/citrus/reference/4.2.0/html/index.html[HTML] |link:/citrus/reference/4.2.0/pdf/citrus-reference-4.2.0.pdf[PDF] |4.1.1 |link:/citrus/reference/4.1.1/html/index.html[HTML] |link:/citrus/reference/4.1.1/pdf/citrus-reference-4.1.1.pdf[PDF] |4.1.0 |link:/citrus/reference/4.1.0/html/index.html[HTML] |link:/citrus/reference/4.1.0/pdf/citrus-reference-4.1.0.pdf[PDF] diff --git a/src/manual/validation-json.adoc b/src/manual/validation-json.adoc index bc62d84c82..315c7fe59c 100644 --- a/src/manual/validation-json.adoc +++ b/src/manual/validation-json.adoc @@ -1,16 +1,16 @@ [[json-message-validation]] == Json validation -Message formats such as Json have become very popular, in particular when dealing with RESTful services. Citrus is able to -expect and validate Json messages with a powerful comparison of Json structures. +Message formats such as Json have become very popular, in particular when dealing with RESTful services. +Citrus is able to expect and validate Json messages with a powerful comparison of Json structures. -IMPORTANT: By default, Citrus will use XML message formats when sending and receiving messages. This also reflects to the -message validation logic Citrus uses for incoming messages. So by default Citrus will try to parse the incoming message as -XML DOM element tree. In case we would like to enable Json message validation we have to tell Citrus that we expect a Json -message right now. +IMPORTANT: By default, Citrus will use XML message formats when sending and receiving messages. +This also reflects to the message validation logic Citrus uses for incoming messages. +So by default Citrus will try to parse the incoming message as XML DOM element tree. +In case we would like to enable Json message validation we have to tell Citrus that we expect a Json message right now. -Json message validation is not enabled by default in your project. You need to add the validation module to your project -as a Maven dependency. +Json message validation is not enabled by default in your project. +You need to add the validation module to your project as a Maven dependency. .Json validation module dependency [source,xml] @@ -25,23 +25,25 @@ as a Maven dependency. Citrus provides several default message validator implementations for Json messages: [horizontal] -JsonTextMessageValidator:: Basic Json message validator implementation compares Json objects (expected and received). The -order of Json entries can differ. Tester defines an expected control Json object with test variables and ignored entries. -JsonArray as well as nested JsonObjects are supported, too. -GroovyJsonMessageValidator:: Extended groovy message validator provides specific Json slurper support. With Json slurper -the tester can validate the Json message body with closures for instance. - -IMPORTANT: The Json validator offers two different modes to operate. By default, *strict* mode is enabled and the validator -will also check the exact amount of object fields to match in received and control message. No additional fields in received -Json data structure will be accepted then. In *soft* mode the validator allows additional fields in received Json data structure -so the control Json object can be a partial subset in which case only the control fields are validated. Additional fields in -the received Json data structure are ignored then. - -TIP: The Json validation mode (strict or soft) is settable via environment variable `CITRUS_JSON_MESSAGE_VALIDATION_STRICT` or -system property `citrus.json.message.validation.strict=false`. This will set soft mode to all Json text message validators. - -You can also overwrite these default message validators for Json by placing a bean into the Spring Application context. The -bean uses a default name as identifier. Then your custom bean will overwrite the default validator: +JsonTextMessageValidator:: Basic Json message validator implementation compares Json objects/arrays (expected and received). +- The order of Json object properties can differ, whereas array order is always validated. +- Test variables and ignored-placeholders (`@ignore@`) can be used. +- JsonArray as well as nested JsonObjects are supported. +GroovyJsonMessageValidator:: Extended groovy message validator provides specific Json slurper support. +With Json slurper the tester can validate the Json message body with closures for instance. + +IMPORTANT: The Json validator offers two different modes to operate. +By default, *strict* mode is enabled and the validator will also check the exact amount of entries (object properties / array items) to match in received and control message. +No additional fields in received Json data structure will be accepted. +In *soft* mode the validator allows additional entries (object properties / array items) in received Json, so the control Json can be a subset of the recieved. +Additional entries in the received Json data structure are ignored. + +TIP: The Json validation mode (strict or soft) is settable via environment variable `CITRUS_JSON_MESSAGE_VALIDATION_STRICT` or system property `citrus.json.message.validation.strict=false`. +This will set soft mode to all Json text message validators. + +You can also overwrite these default message validators for Json by placing a bean into the Spring Application context. +The bean uses a default name as identifier. +Then your custom bean will overwrite the default validator: .Java [source,java,indent=0,role="primary"] @@ -77,8 +79,8 @@ public GroovyJsonMessageValidator defaultGroovyJsonMessageValidator() { This is how you can customize the message validators used for Json message data. -When a message has been received in Citrus the message validation will try to find a matching message validator according to -the message content. You can also specify the Json message format on a receive action in order to force Json message validation. +When a message has been received in Citrus the message validation will try to find a matching message validator according to the message content. +You can also specify the Json message format on a receive action in order to force Json message validation. .Java [source,java,indent=0,role="primary"] @@ -115,18 +117,14 @@ receive(someEndpoint) ---- -The message receiving action in our test case specifies a message format type `type="json"` . This tells Citrus to look -for some message validator implementation capable of validating Json messages. As we have added the proper message validator -to the Spring application context Citrus will pick the right validator and Json message validation is performed on this message. - -As you can see you can use test variables as well as ignore element syntax here, too. Citrus is able to handle -different Json element orders when comparing received and expected Json object. We can also use Json arrays and nested objects. -The default Json message validator implementation in Citrus is very powerful in comparing Json objects. +The message receiving action in our test case specifies a message format type `type="json"` . This tells Citrus to look for some message validator implementation capable of validating Json messages. +As we have added the proper message validator to the Spring application context Citrus will pick the right validator and Json message validation is performed on this message. -Instead of defining an expected message body template we can also use Groovy validation scripts. Let's have a look at -the Groovy Json message validator example. As usual the default Groovy Json message validator is active by default. But -the special Groovy message validator implementation will only jump in when we used a validation script in our receive -message definition. Let's have an example for that. +Instead of defining an expected message body template we can also use Groovy validation scripts. +Let's have a look at the Groovy Json message validator example. +As usual the default Groovy Json message validator is active by default. +But the special Groovy message validator implementation will only jump in when we used a validation script in our receive message definition. +Let's have an example for that. .Java [source,java,indent=0,role="primary"] @@ -160,17 +158,19 @@ receive(someEndpoint) ---- -Again the message type tells Citrus that we expect a message of type *json*. The action uses a validation script written -in Groovy to verify the incoming message. Citrus will automatically activate the special message validator that executes -our Groovy script. +Again the message type tells Citrus that we expect a message of type *json*. +The action uses a validation script written in Groovy to verify the incoming message. +Citrus will automatically activate the special message validator that executes our Groovy script. -The script validation is very powerful as we can use the full power of the Groovy language. The validation script automatically -has access to the incoming Json message object *json*. We can use the Groovy Json dot notated syntax in order to navigate -through the Json structure. The Groovy Json slurper object *json* is automatically injected in the validation script. This -way you can access the Json object elements in your code doing some assertions. +The script validation is very powerful as we can use the full power of the Groovy language. +The validation script automatically has access to the incoming Json message object *json*. +We can use the Groovy Json dot notated syntax in order to navigate through the Json structure. +The Groovy Json slurper object *json* is automatically injected in the validation script. +This way you can access the Json object elements in your code doing some assertions. -There is even more object injection for the validation script. With the automatically added object *_receivedMessage_* you -have access to the Citrus message object for this receive action. This enables you to do whatever you want with the message body or header. +There is even more object injection for the validation script. +With the automatically added object *_receivedMessage_* you have access to the Citrus message object for this receive action. +This enables you to do whatever you want with the message body or header. .Java [source,java,indent=0,role="primary"] @@ -201,8 +201,9 @@ receive(someEndpoint) ---- -The listing above shows some power of the validation script. We can access the message body, we can access the message -header. With test context access we can also save the whole message body as a new test variable for later usage in the test. +The listing above shows some power of the validation script. +We can access the message body, we can access the message header. +With test context access we can also save the whole message body as a new test variable for later usage in the test. In general Groovy code inside the XML test case definition or as part of the Java DSL code is not very comfortable to maintain. Neither you do have code syntax assist nor code completion when using inline Groovy scripts. @@ -231,16 +232,15 @@ receive(someEndpoint) ---- -We referenced some external file resource *_validationScript.groovy_* . This file content is loaded at runtime and is used -as script body. Now that we have a normal groovy file we can use the code completion and syntax highlighting of our favorite -Groovy editor. +We referenced some external file resource *_validationScript.groovy_* . This file content is loaded at runtime and is used as script body. +Now that we have a normal groovy file we can use the code completion and syntax highlighting of our favorite Groovy editor. -IMPORTANT: Using several message validator implementations at the same time in the Spring application context is also no -problem. Citrus automatically searches for all available message validators applicable for the given message format and -executes these validators in sequence. This means that multiple message validators can coexist in a Citrus project. +IMPORTANT: Using several message validator implementations at the same time in the Spring application context is also no problem. +Citrus automatically searches for all available message validators applicable for the given message format and executes these validators in sequence. +This means that multiple message validators can coexist in a Citrus project. -Multiple message validators that all apply to the message content format will run in sequence. In case you need to explicitly -choose a message validator implementation you can do so in the receive action: +Multiple message validators that all apply to the message content format will run in sequence. +In case you need to explicitly choose a message validator implementation you can do so in the receive action: .Java [source,java,indent=0,role="primary"] @@ -265,23 +265,24 @@ receive(someEndpoint) ---- -In this example we use the *groovyJsonMessageValidator* explicitly in the receive test action. The message validator -implementation was added as Spring bean with id *groovyJsonMessageValidator* to the Spring application context before. Now -Citrus will only execute the explicit message validator. Other implementations that might also apply are skipped. +In this example we use the *groovyJsonMessageValidator* explicitly in the receive test action. +The message validator implementation was added as Spring bean with id *groovyJsonMessageValidator* to the Spring application context before. +Now Citrus will only execute the explicit message validator. +Other implementations that might also apply are skipped. -TIP: By default, Citrus consolidates all available message validators. You can explicitly pick a special message validator -in the receive message action as shown in the example above. In this case all other validators will not take part in this -special message validation. But be careful: When picking a message validator explicitly you are of course limited to this -message validator capabilities. Validation features of other validators are not valid in this case (e.g. message header -validation, XPath validation, etc.) +TIP: By default, Citrus consolidates all available message validators. +You can explicitly pick a special message validator in the receive message action as shown in the example above. +In this case all other validators will not take part in this special message validation. +But be careful: When picking a message validator explicitly you are of course limited to this message validator capabilities. +Validation features of other validators are not valid in this case (e.g. message header validation, XPath validation, etc.) [[json-ignore-validation]] === Ignore with JsonPath -The next usage scenario for JsonPath expressions in Citrus is the ignoring of elements during message validation. As you -already know Citrus provides powerful validation mechanisms for XML and Json message format. The framework is able to compare -received and expected message contents with powerful validator implementations. You can use a JsonPath expression for ignoring -a very specific entry in the Json object structure. +The next usage scenario for JsonPath expressions in Citrus is the ignoring of elements during message validation. +As you already know Citrus provides powerful validation mechanisms for XML and Json message format. +The framework is able to compare received and expected message contents with powerful validator implementations. +You can use a JsonPath expression for ignoring a very specific entry in the Json object structure. .Java [source,java,indent=0,role="primary"] @@ -342,13 +343,13 @@ receive(someEndpoint) ---- -This time we add JsonPath expressions as ignore statements. This means that we explicitly leave out the evaluated elements -from validation. Obviously this mechanism is a good thing to do when dynamic message data simply is not deterministic such -as timestamps and dynamic identifiers. In the example above we explicitly skip the *token* entry and all *lastLogin* values -that are obviously timestamp values in milliseconds. +This time we add JsonPath expressions as ignore statements. +This means that we explicitly leave out the evaluated elements from validation. +Obviously this mechanism is a good thing to do when dynamic message data simply is not deterministic such as timestamps and dynamic identifiers. +In the example above we explicitly skip the *token* entry and all *lastLogin* values that are obviously timestamp values in milliseconds. -The JsonPath evaluation is very powerful when it comes to select a set of Json objects and elements. This is how we can ignore -several elements with one single JsonPath expression which is very powerful. +The JsonPath evaluation is very powerful when it comes to select a set of Json objects and elements. +This is how we can ignore several elements with one single JsonPath expression which is very powerful. [[json-path-validation]] === JsonPath validation @@ -402,24 +403,26 @@ receive(someEndpoint) .validate(jsonPath().expressions(validationMap)); ---- -The above JsonPath expressions will be evaluated when Citrus validates the received message. The expression result is compared -to the expected value where expectations can be static values as well as test variables and validation matcher expressions. +The above JsonPath expressions will be evaluated when Citrus validates the received message. +The expression result is compared to the expected value where expectations can be static values as well as test variables and validation matcher expressions. In case a JsonPath expression should not be able to find any elements the test case will also fail. -Json is a pretty simple yet powerful message format. Simply put, a Json message just knows JsonObject, JsonArray and JsonValue -items. The handling of JsonObject and JsonValue items in JsonPath expressions is straight forward. We just use a dot notated -syntax for walking through the JsonObject hierarchy. The handling of JsonArray items is also not very difficult either. Citrus -will try the best to convert JsonArray items to String representation values for comparison. +Json is a pretty simple yet powerful message format. +Simply put, a Json message just knows JsonObject, JsonArray and JsonValue items. +The handling of JsonObject and JsonValue items in JsonPath expressions is straight forward. +We just use a dot notated syntax for walking through the JsonObject hierarchy. +The handling of JsonArray items is also not very difficult either. +Citrus will try the best to convert JsonArray items to String representation values for comparison. -IMPORTANT: JsonPath expressions will only work on Json message formats. This is why we have to tell Citrus the correct message -format. By default, Citrus is working with XML message data and therefore the XML validation mechanisms do apply by default. -With the message type attribute set to *json* we make sure that Citrus enables Json specific features on the message validation -such as JsonPath support. +IMPORTANT: JsonPath expressions will only work on Json message formats. +This is why we have to tell Citrus the correct message format. +By default, Citrus is working with XML message data and therefore the XML validation mechanisms do apply by default. +With the message type attribute set to *json* we make sure that Citrus enables Json specific features on the message validation such as JsonPath support. -Now let's get a bit more complex with validation matchers and Json object functions. Citrus tries to give you the most comfortable -validation capabilities when comparing Json object values and Json arrays. One first thing you can use is object functions -like *keySet()* or *size()* . This functionality is not covered by JsonPath out of the box but added by Citrus. See the following -example on how to use it: +Now let's get a bit more complex with validation matchers and Json object functions. +Citrus tries to give you the most comfortable validation capabilities when comparing Json object values and Json arrays. +One first thing you can use is object functions like *keySet()* or *size()* . This functionality is not covered by JsonPath out of the box but added by Citrus. +See the following example on how to use it: .Java [source,java,indent=0,role="primary"] @@ -445,11 +448,11 @@ receive(someEndpoint) ---- -The object functions do return special Json object related properties such as the set of *keys* for an object or the size -of a Json array. +The object functions do return special Json object related properties such as the set of *keys* for an object or the size of a Json array. -Now let's get even more comfortable validation capabilities with matchers. Citrus supports Hamcrest matchers which gives -us a very powerful way of validating Json object elements and arrays. See the following examples that demonstrate how this works: +Now let's get even more comfortable validation capabilities with matchers. +Citrus supports Hamcrest matchers which gives us a very powerful way of validating Json object elements and arrays. +See the following examples that demonstrate how this works: .Java [source,java,indent=0,role="primary"] @@ -475,9 +478,10 @@ receive(someEndpoint) ---- -When using the XML DSL we have to use the *assertThat* validation matcher syntax for defining the Hamcrest matchers. You -can combine matcher implementation as seen in the *allOf(greaterThan(0), lessThan(5))* expression. When using the Java DSL -you can just add the matcher as expected result object. Citrus evaluates the matchers and makes sure everything is as expected. +When using the XML DSL we have to use the *assertThat* validation matcher syntax for defining the Hamcrest matchers. +You can combine matcher implementation as seen in the *allOf(greaterThan(0), lessThan(5))* expression. +When using the Java DSL you can just add the matcher as expected result object. +Citrus evaluates the matchers and makes sure everything is as expected. This is a very powerful validation mechanism as it combines the Hamcrest matcher capabilities with Json message validation. [[json-schema-validation]] @@ -486,8 +490,8 @@ This is a very powerful validation mechanism as it combines the Hamcrest matcher The Json schema validation in Citrus is based on the drafts provided by http://json-schema.org/[json-schema.org]. Because Json schema is a fast evolving project, only Json schema V3 and V4 are currently supported. -IMPORTANT: In contrast to the XML validation, the Json validation is an optional feature. You have to activate it -within every receive-message action by setting `schema-validation="true"` +IMPORTANT: In contrast to the XML validation, the Json validation is an optional feature. +You have to activate it within every receive-message action by setting `schema-validation="true"` .Java [source,java,indent=0,role="primary"] @@ -517,17 +521,17 @@ receive(someEndpoint) ---- -Json schema validation in Citrus is optional and disabled by default. This is why the action required to explicitly enable -the schema validation with `schemaValidation(true)`. The schema references a bean in the Citrus context (e.g. a Spring bean in -the application context). Read more about how to declare schemas in link:#schema-definition[schema validation]. +Json schema validation in Citrus is optional and disabled by default. +This is why the action required to explicitly enable the schema validation with `schemaValidation(true)`. +The schema references a bean in the Citrus context (e.g. a Spring bean in the application context). +Read more about how to declare schemas in link:#schema-definition[schema validation]. -We encourage you to add Json schema validation to your test cases as soon as possible, because we think that message validation -is an important part of integration testing. +We encourage you to add Json schema validation to your test cases as soon as possible, because we think that message validation is an important part of integration testing. === Json schema repositories -Because Citrus supports different types of schema repositories, it is necessary to declare a Json schema repository -as `type="json"`. This allows Citrus to collect all Json schema files for the message validation. +Because Citrus supports different types of schema repositories, it is necessary to declare a Json schema repository as `type="json"`. +This allows Citrus to collect all Json schema files for the message validation. .Java [source,java,indent=0,role="primary"] @@ -570,9 +574,8 @@ public SimpleJsonSchema productSchema() { === Json schema filtering and validation strategy -In reference to the current Json schema definition, it is not possible to create a direct reference between a Json -message and a set of schemas, as it would be possible with XML namespaces. Because of that, Citrus follows a rule set -for choosing the relevant schemas based on the configuration within the test case in relation to the given context. +In reference to the current Json schema definition, it is not possible to create a direct reference between a Json message and a set of schemas, as it would be possible with XML namespaces. +Because of that, Citrus follows a rule set for choosing the relevant schemas based on the configuration within the test case in relation to the given context. The following table assumes that the Json schema validation is activated for the test action. |=== diff --git a/test-api-generator/citrus-test-api-generator-core/pom.xml b/test-api-generator/citrus-test-api-generator-core/pom.xml index 224c53c55a..c00b9f1ce9 100644 --- a/test-api-generator/citrus-test-api-generator-core/pom.xml +++ b/test-api-generator/citrus-test-api-generator-core/pom.xml @@ -41,6 +41,12 @@ ${project.version} + + org.assertj + assertj-core + ${assertj.version} + test + com.fasterxml.jackson.dataformat jackson-dataformat-yaml @@ -48,6 +54,7 @@ org.openapitools openapi-generator + ${org.openapitools.version} wsdl4j @@ -74,20 +81,9 @@ test - org.junit.jupiter - junit-jupiter - test - - - org.citrusframework - citrus-openapi - ${project.version} - test - - - org.assertj - assertj-core - ${assertj.version} + org.springframework.boot + spring-boot-test + ${spring.boot.version} test @@ -132,6 +128,7 @@ org.openapitools openapi-generator-maven-plugin + ${org.openapitools.version} org.citrusframework diff --git a/test-api-generator/citrus-test-api-generator-core/src/main/java/org/citrusframework/openapi/generator/JavaCitrusCodegen.java b/test-api-generator/citrus-test-api-generator-core/src/main/java/org/citrusframework/openapi/generator/JavaCitrusCodegen.java index a1c0de6e4c..5228157320 100644 --- a/test-api-generator/citrus-test-api-generator-core/src/main/java/org/citrusframework/openapi/generator/JavaCitrusCodegen.java +++ b/test-api-generator/citrus-test-api-generator-core/src/main/java/org/citrusframework/openapi/generator/JavaCitrusCodegen.java @@ -16,6 +16,7 @@ package org.citrusframework.openapi.generator; +import static java.lang.String.format; import static java.util.Arrays.asList; import static java.util.stream.Collectors.toMap; import static org.openapitools.codegen.CliOption.newString; @@ -27,12 +28,16 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Set; +import lombok.Getter; +import lombok.Setter; import org.openapitools.codegen.CodegenType; import org.openapitools.codegen.SupportingFile; import org.openapitools.codegen.languages.AbstractJavaCodegen; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +@Getter +@Setter public class JavaCitrusCodegen extends AbstractJavaCodegen { private static final Logger logger = LoggerFactory.getLogger(JavaCitrusCodegen.class); @@ -68,6 +73,7 @@ public class JavaCitrusCodegen extends AbstractJavaCodegen { public JavaCitrusCodegen() { super(); + // the root folder where all files are emitted outputFolder = "generated-code" + File.separator + "java"; @@ -108,8 +114,9 @@ public JavaCitrusCodegen() { ); setReservedWordsLowerCase(new ArrayList<>(reservedWordsTemp)); - // add posibility to set a new value for the properties - cliOptions.add(newString(API_ENDPOINT, + // add possibility to set a new value for the properties + cliOptions.add( + newString(API_ENDPOINT, "Which http client should be used (default " + httpClient + ").")); cliOptions.add( newString( @@ -121,9 +128,11 @@ public JavaCitrusCodegen() { newString(GENERATED_SCHEMA_FOLDER, "The schema output directory (default " + generatedSchemaFolder + ").") ); - cliOptions.add(newString(HTTP_PATH_PREFIX, + cliOptions.add( + newString(HTTP_PATH_PREFIX, "Add a prefix to http path for all APIs (default " + httpPathPrefix + ").")); - cliOptions.add(newString(OPENAPI_SCHEMA, + cliOptions.add( + newString(OPENAPI_SCHEMA, "Which OpenAPI schema should be used (default " + openapiSchema + ").")); cliOptions.add( newString( @@ -133,7 +142,8 @@ public JavaCitrusCodegen() { ) ); cliOptions.add(newString(PREFIX, "The api prefix (default " + apiPrefix + ").")); - cliOptions.add(newString(RESOURCE_FOLDER, + cliOptions.add( + newString(RESOURCE_FOLDER, "Where the resource files are emitted (default " + resourceFolder + ").")); cliOptions.add( newString(TARGET_XMLNS_NAMESPACE, @@ -184,8 +194,7 @@ public void processOpts() { additionalProperties.put(API_ENDPOINT, httpClient); if (additionalProperties.containsKey(GENERATED_SCHEMA_FOLDER)) { - this.setGeneratedSchemaFolder( - additionalProperties.get(GENERATED_SCHEMA_FOLDER).toString()); + this.setGeneratedSchemaFolder(additionalProperties.get(GENERATED_SCHEMA_FOLDER).toString()); } additionalProperties.put(GENERATED_SCHEMA_FOLDER, generatedSchemaFolder); @@ -222,17 +231,14 @@ public void processOpts() { additionalProperties.put(RESOURCE_FOLDER, resourceFolder); if (additionalProperties.containsKey(TARGET_XMLNS_NAMESPACE)) { - this.setTargetXmlnsNamespace( - additionalProperties.get(TARGET_XMLNS_NAMESPACE).toString()); + this.setTargetXmlnsNamespace(additionalProperties.get(TARGET_XMLNS_NAMESPACE).toString()); } else { - this.targetXmlnsNamespace = String.format( - "http://www.citrusframework.org/citrus-test-schema/%s-api", apiPrefix.toLowerCase()); + this.targetXmlnsNamespace = format("http://www.citrusframework.org/citrus-test-schema/%s-api", apiPrefix.toLowerCase()); } additionalProperties.put(TARGET_XMLNS_NAMESPACE, targetXmlnsNamespace); // define different folders where the files will be emitted - final String invokerFolder = (sourceFolder + File.separator + invokerPackage).replace(".", - File.separator); + final String invokerFolder = (sourceFolder + File.separator + invokerPackage).replace(".", File.separator); final String citrusFolder = invokerFolder + File.separator + "citrus"; final String extensionFolder = citrusFolder + File.separator + "extension"; final String springFolder = invokerFolder + File.separator + "spring"; @@ -244,7 +250,7 @@ public void processOpts() { } else if (API_TYPE_SOAP.equals(apiType)) { addSoapSupportingFiles(citrusFolder, schemaFolder); } else { - throw new IllegalArgumentException(String.format("Unknown API_TYPE: '%s'", apiType)); + throw new IllegalArgumentException(format("Unknown API_TYPE: '%s'", apiType)); } addDefaultSupportingFiles(citrusFolder, extensionFolder, springFolder); @@ -260,8 +266,7 @@ public void preprocessOpenAPI(OpenAPI openAPI) { additionalProperties.putAll(extensions); Map infoExtensions = extensions.entrySet().stream() - .filter(entry -> entry.getKey().toUpperCase( - ).startsWith("X-")) + .filter(entry -> entry.getKey().toUpperCase().startsWith("X-")) .collect(toMap(Entry::getKey, Entry::getValue)); additionalProperties.put("infoExtensions", infoExtensions); } @@ -324,10 +329,8 @@ public String getApiPrefix() { } private void addRestSupportingFiles(final String citrusFolder, String schemaFolder) { - supportingFiles.add(new SupportingFile("schema.mustache", schemaFolder, - apiPrefix.toLowerCase() + "-api.xsd")); - supportingFiles.add(new SupportingFile("test_base.mustache", citrusFolder, - apiPrefix + ABSTRACT_TEST_REQUEST_JAVA)); + supportingFiles.add(new SupportingFile("schema.mustache", schemaFolder, apiPrefix.toLowerCase() + "-api.xsd")); + supportingFiles.add(new SupportingFile("test_base.mustache", citrusFolder, apiPrefix + ABSTRACT_TEST_REQUEST_JAVA)); } private void addSoapSupportingFiles(final String citrusFolder, String schemaFolder) { @@ -335,24 +338,16 @@ private void addSoapSupportingFiles(final String citrusFolder, String schemaFold apiTemplateFiles().remove("api.mustache"); apiTemplateFiles().put("api_soap.mustache", ".java"); - supportingFiles.add(new SupportingFile("schema_soap.mustache", schemaFolder, - apiPrefix.toLowerCase() + "-api.xsd")); - supportingFiles.add(new SupportingFile("api_soap.mustache", citrusFolder, - apiPrefix + ABSTRACT_TEST_REQUEST_JAVA)); - supportingFiles.add(new SupportingFile("test_base_soap.mustache", citrusFolder, - apiPrefix + ABSTRACT_TEST_REQUEST_JAVA)); + supportingFiles.add(new SupportingFile("schema_soap.mustache", schemaFolder, apiPrefix.toLowerCase() + "-api.xsd")); + supportingFiles.add(new SupportingFile("api_soap.mustache", citrusFolder, apiPrefix + ABSTRACT_TEST_REQUEST_JAVA)); + supportingFiles.add(new SupportingFile("test_base_soap.mustache", citrusFolder, apiPrefix + ABSTRACT_TEST_REQUEST_JAVA)); } - private void addDefaultSupportingFiles(final String citrusFolder, final String extensionFolder, - final String springFolder) { - supportingFiles.add(new SupportingFile("bean_configuration.mustache", springFolder, - apiPrefix + "BeanConfiguration.java")); - supportingFiles.add(new SupportingFile("bean_definition_parser.mustache", citrusFolder, - apiPrefix + "BeanDefinitionParser.java")); - supportingFiles.add(new SupportingFile("namespace_handler.mustache", extensionFolder, - apiPrefix + "NamespaceHandler.java")); - supportingFiles.add(new SupportingFile("api-model.mustache", resourceFolder, - apiPrefix.toLowerCase() + "-api-model.csv")); + private void addDefaultSupportingFiles(final String citrusFolder, final String extensionFolder, final String springFolder) { + supportingFiles.add(new SupportingFile("bean_configuration.mustache", springFolder, apiPrefix + "BeanConfiguration.java")); + supportingFiles.add(new SupportingFile("bean_definition_parser.mustache", citrusFolder, apiPrefix + "BeanDefinitionParser.java")); + supportingFiles.add(new SupportingFile("namespace_handler.mustache", extensionFolder, apiPrefix + "NamespaceHandler.java")); + supportingFiles.add(new SupportingFile("api-model.mustache", resourceFolder, apiPrefix.toLowerCase() + "-api-model.csv")); } } diff --git a/test-api-generator/citrus-test-api-generator-core/src/main/java/org/citrusframework/openapi/generator/SimpleWsdlToOpenApiTransformer.java b/test-api-generator/citrus-test-api-generator-core/src/main/java/org/citrusframework/openapi/generator/SimpleWsdlToOpenApiTransformer.java index fc7487aff4..8243be5aa8 100644 --- a/test-api-generator/citrus-test-api-generator-core/src/main/java/org/citrusframework/openapi/generator/SimpleWsdlToOpenApiTransformer.java +++ b/test-api-generator/citrus-test-api-generator-core/src/main/java/org/citrusframework/openapi/generator/SimpleWsdlToOpenApiTransformer.java @@ -86,9 +86,6 @@ public String transformToOpenApi() throws WsdlToOpenApiTransformationException { /** * Performs the actual transformation from bindings into OpenApi operations. - * - * @param bindings - * @return */ private OpenAPI transformToOpenApi(Map bindings) { OpenAPI openAPI = new OpenAPI(); @@ -100,10 +97,11 @@ private OpenAPI transformToOpenApi(Map bindings) { Object key = entry.getKey(); Object value = entry.getValue(); - if (key instanceof QName && value instanceof Binding) { - addOperations(openAPI, (QName) key, (Binding) value); + if (key instanceof QName qName && value instanceof Binding binding) { + addOperations(openAPI, qName, binding); } } + return openAPI; } @@ -138,6 +136,7 @@ private Info createInfo() { Contact contact = new Contact(); contact.setName("org.citrusframework.openapi.generator.SimpleWsdlToOpenApiTransformer"); info.setContact(contact); + return info; } diff --git a/test-api-generator/citrus-test-api-generator-core/src/main/resources/java-citrus/api.mustache b/test-api-generator/citrus-test-api-generator-core/src/main/resources/java-citrus/api.mustache index 59d38fef94..edfca41a08 100644 --- a/test-api-generator/citrus-test-api-generator-core/src/main/resources/java-citrus/api.mustache +++ b/test-api-generator/citrus-test-api-generator-core/src/main/resources/java-citrus/api.mustache @@ -1,3 +1,25 @@ +/* +* Copyright the original author or authors. +* +* Licensed 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. +*/ + +/** +* ================================================== +* GENERATED CLASS, ALL CHANGES WILL BE LOST +* ================================================== +*/ + package {{package}}; import org.citrusframework.endpoint.Endpoint; @@ -13,85 +35,85 @@ import java.util.function.UnaryOperator; import static org.citrusframework.spi.Resources.create; public class {{classname}} { - private static final OpenApiSpecification petstoreSpec = OpenApiSpecification.from( - create("{{inputSpec}}") - ); +private static final OpenApiSpecification petstoreSpec = OpenApiSpecification.from( +create("{{inputSpec}}") +); - public static {{classname}} openapiPetstore(HttpClient httpClient) { - return new {{classname}}(httpClient); - } +public static {{classname}} openapiPetstore(HttpClient httpClient) { +return new {{classname}}(httpClient); +} - private final HttpClient httpClient; +private final HttpClient httpClient; - private {{classname}}(HttpClient httpClient) { - this.httpClient = httpClient; - } +private {{classname}}(HttpClient httpClient) { +this.httpClient = httpClient; +} - {{#operations}} +{{#operations}} {{#operation}} - public PetstoreAction<{{operationIdCamelCase}}Request> {{#lambda.camelcase}}{{operationIdCamelCase}}{{/lambda.camelcase}}() { - return petstoreAction(new {{operationIdCamelCase}}Request()); - } + public PetstoreAction<{{operationIdCamelCase}}Request> {{#lambda.camelcase}}{{operationIdCamelCase}}{{/lambda.camelcase}}() { + return petstoreAction(new {{operationIdCamelCase}}Request()); + } {{/operation}} - {{/operations}} +{{/operations}} private PetstoreAction petstoreAction(B requestBuilder) { - return new PetstoreAction<>(httpClient, petstoreSpec, requestBuilder); + return new PetstoreAction<>(httpClient, petstoreSpec, requestBuilder); } {{#operations}} - {{#operation}} - /** - * {{operationId}} ({{httpMethod}} {{httpPathPrefix}}{{{path}}}){{#summary}} - * {{summary}}{{/summary}}{{#description}} - * {{description}}{{/description}} - **/ - public static class {{operationIdCamelCase}}Request extends OperationRequestBuilder { - @Override - public String getOperationId() { + {{#operation}} + /** + * {{operationId}} ({{httpMethod}} {{httpPathPrefix}}{{{path}}}){{#summary}} + * {{summary}}{{/summary}}{{#description}} + * {{description}}{{/description}} + **/ + public static class {{operationIdCamelCase}}Request extends OperationRequestBuilder { + @Override + public String getOperationId() { return "{{operationId}}"; - } - - {{#pathParams}} - public {{operationIdCamelCase}}Request with{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}({{dataType}} {{paramName}}) { - openApiOperation.withParameter("{{paramName}}", {{paramName}}); - return this; - } - {{/pathParams}} - - {{#queryParams}} - public {{operationIdCamelCase}}Request with{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}({{dataType}} {{paramName}}) { - openApiOperation.withParameter("{{paramName}}", {{paramName}}); - return this; - } - {{/queryParams}} - - {{#headerParams}} - public {{operationIdCamelCase}}Request with{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}({{dataType}} {{paramName}}) { - openApiOperation.withParameter("{{paramName}}", {{paramName}}); - return this; - } - {{/headerParams}} - } - - {{/operation}} + } + + {{#pathParams}} + public {{operationIdCamelCase}}Request with{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}({{dataType}} {{paramName}}) { + openApiOperation.withParameter("{{paramName}}", {{paramName}}); + return this; + } + {{/pathParams}} + + {{#queryParams}} + public {{operationIdCamelCase}}Request with{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}({{dataType}} {{paramName}}) { + openApiOperation.withParameter("{{paramName}}", {{paramName}}); + return this; + } + {{/queryParams}} + + {{#headerParams}} + public {{operationIdCamelCase}}Request with{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}({{dataType}} {{paramName}}) { + openApiOperation.withParameter("{{paramName}}", {{paramName}}); + return this; + } + {{/headerParams}} + } + + {{/operation}} {{/operations}} public static abstract class OperationRequestBuilder { - protected final OpenApiOperationBuilder openApiOperation = OpenApiOperationBuilder.operation(getOperationId()); + protected final OpenApiOperationBuilder openApiOperation = OpenApiOperationBuilder.operation(getOperationId()); - public abstract String getOperationId(); + public abstract String getOperationId(); - public OpenApiOperationBuilder build() { - return openApiOperation; - } + public OpenApiOperationBuilder build() { + return openApiOperation; + } } public static class PetstoreAction extends OpenApiClientActionBuilder { private final T operation; private PetstoreAction(Endpoint httpClient, OpenApiSpecification specification, T operation) { - super(httpClient, specification); - this.operation = operation; + super(httpClient, specification); + this.operation = operation; } public OpenApiClientRequestActionBuilder send(UnaryOperator builderProvider) { @@ -99,10 +121,10 @@ public class {{classname}} { var send = send(builder.build()); send.fork(true); return send; - } + } - public OpenApiClientResponseActionBuilder receive() { + public OpenApiClientResponseActionBuilder receive() { return receive(operation.getOperationId(), "200"); - } - } -} + } + } + } diff --git a/test-api-generator/citrus-test-api-generator-core/src/main/resources/java-citrus/bean_definition_parser.mustache b/test-api-generator/citrus-test-api-generator-core/src/main/resources/java-citrus/bean_definition_parser.mustache index 3707465ce5..01f90d2509 100644 --- a/test-api-generator/citrus-test-api-generator-core/src/main/resources/java-citrus/bean_definition_parser.mustache +++ b/test-api-generator/citrus-test-api-generator-core/src/main/resources/java-citrus/bean_definition_parser.mustache @@ -31,7 +31,6 @@ import java.util.regex.Pattern; import javax.annotation.processing.Generated; -import org.citrusframework.exceptions.CitrusRuntimeException; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.xml.BeanDefinitionParser; diff --git a/test-api-generator/citrus-test-api-generator-core/src/main/resources/java-citrus/test_base.mustache b/test-api-generator/citrus-test-api-generator-core/src/main/resources/java-citrus/test_base.mustache index fbf2003a58..03d8078933 100644 --- a/test-api-generator/citrus-test-api-generator-core/src/main/resources/java-citrus/test_base.mustache +++ b/test-api-generator/citrus-test-api-generator-core/src/main/resources/java-citrus/test_base.mustache @@ -39,6 +39,7 @@ import org.citrusframework.http.actions.HttpClientRequestActionBuilder; import org.citrusframework.http.actions.HttpClientResponseActionBuilder; import org.citrusframework.http.actions.HttpClientResponseActionBuilder.HttpMessageBuilderSupport; import org.citrusframework.http.client.HttpClient; +import org.citrusframework.spi.Resources; import org.citrusframework.message.Message; import org.citrusframework.testapi.ApiActionBuilderCustomizerService; import org.citrusframework.testapi.GeneratedApi; diff --git a/test-api-generator/citrus-test-api-generator-core/src/test/java/org/citrusframework/openapi/generator/JavaCitrusCodegenTest.java b/test-api-generator/citrus-test-api-generator-core/src/test/java/org/citrusframework/openapi/generator/JavaCitrusCodegenTest.java index 394839c407..d88732ca5d 100644 --- a/test-api-generator/citrus-test-api-generator-core/src/test/java/org/citrusframework/openapi/generator/JavaCitrusCodegenTest.java +++ b/test-api-generator/citrus-test-api-generator-core/src/test/java/org/citrusframework/openapi/generator/JavaCitrusCodegenTest.java @@ -5,6 +5,7 @@ import java.io.File; import java.io.IOException; +import java.net.URL; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.util.HashMap; @@ -32,6 +33,31 @@ class JavaCitrusCodegenTest { + /** + * Get the absolute path to the test resources directory. + * + * @param pathToFileInTestResources The file within {@code src/test/resources} to look for + * @return the absolute path to the file + */ + private String getTestResource(String pathToFileInTestResources) { + URL resourceUrl = getClass().getClassLoader().getResource(pathToFileInTestResources); + assert resourceUrl != null; + File inputSpecFile = new File(resourceUrl.getFile()); + return inputSpecFile.getAbsolutePath(); + } + + /** + * Get the absolute path to the project's target directory. + * + * @param pathToFileInTargetDirectory The file within {@code target} to look for + * @return the absolute path to the file + */ + private static String getAbsoluteTargetDirectoryPath(String pathToFileInTargetDirectory) { + String projectBaseDir = System.getProperty("user.dir"); // Base directory of the project + File outputDirFile = new File(projectBaseDir, "target/" + pathToFileInTargetDirectory); + return outputDirFile.getAbsolutePath(); + } + @Test void retrieveGeneratorBsSpi() { JavaCitrusCodegen codegen = (JavaCitrusCodegen) CodegenConfigLoader.forName("java-citrus"); diff --git a/test-api-generator/citrus-test-api-generator-core/src/test/java/org/citrusframework/openapi/generator/ServiceLoaderTest.java b/test-api-generator/citrus-test-api-generator-core/src/test/java/org/citrusframework/openapi/generator/ServiceLoaderTest.java index 6b17f01f13..274ff8c9d9 100644 --- a/test-api-generator/citrus-test-api-generator-core/src/test/java/org/citrusframework/openapi/generator/ServiceLoaderTest.java +++ b/test-api-generator/citrus-test-api-generator-core/src/test/java/org/citrusframework/openapi/generator/ServiceLoaderTest.java @@ -7,6 +7,7 @@ import java.util.ServiceLoader.Provider; import org.citrusframework.testapi.ApiActionBuilderCustomizerService; import org.citrusframework.openapi.generator.util.TestApiActionBuilderCustomizer; +import org.citrusframework.testapi.ApiActionBuilderCustomizerService; import org.junit.jupiter.api.Test; class ServiceLoaderTest { diff --git a/test-api-generator/citrus-test-api-generator-core/src/test/java/org/citrusframework/openapi/generator/SpringBeanConfigurationIT.java b/test-api-generator/citrus-test-api-generator-core/src/test/java/org/citrusframework/openapi/generator/SpringBeanConfigurationIT.java index 83491b5d48..6f5418b7bf 100644 --- a/test-api-generator/citrus-test-api-generator-core/src/test/java/org/citrusframework/openapi/generator/SpringBeanConfigurationIT.java +++ b/test-api-generator/citrus-test-api-generator-core/src/test/java/org/citrusframework/openapi/generator/SpringBeanConfigurationIT.java @@ -9,6 +9,7 @@ import org.citrusframework.http.client.HttpClient; import org.citrusframework.http.client.HttpEndpointConfiguration; import org.citrusframework.junit.jupiter.spring.CitrusSpringSupport; +import org.citrusframework.openapi.generator.SpringBeanConfigurationIT.ClientConfiguration; //import org.citrusframework.openapi.generator.rest.petstore.request.PetApi.AddPetRequest; import org.citrusframework.openapi.generator.rest.petstore.spring.PetStoreBeanConfiguration; import org.junit.jupiter.api.Test; diff --git a/test-api-generator/citrus-test-api-generator-core/src/test/resources/apis/multiparttest-rest-resource.yaml b/test-api-generator/citrus-test-api-generator-core/src/test/resources/apis/multiparttest-rest-resource.yaml index b77b55c4d2..cfac634788 100644 --- a/test-api-generator/citrus-test-api-generator-core/src/test/resources/apis/multiparttest-rest-resource.yaml +++ b/test-api-generator/citrus-test-api-generator-core/src/test/resources/apis/multiparttest-rest-resource.yaml @@ -7,9 +7,9 @@ info: x-citrus-app: MPT x-citrus-api-name: multiparttest-rest-resource contact: - name: IT-Services-CI TAuBE - email: IT-Serv-CI-ETAdl@post.ch - url: https://confluence.pnet.ch/pages/viewpage.action?pageId=314828825 + name: Citrusframework Authors + email: citrus-dev@googlegroups.com + url: https://citrusframework.org tags: - name: multiparttest-controller paths: diff --git a/test-api-generator/citrus-test-api-generator-core/src/test/resources/org/citrusframework/openapi/generator/JavaCitrusCodegenIntegrationTest/expectedgen/rest/multiparttest/citrus/MultipartTestAbstractTestRequest.java b/test-api-generator/citrus-test-api-generator-core/src/test/resources/org/citrusframework/openapi/generator/JavaCitrusCodegenIntegrationTest/expectedgen/rest/multiparttest/citrus/MultipartTestAbstractTestRequest.java index 478a8e8742..6254c5c489 100644 --- a/test-api-generator/citrus-test-api-generator-core/src/test/resources/org/citrusframework/openapi/generator/JavaCitrusCodegenIntegrationTest/expectedgen/rest/multiparttest/citrus/MultipartTestAbstractTestRequest.java +++ b/test-api-generator/citrus-test-api-generator-core/src/test/resources/org/citrusframework/openapi/generator/JavaCitrusCodegenIntegrationTest/expectedgen/rest/multiparttest/citrus/MultipartTestAbstractTestRequest.java @@ -39,6 +39,7 @@ import org.citrusframework.http.actions.HttpClientResponseActionBuilder; import org.citrusframework.http.actions.HttpClientResponseActionBuilder.HttpMessageBuilderSupport; import org.citrusframework.http.client.HttpClient; +import org.citrusframework.spi.Resources; import org.citrusframework.message.Message; import org.citrusframework.testapi.ApiActionBuilderCustomizerService; import org.citrusframework.testapi.GeneratedApi; diff --git a/test-api-generator/citrus-test-api-generator-maven-plugin/pom.xml b/test-api-generator/citrus-test-api-generator-maven-plugin/pom.xml index 38f2cc887f..defd001b40 100644 --- a/test-api-generator/citrus-test-api-generator-maven-plugin/pom.xml +++ b/test-api-generator/citrus-test-api-generator-maven-plugin/pom.xml @@ -50,8 +50,9 @@ org.openapitools openapi-generator-maven-plugin - ${openapi-generator-maven-plugin} + ${org.openapitools.version} + commons-io commons-io diff --git a/test-api-generator/citrus-test-api-generator-maven-plugin/src/main/java/org/citrusframework/maven/plugin/CodeGenMojoWrapper.java b/test-api-generator/citrus-test-api-generator-maven-plugin/src/main/java/org/citrusframework/maven/plugin/CodeGenMojoWrapper.java index 513f9ace80..c3f38690b6 100644 --- a/test-api-generator/citrus-test-api-generator-maven-plugin/src/main/java/org/citrusframework/maven/plugin/CodeGenMojoWrapper.java +++ b/test-api-generator/citrus-test-api-generator-maven-plugin/src/main/java/org/citrusframework/maven/plugin/CodeGenMojoWrapper.java @@ -18,6 +18,7 @@ import static org.citrusframework.openapi.generator.JavaCitrusCodegen.CODEGEN_NAME; import static java.lang.String.format; +import static org.citrusframework.openapi.generator.JavaCitrusCodegen.CODEGEN_NAME; import org.citrusframework.openapi.generator.JavaCitrusCodegen; import java.io.File; @@ -26,6 +27,7 @@ import org.apache.maven.plugin.MojoExecution; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.project.MavenProject; +import org.citrusframework.openapi.generator.JavaCitrusCodegen; import org.openapitools.codegen.plugin.CodeGenMojo; /** diff --git a/test-api-generator/citrus-test-api-generator-maven-plugin/src/main/java/org/citrusframework/maven/plugin/SpringMetaFileGenerator.java b/test-api-generator/citrus-test-api-generator-maven-plugin/src/main/java/org/citrusframework/maven/plugin/SpringMetaFileGenerator.java index 2e1cdd2e0f..069cdb3ad2 100644 --- a/test-api-generator/citrus-test-api-generator-maven-plugin/src/main/java/org/citrusframework/maven/plugin/SpringMetaFileGenerator.java +++ b/test-api-generator/citrus-test-api-generator-maven-plugin/src/main/java/org/citrusframework/maven/plugin/SpringMetaFileGenerator.java @@ -30,6 +30,7 @@ import java.util.function.BiConsumer; import org.apache.maven.plugin.MojoExecutionException; import org.citrusframework.exceptions.CitrusRuntimeException; +import org.citrusframework.maven.plugin.TestApiGeneratorMojo.ApiConfig; /** * Utility class responsible for generating the Spring meta files 'spring.handlers' and 'spring.schemas', used @@ -52,9 +53,7 @@ public SpringMetaFileGenerator(TestApiGeneratorMojo testApiGeneratorMojo) { } public void generateSpringIntegrationMetaFiles() throws MojoExecutionException { - - String springMetafileDirectory = format("%s/%s", testApiGeneratorMojo.getMavenProject().getBasedir(), - testApiGeneratorMojo.metaInfFolder()); + String springMetafileDirectory = format("%s/%s", testApiGeneratorMojo.getMavenProject().getBasedir(), testApiGeneratorMojo.metaInfFolder()); File metaFolder = new File(springMetafileDirectory); if (!metaFolder.exists() && !metaFolder.mkdirs()) { throw new CitrusRuntimeException( @@ -94,9 +93,7 @@ private void writeSpringHandlerMetaFile(File springMetafileDirectory) throws Moj }); } - private void writeSpringMetaFile(File springMetafileDirectory, String filename, BiConsumer contentFormatter) - throws MojoExecutionException { - + private void writeSpringMetaFile(File springMetafileDirectory, String filename, BiConsumer contentFormatter) throws MojoExecutionException { File handlerFile = new File(format("%s/%s", springMetafileDirectory.getPath(), filename)); List filteredLines = readAndFilterLines(handlerFile); diff --git a/test-api-generator/citrus-test-api-generator-maven-plugin/src/main/java/org/citrusframework/maven/plugin/TestApiGeneratorMojo.java b/test-api-generator/citrus-test-api-generator-maven-plugin/src/main/java/org/citrusframework/maven/plugin/TestApiGeneratorMojo.java index aeee254011..e8a639a585 100644 --- a/test-api-generator/citrus-test-api-generator-maven-plugin/src/main/java/org/citrusframework/maven/plugin/TestApiGeneratorMojo.java +++ b/test-api-generator/citrus-test-api-generator-maven-plugin/src/main/java/org/citrusframework/maven/plugin/TestApiGeneratorMojo.java @@ -16,6 +16,8 @@ package org.citrusframework.maven.plugin; +import static java.lang.String.format; +import static org.apache.commons.lang3.StringUtils.isBlank; import static org.citrusframework.openapi.generator.JavaCitrusCodegen.API_ENDPOINT; import static org.citrusframework.openapi.generator.JavaCitrusCodegen.API_TYPE; import static org.citrusframework.openapi.generator.JavaCitrusCodegen.PREFIX; @@ -28,6 +30,8 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import lombok.Getter; +import lombok.Setter; import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoExecution; import org.apache.maven.plugin.MojoExecutionException; @@ -66,8 +70,8 @@ public class TestApiGeneratorMojo extends AbstractMojo { public static final String DEFAULT_RESOURCE_FOLDER = "generated-test-resources"; public static final String DEFAULT_BASE_PACKAGE = "org.citrusframework.automation.%PREFIX%.%VERSION%"; public static final String DEFAULT_INVOKER_PACKAGE = DEFAULT_BASE_PACKAGE; - public static final String DEFAULT_API_PACKAGE = DEFAULT_BASE_PACKAGE+".api"; - public static final String DEFAULT_MODEL_PACKAGE = DEFAULT_BASE_PACKAGE+".model"; + public static final String DEFAULT_API_PACKAGE = DEFAULT_BASE_PACKAGE + ".api"; + public static final String DEFAULT_MODEL_PACKAGE = DEFAULT_BASE_PACKAGE + ".model"; public static final String DEFAULT_SCHEMA_FOLDER_TEMPLATE = "schema/xsd/%VERSION%"; public static final ApiType DEFAULT_API_TYPE = ApiType.REST; @@ -199,6 +203,7 @@ CodeGenMojo configureCodeGenMojo(ApiConfig apiConfig) throws MojoExecutionExcept codeGenMojo.setPluginContext(getPluginContext()); codeGenMojo.setBuildContext(buildContext); + return codeGenMojo; } @@ -244,6 +249,8 @@ public enum ApiType { * Note that the default values are not properly set by maven processor. Therefore, the default values have been assigned additionally * on field level. */ + @Getter + @Setter public static class ApiConfig { public static final String DEFAULT_ENDPOINT = "PREFIX_ENDPOINT"; diff --git a/test-api-generator/citrus-test-api-generator-maven-plugin/src/test/java/org/citrusframework/maven/plugin/TestApiGeneratorMojoIntegrationTest.java b/test-api-generator/citrus-test-api-generator-maven-plugin/src/test/java/org/citrusframework/maven/plugin/TestApiGeneratorMojoIntegrationTest.java index 231120d1d1..33be17b44e 100644 --- a/test-api-generator/citrus-test-api-generator-maven-plugin/src/test/java/org/citrusframework/maven/plugin/TestApiGeneratorMojoIntegrationTest.java +++ b/test-api-generator/citrus-test-api-generator-maven-plugin/src/test/java/org/citrusframework/maven/plugin/TestApiGeneratorMojoIntegrationTest.java @@ -50,17 +50,17 @@ public class TestApiGeneratorMojoIntegrationTest extends AbstractMojoTestCase { * Array containing path templates for each generated file, specified with tokens. Tokens can be replaced with values of the respective * testing scenario. */ - private static final String[] STANDARD_FILE_PATH_TEMPLATES = new String[]{ - "%TARGET_FOLDER%/%GENERATED_SOURCES_FOLDER%/%INVOKER_FOLDER%/citrus/extension/%CAMEL_PREFIX%NamespaceHandler.java", - "%TARGET_FOLDER%/%GENERATED_SOURCES_FOLDER%/%INVOKER_FOLDER%/citrus/%CAMEL_PREFIX%AbstractTestRequest.java", - "%TARGET_FOLDER%/%GENERATED_SOURCES_FOLDER%/%INVOKER_FOLDER%/citrus/%CAMEL_PREFIX%BeanDefinitionParser.java", - "%TARGET_FOLDER%/%GENERATED_SOURCES_FOLDER%/%INVOKER_FOLDER%/spring/%CAMEL_PREFIX%BeanConfiguration.java", - "%TARGET_FOLDER%/%GENERATED_SOURCES_FOLDER%/%MODEL_FOLDER%/PingReqType.java", - "%TARGET_FOLDER%/%GENERATED_SOURCES_FOLDER%/%MODEL_FOLDER%/PingRespType.java", - "%TARGET_FOLDER%/%GENERATED_SOURCES_FOLDER%/%REQUEST_FOLDER%/PingApi.java", - "%TARGET_FOLDER%/%GENERATED_SOURCES_FOLDER%/%REQUEST_FOLDER%/PungApi.java", - "%TARGET_FOLDER%/%GENERATED_RESOURCES_FOLDER%/%SCHEMA_FOLDER%/%LOWER_PREFIX%-api.xsd", - "%TARGET_FOLDER%/%GENERATED_RESOURCES_FOLDER%/%LOWER_PREFIX%-api-model.csv" + private static final String[] STANDARD_FILE_PATH_TEMPLATES = new String[]{ + "%TARGET_FOLDER%/%GENERATED_SOURCES_FOLDER%/%INVOKER_FOLDER%/citrus/extension/%CAMEL_PREFIX%NamespaceHandler.java", + "%TARGET_FOLDER%/%GENERATED_SOURCES_FOLDER%/%INVOKER_FOLDER%/citrus/%CAMEL_PREFIX%AbstractTestRequest.java", + "%TARGET_FOLDER%/%GENERATED_SOURCES_FOLDER%/%INVOKER_FOLDER%/citrus/%CAMEL_PREFIX%BeanDefinitionParser.java", + "%TARGET_FOLDER%/%GENERATED_SOURCES_FOLDER%/%INVOKER_FOLDER%/spring/%CAMEL_PREFIX%BeanConfiguration.java", + "%TARGET_FOLDER%/%GENERATED_SOURCES_FOLDER%/%MODEL_FOLDER%/PingReqType.java", + "%TARGET_FOLDER%/%GENERATED_SOURCES_FOLDER%/%MODEL_FOLDER%/PingRespType.java", + "%TARGET_FOLDER%/%GENERATED_SOURCES_FOLDER%/%REQUEST_FOLDER%/PingApi.java", + "%TARGET_FOLDER%/%GENERATED_SOURCES_FOLDER%/%REQUEST_FOLDER%/PungApi.java", + "%TARGET_FOLDER%/%GENERATED_RESOURCES_FOLDER%/%SCHEMA_FOLDER%/%LOWER_PREFIX%-api.xsd", + "%TARGET_FOLDER%/%GENERATED_RESOURCES_FOLDER%/%LOWER_PREFIX%-api-model.csv" }; /** @@ -68,8 +68,8 @@ public class TestApiGeneratorMojoIntegrationTest extends AbstractMojoTestCase { * testing scenario. */ private static final String[] SPRING_META_FILE_TEMPLATES = new String[]{ - "%BASE_FOLDER%/%META_INF_FOLDER%/spring.handlers", - "%BASE_FOLDER%/%META_INF_FOLDER%/spring.schemas" + "%BASE_FOLDER%/%META_INF_FOLDER%/spring.handlers", + "%BASE_FOLDER%/%META_INF_FOLDER%/spring.schemas" }; private TestApiGeneratorMojo fixture; @@ -82,16 +82,16 @@ void beforeEachSetup() throws Exception { public static Stream executeMojoWithConfigurations() { return Stream.of( - arguments("pom-missing-prefix", - new MojoExecutionException("Required parameter 'prefix' not set for api at index '0'!")), - arguments("pom-missing-source", - new MojoExecutionException("Required parameter 'source' not set for api at index '0'!")), - arguments("pom-minimal-config", null), - arguments("pom-minimal-with-version-config", null), - arguments("pom-multi-config", null), - arguments("pom-full-config", null), - arguments("pom-full-with-version-config", null), - arguments("pom-soap-config", null) + arguments("pom-missing-prefix", + new MojoExecutionException("Required parameter 'prefix' not set for api at index '0'!")), + arguments("pom-missing-source", + new MojoExecutionException("Required parameter 'source' not set for api at index '0'!")), + arguments("pom-minimal-config", null), + arguments("pom-minimal-with-version-config", null), + arguments("pom-multi-config", null), + arguments("pom-full-config", null), + arguments("pom-full-with-version-config", null), + arguments("pom-soap-config", null) ); } @@ -100,7 +100,11 @@ public static Stream executeMojoWithConfigurations() { public void executeMojoWithConfigurations(String configName, Exception expectedException) throws Exception { - fixture = fixtureFromPom(configName); + try { + fixture = fixtureFromPom(configName); + } catch (MojoExecutionException | MojoFailureException e) { + Assertions.fail("Test setup failed!", e); + } @SuppressWarnings("unchecked") List apiConfigs = (List) getField(fixture, "apis"); @@ -122,7 +126,7 @@ public void executeMojoWithConfigurations(String configName, Exception expectedE } else { // When/Then assertThatThrownBy(() -> fixture.execute()).isInstanceOf(expectedException.getClass()) - .hasMessage(expectedException.getMessage()); + .hasMessage(expectedException.getMessage()); } } @@ -218,7 +222,7 @@ private void assertSchemasInSpringSchemas(ApiConfig apiConfig) throws IOExceptio String targetNamespace = replaceDynamicVarsToLowerCase(apiConfig.getTargetXmlnsNamespace(), apiConfig.getPrefix(), apiConfig.getVersion()); targetNamespace = targetNamespace.replace(":", "\\:"); - String schemaPath = replaceDynamicVarsToLowerCase((String) getField(fixture, "schemaFolder"), apiConfig.getPrefix(), apiConfig.getVersion()); + String schemaPath = replaceDynamicVarsToLowerCase((String)getField(fixture, "schemaFolder"), apiConfig.getPrefix(), apiConfig.getVersion()); String text = String.format("%s.xsd=%s/%s-api.xsd", targetNamespace, schemaPath, apiConfig.getPrefix().toLowerCase()); @@ -243,13 +247,13 @@ private void assertApiType(ApiConfig apiConfig) throws IOException { private void assertTargetNamespace(ApiConfig apiConfig) throws IOException { assertThat(getContentOfFile(apiConfig, "-api.xsd")).contains( - String.format("targetNamespace=\"%s\"", - replaceDynamicVarsToLowerCase(apiConfig.getTargetXmlnsNamespace(), apiConfig.getPrefix(), apiConfig.getVersion()))); + String.format("targetNamespace=\"%s\"", + replaceDynamicVarsToLowerCase(apiConfig.getTargetXmlnsNamespace(), apiConfig.getPrefix(), apiConfig.getVersion()))); } private void assertEndpointName(ApiConfig apiConfig) throws IOException { assertThat(getContentOfFile(apiConfig, "AbstractTestRequest")).contains( - String.format("@Qualifier(\"%s\")", apiConfig.qualifiedEndpoint())); + String.format("@Qualifier(\"%s\")", apiConfig.qualifiedEndpoint())); } private String getContentOfFile(ApiConfig apiConfig, String fileIdentifier) throws IOException { @@ -266,8 +270,8 @@ private String getContentOfFile(ApiConfig apiConfig, String fileIdentifier) thro private String getTemplateContaining(String text) { return concat(stream(STANDARD_FILE_PATH_TEMPLATES), stream(SPRING_META_FILE_TEMPLATES)) - .filter(path -> path.contains(text)).findFirst() - .orElseThrow(() -> new AssertionError(String.format("Can't find file template with content: '%s'", text))); + .filter(path -> path.contains(text)).findFirst() + .orElseThrow(() -> new AssertionError(String.format("Can't find file template with content: '%s'", text))); } @NotNull @@ -279,31 +283,31 @@ private String resolveFilePath(ApiConfig apiConfig, String filePathTemplate) { String camelCasePrefix = new String(prefixCharArray); String invokerFolder = toFolder( - replaceDynamicVarsToLowerCase(apiConfig.getInvokerPackage(), apiConfig.getPrefix(), apiConfig.getVersion())); + replaceDynamicVarsToLowerCase(apiConfig.getInvokerPackage(), apiConfig.getPrefix(), apiConfig.getVersion())); String modelFolder = toFolder( - replaceDynamicVarsToLowerCase(apiConfig.getModelPackage(), apiConfig.getPrefix(), apiConfig.getVersion())); + replaceDynamicVarsToLowerCase(apiConfig.getModelPackage(), apiConfig.getPrefix(), apiConfig.getVersion())); String requestFolder = toFolder( - replaceDynamicVarsToLowerCase(apiConfig.getApiPackage(), apiConfig.getPrefix(), apiConfig.getVersion())); + replaceDynamicVarsToLowerCase(apiConfig.getApiPackage(), apiConfig.getPrefix(), apiConfig.getVersion())); String schemaFolder = toFolder( - replaceDynamicVars((String) getField(fixture, "schemaFolder"), apiConfig.getPrefix(), apiConfig.getVersion())); + replaceDynamicVars((String)getField(fixture, "schemaFolder"), apiConfig.getPrefix(), apiConfig.getVersion())); String generatedSourcesFolder = toFolder( - replaceDynamicVars((String) getField(fixture, "sourceFolder"), apiConfig.getPrefix(), apiConfig.getVersion())); + replaceDynamicVars((String)getField(fixture, "sourceFolder"), apiConfig.getPrefix(), apiConfig.getVersion())); String generatedResourcesFolder = toFolder( - replaceDynamicVars((String) getField(fixture, "resourceFolder"), apiConfig.getPrefix(), apiConfig.getVersion())); + replaceDynamicVars((String)getField(fixture, "resourceFolder"), apiConfig.getPrefix(), apiConfig.getVersion())); return filePathTemplate - .replace("%BASE_FOLDER%", fixture.getMavenProject().getBasedir().getPath()) - .replace("%TARGET_FOLDER%", fixture.getMavenProject().getBuild().getDirectory()) - .replace("%SOURCE_FOLDER%", fixture.getMavenProject().getBuild().getSourceDirectory()) - .replace("%GENERATED_SOURCES_FOLDER%", generatedSourcesFolder) - .replace("%GENERATED_RESOURCES_FOLDER%", generatedResourcesFolder) - .replace("%INVOKER_FOLDER%", invokerFolder) - .replace("%MODEL_FOLDER%", modelFolder) - .replace("%REQUEST_FOLDER%", requestFolder) - .replace("%SCHEMA_FOLDER%", schemaFolder) - .replace("%LOWER_PREFIX%", lowerCasePrefix) - .replace("%CAMEL_PREFIX%", camelCasePrefix) - .replace("%META_INF_FOLDER%", toFolder((String) getField(fixture, "metaInfFolder"))); + .replace("%BASE_FOLDER%", fixture.getMavenProject().getBasedir().getPath()) + .replace("%TARGET_FOLDER%", fixture.getMavenProject().getBuild().getDirectory()) + .replace("%SOURCE_FOLDER%", fixture.getMavenProject().getBuild().getSourceDirectory()) + .replace("%GENERATED_SOURCES_FOLDER%", generatedSourcesFolder) + .replace("%GENERATED_RESOURCES_FOLDER%", generatedResourcesFolder) + .replace("%INVOKER_FOLDER%", invokerFolder) + .replace("%MODEL_FOLDER%", modelFolder) + .replace("%REQUEST_FOLDER%", requestFolder) + .replace("%SCHEMA_FOLDER%", schemaFolder) + .replace("%LOWER_PREFIX%", lowerCasePrefix) + .replace("%CAMEL_PREFIX%", camelCasePrefix) + .replace("%META_INF_FOLDER%", toFolder((String) getField(fixture, "metaInfFolder"))); } private String toFolder(String text) { @@ -320,16 +324,16 @@ private TestApiGeneratorMojo fixtureFromPom(String configName) throws Exception try { String goal = "create-test-api"; - File pomFile = new File(getBasedir(), String.format("src/test/resources/%s/%s", getClass().getSimpleName(), configName + ".xml")); - assertThat(pomFile).exists(); + File pomFile = new File(getBasedir(), String.format("src/test/resources/%s/%s", getClass().getSimpleName(), configName + ".xml")); + assertThat(pomFile).exists(); - MavenProject mavenProject = new CitrusOpenApiGeneratorMavenProjectStub(configName); + MavenProject mavenProject = new CitrusOpenApiGeneratorMavenProjectStub(configName); - TestApiGeneratorMojo testApiGeneratorMojo = (TestApiGeneratorMojo) lookupMojo(goal, pomFile); - testApiGeneratorMojo.setMavenProject(mavenProject); - testApiGeneratorMojo.setMojoExecution(newMojoExecution(goal)); + TestApiGeneratorMojo testApiGeneratorMojo = (TestApiGeneratorMojo) lookupMojo(goal, pomFile); + testApiGeneratorMojo.setMavenProject(mavenProject); + testApiGeneratorMojo.setMojoExecution(newMojoExecution(goal)); - return testApiGeneratorMojo; + return testApiGeneratorMojo; } catch (MojoExecutionException | MojoFailureException e) { Assertions.fail("Test setup failed!", e); return new TestApiGeneratorMojo(); diff --git a/test-api-generator/citrus-test-api-generator-maven-plugin/src/test/java/org/citrusframework/maven/plugin/TestApiGeneratorMojoUnitTest.java b/test-api-generator/citrus-test-api-generator-maven-plugin/src/test/java/org/citrusframework/maven/plugin/TestApiGeneratorMojoUnitTest.java index 1bb8781631..39007a77c0 100644 --- a/test-api-generator/citrus-test-api-generator-maven-plugin/src/test/java/org/citrusframework/maven/plugin/TestApiGeneratorMojoUnitTest.java +++ b/test-api-generator/citrus-test-api-generator-maven-plugin/src/test/java/org/citrusframework/maven/plugin/TestApiGeneratorMojoUnitTest.java @@ -1,5 +1,7 @@ package org.citrusframework.maven.plugin; +import static java.lang.Boolean.TRUE; +import static org.assertj.core.api.Assertions.assertThat; import static org.citrusframework.maven.plugin.TestApiGeneratorMojo.DEFAULT_API_PACKAGE; import static org.citrusframework.maven.plugin.TestApiGeneratorMojo.DEFAULT_API_TYPE; import static org.citrusframework.maven.plugin.TestApiGeneratorMojo.DEFAULT_INVOKER_PACKAGE; @@ -30,6 +32,8 @@ import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.testing.AbstractMojoTestCase; import org.apache.maven.project.MavenProject; +import org.citrusframework.maven.plugin.TestApiGeneratorMojo.ApiConfig; +import org.citrusframework.maven.plugin.TestApiGeneratorMojo.ApiType; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; diff --git a/test-api-generator/pom.xml b/test-api-generator/pom.xml index f6298e3e11..04ed20c530 100644 --- a/test-api-generator/pom.xml +++ b/test-api-generator/pom.xml @@ -19,19 +19,65 @@ true + + citrus-test-api-generator-core + citrus-test-api-generator-maven-plugin + + org.junit.jupiter junit-jupiter-engine - ${junit.jupiter.version} + ${junit.jupiter.version} + test + + + + org.junit.jupiter + junit-jupiter-params + ${junit.jupiter.version} test - - citrus-test-api-generator-core - citrus-test-api-generator-maven-plugin - + + + + org.apache.maven.plugins + maven-surefire-plugin + + + *IntegrationTest.java + *IT.java + + + + + org.apache.maven.surefire + surefire-junit-platform + ${maven.surefire.plugin.version} + + + + + org.apache.maven.plugins + maven-failsafe-plugin + + + *IntegrationTest.java + *IT.java + + + + + org.apache.maven.surefire + surefire-junit-platform + ${maven.surefire.plugin.version} + + + + + diff --git a/tools/jbang/dist/CitrusJBang.java b/tools/jbang/dist/CitrusJBang.java index 3e59a03a79..d55ed6508d 100755 --- a/tools/jbang/dist/CitrusJBang.java +++ b/tools/jbang/dist/CitrusJBang.java @@ -18,13 +18,13 @@ //JAVA 17+ //REPOS mavencentral -//DEPS org.citrusframework:citrus:${citrus.jbang.version:4.2.0}@pom -//DEPS org.citrusframework:citrus-base:${citrus.jbang.version:4.2.0} -//DEPS org.citrusframework:citrus-main:${citrus.jbang.version:4.2.0} -//DEPS org.citrusframework:citrus-jbang:${citrus.jbang.version:4.2.0} -//DEPS org.citrusframework:citrus-groovy:${citrus.jbang.version:4.2.0} -//DEPS org.citrusframework:citrus-xml:${citrus.jbang.version:4.2.0} -//DEPS org.citrusframework:citrus-yaml:${citrus.jbang.version:4.2.0} +//DEPS org.citrusframework:citrus:${citrus.jbang.version:4.2.1}@pom +//DEPS org.citrusframework:citrus-base:${citrus.jbang.version:4.2.1} +//DEPS org.citrusframework:citrus-main:${citrus.jbang.version:4.2.1} +//DEPS org.citrusframework:citrus-jbang:${citrus.jbang.version:4.2.1} +//DEPS org.citrusframework:citrus-groovy:${citrus.jbang.version:4.2.1} +//DEPS org.citrusframework:citrus-xml:${citrus.jbang.version:4.2.1} +//DEPS org.citrusframework:citrus-yaml:${citrus.jbang.version:4.2.1} package main; import org.citrusframework.jbang.CitrusJBangMain; diff --git a/tools/restdocs/src/main/resources/META-INF/spring.schemas b/tools/restdocs/src/main/resources/META-INF/spring.schemas index da419b95ab..c3c755bd89 100644 --- a/tools/restdocs/src/main/resources/META-INF/spring.schemas +++ b/tools/restdocs/src/main/resources/META-INF/spring.schemas @@ -30,6 +30,7 @@ http\://www.citrusframework.org/schema/restdocs/config/citrus-restdocs-config-4. http\://www.citrusframework.org/schema/restdocs/config/citrus-restdocs-config-4.0.2.xsd=org/citrusframework/schema/citrus-restdocs-config-4.0.2.xsd http\://www.citrusframework.org/schema/restdocs/config/citrus-restdocs-config-4.1.0.xsd=org/citrusframework/schema/citrus-restdocs-config-4.1.0.xsd http\://www.citrusframework.org/schema/restdocs/config/citrus-restdocs-config-4.1.1.xsd=org/citrusframework/schema/citrus-restdocs-config-4.1.1.xsd -http\://www.citrusframework.org/schema/restdocs/config/citrus-restdocs-config-4.3.0-SNAPSHOT.xsd=org/citrusframework/schema/citrus-restdocs-config-4.3.0-SNAPSHOT.xsd http\://www.citrusframework.org/schema/restdocs/config/citrus-restdocs-config-4.2.0.xsd=org/citrusframework/schema/citrus-restdocs-config-4.2.0.xsd +http\://www.citrusframework.org/schema/restdocs/config/citrus-restdocs-config-4.2.1.xsd=org/citrusframework/schema/citrus-restdocs-config-4.2.1.xsd +http\://www.citrusframework.org/schema/restdocs/config/citrus-restdocs-config-4.3.0-SNAPSHOT.xsd=org/citrusframework/schema/citrus-restdocs-config-4.3.0-SNAPSHOT.xsd http\://www.citrusframework.org/schema/restdocs/config/citrus-restdocs-config.xsd=org/citrusframework/schema/citrus-restdocs-config.xsd diff --git a/validation/citrus-validation-json/src/main/java/org/citrusframework/validation/json/JsonElementValidator.java b/validation/citrus-validation-json/src/main/java/org/citrusframework/validation/json/JsonElementValidator.java index 87612e5c28..b8f6d6f777 100644 --- a/validation/citrus-validation-json/src/main/java/org/citrusframework/validation/json/JsonElementValidator.java +++ b/validation/citrus-validation-json/src/main/java/org/citrusframework/validation/json/JsonElementValidator.java @@ -96,21 +96,28 @@ static boolean isIgnoredByPlaceholderOrExpressionList(Collection ignoreE return true; } - if (ignoreExpressions.stream().anyMatch(controlEntry::isPathIgnoredBy)) { - return true; - } - - return false; + return ignoreExpressions.stream().anyMatch(controlEntry::isPathIgnoredBy); } - private void validateJSONArray(JsonElementValidator validator, JsonElementValidatorItem control) { var arrayControl = control.ensureType(JSONArray.class); if (strict) { validateSameSize(control.getJsonPath(), arrayControl.expected, arrayControl.actual); } + int actualIndex = 0; for (int i = 0; i < arrayControl.expected.size(); i++) { - if (!isAnyValidItemInActualArray(validator, arrayControl, i)) { + if (isIgnoredByPlaceholderOrExpressionList(ignoreExpressions, arrayControl.child(i, i))) { + continue; + } + boolean isValid = false; + + while (!isValid && actualIndex < arrayControl.actual.size()) { + JsonElementValidatorItem item = arrayControl.child(i, arrayControl.actual.get(actualIndex)); + isValid = isValidItem(item, validator); + actualIndex++; + } + + if (!isValid) { throw new ValidationException(buildValueToBeInCollectionErrorMessage( "An item in '%s' is missing".formatted(arrayControl.getJsonPath()), arrayControl.expected.get(i), @@ -120,17 +127,13 @@ private void validateJSONArray(JsonElementValidator validator, JsonElementValida } } - private boolean isAnyValidItemInActualArray(JsonElementValidator validator, JsonElementValidatorItem control, int index) { - Object expectedItem = control.expected.get(index); - return control.actual.stream().map(recivedItem -> { - try { - var itemControl = new JsonElementValidatorItem<>(index, recivedItem, expectedItem).parent(control); - validator.validate(itemControl); - return null; - } catch (ValidationException e) { - return e; - } - }).anyMatch(Objects::isNull); + private static boolean isValidItem(JsonElementValidatorItem validatorItem, JsonElementValidator validator) { + try { + validator.validate(validatorItem); + return true; + } catch (ValidationException e) { + return false; + } } private void validateSameSize(String path, Collection expected, Collection actual) { diff --git a/validation/citrus-validation-json/src/main/java/org/citrusframework/validation/json/JsonElementValidatorItem.java b/validation/citrus-validation-json/src/main/java/org/citrusframework/validation/json/JsonElementValidatorItem.java index c6b58919d5..b617b8574b 100644 --- a/validation/citrus-validation-json/src/main/java/org/citrusframework/validation/json/JsonElementValidatorItem.java +++ b/validation/citrus-validation-json/src/main/java/org/citrusframework/validation/json/JsonElementValidatorItem.java @@ -19,6 +19,7 @@ import com.jayway.jsonpath.Configuration; import com.jayway.jsonpath.JsonPath; import com.jayway.jsonpath.JsonPathException; +import net.minidev.json.JSONArray; import net.minidev.json.parser.JSONParser; import net.minidev.json.parser.ParseException; import org.citrusframework.exceptions.CitrusRuntimeException; @@ -32,9 +33,9 @@ /** * Wraps all needed data to validate an actual json with an expected json-template. - * @see JsonElementValidator for usage * * @param the type of the actual and expected json + * @see JsonElementValidator for usage */ public class JsonElementValidatorItem { private final String name; @@ -47,8 +48,8 @@ public class JsonElementValidatorItem { * Parses and wraps the given json's. * * @param permissiveMode see {@code JSONParser#MODE_*} or {@link JSONParser#DEFAULT_PERMISSIVE_MODE} - * @param actualJson as string - * @param expectedJson as string + * @param actualJson as string + * @param expectedJson as string * @return the two json's wrapped in a {@link JsonElementValidatorItem} */ public static JsonElementValidatorItem parseJson(int permissiveMode, String actualJson, String expectedJson) { @@ -73,7 +74,7 @@ public JsonElementValidatorItem(int index, T actual, T expected) { } /** - * For array-items. + * For object-items. * * @param name/key of the json value in the {@link JsonElementValidatorItem#parent}-element */ @@ -99,13 +100,12 @@ public String expectedAsStringOrNull() { } /** - * @throws ValidationException if either {@link JsonElementValidatorItem#expected} - * or {@link JsonElementValidatorItem#expected} is not of the given {@code type} * @param type to cast the values to * @return {@link this} as {@link JsonElementValidatorItem} + * @throws ValidationException if either {@link JsonElementValidatorItem#expected} + * or {@link JsonElementValidatorItem#expected} is not of the given {@code type} */ public JsonElementValidatorItem ensureType(Class type) { - JsonElementValidatorItem self = this; if (((actual != null) && !type.isInstance(actual)) || ((expected != null) && !type.isInstance(expected))) { throw new ValidationException(buildValueMismatchErrorMessage( "Type mismatch for JSON entry '" + name + "'", @@ -113,7 +113,7 @@ public JsonElementValidatorItem ensureType(Class type) { actual == null ? null : actual.getClass().getSimpleName() )); } - return (JsonElementValidatorItem) self; + return (JsonElementValidatorItem) this; } /** @@ -145,8 +145,6 @@ public String getJsonPath() { *
  • {@link JsonElementValidatorItem#name} for an entry in a json map
  • *
  • {@link JsonElementValidatorItem#index} in square brackets for an item in a json array, i.e. {@code "[2]"}
  • * - * - * @return */ public String getName() { if (index != null) return "[%s]".formatted(index); @@ -159,14 +157,15 @@ public JsonElementValidatorItem getRoot() { } public boolean isPathIgnoredBy(String jsonPathExpression) { - String currentPath = getJsonPath(); - return Stream.concat( - getAllMatchedPathsInJson(jsonPathExpression, getRoot().expected), - getAllMatchedPathsInJson(jsonPathExpression, getRoot().actual) - ).anyMatch(currentPath::equals); + return isPathIgnoredBy(jsonPathExpression, getJsonPath(), getRoot().actual) + || isPathIgnoredBy(jsonPathExpression, getJsonPath(), getRoot().expected); } - private Stream getAllMatchedPathsInJson(String jsonPathExpression, Object json) { + public static boolean isPathIgnoredBy(String jsonPathExpression, String currentPath, Object json) { + return getAllMatchedPathsInJson(jsonPathExpression, json).anyMatch(currentPath::equals); + } + + private static Stream getAllMatchedPathsInJson(String jsonPathExpression, Object json) { Configuration config = Configuration.builder().options(AS_PATH_LIST).build(); List foundJsonPaths; try { @@ -176,4 +175,14 @@ private Stream getAllMatchedPathsInJson(String jsonPathExpression, Objec } return foundJsonPaths.stream(); } + + public JsonElementValidatorItem child(int expectedIndex, Object other) { + var arrayControl = this.ensureType(JSONArray.class); + + return new JsonElementValidatorItem<>( + expectedIndex, + other, + arrayControl.expected.get(expectedIndex) + ).parent(arrayControl); + } } diff --git a/validation/citrus-validation-json/src/test/java/org/citrusframework/validation/json/JsonElementValidatorTest.java b/validation/citrus-validation-json/src/test/java/org/citrusframework/validation/json/JsonElementValidatorTest.java index 236354f70a..9db9b360f1 100644 --- a/validation/citrus-validation-json/src/test/java/org/citrusframework/validation/json/JsonElementValidatorTest.java +++ b/validation/citrus-validation-json/src/test/java/org/citrusframework/validation/json/JsonElementValidatorTest.java @@ -16,7 +16,6 @@ package org.citrusframework.validation.json; -import org.assertj.core.api.AbstractThrowableAssert; import org.citrusframework.UnitTestSupport; import org.citrusframework.exceptions.ValidationException; import org.testng.annotations.DataProvider; @@ -72,6 +71,14 @@ public static JsonAssertion[] validJsonPairsIfNotStrict() { new JsonAssertion( "[1, 2, 3]", "[2] " + ), + new JsonAssertion( + "[1, 2, 1]", + "[2, 1]" + ), + new JsonAssertion( + "[1, 2, 1]", + "[1, 2]" ) ).toArray(new JsonAssertion[0]); } @@ -128,25 +135,32 @@ public static JsonAssertion[] validIfStrict() { ), new JsonAssertion( "[1, 2, 3]", - "[3, 2, 1]" + "[1, 2, 3]" ), new JsonAssertion( - "{ \"books\": [\"book-c\", \"book-b\", \"book-a\"] }", + "{ \"books\": [\"book-a\", \"book-b\", \"book-c\"] }", "{ \"books\": [\"book-a\", \"book-b\", \"book-c\"] }" ) ).toArray(new JsonAssertion[0]); } - @Test(dataProvider = "invalidJsonPairs") - public AbstractThrowableAssert shouldBeInvalid(JsonAssertion jsonAssertion) { + @Test(dataProvider = "invalidJsonPairsOnStrictAndNonStrict") + public void shouldBeInvalid(JsonAssertion jsonAssertion) { var validationItem = toValidationItem(jsonAssertion); fixture = new JsonElementValidator(STRICT, context, Set.of()); - return assertThatThrownBy(() -> fixture.validate(validationItem)).isInstanceOf(ValidationException.class); + assertThatThrownBy(() -> fixture.validate(validationItem)).isInstanceOf(ValidationException.class); + } + + @Test(dataProvider = "invalidJsonPairsOnStrictAndNonStrict") + public void shouldBeInvalidIfNotStrict(JsonAssertion jsonAssertion) { + var validationItem = toValidationItem(jsonAssertion); + fixture = new JsonElementValidator(NOT_STRICT, context, Set.of()); + assertThatThrownBy(() -> fixture.validate(validationItem)).isInstanceOf(ValidationException.class); } @DataProvider - public static JsonAssertion[] invalidJsonPairs() { + public static JsonAssertion[] invalidJsonPairsOnStrictAndNonStrict() { return List.of( new JsonAssertion( "{\"myNumbers\": [11, 22, 44]}", @@ -214,6 +228,22 @@ public static JsonAssertion[] invalidJsonPairs() { "", "{\"text\":\"Hello World!\", \"index\":5, \"id\":\"x123456789x\"}", "expected message contents, but received empty message" + ), + new JsonAssertion( + "[1, 2, 2, 1]", + "[1, 1, 2, 1]" + ), + new JsonAssertion( + "[1]", + "[1, 1]" + ), + new JsonAssertion( + "[1, 3, 2]", + "[1, 2, 3]" + ), + new JsonAssertion( + "[3, 2, 1]", + "[1, 2, 3]" ) ).toArray(new JsonAssertion[0]); } @@ -262,7 +292,7 @@ private static JsonElementValidatorItem toValidationItem(JsonAssertion j return JsonElementValidatorItem.parseJson(DEFAULT_PERMISSIVE_MODE, jsonAssertion.actual, jsonAssertion.expected); } - private record JsonAssertion( + public record JsonAssertion( String actual, String expected, Set ignoreExpressions,