From c9b64a3c8e36bc240b236f9ab2d60602a75acce0 Mon Sep 17 00:00:00 2001 From: Abhishek Date: Mon, 28 Sep 2020 00:10:37 +0530 Subject: [PATCH 01/44] Issue 401 # corrected string casting --- .../jsmart/zerocode/core/httpclient/utils/FileUploadUtils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/org/jsmart/zerocode/core/httpclient/utils/FileUploadUtils.java b/core/src/main/java/org/jsmart/zerocode/core/httpclient/utils/FileUploadUtils.java index 8774de198..3c86220fe 100644 --- a/core/src/main/java/org/jsmart/zerocode/core/httpclient/utils/FileUploadUtils.java +++ b/core/src/main/java/org/jsmart/zerocode/core/httpclient/utils/FileUploadUtils.java @@ -57,7 +57,7 @@ public static void buildOtherRequestParams(Map fileFieldNameValu if (entry.getKey().equals(FILES_FIELD) || entry.getKey().equals(BOUNDARY_FIELD)) { continue; } - multipartEntityBuilder.addPart(entry.getKey(), new StringBody((String) entry.getValue(), TEXT_PLAIN)); + multipartEntityBuilder.addPart(entry.getKey(), new StringBody(entry.getValue().toString(), TEXT_PLAIN)); } } From cf51fbeecc744b9913b2a1e483570714ae9a9910 Mon Sep 17 00:00:00 2001 From: Abhishek Date: Wed, 30 Sep 2020 20:40:33 +0530 Subject: [PATCH 02/44] Issue 401 # Added UT cases for the fix --- .../core/utils/FileUploadUtilsTest.java | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 core/src/test/java/org/jsmart/zerocode/core/utils/FileUploadUtilsTest.java diff --git a/core/src/test/java/org/jsmart/zerocode/core/utils/FileUploadUtilsTest.java b/core/src/test/java/org/jsmart/zerocode/core/utils/FileUploadUtilsTest.java new file mode 100644 index 000000000..54e45a6a9 --- /dev/null +++ b/core/src/test/java/org/jsmart/zerocode/core/utils/FileUploadUtilsTest.java @@ -0,0 +1,27 @@ +package org.jsmart.zerocode.core.utils; + +import org.apache.http.entity.mime.MultipartEntityBuilder; +import org.jsmart.zerocode.core.httpclient.utils.FileUploadUtils; +import org.junit.Test; + +import java.util.LinkedHashMap; +import java.util.Map; + +import static org.junit.Assert.fail; + +public class FileUploadUtilsTest { + + @Test + public void buildOtherRequestParamsTest1() { + Map fileFieldNameValueMapStub = new LinkedHashMap<>(); + fileFieldNameValueMapStub.put("name", "name"); + fileFieldNameValueMapStub.put("fileName", "test.wav"); + fileFieldNameValueMapStub.put("location", "location"); + MultipartEntityBuilder multipartEntityBuilderStub = MultipartEntityBuilder.create(); + try { + FileUploadUtils.buildOtherRequestParams(fileFieldNameValueMapStub, multipartEntityBuilderStub); + } catch (Exception e) { + fail("Should not have thrown any exception"); + } + } +} From c6ad3d7a2a70edc4b32661a36b47df0aac903c01 Mon Sep 17 00:00:00 2001 From: prashantmurkute Date: Sat, 23 Jan 2021 13:22:53 +0530 Subject: [PATCH 03/44] Added support for csv file for csvSource --- .../zerocode/core/domain/Parameterized.java | 37 ++++++++++++++++++- .../ZeroCodeParameterizedProcessorImpl.java | 23 ++++++------ .../httpclient/JustHelloWorldSuite.java | 3 -- .../HelloWorldParameterizedCsvTest.java | 5 +++ ...d_test_parameterized_csv_source_files.json | 25 +++++++++++++ .../resources/parameterized_csv/params.csv | 2 + 6 files changed, 79 insertions(+), 16 deletions(-) create mode 100644 http-testing/src/test/resources/parameterized_csv/hello_world_test_parameterized_csv_source_files.json create mode 100644 http-testing/src/test/resources/parameterized_csv/params.csv diff --git a/core/src/main/java/org/jsmart/zerocode/core/domain/Parameterized.java b/core/src/main/java/org/jsmart/zerocode/core/domain/Parameterized.java index 14b119b4f..2e24b65a4 100644 --- a/core/src/main/java/org/jsmart/zerocode/core/domain/Parameterized.java +++ b/core/src/main/java/org/jsmart/zerocode/core/domain/Parameterized.java @@ -1,7 +1,19 @@ package org.jsmart.zerocode.core.domain; import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.ObjectReader; +import org.apache.commons.lang.StringUtils; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Collections; import java.util.List; +import java.util.stream.Collectors; public class Parameterized { private final List valueSource; @@ -9,9 +21,9 @@ public class Parameterized { public Parameterized( @JsonProperty("valueSource") List valueSource, - @JsonProperty("csvSource") List csvSource) { + @JsonProperty("csvSource") JsonNode csvSourceJsonNode) { this.valueSource = valueSource; - this.csvSource = csvSource; + this.csvSource = getCsvSourceFrom(csvSourceJsonNode); } public List getValueSource() { @@ -22,6 +34,27 @@ public List getCsvSource() { return csvSource; } + private List getCsvSourceFrom(JsonNode csvSourceJsonNode) { + try { + if (csvSourceJsonNode.isArray()) { + ObjectMapper mapper = new ObjectMapper(); + ObjectReader reader = mapper.readerFor(new TypeReference>() { + }); + return reader.readValue(csvSourceJsonNode); + + } else { + String csvSourceFilePath = csvSourceJsonNode.textValue(); + if (StringUtils.isNotBlank(csvSourceFilePath)) { + Path path = Paths.get(csvSourceFilePath); + return Files.lines(path).collect(Collectors.toList()); + } + } + } catch (IOException e) { + throw new RuntimeException("Error deserializing csvSource", e); + } + return Collections.emptyList(); + } + @Override public String toString() { return "Parameterized{" + diff --git a/core/src/main/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeParameterizedProcessorImpl.java b/core/src/main/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeParameterizedProcessorImpl.java index 466cf145f..79d5518c0 100644 --- a/core/src/main/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeParameterizedProcessorImpl.java +++ b/core/src/main/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeParameterizedProcessorImpl.java @@ -4,17 +4,18 @@ import com.google.inject.Inject; import com.google.inject.Singleton; import com.univocity.parsers.csv.CsvParser; +import org.apache.commons.lang.text.StrSubstitutor; +import org.jsmart.zerocode.core.domain.ScenarioSpec; +import org.slf4j.Logger; + import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.atomic.AtomicLong; -import org.apache.commons.lang.text.StrSubstitutor; -import org.jsmart.zerocode.core.domain.ScenarioSpec; -import org.slf4j.Logger; -import static org.jsmart.zerocode.core.di.provider.CsvParserProvider.LINE_SEPARATOR; import static org.jsmart.zerocode.core.constants.ZerocodeConstants.DSL_FORMAT; +import static org.jsmart.zerocode.core.di.provider.CsvParserProvider.LINE_SEPARATOR; import static org.slf4j.LoggerFactory.getLogger; /** @@ -25,17 +26,17 @@ *

* Parameters can be * "parameterized": [ - * 200, - * "Hello", - * true + * 200, + * "Hello", + * true * ] *

* -or- *

* "parameterizedCsv": [ - * "1, 2, 200", - * "11, 22, 400", - * "21, 31, 500" + * "1, 2, 200", + * "11, 22, 400", + * "21, 31, 500" * ] *

* In each the above cases, the step will execute 3 times. @@ -64,7 +65,7 @@ public ZeroCodeParameterizedProcessorImpl(ObjectMapper objectMapper, CsvParser c @Override public ScenarioSpec resolveParameterized(ScenarioSpec scenario, int iteration) { - if(scenario.getParameterized() == null){ + if (scenario.getParameterized() == null) { return scenario; diff --git a/http-testing/src/main/java/org/jsmart/zerocode/zerocodejavaexec/httpclient/JustHelloWorldSuite.java b/http-testing/src/main/java/org/jsmart/zerocode/zerocodejavaexec/httpclient/JustHelloWorldSuite.java index 413cf203d..97e3e7d75 100644 --- a/http-testing/src/main/java/org/jsmart/zerocode/zerocodejavaexec/httpclient/JustHelloWorldSuite.java +++ b/http-testing/src/main/java/org/jsmart/zerocode/zerocodejavaexec/httpclient/JustHelloWorldSuite.java @@ -1,11 +1,8 @@ package org.jsmart.zerocode.zerocodejavaexec.httpclient; -import org.jsmart.zerocode.core.domain.Scenario; import org.jsmart.zerocode.core.domain.TargetEnv; import org.jsmart.zerocode.core.domain.TestPackageRoot; import org.jsmart.zerocode.core.runner.ZeroCodePackageRunner; -import org.jsmart.zerocode.core.runner.ZeroCodeUnitRunner; -import org.junit.Test; import org.junit.runner.RunWith; @TargetEnv("hello_github_host.properties") diff --git a/http-testing/src/test/java/org/jsmart/zerocode/testhelp/tests/helloworldparameterizedcsv/HelloWorldParameterizedCsvTest.java b/http-testing/src/test/java/org/jsmart/zerocode/testhelp/tests/helloworldparameterizedcsv/HelloWorldParameterizedCsvTest.java index e169a8a24..649bd8118 100644 --- a/http-testing/src/test/java/org/jsmart/zerocode/testhelp/tests/helloworldparameterizedcsv/HelloWorldParameterizedCsvTest.java +++ b/http-testing/src/test/java/org/jsmart/zerocode/testhelp/tests/helloworldparameterizedcsv/HelloWorldParameterizedCsvTest.java @@ -15,4 +15,9 @@ public class HelloWorldParameterizedCsvTest { public void testGetByUserNames_csv() throws Exception { } + @Test + @Scenario("parameterized_csv/hello_world_test_parameterized_csv_source_files.json") + public void testGetByUserNames_csvSourceFiles() throws Exception { + } + } diff --git a/http-testing/src/test/resources/parameterized_csv/hello_world_test_parameterized_csv_source_files.json b/http-testing/src/test/resources/parameterized_csv/hello_world_test_parameterized_csv_source_files.json new file mode 100644 index 000000000..264f96f66 --- /dev/null +++ b/http-testing/src/test/resources/parameterized_csv/hello_world_test_parameterized_csv_source_files.json @@ -0,0 +1,25 @@ +{ + "scenarioName": "Fetch and assert GitHub userIds by their userNames", + "steps": [ + { + "name": "get_user_details", + "url": "/users/${0}", + "method": "GET", + "request": { + }, + "assertions": { + "status": 200, + "body": { + "login" : "${0}", + "type" : "User", + "name" : "${1}", + "location" : "${2}", + "id" : "$EQ.${3}" + } + } + } + ], + "parameterized": { + "csvSource":"./src/test/resources/parameterized_csv/params.csv" + } +} diff --git a/http-testing/src/test/resources/parameterized_csv/params.csv b/http-testing/src/test/resources/parameterized_csv/params.csv new file mode 100644 index 000000000..faef91767 --- /dev/null +++ b/http-testing/src/test/resources/parameterized_csv/params.csv @@ -0,0 +1,2 @@ +octocat,The Octocat,San Francisco,583231 +siddhagalaxy,Sidd,UK,33847730 \ No newline at end of file From 5db65b47900d7885890089cd9cdc6eae45c67092 Mon Sep 17 00:00:00 2001 From: prashantmurkute Date: Sat, 23 Jan 2021 14:03:02 +0530 Subject: [PATCH 04/44] Added support to ignore header in CSV file --- .../zerocode/core/domain/Parameterized.java | 40 ++++++++++++++----- ...terized_csv_source_file_ignore_header.json | 26 ++++++++++++ .../parameterized_csv/params_with_header.csv | 3 ++ 3 files changed, 59 insertions(+), 10 deletions(-) create mode 100644 http-testing/src/test/resources/parameterized_csv/hello_world_test_parameterized_csv_source_file_ignore_header.json create mode 100644 http-testing/src/test/resources/parameterized_csv/params_with_header.csv diff --git a/core/src/main/java/org/jsmart/zerocode/core/domain/Parameterized.java b/core/src/main/java/org/jsmart/zerocode/core/domain/Parameterized.java index 2e24b65a4..2f85f4c5b 100644 --- a/core/src/main/java/org/jsmart/zerocode/core/domain/Parameterized.java +++ b/core/src/main/java/org/jsmart/zerocode/core/domain/Parameterized.java @@ -13,16 +13,20 @@ import java.nio.file.Paths; import java.util.Collections; import java.util.List; +import java.util.Optional; import java.util.stream.Collectors; public class Parameterized { private final List valueSource; private final List csvSource; + private final Boolean ignoreHeader; public Parameterized( @JsonProperty("valueSource") List valueSource, - @JsonProperty("csvSource") JsonNode csvSourceJsonNode) { + @JsonProperty("csvSource") JsonNode csvSourceJsonNode, + @JsonProperty("ignoreHeader") Boolean ignoreHeader) { this.valueSource = valueSource; + this.ignoreHeader = Optional.ofNullable(ignoreHeader).orElse(false); this.csvSource = getCsvSourceFrom(csvSourceJsonNode); } @@ -37,21 +41,37 @@ public List getCsvSource() { private List getCsvSourceFrom(JsonNode csvSourceJsonNode) { try { if (csvSourceJsonNode.isArray()) { - ObjectMapper mapper = new ObjectMapper(); - ObjectReader reader = mapper.readerFor(new TypeReference>() { - }); - return reader.readValue(csvSourceJsonNode); + return readCsvSourceFromJson(csvSourceJsonNode); } else { - String csvSourceFilePath = csvSourceJsonNode.textValue(); - if (StringUtils.isNotBlank(csvSourceFilePath)) { - Path path = Paths.get(csvSourceFilePath); - return Files.lines(path).collect(Collectors.toList()); - } + return readCsvSourceFromExternalCsvFile(csvSourceJsonNode); } } catch (IOException e) { throw new RuntimeException("Error deserializing csvSource", e); } + } + + private List readCsvSourceFromJson(JsonNode csvSourceJsonNode) throws IOException { + ObjectMapper mapper = new ObjectMapper(); + ObjectReader reader = mapper.readerFor(new TypeReference>() { + }); + return reader.readValue(csvSourceJsonNode); + } + + private List readCsvSourceFromExternalCsvFile(JsonNode csvSourceJsonNode) throws IOException { + String csvSourceFilePath = csvSourceJsonNode.textValue(); + if (StringUtils.isNotBlank(csvSourceFilePath)) { + Path path = Paths.get(csvSourceFilePath); + List csvSourceFileLines = Files.lines(path) + .filter(StringUtils::isNotBlank) + .collect(Collectors.toList()); + if (this.ignoreHeader) { + return csvSourceFileLines.stream() + .skip(1) + .collect(Collectors.toList()); + } + return csvSourceFileLines; + } return Collections.emptyList(); } diff --git a/http-testing/src/test/resources/parameterized_csv/hello_world_test_parameterized_csv_source_file_ignore_header.json b/http-testing/src/test/resources/parameterized_csv/hello_world_test_parameterized_csv_source_file_ignore_header.json new file mode 100644 index 000000000..48a7e741e --- /dev/null +++ b/http-testing/src/test/resources/parameterized_csv/hello_world_test_parameterized_csv_source_file_ignore_header.json @@ -0,0 +1,26 @@ +{ + "scenarioName": "Fetch and assert GitHub userIds by their userNames", + "steps": [ + { + "name": "get_user_details", + "url": "/users/${0}", + "method": "GET", + "request": { + }, + "assertions": { + "status": 200, + "body": { + "login" : "${0}", + "type" : "User", + "name" : "${1}", + "location" : "${2}", + "id" : "$EQ.${3}" + } + } + } + ], + "parameterized": { + "ignoreHeader": true, + "csvSource":"./src/test/resources/parameterized_csv/params_with_header.csv" + } +} diff --git a/http-testing/src/test/resources/parameterized_csv/params_with_header.csv b/http-testing/src/test/resources/parameterized_csv/params_with_header.csv new file mode 100644 index 000000000..3df16ea8d --- /dev/null +++ b/http-testing/src/test/resources/parameterized_csv/params_with_header.csv @@ -0,0 +1,3 @@ +user,name,city,userid +octocat,The Octocat,San Francisco,583231 +siddhagalaxy,Sidd,UK,33847730 \ No newline at end of file From 5f15cc8ec7eb385667184a7788a190770b2541aa Mon Sep 17 00:00:00 2001 From: prashantmurkute Date: Sat, 23 Jan 2021 14:28:24 +0530 Subject: [PATCH 05/44] Added Unit tests for Parameterized csv source from file --- .../core/domain/ParameterizedTest.java | 33 ++++++++++++++++++- ....1_parameterized_csv_source_from_file.json | 8 +++++ ...sv_source_from_file_containing_header.json | 9 +++++ .../engine_unit_test_jsons/params.csv | 2 ++ .../params_with_header.csv | 3 ++ 5 files changed, 54 insertions(+), 1 deletion(-) create mode 100755 core/src/test/resources/unit_test_files/engine_unit_test_jsons/08.1_parameterized_csv_source_from_file.json create mode 100755 core/src/test/resources/unit_test_files/engine_unit_test_jsons/08.2_parameterized_csv_source_from_file_containing_header.json create mode 100644 core/src/test/resources/unit_test_files/engine_unit_test_jsons/params.csv create mode 100644 core/src/test/resources/unit_test_files/engine_unit_test_jsons/params_with_header.csv diff --git a/core/src/test/java/org/jsmart/zerocode/core/domain/ParameterizedTest.java b/core/src/test/java/org/jsmart/zerocode/core/domain/ParameterizedTest.java index a2be5436d..09569bd21 100644 --- a/core/src/test/java/org/jsmart/zerocode/core/domain/ParameterizedTest.java +++ b/core/src/test/java/org/jsmart/zerocode/core/domain/ParameterizedTest.java @@ -10,7 +10,9 @@ import org.junit.Test; import org.junit.runner.RunWith; -import static org.hamcrest.CoreMatchers.hasItem; +import java.io.IOException; + +import static org.hamcrest.CoreMatchers.*; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; @@ -58,4 +60,33 @@ public void testSerDe_csvSource() throws Exception { assertThat(parameterized.getCsvSource(), hasItem("11, 22, 400")); } + @Test + public void shouldReadCsvSourceFromCsvFile() throws IOException { + //given + String jsonDocumentAsString = + smartUtils.getJsonDocumentAsString("unit_test_files/engine_unit_test_jsons/08.1_parameterized_csv_source_from_file.json"); + + //when + Parameterized parameterized = mapper.readValue(jsonDocumentAsString, Parameterized.class); + + //then + assertThat(parameterized.getCsvSource(), hasItem("octocat,The Octocat,San Francisco,583231")); + assertThat(parameterized.getCsvSource(), hasItem("siddhagalaxy,Sidd,UK,33847730")); + } + + @Test + public void shouldReadCsvSourceFromCsvFileIgnoringHeader() throws IOException { + //given + String jsonDocumentAsString = + smartUtils.getJsonDocumentAsString("unit_test_files/engine_unit_test_jsons/08.2_parameterized_csv_source_from_file_containing_header.json"); + + //when + Parameterized parameterized = mapper.readValue(jsonDocumentAsString, Parameterized.class); + + //then + assertThat(parameterized.getCsvSource(), hasItem("octocat,The Octocat,San Francisco,583231")); + assertThat(parameterized.getCsvSource(), hasItem("siddhagalaxy,Sidd,UK,33847730")); + assertThat(parameterized.getCsvSource(), everyItem(not(is("user,name,city,userid"))));//assert header is ignored + } + } \ No newline at end of file diff --git a/core/src/test/resources/unit_test_files/engine_unit_test_jsons/08.1_parameterized_csv_source_from_file.json b/core/src/test/resources/unit_test_files/engine_unit_test_jsons/08.1_parameterized_csv_source_from_file.json new file mode 100755 index 000000000..feedf0b89 --- /dev/null +++ b/core/src/test/resources/unit_test_files/engine_unit_test_jsons/08.1_parameterized_csv_source_from_file.json @@ -0,0 +1,8 @@ +{ + "valueSource": [ + "hello", + 123, + true + ], + "csvSource": "./src/test/resources/unit_test_files/engine_unit_test_jsons/params.csv" +} diff --git a/core/src/test/resources/unit_test_files/engine_unit_test_jsons/08.2_parameterized_csv_source_from_file_containing_header.json b/core/src/test/resources/unit_test_files/engine_unit_test_jsons/08.2_parameterized_csv_source_from_file_containing_header.json new file mode 100755 index 000000000..c7500a8c1 --- /dev/null +++ b/core/src/test/resources/unit_test_files/engine_unit_test_jsons/08.2_parameterized_csv_source_from_file_containing_header.json @@ -0,0 +1,9 @@ +{ + "valueSource": [ + "hello", + 123, + true + ], + "ignoreHeader": true, + "csvSource": "./src/test/resources/unit_test_files/engine_unit_test_jsons/params_with_header.csv" +} diff --git a/core/src/test/resources/unit_test_files/engine_unit_test_jsons/params.csv b/core/src/test/resources/unit_test_files/engine_unit_test_jsons/params.csv new file mode 100644 index 000000000..faef91767 --- /dev/null +++ b/core/src/test/resources/unit_test_files/engine_unit_test_jsons/params.csv @@ -0,0 +1,2 @@ +octocat,The Octocat,San Francisco,583231 +siddhagalaxy,Sidd,UK,33847730 \ No newline at end of file diff --git a/core/src/test/resources/unit_test_files/engine_unit_test_jsons/params_with_header.csv b/core/src/test/resources/unit_test_files/engine_unit_test_jsons/params_with_header.csv new file mode 100644 index 000000000..3df16ea8d --- /dev/null +++ b/core/src/test/resources/unit_test_files/engine_unit_test_jsons/params_with_header.csv @@ -0,0 +1,3 @@ +user,name,city,userid +octocat,The Octocat,San Francisco,583231 +siddhagalaxy,Sidd,UK,33847730 \ No newline at end of file From 8b5e52f5b0dd365f8d004d644127813a0506079d Mon Sep 17 00:00:00 2001 From: prashantmurkute Date: Sat, 23 Jan 2021 14:28:56 +0530 Subject: [PATCH 06/44] Added Integration tests for Parameterized csv source from file --- .../HelloWorldParameterizedCsvTest.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/http-testing/src/test/java/org/jsmart/zerocode/testhelp/tests/helloworldparameterizedcsv/HelloWorldParameterizedCsvTest.java b/http-testing/src/test/java/org/jsmart/zerocode/testhelp/tests/helloworldparameterizedcsv/HelloWorldParameterizedCsvTest.java index 649bd8118..6baea481e 100644 --- a/http-testing/src/test/java/org/jsmart/zerocode/testhelp/tests/helloworldparameterizedcsv/HelloWorldParameterizedCsvTest.java +++ b/http-testing/src/test/java/org/jsmart/zerocode/testhelp/tests/helloworldparameterizedcsv/HelloWorldParameterizedCsvTest.java @@ -20,4 +20,9 @@ public void testGetByUserNames_csv() throws Exception { public void testGetByUserNames_csvSourceFiles() throws Exception { } + @Test + @Scenario("parameterized_csv/hello_world_test_parameterized_csv_source_file_ignore_header.json") + public void testGetByUserNames_csvSourceFiles_ignoringHeader() throws Exception { + } + } From 0fa5260e4cd3c702ba6d9941ab8c906e484e342c Mon Sep 17 00:00:00 2001 From: prashantmurkute Date: Sat, 23 Jan 2021 16:42:00 +0530 Subject: [PATCH 07/44] Fixed failing tests --- .../ZeroCodeParameterizedProcessorImpl.java | 3 ++- .../zerocode/core/utils/SmartUtilsTest.java | 24 +++++++++---------- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/core/src/main/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeParameterizedProcessorImpl.java b/core/src/main/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeParameterizedProcessorImpl.java index 79d5518c0..5d627111a 100644 --- a/core/src/main/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeParameterizedProcessorImpl.java +++ b/core/src/main/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeParameterizedProcessorImpl.java @@ -4,6 +4,7 @@ import com.google.inject.Inject; import com.google.inject.Singleton; import com.univocity.parsers.csv.CsvParser; +import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.text.StrSubstitutor; import org.jsmart.zerocode.core.domain.ScenarioSpec; import org.slf4j.Logger; @@ -73,7 +74,7 @@ public ScenarioSpec resolveParameterized(ScenarioSpec scenario, int iteration) { return resolveParamsValues(scenario, iteration); - } else if (scenario.getParameterized().getCsvSource() != null) { + } else if (CollectionUtils.isNotEmpty(scenario.getParameterized().getCsvSource())) { return resolveParamsCsv(scenario, iteration); diff --git a/core/src/test/java/org/jsmart/zerocode/core/utils/SmartUtilsTest.java b/core/src/test/java/org/jsmart/zerocode/core/utils/SmartUtilsTest.java index 5e8374d0f..ad7ddb206 100644 --- a/core/src/test/java/org/jsmart/zerocode/core/utils/SmartUtilsTest.java +++ b/core/src/test/java/org/jsmart/zerocode/core/utils/SmartUtilsTest.java @@ -74,14 +74,14 @@ public void willGetJsonFileIntoA_JavaString() throws Exception { } @Test - public void willReadAllfileNamesFrom_TestResource() throws Exception { + public void willReadAllfileNamesFrom_TestResource() { List allTestCaseFiles = SmartUtils.getAllEndPointFiles("unit_test_files/engine_unit_test_jsons"); - assertThat(allTestCaseFiles.size(), is(18)); + assertThat(allTestCaseFiles.size(), is(20)); assertThat(allTestCaseFiles.get(0), is("unit_test_files/engine_unit_test_jsons/00_test_json_single_step_verifications.json")); } @Test - public void willReadAllfileNames_AND_return_FlowSpecList() throws Exception { + public void willReadAllfileNames_AND_return_FlowSpecList() { List allTestCaseFiles = smartUtils.getScenarioSpecListByPackage("unit_test_files/test_scenario_cases"); assertThat(allTestCaseFiles.size(), is(3)); @@ -91,19 +91,19 @@ public void willReadAllfileNames_AND_return_FlowSpecList() throws Exception { @Test(expected = RuntimeException.class) - public void willReadAllfiles_find_DuplicatesScenarioNamenames_old_style() throws Exception { + public void willReadAllfiles_find_DuplicatesScenarioNamenames_old_style() { smartUtils.checkDuplicateScenarios("unit_test_files/test_scenario_cases"); } @Test - public void willReadAllfiles_find_DuplicateScenarioNames() throws Exception { + public void willReadAllfiles_find_DuplicateScenarioNames() { expectedException.expect(RuntimeException.class); expectedException.expectMessage("Oops! Can not run with multiple Scenarios with same name."); smartUtils.checkDuplicateScenarios("unit_test_files/test_scenario_cases"); } @Test - public void willEvaluatePlaceHolder() throws Exception { + public void willEvaluatePlaceHolder() { String aString = "Hello_${WORLD}"; List placeHolders = getTestCaseTokens(aString); @@ -118,7 +118,7 @@ public void willEvaluatePlaceHolder() throws Exception { } @Test - public void testNullOrEmptyString_withPlaceHolders() throws Exception { + public void testNullOrEmptyString_withPlaceHolders() { String aString = ""; List placeHolders = getTestCaseTokens(aString); @@ -130,7 +130,7 @@ public void testNullOrEmptyString_withPlaceHolders() throws Exception { } @Test - public void testReplaceTokensOrPlaceHolders() throws Exception { + public void testReplaceTokensOrPlaceHolders() { String aString = "_${ENV_PROPERTY_NAME}"; Map paramMap = new HashMap<>(); @@ -142,7 +142,7 @@ public void testReplaceTokensOrPlaceHolders() throws Exception { } @Test - public void testEnvValue() throws Exception { + public void testEnvValue() { final String javaHomeValue = SmartUtils.getEnvPropertyValue("JAVA_HOME"); assertThat(javaHomeValue, notNullValue()); @@ -217,7 +217,7 @@ public void testScenarioFile_absolutePath() throws Exception { @Ignore("Tested in local laptop. Ignored for Ci build. Follow testSuiteFolder_absolutePath() like flow ") @Test - public void testSuiteFolder_symAbsolutePath() throws Exception { + public void testSuiteFolder_symAbsolutePath() { String absPath = "~/dev/ZEROCODE_REPOS/zerocode/core/src/test/resources/unit_test_files/cherry_pick_tests"; List allScenarios = SmartUtils.retrieveScenariosByAbsPath(absPath); assertThat(allScenarios.size(), is(2)); @@ -231,9 +231,7 @@ private static File createCascadeIfNotExisting(String fileName) { Path path = Paths.get(fileName); Files.createDirectories(path.getParent()); - File file = new File(fileName); - - return file; + return new File(fileName); } catch (IOException exx) { throw new RuntimeException("Create file '" + fileName + "' Exception" + exx); } From b5979b3a3119a69fecb42c1a678fd402293794c6 Mon Sep 17 00:00:00 2001 From: Vivek Kumar Date: Fri, 15 Dec 2023 23:57:08 +0530 Subject: [PATCH 08/44] ISSUE-601 # Resolve JSON.CONTENT as object or array --- .../ZeroCodeAssertionsProcessor.java | 4 ++ .../ZeroCodeAssertionsProcessorImpl.java | 71 +++++++++++++++++++ .../ZeroCodeExternalFileProcessorImpl.java | 23 ++---- .../engine/tokens/ZeroCodeValueTokens.java | 2 + .../ZeroCodeMultiStepsScenarioRunnerImpl.java | 2 + .../zerocode/core/utils/SmartUtils.java | 36 +++++++++- 6 files changed, 118 insertions(+), 20 deletions(-) diff --git a/core/src/main/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeAssertionsProcessor.java b/core/src/main/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeAssertionsProcessor.java index 4b844fdd6..0d5ac829c 100644 --- a/core/src/main/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeAssertionsProcessor.java +++ b/core/src/main/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeAssertionsProcessor.java @@ -1,5 +1,6 @@ package org.jsmart.zerocode.core.engine.preprocessor; +import org.jsmart.zerocode.core.domain.Step; import org.jsmart.zerocode.core.engine.assertion.FieldAssertionMatcher; import org.jsmart.zerocode.core.engine.assertion.JsonAsserter; @@ -18,4 +19,7 @@ public interface ZeroCodeAssertionsProcessor { List createJsonAsserters(String resolvedAssertionJson); List assertAllAndReturnFailed(List asserters, String executionResult); + + Step resolveJsonContent(Step thisStep, ScenarioExecutionState scenarioExecutionState); + } diff --git a/core/src/main/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeAssertionsProcessorImpl.java b/core/src/main/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeAssertionsProcessorImpl.java index 6eacf0c76..01e669bb4 100644 --- a/core/src/main/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeAssertionsProcessorImpl.java +++ b/core/src/main/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeAssertionsProcessorImpl.java @@ -1,5 +1,6 @@ package org.jsmart.zerocode.core.engine.preprocessor; +import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; @@ -20,11 +21,13 @@ import java.util.Properties; import net.minidev.json.JSONArray; import org.apache.commons.lang.text.StrSubstitutor; +import org.jsmart.zerocode.core.domain.Step; import org.jsmart.zerocode.core.engine.assertion.FieldAssertionMatcher; import org.jsmart.zerocode.core.engine.assertion.JsonAsserter; import org.jsmart.zerocode.core.engine.assertion.array.ArrayIsEmptyAsserterImpl; import org.jsmart.zerocode.core.engine.assertion.array.ArraySizeAsserterImpl; import org.jsmart.zerocode.core.engine.assertion.field.*; +import org.jsmart.zerocode.core.utils.SmartUtils; import static java.lang.Integer.valueOf; import static java.lang.String.format; @@ -32,10 +35,17 @@ import static org.apache.commons.lang.StringUtils.substringBetween; import static org.jsmart.zerocode.core.engine.tokens.ZeroCodeAssertionTokens.*; import static org.jsmart.zerocode.core.engine.tokens.ZeroCodeValueTokens.$VALUE; +import static org.jsmart.zerocode.core.engine.tokens.ZeroCodeValueTokens.JSON_CONTENT; +import static org.jsmart.zerocode.core.engine.tokens.ZeroCodeValueTokens.JSON_PAYLOAD_FILE; +import static org.jsmart.zerocode.core.engine.tokens.ZeroCodeValueTokens.YAML_PAYLOAD_FILE; import static org.jsmart.zerocode.core.utils.FieldTypeConversionUtils.deepTypeCast; import static org.jsmart.zerocode.core.utils.FieldTypeConversionUtils.fieldTypes; import static org.jsmart.zerocode.core.utils.PropertiesProviderUtils.loadAbsoluteProperties; import static org.jsmart.zerocode.core.utils.SmartUtils.isValidAbsolutePath; +import static org.jsmart.zerocode.core.utils.SmartUtils.readJsonAsString; +import static org.jsmart.zerocode.core.utils.SmartUtils.readYamlAsString; +import static org.jsmart.zerocode.core.utils.SmartUtils.checkDigNeeded;; +import static org.jsmart.zerocode.core.utils.SmartUtils.getJsonFilePhToken;; import static org.jsmart.zerocode.core.utils.TokenUtils.getTestCaseTokens; import static org.jsmart.zerocode.core.utils.TokenUtils.populateParamMap; import static org.slf4j.LoggerFactory.getLogger; @@ -337,6 +347,39 @@ public List assertAllAndReturnFailed(List a return failedReports; } + /** + * Resolves JSON.CONTENT as object or array + * + * First the logic checks if dig-deep needed to avoid unwanted recursions. If not needed, the step definition is + * returned intact. Otherwise calls the dig deep method to perform the operation. + * + * @param thisStep + * @return The effective step definition + */ + @Override + public Step resolveJsonContent(Step thisStep, ScenarioExecutionState scenarioExecutionState) { + try { + if (!checkDigNeeded(mapper, thisStep, JSON_CONTENT)) { + return thisStep; + } + + JsonNode stepNode = mapper.convertValue(thisStep, JsonNode.class); + + Map stepMap = mapper.readValue(stepNode.toString(), new TypeReference>() { + }); + + digReplaceContent(stepMap, scenarioExecutionState); + + JsonNode jsonStepNode = mapper.valueToTree(stepMap); + + return mapper.treeToValue(jsonStepNode, Step.class); + + } catch (Exception e) { + LOGGER.error("Json content reading exception - {}", e.getMessage()); + throw new RuntimeException("Json content reading exception. Details - " + e); + } + } + private void loadAnnotatedHostProperties() { try { if(isValidAbsolutePath(hostFileName)){ @@ -408,4 +451,32 @@ private boolean hasNoTypeCast(String resolvedJson) { } + private void digReplaceContent(Map map, ScenarioExecutionState scenarioExecutionState) { + map.entrySet().forEach(entry -> { + Object value = entry.getValue(); + + if (value instanceof Map) { + digReplaceContent((Map) value, scenarioExecutionState); + } else { + LOGGER.debug("Leaf node found = {}, checking for any json content...", value); + if (value != null && (value.toString().contains(JSON_CONTENT))) { + LOGGER.debug("Found JSON content place holder = {}. Replacing with content", value); + String valueString = value.toString(); + String token = getJsonFilePhToken(valueString); + + if (token != null && (token.startsWith(JSON_CONTENT))) { + try { + String resolvedRequestJson = resolveStringJson( + "${" + token.substring(JSON_CONTENT.length()) + "}", + scenarioExecutionState.getResolvedScenarioState()); + entry.setValue(resolvedRequestJson); + } catch (Exception exx) { + LOGGER.error("External file reference exception - {}", exx.getMessage()); + throw new RuntimeException(exx); + } + } + } + } + }); + } } diff --git a/core/src/main/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeExternalFileProcessorImpl.java b/core/src/main/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeExternalFileProcessorImpl.java index daf3ac329..b34fd1c00 100644 --- a/core/src/main/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeExternalFileProcessorImpl.java +++ b/core/src/main/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeExternalFileProcessorImpl.java @@ -13,12 +13,15 @@ import com.google.inject.name.Named; import org.jsmart.zerocode.core.domain.Step; +import org.jsmart.zerocode.core.utils.SmartUtils; import org.slf4j.Logger; import static org.jsmart.zerocode.core.engine.tokens.ZeroCodeValueTokens.JSON_PAYLOAD_FILE; import static org.jsmart.zerocode.core.engine.tokens.ZeroCodeValueTokens.YAML_PAYLOAD_FILE; import static org.jsmart.zerocode.core.utils.SmartUtils.readJsonAsString; import static org.jsmart.zerocode.core.utils.SmartUtils.readYamlAsString; +import static org.jsmart.zerocode.core.utils.SmartUtils.checkDigNeeded; +import static org.jsmart.zerocode.core.utils.SmartUtils.getJsonFilePhToken; import static org.jsmart.zerocode.core.utils.TokenUtils.getTestCaseTokens; import static org.slf4j.LoggerFactory.getLogger; @@ -69,7 +72,7 @@ public Step resolveExtJsonFile(Step thisStep) { try { - if (!checkDigNeeded(thisStep)) { + if (!checkDigNeeded(objectMapper, thisStep, JSON_PAYLOAD_FILE, YAML_PAYLOAD_FILE)) { return thisStep; } @@ -176,22 +179,4 @@ else if (token != null && token.startsWith(OTHER_FILE)) { } }); } - - private String getJsonFilePhToken(String valueString) { - if (valueString != null) { - List allTokens = getTestCaseTokens(valueString); - if (allTokens != null && !allTokens.isEmpty()) { - return allTokens.get(0); - } - } - return null; - } - - boolean checkDigNeeded(Step thisStep) throws JsonProcessingException { - String stepJson = objectMapper.writeValueAsString(thisStep); - List allTokens = getTestCaseTokens(stepJson); - - return allTokens.toString().contains(JSON_PAYLOAD_FILE) || allTokens.toString().contains(YAML_PAYLOAD_FILE); - } - } diff --git a/core/src/main/java/org/jsmart/zerocode/core/engine/tokens/ZeroCodeValueTokens.java b/core/src/main/java/org/jsmart/zerocode/core/engine/tokens/ZeroCodeValueTokens.java index 496fda747..3104c7a16 100644 --- a/core/src/main/java/org/jsmart/zerocode/core/engine/tokens/ZeroCodeValueTokens.java +++ b/core/src/main/java/org/jsmart/zerocode/core/engine/tokens/ZeroCodeValueTokens.java @@ -31,6 +31,8 @@ public class ZeroCodeValueTokens { public static final String SYSTEM_ENV = "SYSTEM.ENV:"; public static final String $VALUE = ".$VALUE"; public static final String ABS_PATH = "ABS.PATH:"; + public static final String JSON_CONTENT = "JSON.CONTENT:"; + public static Map globalTokenCache = new HashMap<>(); diff --git a/core/src/main/java/org/jsmart/zerocode/core/runner/ZeroCodeMultiStepsScenarioRunnerImpl.java b/core/src/main/java/org/jsmart/zerocode/core/runner/ZeroCodeMultiStepsScenarioRunnerImpl.java index 4f7e7d05b..fd9190e76 100644 --- a/core/src/main/java/org/jsmart/zerocode/core/runner/ZeroCodeMultiStepsScenarioRunnerImpl.java +++ b/core/src/main/java/org/jsmart/zerocode/core/runner/ZeroCodeMultiStepsScenarioRunnerImpl.java @@ -181,6 +181,8 @@ private Boolean executeRetryWithSteps(RunNotifier notifier, ScenarioExecutionState scenarioExecutionState, ScenarioSpec scenario, Step thisStep) { thisStep = extFileProcessor.resolveExtJsonFile(thisStep); + thisStep = zeroCodeAssertionsProcessor.resolveJsonContent(thisStep, scenarioExecutionState); + List thisSteps = extFileProcessor.createFromStepFile(thisStep, thisStep.getId()); if(null == thisSteps || thisSteps.isEmpty()) thisSteps.add(thisStep); Boolean wasExecSuccess = null; diff --git a/core/src/main/java/org/jsmart/zerocode/core/utils/SmartUtils.java b/core/src/main/java/org/jsmart/zerocode/core/utils/SmartUtils.java index 528659a26..bdea084bf 100644 --- a/core/src/main/java/org/jsmart/zerocode/core/utils/SmartUtils.java +++ b/core/src/main/java/org/jsmart/zerocode/core/utils/SmartUtils.java @@ -27,10 +27,10 @@ import java.util.Map; import java.util.Set; import java.util.stream.Collectors; -import java.util.stream.Stream; import org.apache.commons.lang.text.StrSubstitutor; import org.jsmart.zerocode.core.di.provider.ObjectMapperProvider; import org.jsmart.zerocode.core.domain.ScenarioSpec; +import org.jsmart.zerocode.core.domain.Step; import org.jsmart.zerocode.core.engine.assertion.FieldAssertionMatcher; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -39,7 +39,10 @@ import static java.nio.charset.StandardCharsets.UTF_8; import static org.jsmart.zerocode.core.engine.assertion.FieldAssertionMatcher.aMatchingMessage; import static org.jsmart.zerocode.core.engine.assertion.FieldAssertionMatcher.aNotMatchingMessage; +import static org.jsmart.zerocode.core.engine.tokens.ZeroCodeValueTokens.JSON_PAYLOAD_FILE; +import static org.jsmart.zerocode.core.engine.tokens.ZeroCodeValueTokens.YAML_PAYLOAD_FILE; import static org.jsmart.zerocode.core.utils.PropertiesProviderUtils.loadAbsoluteProperties; +import static org.jsmart.zerocode.core.utils.TokenUtils.getTestCaseTokens; import static org.skyscreamer.jsonassert.JSONAssert.assertEquals; import static org.skyscreamer.jsonassert.JSONCompareMode.STRICT; @@ -240,4 +243,35 @@ public static String getEnvPropertyValue(String envPropertyKey) { return System.getenv(envPropertyKey); } } + + /** + * + * @param thisStep --> Currently executing step + * @param tokenString --> JSON_PAYLAOD_FILE or JSON_CONTENT + * @return if there is a match for the token, then the json traversal will happen + * @throws JsonProcessingException + */ + public static boolean checkDigNeeded(ObjectMapper mapper, Step thisStep, String tokenString) throws JsonProcessingException { + String stepJson = mapper.writeValueAsString(thisStep); + List allTokens = getTestCaseTokens(stepJson); + + return allTokens.toString().contains(tokenString); + } + public static boolean checkDigNeeded(ObjectMapper mapper, Step thisStep, String tokenString, String alternateTokenString) throws JsonProcessingException { + String stepJson = mapper.writeValueAsString(thisStep); + List allTokens = getTestCaseTokens(stepJson); + + return allTokens.toString().contains(tokenString) || allTokens.toString().contains(alternateTokenString); + } + + public static String getJsonFilePhToken(String valueString) { + if (valueString != null) { + List allTokens = getTestCaseTokens(valueString); + if (allTokens != null && !allTokens.isEmpty()) { + return allTokens.get(0); + } + } + return null; + } + } From 4206fa255232f52c532ea742f68a576de059b935 Mon Sep 17 00:00:00 2001 From: authorjapps Date: Sat, 16 Dec 2023 23:14:02 +0000 Subject: [PATCH 09/44] Method doc updated --- .../java/org/jsmart/zerocode/core/utils/SmartUtils.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/core/src/main/java/org/jsmart/zerocode/core/utils/SmartUtils.java b/core/src/main/java/org/jsmart/zerocode/core/utils/SmartUtils.java index bdea084bf..819746ff0 100644 --- a/core/src/main/java/org/jsmart/zerocode/core/utils/SmartUtils.java +++ b/core/src/main/java/org/jsmart/zerocode/core/utils/SmartUtils.java @@ -264,6 +264,13 @@ public static boolean checkDigNeeded(ObjectMapper mapper, Step thisStep, String return allTokens.toString().contains(tokenString) || allTokens.toString().contains(alternateTokenString); } + /** + * Retrieves the first token from the given value string that matches the format "${token}". + * Ph = Placeholder (e.g. ${JSON.FILE:unit_test_files/filebody_unit_test/common/common_content.json} ) + * + * @param valueString The string from which to extract the jsonfile path + * @return The extracted token, or null if no token is found + */ public static String getJsonFilePhToken(String valueString) { if (valueString != null) { List allTokens = getTestCaseTokens(valueString); From 6b2121e478a1912e314e845aeb86c53411230a29 Mon Sep 17 00:00:00 2001 From: Baule A <65255151+baulea@users.noreply.github.com> Date: Fri, 27 Oct 2023 21:19:33 +0200 Subject: [PATCH 10/44] consolidate maven plugins Move maven plugin versions and configuration to section in parent.pom. Upgrade maven plugin versions. Fix warnings during maven build regarding missing version for maven-compiler-plugin [WARNING] [WARNING] Some problems were encountered while building the effective model for org.jsmart:http-testing:jar:1.3.36-SNAPSHOT [WARNING] 'build.plugins.plugin.version' for org.apache.maven.plugins:maven-compiler-plugin is missing. @ line 50, column 21 [WARNING] [WARNING] Some problems were encountered while building the effective model for org.jsmart:kafka-testing:jar:1.3.36-SNAPSHOT [WARNING] 'build.plugins.plugin.version' for org.apache.maven.plugins:maven-compiler-plugin is missing. @ line 56, column 12 [WARNING] [WARNING] Some problems were encountered while building the effective model for org.jsmart:zerocode-tdd-jupiter:jar:1.3.36-SNAPSHOT [WARNING] 'build.plugins.plugin.version' for org.apache.maven.plugins:maven-compiler-plugin is missing. @ line 145, column 21 [WARNING] [WARNING] It is highly recommended to fix these problems because they threaten the stability of your build. [WARNING] [WARNING] For this reason, future Maven versions might no longer support building such malformed projects. [WARNING] --- core/pom.xml | 15 ------ http-testing/pom.xml | 5 -- junit5-testing/pom.xml | 5 -- kafka-testing/pom.xml | 5 -- pom.xml | 101 +++++++++++++++++++++++++++++++++-------- 5 files changed, 81 insertions(+), 50 deletions(-) diff --git a/core/pom.xml b/core/pom.xml index de612cc51..8f0d66fb4 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -201,11 +201,6 @@ org.apache.maven.plugins maven-compiler-plugin - ${maven-compiler-plugin.version} - - ${java-compiler-source.version} - ${java-compiler-target.version} - @@ -218,20 +213,13 @@ - org.apache.maven.plugins maven-compiler-plugin - ${maven-compiler-plugin.version} - - ${java-compiler-source.version} - ${java-compiler-target.version} - org.apache.maven.plugins maven-source-plugin - 2.2.1 attach-sources @@ -244,7 +232,6 @@ org.apache.maven.plugins maven-javadoc-plugin - attach-javadocs @@ -257,7 +244,6 @@ org.apache.maven.plugins maven-gpg-plugin - 1.5 sign-artifacts @@ -283,7 +269,6 @@ org.apache.maven.plugins maven-release-plugin - 2.5 true false diff --git a/http-testing/pom.xml b/http-testing/pom.xml index 7e2b18472..f36788a06 100644 --- a/http-testing/pom.xml +++ b/http-testing/pom.xml @@ -50,15 +50,10 @@ org.apache.maven.plugins maven-compiler-plugin - - ${java.version} - ${java.version} - org.apache.maven.plugins maven-surefire-plugin - 2.19.1 org.jsmart.zerocode.testhelp.tests.MockServerTest diff --git a/junit5-testing/pom.xml b/junit5-testing/pom.xml index 03cbdcdeb..7fdc97a42 100644 --- a/junit5-testing/pom.xml +++ b/junit5-testing/pom.xml @@ -145,15 +145,10 @@ org.apache.maven.plugins maven-compiler-plugin - - ${java.version} - ${java.version} - org.apache.maven.plugins maven-surefire-plugin - 3.0.0-M3 diff --git a/kafka-testing/pom.xml b/kafka-testing/pom.xml index 0a15cbefb..3d34893d1 100644 --- a/kafka-testing/pom.xml +++ b/kafka-testing/pom.xml @@ -56,15 +56,10 @@ org.apache.maven.plugins maven-compiler-plugin - - ${java.version} - ${java.version} - org.apache.maven.plugins maven-surefire-plugin - 2.19.1 org.jsmart.zerocode.integration.tests.kafka.KafkaSuite diff --git a/pom.xml b/pom.xml index e19726b09..ad246b382 100644 --- a/pom.xml +++ b/pom.xml @@ -85,11 +85,19 @@ 3.3.1 2.6.2 2.8.2 + - 3.2 + 3.11.0 1.8 1.8 - 2.5.4 + 3.6.0 + 3.3.0 + 3.6.0 + 3.1.0 + 3.0.1 + 3.2.1 + 3.6.1 + false 3.13.0 @@ -281,24 +289,77 @@ + + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + ${java-compiler-source.version} + ${java-compiler-target.version} + + + + org.apache.maven.plugins + maven-assembly-plugin + ${maven-assembly-plugin.version} + + + org.apache.maven.plugins + maven-source-plugin + ${maven-source-plugin.version} + + + org.apache.maven.plugins + maven-javadoc-plugin + ${maven-javadoc-plugin.version} + + + org.apache.maven.plugins + maven-gpg-plugin + ${maven-gpg-plugin.version} + + + org.apache.maven.plugins + maven-release-plugin + ${maven-release-plugin.version} + + + org.apache.maven.plugins + maven-surefire-plugin + ${maven-surefire-plugin.version} + + + org.apache.maven.plugins + maven-dependency-plugin + ${maven-dependency-plugin.version} + + + + - + + org.apache.maven.plugins + maven-shade-plugin + + false + + + + package + + shade + + + + + + --> + + From 1633e740059effbdc7e6b8c913bf8f78749e2a97 Mon Sep 17 00:00:00 2001 From: Baule A <65255151+baulea@users.noreply.github.com> Date: Sun, 29 Oct 2023 15:24:49 +0100 Subject: [PATCH 11/44] upgrade multiple dependencies upgrade dependencies in pom.xml: - upgrade org.jukito:jukito from 1.4.1 to 1.5 - upgrade commons-io:commons-io:2.4 to 2.15.0 - upgrade com.aventstack:extentreports:4.0.9 to 5.0.9 - upgrade com.google.code.gson:gson:2.6.2 to 2.10.1 - upgrade com.google.protobuf:protobuf-java:3.13.0 to 3.24.4 with upgrade com.aventstack:extentreports:4.0.9 to 5.0.9 replace ExtentHtmlReporter with ExtentSparkReporter in ExtentReportsFactory.java change in core/pom.xml: - set test scope for org.jukito:jukito - remove unused dependency com.fasterxml.jackson.datatype:jackson-datatype-jdk8 - remove direct dependency ch.qos.logback:logback-core, because it is a direct dependency from ch.qos.logback:logback-classic - add direct dependency org.apache.httpcomponents:httpmime:4.5.12 change in kafka-testing/pom.xml: - remove com.google.protobuf:protobuf-java-util - remove dependency for com.github.os72:protoc-jar --- core/pom.xml | 15 +++++-------- .../domain/builders/ExtentReportsFactory.java | 21 ++++++++++--------- kafka-testing/pom.xml | 9 -------- pom.xml | 21 ++++++++++--------- 4 files changed, 27 insertions(+), 39 deletions(-) diff --git a/core/pom.xml b/core/pom.xml index 8f0d66fb4..3aa0f7158 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -50,7 +50,6 @@ 4.12 - 2.6.2 @@ -103,10 +102,6 @@ ch.qos.logback logback-classic - - ch.qos.logback - logback-core - org.jboss.resteasy @@ -127,6 +122,7 @@ org.jukito jukito + test com.google.inject @@ -152,10 +148,6 @@ com.fasterxml.jackson.core jackson-databind - - com.fasterxml.jackson.datatype - jackson-datatype-jdk8 - junit junit @@ -164,7 +156,10 @@ org.apache.httpcomponents httpclient - ${httpclient.version} + + + org.apache.httpcomponents + httpmime org.jsmart diff --git a/core/src/main/java/org/jsmart/zerocode/core/domain/builders/ExtentReportsFactory.java b/core/src/main/java/org/jsmart/zerocode/core/domain/builders/ExtentReportsFactory.java index 929e85092..434cf5590 100644 --- a/core/src/main/java/org/jsmart/zerocode/core/domain/builders/ExtentReportsFactory.java +++ b/core/src/main/java/org/jsmart/zerocode/core/domain/builders/ExtentReportsFactory.java @@ -1,7 +1,8 @@ package org.jsmart.zerocode.core.domain.builders; import com.aventstack.extentreports.ExtentReports; -import com.aventstack.extentreports.reporter.ExtentHtmlReporter; +import com.aventstack.extentreports.reporter.ExtentSparkReporter; + import java.util.HashMap; import java.util.Map; import java.util.Properties; @@ -14,14 +15,14 @@ public class ExtentReportsFactory { private static final org.slf4j.Logger LOGGER = getLogger(ExtentReportsFactory.class); - private static ExtentHtmlReporter extentHtmlReporter; + private static ExtentSparkReporter extentSparkReporter; private static ExtentReports extentReports; private static Map systemProperties = new HashMap<>(); public static ExtentReports createReportTheme(String reportFileName) { - ExtentHtmlReporter extentHtmlReporter = createExtentHtmlReporter(reportFileName); + ExtentSparkReporter extentHtmlReporter = createExtentHtmlReporter(reportFileName); extentReports = new ExtentReports(); @@ -52,14 +53,14 @@ public static void attachSystemInfo() { extentReports.setSystemInfo("Java Vendor : ", javaVendor); } - public static ExtentHtmlReporter createExtentHtmlReporter(String reportFileName) { - extentHtmlReporter = new ExtentHtmlReporter(reportFileName); + public static ExtentSparkReporter createExtentHtmlReporter(String reportFileName) { + extentSparkReporter = new ExtentSparkReporter(reportFileName); - extentHtmlReporter.config().setDocumentTitle(REPORT_TITLE_DEFAULT); - extentHtmlReporter.config().setReportName(REPORT_DISPLAY_NAME_DEFAULT); + extentSparkReporter.config().setDocumentTitle(REPORT_TITLE_DEFAULT); + extentSparkReporter.config().setReportName(REPORT_DISPLAY_NAME_DEFAULT); - return extentHtmlReporter; + return extentSparkReporter; } @@ -88,11 +89,11 @@ public static Map getSystemProperties() { } public static void reportName(String reportName) { - extentHtmlReporter.config().setReportName(reportName); + extentSparkReporter.config().setReportName(reportName); } public static String getReportName() { - return extentHtmlReporter.config().getReportName(); + return extentSparkReporter.config().getReportName(); } } diff --git a/kafka-testing/pom.xml b/kafka-testing/pom.xml index 3d34893d1..db278f9fe 100644 --- a/kafka-testing/pom.xml +++ b/kafka-testing/pom.xml @@ -31,10 +31,6 @@ com.google.protobuf protobuf-java - - com.google.protobuf - protobuf-java-util - org.apache.kafka kafka-clients @@ -44,11 +40,6 @@ kafka-avro-serializer 5.1.0 - - com.github.os72 - protoc-jar - 3.11.4 - diff --git a/pom.xml b/pom.xml index ad246b382..ec48bdc66 100644 --- a/pom.xml +++ b/pom.xml @@ -68,7 +68,7 @@ 23.0 1.5.0 1.0 - 1.4.1 + 1.5 4.0 2.6 2.2.0 @@ -77,13 +77,14 @@ 2.19.0 1.7 2.9.8 - 2.4 + 2.15.0 1.1.10 4.5 + 4.5.12 1.4.191 - 4.0.9 + 5.0.9 3.3.1 - 2.6.2 + 2.10.1 2.8.2 @@ -100,7 +101,7 @@ false - 3.13.0 + 3.24.4 1.1.8.4 @@ -176,11 +177,6 @@ logback-classic ${logback.version} - - ch.qos.logback - logback-core - ${logback.version} - org.jboss.resteasy @@ -253,6 +249,11 @@ httpclient ${httpclient.version} + + org.apache.httpcomponents + httpmime + ${httpmime.version} + org.jsmart micro-simulator From 5a71432683b6964b05b99b68cbb222883a661fbd Mon Sep 17 00:00:00 2001 From: Vivek Kumar Date: Tue, 19 Dec 2023 23:12:00 +0530 Subject: [PATCH 12/44] ISSUE-601 # fix failing test --- .../ZeroCodeExternalFileProcessorImplTest.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/core/src/test/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeExternalFileProcessorImplTest.java b/core/src/test/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeExternalFileProcessorImplTest.java index 2cd3f7da2..e30837331 100644 --- a/core/src/test/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeExternalFileProcessorImplTest.java +++ b/core/src/test/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeExternalFileProcessorImplTest.java @@ -4,7 +4,10 @@ import com.fasterxml.jackson.databind.ObjectMapper; import org.jsmart.zerocode.core.di.provider.ObjectMapperProvider; import org.jsmart.zerocode.core.domain.Step; +import org.jsmart.zerocode.core.engine.tokens.ZeroCodeValueTokens; import org.junit.Test; +import static org.jsmart.zerocode.core.utils.SmartUtils.checkDigNeeded; + import java.io.IOException; import java.util.Map; @@ -79,11 +82,11 @@ public void test_NoExtJsonFile() throws IOException { public void test_NoExtFileCheckDigNeeded() throws IOException { String jsonAsString = readJsonAsString("unit_test_files/filebody_unit_test/json_step_no_ext_json_test_file.json"); Step step = objectMapper.readValue(jsonAsString, Step.class); - assertThat(externalFileProcessor.checkDigNeeded(step), is(false)); + assertThat(checkDigNeeded(objectMapper, step, ZeroCodeValueTokens.JSON_PAYLOAD_FILE, ZeroCodeValueTokens.YAML_PAYLOAD_FILE), is(false)); jsonAsString = readJsonAsString("unit_test_files/filebody_unit_test/json_step_text_node_ext_json_file_test.json"); step = objectMapper.readValue(jsonAsString, Step.class); - assertThat(externalFileProcessor.checkDigNeeded(step), is(true)); + assertThat(checkDigNeeded(objectMapper, step, ZeroCodeValueTokens.JSON_PAYLOAD_FILE, ZeroCodeValueTokens.YAML_PAYLOAD_FILE), is(true)); } @Test From ac5eb574f782c191eac083f4b23d6594522b3928 Mon Sep 17 00:00:00 2001 From: Vivek Kumar Date: Tue, 19 Dec 2023 23:58:09 +0530 Subject: [PATCH 13/44] ISSUE-601 # Add Unit tests for JSON Content --- .../ZeroCodeAssertionsProcessorImpl.java | 2 +- .../ZeroCodeAssertionsProcessorImplTest.java | 32 +++++++++++++++ .../json_step_no_json_content_test.json | 21 ++++++++++ .../json_step_test_json_content.json | 41 +++++++++++++++++++ .../json_step_test_wrong_json_path.json | 22 ++++++++++ 5 files changed, 117 insertions(+), 1 deletion(-) create mode 100644 core/src/test/resources/unit_test_files/json_content_unit_test/json_step_no_json_content_test.json create mode 100644 core/src/test/resources/unit_test_files/json_content_unit_test/json_step_test_json_content.json create mode 100644 core/src/test/resources/unit_test_files/json_content_unit_test/json_step_test_wrong_json_path.json diff --git a/core/src/main/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeAssertionsProcessorImpl.java b/core/src/main/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeAssertionsProcessorImpl.java index 01e669bb4..57cc6e0df 100644 --- a/core/src/main/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeAssertionsProcessorImpl.java +++ b/core/src/main/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeAssertionsProcessorImpl.java @@ -451,7 +451,7 @@ private boolean hasNoTypeCast(String resolvedJson) { } - private void digReplaceContent(Map map, ScenarioExecutionState scenarioExecutionState) { + void digReplaceContent(Map map, ScenarioExecutionState scenarioExecutionState) { map.entrySet().forEach(entry -> { Object value = entry.getValue(); diff --git a/core/src/test/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeAssertionsProcessorImplTest.java b/core/src/test/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeAssertionsProcessorImplTest.java index 531878755..ed98c96c8 100644 --- a/core/src/test/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeAssertionsProcessorImplTest.java +++ b/core/src/test/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeAssertionsProcessorImplTest.java @@ -1,17 +1,25 @@ package org.jsmart.zerocode.core.engine.preprocessor; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.inject.Guice; import com.google.inject.Injector; import com.jayway.jsonpath.JsonPath; + +import java.io.IOException; import java.util.HashMap; import java.util.List; import java.util.Map; + +import org.hamcrest.core.Is; import org.jsmart.zerocode.core.di.main.ApplicationMainModule; import org.jsmart.zerocode.core.di.provider.ObjectMapperProvider; import org.jsmart.zerocode.core.domain.ScenarioSpec; +import org.jsmart.zerocode.core.domain.Step; import org.jsmart.zerocode.core.engine.assertion.FieldAssertionMatcher; import org.jsmart.zerocode.core.engine.assertion.JsonAsserter; +import org.jsmart.zerocode.core.engine.tokens.ZeroCodeValueTokens; import org.jsmart.zerocode.core.utils.SmartUtils; import org.junit.Before; import org.junit.Rule; @@ -21,6 +29,8 @@ import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.not; +import static org.jsmart.zerocode.core.utils.SmartUtils.checkDigNeeded; +import static org.jsmart.zerocode.core.utils.SmartUtils.readJsonAsString; import static org.jsmart.zerocode.core.utils.TokenUtils.getTestCaseTokens; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertThat; @@ -1449,4 +1459,26 @@ public void testLeafValuesArray_badIndex() { expectedException.expect(IndexOutOfBoundsException.class); jsonPreProcessor.resolveLeafOnlyNodeValue(scenarioState, paramMap, thisPath); } + + @Test(expected = RuntimeException.class) + public void test_wrongJsonPath() throws JsonProcessingException { + String jsonAsString = readJsonAsString("unit_test_files/json_content_unit_test/json_step_test_wrong_json_path.json"); + Map map = mapper.readValue(jsonAsString, new TypeReference>() {}); + + jsonPreProcessor.digReplaceContent(map, new ScenarioExecutionState()); + } + + @Test + public void test_NoJSONContentCheckDigNeeded() throws IOException { + String jsonAsString = readJsonAsString("unit_test_files/json_content_unit_test/json_step_no_json_content_test.json"); + Step step = mapper.readValue(jsonAsString, Step.class); + assertThat(checkDigNeeded(mapper, step, ZeroCodeValueTokens.JSON_CONTENT), Is.is(false)); + + + ScenarioSpec scenarioSpec = + smartUtils.scenarioFileToJava( + "unit_test_files/json_content_unit_test/json_step_test_json_content.json", ScenarioSpec.class); + step = scenarioSpec.getSteps().get(1); + assertThat(checkDigNeeded(mapper, step, ZeroCodeValueTokens.JSON_CONTENT), Is.is(true)); + } } diff --git a/core/src/test/resources/unit_test_files/json_content_unit_test/json_step_no_json_content_test.json b/core/src/test/resources/unit_test_files/json_content_unit_test/json_step_no_json_content_test.json new file mode 100644 index 000000000..271d22bf6 --- /dev/null +++ b/core/src/test/resources/unit_test_files/json_content_unit_test/json_step_no_json_content_test.json @@ -0,0 +1,21 @@ +{ + "name": "get_user_details", + "url": "/api/v1/employees/${$.create_emp.response.body.id}", + "method": "GET", + "request": { + "body" : { + "fullName":"Bob Luis", + "empLogin":"bolu_lon", + "type":"CONTRACT" + } + }, + "verify": { + "status": 200, + "body": { + "id": 39001, + "ldapId": "emmanorton", + "name": "Emma", + "surName": "Norton" + } + } +} diff --git a/core/src/test/resources/unit_test_files/json_content_unit_test/json_step_test_json_content.json b/core/src/test/resources/unit_test_files/json_content_unit_test/json_step_test_json_content.json new file mode 100644 index 000000000..3ed60699e --- /dev/null +++ b/core/src/test/resources/unit_test_files/json_content_unit_test/json_step_test_json_content.json @@ -0,0 +1,41 @@ +{ + "scenarioName": "POST API - File json as request content - Reuse body", + "steps": [ + { + "name": "create_emp", + "url": "/api/v1/employees", + "method": "POST", + "request": { + "body": { + "name": "Emma", + "surName": "Norton" + } + }, + "verify": { + "status": 201 + } + }, + { + "name": "get_user_details", + "url": "/api/v1/employees/${$.create_emp.response.body.id}", + "method": "GET", + "request": { + "body": { + "fullName": "Bob Luis", + "empLogin": "bolu_lon", + "type": "CONTRACT", + "address": "${JSON.CONTENT:$.create_emp.response.body.id}" + } + }, + "verify": { + "status": 200, + "body": { + "id": 39001, + "ldapId": "emmanorton", + "name": "Emma", + "surName": "Norton" + } + } + } + ] +} diff --git a/core/src/test/resources/unit_test_files/json_content_unit_test/json_step_test_wrong_json_path.json b/core/src/test/resources/unit_test_files/json_content_unit_test/json_step_test_wrong_json_path.json new file mode 100644 index 000000000..5fe61831b --- /dev/null +++ b/core/src/test/resources/unit_test_files/json_content_unit_test/json_step_test_wrong_json_path.json @@ -0,0 +1,22 @@ +{ + "name": "get_user_details", + "url": "/api/v1/employees/${$.create_emp.response.body.id}", + "method": "GET", + "request": { + "body" : { + "fullName":"Bob Luis", + "empLogin":"bolu_lon", + "type":"CONTRACT", + "address":"${JSON.CONTENT:$.create_emp.response.body.id}" + } + }, + "verify": { + "status": 200, + "body": { + "id": 39001, + "ldapId": "emmanorton", + "name": "Emma", + "surName": "Norton" + } + } +} From dce656c69a9b0fdf2cade8c2157f0529d3d2103f Mon Sep 17 00:00:00 2001 From: Vivek Kumar Date: Fri, 22 Dec 2023 20:01:17 +0530 Subject: [PATCH 14/44] ISSUE-601 # Add Unit tests for JSON Content --- .../ZeroCodeAssertionsProcessorImplTest.java | 72 ++++++++++++++++++- .../json_step_test_json_content_array.json | 41 +++++++++++ 2 files changed, 112 insertions(+), 1 deletion(-) create mode 100644 core/src/test/resources/unit_test_files/json_content_unit_test/json_step_test_json_content_array.json diff --git a/core/src/test/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeAssertionsProcessorImplTest.java b/core/src/test/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeAssertionsProcessorImplTest.java index ed98c96c8..8002f4862 100644 --- a/core/src/test/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeAssertionsProcessorImplTest.java +++ b/core/src/test/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeAssertionsProcessorImplTest.java @@ -2,6 +2,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.inject.Guice; import com.google.inject.Injector; @@ -12,6 +13,7 @@ import java.util.List; import java.util.Map; +import org.apache.commons.lang.text.StrSubstitutor; import org.hamcrest.core.Is; import org.jsmart.zerocode.core.di.main.ApplicationMainModule; import org.jsmart.zerocode.core.di.provider.ObjectMapperProvider; @@ -21,6 +23,7 @@ import org.jsmart.zerocode.core.engine.assertion.JsonAsserter; import org.jsmart.zerocode.core.engine.tokens.ZeroCodeValueTokens; import org.jsmart.zerocode.core.utils.SmartUtils; +import org.junit.Assert; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -1461,13 +1464,62 @@ public void testLeafValuesArray_badIndex() { } @Test(expected = RuntimeException.class) - public void test_wrongJsonPath() throws JsonProcessingException { + public void test_wrongJsonPathException() throws JsonProcessingException { String jsonAsString = readJsonAsString("unit_test_files/json_content_unit_test/json_step_test_wrong_json_path.json"); Map map = mapper.readValue(jsonAsString, new TypeReference>() {}); jsonPreProcessor.digReplaceContent(map, new ScenarioExecutionState()); } + @Test + public void test_deepHashMapTraverse() throws IOException { + ScenarioExecutionState scenarioExecutionState = new ScenarioExecutionState(); + + final String step1 = createStepWith("create_emp", "\"body\" : {\n \"id\" : 39001,\n \"ldapId\" : \"emmanorton\"\n }\n}\n }"); + scenarioExecutionState.addStepState(step1); + + ScenarioSpec scenarioSpec = + smartUtils.scenarioFileToJava( + "unit_test_files/json_content_unit_test/json_step_test_json_content.json", ScenarioSpec.class); + Step thisStep = scenarioSpec.getSteps().get(1); + JsonNode stepNode = mapper.convertValue(thisStep, JsonNode.class); + Map map = mapper.readValue(stepNode.toString(), new TypeReference>() {}); + + jsonPreProcessor.digReplaceContent(map, scenarioExecutionState); + + String jsonResult = mapper.writeValueAsString(map); + + assertThat(JsonPath.read(jsonResult, "$.request.body.address"), is("39001")); + } + + + @Test + public void test_nameArray() throws IOException { + ScenarioExecutionState scenarioExecutionState = new ScenarioExecutionState(); + + final String step1 = createStepWith("create_emp", "\"body\": {\"id\": 38001,\n \"names\": [\"test1\", \"test2\"]\n}"); + scenarioExecutionState.addStepState(step1); + + ScenarioSpec scenarioSpec = + smartUtils.scenarioFileToJava( + "unit_test_files/json_content_unit_test/json_step_test_json_content_array.json", ScenarioSpec.class); + Step thisStep = scenarioSpec.getSteps().get(1); + JsonNode stepNode = mapper.convertValue(thisStep, JsonNode.class); + Map map = mapper.readValue(stepNode.toString(), new TypeReference>() {}); + + jsonPreProcessor.digReplaceContent(map, scenarioExecutionState); + + String jsonResult = mapper.writeValueAsString(map); + + String result = "[\"test1\",\"test2\"]"; + + Object jsonPathValue = JsonPath.read(jsonResult, + "$.request.body.names"); + + + Assert.assertEquals(result, jsonPathValue.toString().replace("\\", "")); + } + @Test public void test_NoJSONContentCheckDigNeeded() throws IOException { String jsonAsString = readJsonAsString("unit_test_files/json_content_unit_test/json_step_no_json_content_test.json"); @@ -1481,4 +1533,22 @@ public void test_NoJSONContentCheckDigNeeded() throws IOException { step = scenarioSpec.getSteps().get(1); assertThat(checkDigNeeded(mapper, step, ZeroCodeValueTokens.JSON_CONTENT), Is.is(true)); } + + protected String createStepWith(String stepName, String body) { + Map parammap = new HashMap<>(); + + parammap.put("STEP.NAME", stepName); + parammap.put("STEP.REQUEST", "{\n" + + " \"customer\": {\n" + + " \"firstName\": \"FIRST_NAME\"\n" + + " }\n" + + "}"); + parammap.put("STEP.RESPONSE", "{\n" + + body + + "}"); + + StrSubstitutor sub = new StrSubstitutor(parammap); + + return sub.replace((new StepExecutionState()).getRequestResponseState()); + } } diff --git a/core/src/test/resources/unit_test_files/json_content_unit_test/json_step_test_json_content_array.json b/core/src/test/resources/unit_test_files/json_content_unit_test/json_step_test_json_content_array.json new file mode 100644 index 000000000..8c0f619af --- /dev/null +++ b/core/src/test/resources/unit_test_files/json_content_unit_test/json_step_test_json_content_array.json @@ -0,0 +1,41 @@ +{ + "scenarioName": "POST API - File json as request content - Reuse body", + "steps": [ + { + "name": "create_emp", + "url": "/api/v1/employees", + "method": "POST", + "request": { + "body": { + "name": "Emma", + "surName": "Norton" + } + }, + "verify": { + "status": 201 + } + }, + { + "name": "get_user_details", + "url": "/api/v1/employees/${$.create_emp.response.body.id}", + "method": "GET", + "request": { + "body": { + "fullName": "Bob Luis", + "empLogin": "bolu_lon", + "type": "CONTRACT", + "names": "${JSON.CONTENT:$.create_emp.response.body.names}" + } + }, + "verify": { + "status": 200, + "body": { + "id": 39001, + "ldapId": "emmanorton", + "name": "Emma", + "surName": "Norton" + } + } + } + ] +} From 9456d505290c1cb54c3e64988915b98143e37028 Mon Sep 17 00:00:00 2001 From: Vivek Kumar Date: Sat, 23 Dec 2023 11:05:44 +0530 Subject: [PATCH 15/44] ISSUE-601 # Add Unit tests for JSON Content --- .../ZeroCodeAssertionsProcessorImplTest.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/core/src/test/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeAssertionsProcessorImplTest.java b/core/src/test/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeAssertionsProcessorImplTest.java index 8002f4862..f3cfb53b6 100644 --- a/core/src/test/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeAssertionsProcessorImplTest.java +++ b/core/src/test/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeAssertionsProcessorImplTest.java @@ -29,6 +29,7 @@ import org.junit.Test; import org.junit.rules.ExpectedException; +import static com.jayway.jsonpath.JsonPath.read; import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.not; @@ -1534,6 +1535,18 @@ public void test_NoJSONContentCheckDigNeeded() throws IOException { assertThat(checkDigNeeded(mapper, step, ZeroCodeValueTokens.JSON_CONTENT), Is.is(true)); } + @Test + public void test_textNode() throws IOException { + String jsonAsString = readJsonAsString("unit_test_files/filebody_unit_test/json_step_text_request.json"); + Step step = mapper.readValue(jsonAsString, Step.class); + + jsonPreProcessor.resolveJsonContent(step, new ScenarioExecutionState()); + String resultJsonStep = mapper.writeValueAsString(step); + + assertThat(read(resultJsonStep, "$.request"), Is.is("I am a simple text")); + } + + protected String createStepWith(String stepName, String body) { Map parammap = new HashMap<>(); From 22c8c3dc73c976663b816c2bf8454c0f12e1a91b Mon Sep 17 00:00:00 2001 From: Vivek Kumar Date: Sat, 30 Dec 2023 23:49:17 +0530 Subject: [PATCH 16/44] ISSUE-601 # Add integration and http tests --- .../ZeroCodeAssertionsProcessorImpl.java | 11 +++++- .../ZeroCodeAssertionsProcessorImplTest.java | 2 +- .../hello_world_file_request_n_response.json | 17 ++++++++ .../simulators/test_purpose_end_points.json | 14 +++++++ .../HelloJsonContentAsBodyTest.java | 18 +++++++++ ...lo_world_json_content_as_request_body.json | 39 +++++++++++++++++++ 6 files changed, 98 insertions(+), 3 deletions(-) create mode 100644 http-testing/src/test/java/org/jsmart/zerocode/testhelp/tests/helloworldjsoncontent/HelloJsonContentAsBodyTest.java create mode 100644 http-testing/src/test/resources/helloworld_json_content/hello_world_json_content_as_request_body.json diff --git a/core/src/main/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeAssertionsProcessorImpl.java b/core/src/main/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeAssertionsProcessorImpl.java index 57cc6e0df..cafb18f35 100644 --- a/core/src/main/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeAssertionsProcessorImpl.java +++ b/core/src/main/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeAssertionsProcessorImpl.java @@ -1,6 +1,6 @@ package org.jsmart.zerocode.core.engine.preprocessor; -import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; @@ -469,7 +469,14 @@ void digReplaceContent(Map map, ScenarioExecutionState scenarioE String resolvedRequestJson = resolveStringJson( "${" + token.substring(JSON_CONTENT.length()) + "}", scenarioExecutionState.getResolvedScenarioState()); - entry.setValue(resolvedRequestJson); + resolvedRequestJson = resolvedRequestJson.replaceAll("\\\\", ""); + try { + JsonNode jsonNode = mapper.readTree(resolvedRequestJson); + entry.setValue(jsonNode); + } catch (JsonParseException e) { + //value is not a json string, but a string value + entry.setValue(resolvedRequestJson); + } } catch (Exception exx) { LOGGER.error("External file reference exception - {}", exx.getMessage()); throw new RuntimeException(exx); diff --git a/core/src/test/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeAssertionsProcessorImplTest.java b/core/src/test/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeAssertionsProcessorImplTest.java index f3cfb53b6..52277827e 100644 --- a/core/src/test/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeAssertionsProcessorImplTest.java +++ b/core/src/test/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeAssertionsProcessorImplTest.java @@ -1518,7 +1518,7 @@ public void test_nameArray() throws IOException { "$.request.body.names"); - Assert.assertEquals(result, jsonPathValue.toString().replace("\\", "")); + Assert.assertEquals(result, jsonPathValue.toString()); } @Test diff --git a/core/src/test/resources/integration_test_files/filebody/hello_world_file_request_n_response.json b/core/src/test/resources/integration_test_files/filebody/hello_world_file_request_n_response.json index 4f521a905..42f104f76 100644 --- a/core/src/test/resources/integration_test_files/filebody/hello_world_file_request_n_response.json +++ b/core/src/test/resources/integration_test_files/filebody/hello_world_file_request_n_response.json @@ -22,6 +22,23 @@ "status": 200, "body" : "${JSON.FILE:integration_test_files/filebody/bodyonly/response_body.json}" } + }, + { + "name": "create_bathroom_with_name", + "url": "/home/bathroom/21", + "operation": "PUT", + "request": { + "body" : { + "name": "${JSON.CONTENT:$.get_user_details.response.body.name}", + "availability": true + } + }, + "assertions": { + "status": 200, + "body": { + "name": "Shower-21" + } + } } ] } diff --git a/core/src/test/resources/simulators/test_purpose_end_points.json b/core/src/test/resources/simulators/test_purpose_end_points.json index 3971527b6..15dc01d6e 100644 --- a/core/src/test/resources/simulators/test_purpose_end_points.json +++ b/core/src/test/resources/simulators/test_purpose_end_points.json @@ -43,6 +43,20 @@ } } }, + { + "name": "PUT Bathroom - Update", + "operation": "PUT", + "url": "/home/bathroom/21", + "ignoreBody": true, + "response": { + "status": 200, + "body": { + "id": 21, + "name": "Shower-21", + "availability": true + } + } + }, { "name": "Get Bathroom by Id 21", "operation": "GET", diff --git a/http-testing/src/test/java/org/jsmart/zerocode/testhelp/tests/helloworldjsoncontent/HelloJsonContentAsBodyTest.java b/http-testing/src/test/java/org/jsmart/zerocode/testhelp/tests/helloworldjsoncontent/HelloJsonContentAsBodyTest.java new file mode 100644 index 000000000..148a5a91e --- /dev/null +++ b/http-testing/src/test/java/org/jsmart/zerocode/testhelp/tests/helloworldjsoncontent/HelloJsonContentAsBodyTest.java @@ -0,0 +1,18 @@ +package org.jsmart.zerocode.testhelp.tests.helloworldjsoncontent; + +import org.jsmart.zerocode.core.domain.JsonTestCase; +import org.jsmart.zerocode.core.domain.TargetEnv; +import org.jsmart.zerocode.core.runner.ZeroCodeUnitRunner; +import org.junit.Test; +import org.junit.runner.RunWith; + +@TargetEnv("hello_world_host.properties") +@RunWith(ZeroCodeUnitRunner.class) +public class HelloJsonContentAsBodyTest { + + @Test + @JsonTestCase("helloworld_json_content/hello_world_json_content_as_request_body.json") + public void testHelloWorld_jsonContentAsBody() throws Exception { + } + +} diff --git a/http-testing/src/test/resources/helloworld_json_content/hello_world_json_content_as_request_body.json b/http-testing/src/test/resources/helloworld_json_content/hello_world_json_content_as_request_body.json new file mode 100644 index 000000000..bf3cf2a75 --- /dev/null +++ b/http-testing/src/test/resources/helloworld_json_content/hello_world_json_content_as_request_body.json @@ -0,0 +1,39 @@ +{ + "scenarioName": "POST API - JSON content as request body", + "steps": [ + { + "name": "get_screening", + "url": "/api/v1/employees/screening/SCRUNIQUEID5003", + "method": "GET", + "request": {}, + "assertions": { + "status": 200, + "body": { + "id": "SCRUNIQUEID5003", + "empId": "EMP39001", + "originAddress": { + "addressId":"lon-hsbc-5432", + "countryOfOrigin":"UK" + } + } + } + }, + { + "name": "create_screening", + "url": "/api/v1/employees/screening", + "method": "POST", + "request": { + "body": { + "empId": "${JSON.CONTENT:$.get_screening.response.body.empId}", + "originAddress":"${JSON.CONTENT:$.get_screening.response.body.originAddress}" + } + }, + "assertions": { + "status": 201, + "body": { + "id": "SCRUNIQUEID5003" + } + } + } + ] +} From 8cf0bdcd20ad03ad4c61e41cc8b8775a96cf4eed Mon Sep 17 00:00:00 2001 From: nirmalchandra Date: Sat, 13 Jan 2024 21:07:30 +0000 Subject: [PATCH 17/44] resource path retained --- .../java/org/jsmart/zerocode/core/domain/Parameterized.java | 2 +- ..._world_test_parameterized_csv_source_file_ignore_header.json | 2 +- .../hello_world_test_parameterized_csv_source_files.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/org/jsmart/zerocode/core/domain/Parameterized.java b/core/src/main/java/org/jsmart/zerocode/core/domain/Parameterized.java index 2f85f4c5b..e37b50b04 100644 --- a/core/src/main/java/org/jsmart/zerocode/core/domain/Parameterized.java +++ b/core/src/main/java/org/jsmart/zerocode/core/domain/Parameterized.java @@ -61,7 +61,7 @@ private List readCsvSourceFromJson(JsonNode csvSourceJsonNode) throws IO private List readCsvSourceFromExternalCsvFile(JsonNode csvSourceJsonNode) throws IOException { String csvSourceFilePath = csvSourceJsonNode.textValue(); if (StringUtils.isNotBlank(csvSourceFilePath)) { - Path path = Paths.get(csvSourceFilePath); + Path path = Paths.get("./src/test/resources/",csvSourceFilePath); List csvSourceFileLines = Files.lines(path) .filter(StringUtils::isNotBlank) .collect(Collectors.toList()); diff --git a/http-testing/src/test/resources/parameterized_csv/hello_world_test_parameterized_csv_source_file_ignore_header.json b/http-testing/src/test/resources/parameterized_csv/hello_world_test_parameterized_csv_source_file_ignore_header.json index 48a7e741e..e1bada989 100644 --- a/http-testing/src/test/resources/parameterized_csv/hello_world_test_parameterized_csv_source_file_ignore_header.json +++ b/http-testing/src/test/resources/parameterized_csv/hello_world_test_parameterized_csv_source_file_ignore_header.json @@ -21,6 +21,6 @@ ], "parameterized": { "ignoreHeader": true, - "csvSource":"./src/test/resources/parameterized_csv/params_with_header.csv" + "csvSource":"parameterized_csv/params_with_header.csv" } } diff --git a/http-testing/src/test/resources/parameterized_csv/hello_world_test_parameterized_csv_source_files.json b/http-testing/src/test/resources/parameterized_csv/hello_world_test_parameterized_csv_source_files.json index 264f96f66..bce4e78d2 100644 --- a/http-testing/src/test/resources/parameterized_csv/hello_world_test_parameterized_csv_source_files.json +++ b/http-testing/src/test/resources/parameterized_csv/hello_world_test_parameterized_csv_source_files.json @@ -20,6 +20,6 @@ } ], "parameterized": { - "csvSource":"./src/test/resources/parameterized_csv/params.csv" + "csvSource":"parameterized_csv/params.csv" } } From 7be9a1791879f94eead383f5e2334fc9b1fa9cbd Mon Sep 17 00:00:00 2001 From: nirmalchandra Date: Sat, 13 Jan 2024 21:17:43 +0000 Subject: [PATCH 18/44] Unit tests fixed after method path fix --- .../08.1_parameterized_csv_source_from_file.json | 2 +- ....2_parameterized_csv_source_from_file_containing_header.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/test/resources/unit_test_files/engine_unit_test_jsons/08.1_parameterized_csv_source_from_file.json b/core/src/test/resources/unit_test_files/engine_unit_test_jsons/08.1_parameterized_csv_source_from_file.json index feedf0b89..5fe1f5aee 100755 --- a/core/src/test/resources/unit_test_files/engine_unit_test_jsons/08.1_parameterized_csv_source_from_file.json +++ b/core/src/test/resources/unit_test_files/engine_unit_test_jsons/08.1_parameterized_csv_source_from_file.json @@ -4,5 +4,5 @@ 123, true ], - "csvSource": "./src/test/resources/unit_test_files/engine_unit_test_jsons/params.csv" + "csvSource": "unit_test_files/engine_unit_test_jsons/params.csv" } diff --git a/core/src/test/resources/unit_test_files/engine_unit_test_jsons/08.2_parameterized_csv_source_from_file_containing_header.json b/core/src/test/resources/unit_test_files/engine_unit_test_jsons/08.2_parameterized_csv_source_from_file_containing_header.json index c7500a8c1..bb456137f 100755 --- a/core/src/test/resources/unit_test_files/engine_unit_test_jsons/08.2_parameterized_csv_source_from_file_containing_header.json +++ b/core/src/test/resources/unit_test_files/engine_unit_test_jsons/08.2_parameterized_csv_source_from_file_containing_header.json @@ -5,5 +5,5 @@ true ], "ignoreHeader": true, - "csvSource": "./src/test/resources/unit_test_files/engine_unit_test_jsons/params_with_header.csv" + "csvSource": "unit_test_files/engine_unit_test_jsons/params_with_header.csv" } From 58c7c66130f8cfe740c5f5d5c4604f97cb617d6c Mon Sep 17 00:00:00 2001 From: nirmalchandra Date: Sat, 13 Jan 2024 21:33:10 +0000 Subject: [PATCH 19/44] Unit test files count updated --- .../java/org/jsmart/zerocode/core/utils/SmartUtilsTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/test/java/org/jsmart/zerocode/core/utils/SmartUtilsTest.java b/core/src/test/java/org/jsmart/zerocode/core/utils/SmartUtilsTest.java index ad7ddb206..2868eef11 100644 --- a/core/src/test/java/org/jsmart/zerocode/core/utils/SmartUtilsTest.java +++ b/core/src/test/java/org/jsmart/zerocode/core/utils/SmartUtilsTest.java @@ -76,7 +76,7 @@ public void willGetJsonFileIntoA_JavaString() throws Exception { @Test public void willReadAllfileNamesFrom_TestResource() { List allTestCaseFiles = SmartUtils.getAllEndPointFiles("unit_test_files/engine_unit_test_jsons"); - assertThat(allTestCaseFiles.size(), is(20)); + assertThat(allTestCaseFiles.size(), is(22)); assertThat(allTestCaseFiles.get(0), is("unit_test_files/engine_unit_test_jsons/00_test_json_single_step_verifications.json")); } From e4333d02367c822d760df204b2da31253a40c4ab Mon Sep 17 00:00:00 2001 From: nchandra Date: Mon, 22 Jan 2024 21:21:36 +0000 Subject: [PATCH 20/44] More Test coverage and CI Build Fixed --- .../ZeroCodeAssertionsProcessorImplTest.java | 86 +++++++++++++++++-- .../json_step_test_json_content.json | 2 +- .../json_step_test_json_content_block.json | 41 +++++++++ ...on_step_test_json_content_objectarray.json | 41 +++++++++ 4 files changed, 161 insertions(+), 9 deletions(-) create mode 100644 core/src/test/resources/unit_test_files/json_content_unit_test/json_step_test_json_content_block.json create mode 100644 core/src/test/resources/unit_test_files/json_content_unit_test/json_step_test_json_content_objectarray.json diff --git a/core/src/test/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeAssertionsProcessorImplTest.java b/core/src/test/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeAssertionsProcessorImplTest.java index 52277827e..8d569eb74 100644 --- a/core/src/test/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeAssertionsProcessorImplTest.java +++ b/core/src/test/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeAssertionsProcessorImplTest.java @@ -1465,7 +1465,7 @@ public void testLeafValuesArray_badIndex() { } @Test(expected = RuntimeException.class) - public void test_wrongJsonPathException() throws JsonProcessingException { + public void test_wrongJsonPathBy_JSONCONTENT_Exception() throws JsonProcessingException { String jsonAsString = readJsonAsString("unit_test_files/json_content_unit_test/json_step_test_wrong_json_path.json"); Map map = mapper.readValue(jsonAsString, new TypeReference>() {}); @@ -1473,10 +1473,10 @@ public void test_wrongJsonPathException() throws JsonProcessingException { } @Test - public void test_deepHashMapTraverse() throws IOException { + public void test_JSONCONTENT_leafNode() throws IOException { ScenarioExecutionState scenarioExecutionState = new ScenarioExecutionState(); - final String step1 = createStepWith("create_emp", "\"body\" : {\n \"id\" : 39001,\n \"ldapId\" : \"emmanorton\"\n }\n}\n }"); + final String step1 = createStepWithRequestAndResponse("create_emp", "\"body\" : {\n \"id\" : 39001,\n \"ldapId\" : \"emmanorton\"\n }\n}\n }"); scenarioExecutionState.addStepState(step1); ScenarioSpec scenarioSpec = @@ -1490,15 +1490,15 @@ public void test_deepHashMapTraverse() throws IOException { String jsonResult = mapper.writeValueAsString(map); - assertThat(JsonPath.read(jsonResult, "$.request.body.address"), is("39001")); + assertThat(JsonPath.read(jsonResult, "$.request.body.addressId"), is(39001)); } @Test - public void test_nameArray() throws IOException { + public void test_JSONCONTENT_stringArray() throws IOException { ScenarioExecutionState scenarioExecutionState = new ScenarioExecutionState(); - final String step1 = createStepWith("create_emp", "\"body\": {\"id\": 38001,\n \"names\": [\"test1\", \"test2\"]\n}"); + final String step1 = createStepWithRequestAndResponse("create_emp", "\"body\": {\"id\": 38001,\n \"names\": [\"test1\", \"test2\"]\n}"); scenarioExecutionState.addStepState(step1); ScenarioSpec scenarioSpec = @@ -1517,10 +1517,80 @@ public void test_nameArray() throws IOException { Object jsonPathValue = JsonPath.read(jsonResult, "$.request.body.names"); - Assert.assertEquals(result, jsonPathValue.toString()); } + @Test + public void test_JSONCONTENT_objectArray() throws IOException { + ScenarioExecutionState scenarioExecutionState = new ScenarioExecutionState(); + /** + * { + * "id": 38001, + * "allAddresses": [ + * { + * "type": "Home", + * "line1": "North Lon", + * "id": 43 + * }, + * { + * "type": "Office", + * "line1": "Central Lon" + * } + * ] + * } + */ + final String step1 = createStepWithRequestAndResponse("create_emp", + "\"body\": {\"id\": 38001, \"allAddresses\": [{\"type\": \"Home\", \"line1\": \"North Lon\", \"id\": 47}, {\"type\": \"Office\", \"line1\": \"Central Lon\"}]}"); + scenarioExecutionState.addStepState(step1); + + ScenarioSpec scenarioSpec = + smartUtils.scenarioFileToJava( + "unit_test_files/json_content_unit_test/json_step_test_json_content_objectarray.json", ScenarioSpec.class); + + Step thisStep = scenarioSpec.getSteps().get(1); + JsonNode stepNode = mapper.convertValue(thisStep, JsonNode.class); + Map map = mapper.readValue(stepNode.toString(), new TypeReference>() {}); + + jsonPreProcessor.digReplaceContent(map, scenarioExecutionState); + + String jsonResult = mapper.writeValueAsString(map); + + assertThat(JsonPath.read(jsonResult, "$.request.body.allAddresses[0].id"), is(47)); + assertThat(JsonPath.read(jsonResult, "$.request.body.allAddresses[0].type"), is("Home")); + assertThat(JsonPath.read(jsonResult, "$.request.body.allAddresses[1].type"), is("Office")); + assertThat(JsonPath.read(jsonResult, "$.request.body.allAddresses[0].line1"), is("North Lon")); + assertThat(JsonPath.read(jsonResult, "$.request.body.allAddresses[1].line1"), is("Central Lon")); + } + + @Test + public void test_JSONCONTENT_jsonBlock() throws IOException { + ScenarioExecutionState scenarioExecutionState = new ScenarioExecutionState(); + + final String step1 = createStepWithRequestAndResponse("create_emp", + "\"body\": {\n" + + " \"id\": 38001,\n" + + " \"address\": {\n" + + " \"type\": \"Home\",\n" + + " \"line1\": \"River Side\"\n" + + " }\n" + + "}"); + scenarioExecutionState.addStepState(step1); + + ScenarioSpec scenarioSpec = + smartUtils.scenarioFileToJava( + "unit_test_files/json_content_unit_test/json_step_test_json_content_block.json", ScenarioSpec.class); + Step thisStep = scenarioSpec.getSteps().get(1); + JsonNode stepNode = mapper.convertValue(thisStep, JsonNode.class); + Map map = mapper.readValue(stepNode.toString(), new TypeReference>() {}); + + jsonPreProcessor.digReplaceContent(map, scenarioExecutionState); + + String jsonResult = mapper.writeValueAsString(map); + + assertThat(JsonPath.read(jsonResult, "$.request.body.address.type"), is("Home")); + assertThat(JsonPath.read(jsonResult, "$.request.body.address.line1"), is("River Side")); + } + @Test public void test_NoJSONContentCheckDigNeeded() throws IOException { String jsonAsString = readJsonAsString("unit_test_files/json_content_unit_test/json_step_no_json_content_test.json"); @@ -1547,7 +1617,7 @@ public void test_textNode() throws IOException { } - protected String createStepWith(String stepName, String body) { + protected String createStepWithRequestAndResponse(String stepName, String body) { Map parammap = new HashMap<>(); parammap.put("STEP.NAME", stepName); diff --git a/core/src/test/resources/unit_test_files/json_content_unit_test/json_step_test_json_content.json b/core/src/test/resources/unit_test_files/json_content_unit_test/json_step_test_json_content.json index 3ed60699e..1a8af01e0 100644 --- a/core/src/test/resources/unit_test_files/json_content_unit_test/json_step_test_json_content.json +++ b/core/src/test/resources/unit_test_files/json_content_unit_test/json_step_test_json_content.json @@ -24,7 +24,7 @@ "fullName": "Bob Luis", "empLogin": "bolu_lon", "type": "CONTRACT", - "address": "${JSON.CONTENT:$.create_emp.response.body.id}" + "addressId": "${JSON.CONTENT:$.create_emp.response.body.id}" } }, "verify": { diff --git a/core/src/test/resources/unit_test_files/json_content_unit_test/json_step_test_json_content_block.json b/core/src/test/resources/unit_test_files/json_content_unit_test/json_step_test_json_content_block.json new file mode 100644 index 000000000..b287b99d3 --- /dev/null +++ b/core/src/test/resources/unit_test_files/json_content_unit_test/json_step_test_json_content_block.json @@ -0,0 +1,41 @@ +{ + "scenarioName": "POST API - File json as request content - Reuse body", + "steps": [ + { + "name": "create_emp", + "url": "/api/v1/employees", + "method": "POST", + "request": { + "body": { + "name": "Emma", + "surName": "Norton" + } + }, + "verify": { + "status": 201 + } + }, + { + "name": "get_user_details", + "url": "/api/v1/employees/${$.create_emp.response.body.id}", + "method": "GET", + "request": { + "body": { + "fullName": "Bob Luis", + "empLogin": "bolu_lon", + "type": "CONTRACT", + "address": "${JSON.CONTENT:$.create_emp.response.body.address}" + } + }, + "verify": { + "status": 200, + "body": { + "id": 39001, + "ldapId": "emmanorton", + "name": "Emma", + "surName": "Norton" + } + } + } + ] +} diff --git a/core/src/test/resources/unit_test_files/json_content_unit_test/json_step_test_json_content_objectarray.json b/core/src/test/resources/unit_test_files/json_content_unit_test/json_step_test_json_content_objectarray.json new file mode 100644 index 000000000..daf4b95f4 --- /dev/null +++ b/core/src/test/resources/unit_test_files/json_content_unit_test/json_step_test_json_content_objectarray.json @@ -0,0 +1,41 @@ +{ + "scenarioName": "POST API - File json as request content - Reuse body", + "steps": [ + { + "name": "create_emp", + "url": "/api/v1/employees", + "method": "POST", + "request": { + "body": { + "name": "Emma", + "surName": "Norton" + } + }, + "verify": { + "status": 201 + } + }, + { + "name": "get_user_details", + "url": "/api/v1/employees/${$.create_emp.response.body.id}", + "method": "GET", + "request": { + "body": { + "fullName": "Bob Luis", + "empLogin": "bolu_lon", + "type": "CONTRACT", + "allAddresses": "${JSON.CONTENT:$.create_emp.response.body.allAddresses}" + } + }, + "verify": { + "status": 200, + "body": { + "id": 39001, + "ldapId": "emmanorton", + "name": "Emma", + "surName": "Norton" + } + } + } + ] +} From 6f6cb574d2de3040ba114b67b9a031ed4414c1ce Mon Sep 17 00:00:00 2001 From: nchandra Date: Fri, 26 Jan 2024 21:22:33 +0000 Subject: [PATCH 21/44] issues-616 Authors and hashtags aka categories --- .../constants/ZeroCodeReportConstants.java | 1 + .../report/ZeroCodeReportGeneratorImpl.java | 90 ++++++++--------- .../ZeroCodeReportGeneratorImplTest.java | 99 ++++++++++--------- 3 files changed, 92 insertions(+), 98 deletions(-) diff --git a/core/src/main/java/org/jsmart/zerocode/core/constants/ZeroCodeReportConstants.java b/core/src/main/java/org/jsmart/zerocode/core/constants/ZeroCodeReportConstants.java index f812ff6ec..855e4a22b 100644 --- a/core/src/main/java/org/jsmart/zerocode/core/constants/ZeroCodeReportConstants.java +++ b/core/src/main/java/org/jsmart/zerocode/core/constants/ZeroCodeReportConstants.java @@ -16,6 +16,7 @@ public interface ZeroCodeReportConstants { String REPORT_TITLE_DEFAULT = "Zerocode Test Report"; String REPORT_DISPLAY_NAME_DEFAULT = "Zerocode Interactive Report"; String DEFAULT_REGRESSION_CATEGORY = "Regression"; + String DEFAULT_REGRESSION_AUTHOR = "All"; String LINK_LABEL_NAME = "Spike Chart(Click here)"; String ZEROCODE_JUNIT = "zerocode.junit"; String CHARTS_AND_CSV = "gen-smart-charts-csv-reports"; diff --git a/core/src/main/java/org/jsmart/zerocode/core/report/ZeroCodeReportGeneratorImpl.java b/core/src/main/java/org/jsmart/zerocode/core/report/ZeroCodeReportGeneratorImpl.java index db5a3d4af..d356cdde4 100644 --- a/core/src/main/java/org/jsmart/zerocode/core/report/ZeroCodeReportGeneratorImpl.java +++ b/core/src/main/java/org/jsmart/zerocode/core/report/ZeroCodeReportGeneratorImpl.java @@ -12,12 +12,7 @@ import com.fasterxml.jackson.dataformat.csv.CsvSchema; import com.google.inject.Inject; import com.google.inject.name.Named; -import org.apache.commons.lang.StringUtils; -import org.jsmart.zerocode.core.domain.builders.ExtentReportsFactory; -import org.jsmart.zerocode.core.domain.builders.HighChartColumnHtmlBuilder; -import org.jsmart.zerocode.core.domain.builders.ZeroCodeChartKeyValueArrayBuilder; -import org.jsmart.zerocode.core.domain.builders.ZeroCodeChartKeyValueBuilder; -import org.jsmart.zerocode.core.domain.builders.ZeroCodeCsvReportBuilder; +import org.jsmart.zerocode.core.domain.builders.*; import org.jsmart.zerocode.core.domain.reports.ZeroCodeExecResult; import org.jsmart.zerocode.core.domain.reports.ZeroCodeReport; import org.jsmart.zerocode.core.domain.reports.ZeroCodeReportStep; @@ -35,21 +30,8 @@ import static java.util.Collections.emptyList; import static java.util.Optional.ofNullable; -import static org.apache.commons.lang.StringUtils.substringBetween; -import static org.jsmart.zerocode.core.constants.ZeroCodeReportConstants.AUTHOR_MARKER_NEW; -import static org.jsmart.zerocode.core.constants.ZeroCodeReportConstants.CATEGORY_MARKER; +import static org.jsmart.zerocode.core.constants.ZeroCodeReportConstants.*; import static org.jsmart.zerocode.core.domain.builders.ExtentReportsFactory.getReportName; -import static org.jsmart.zerocode.core.constants.ZeroCodeReportConstants.ANONYMOUS_CAT; -import static org.jsmart.zerocode.core.constants.ZeroCodeReportConstants.AUTHOR_MARKER_OLD; -import static org.jsmart.zerocode.core.constants.ZeroCodeReportConstants.DEFAULT_REGRESSION_CATEGORY; -import static org.jsmart.zerocode.core.constants.ZeroCodeReportConstants.HIGH_CHART_HTML_FILE_NAME; -import static org.jsmart.zerocode.core.constants.ZeroCodeReportConstants.LINK_LABEL_NAME; -import static org.jsmart.zerocode.core.constants.ZeroCodeReportConstants.RESULT_PASS; -import static org.jsmart.zerocode.core.constants.ZeroCodeReportConstants.TARGET_FILE_NAME; -import static org.jsmart.zerocode.core.constants.ZeroCodeReportConstants.TARGET_FULL_REPORT_CSV_FILE_NAME; -import static org.jsmart.zerocode.core.constants.ZeroCodeReportConstants.TARGET_FULL_REPORT_DIR; -import static org.jsmart.zerocode.core.constants.ZeroCodeReportConstants.TARGET_REPORT_DIR; -import static org.jsmart.zerocode.core.constants.ZeroCodeReportConstants.TEST_STEP_CORRELATION_ID; public class ZeroCodeReportGeneratorImpl implements ZeroCodeReportGenerator { private static final Logger LOGGER = LoggerFactory.getLogger(ZeroCodeReportGeneratorImpl.class); @@ -115,10 +97,21 @@ public void generateExtentReport() { thisReport.getResults().forEach(thisScenario -> { ExtentTest test = extentReports.createTest(thisScenario.getScenarioName()); + + // Assign Category test.assignCategory(DEFAULT_REGRESSION_CATEGORY); //Super set - test.assignCategory(optionalCategory(thisScenario.getScenarioName())); //Sub sets + String[] hashTagsArray = optionalCategories(thisScenario.getScenarioName()).toArray(new String[0]); + if(hashTagsArray.length > 0) { + test.assignCategory(hashTagsArray); //Sub categories + } + + // Assign Authors + test.assignAuthor(DEFAULT_REGRESSION_AUTHOR); //Super set + String[] authorsArray = optionalAuthors(thisScenario.getScenarioName()).toArray(new String[0]); + if(authorsArray.length > 0) { + test.assignAuthor(authorsArray); //Sub authors + } - test.assignAuthor(optionalAuthor(thisScenario.getScenarioName())); List thisScenarioUniqueSteps = getUniqueSteps(thisScenario.getSteps()); thisScenarioUniqueSteps.forEach(thisStep -> { test.getModel().setStartTime(utilDateOf(thisStep.getRequestTimeStamp())); @@ -166,42 +159,33 @@ public void linkToSpikeChartIfEnabled() { /** * @param scenarioName String containing a name of an author - * @return author of the test scenario + * @return authors of the test scenario */ - protected String optionalAuthor(String scenarioName) { - String authorName = deriveName(scenarioName, AUTHOR_MARKER_OLD); - authorName = ANONYMOUS_CAT.equals(authorName) ? deriveName(scenarioName, AUTHOR_MARKER_NEW) : authorName; - return authorName; + protected List optionalAuthors(String scenarioName) { + return deriveNames(scenarioName, AUTHOR_MARKER_NEW); } /** - * @param scenarioName String containing hash tags of a category - * @return category of the test scenario + * @param scenarioName String containing hashtags of a category + * @return hashtags aka categories of the test scenario */ - protected String optionalCategory(String scenarioName) { - return deriveName(scenarioName, CATEGORY_MARKER); + protected List optionalCategories(String scenarioName) { + return deriveNames(scenarioName, CATEGORY_MARKER); } - private String deriveName(String scenarioName, String marker) { - String authorName = substringBetween(scenarioName, marker, marker); - - if (authorName == null) { - authorName = substringBetween(scenarioName, marker, ","); - } - - if (authorName == null) { - authorName = substringBetween(scenarioName, marker, " "); - } - - if (authorName == null) { - authorName = scenarioName.substring(scenarioName.lastIndexOf(marker) + marker.length()); - } - - if (scenarioName.lastIndexOf(marker) == -1 || StringUtils.isEmpty(authorName)) { - authorName = ANONYMOUS_CAT; + private List deriveNames(String scenarioName, String marker) { + List nameList = new ArrayList<>(); + for(String thisName : scenarioName.trim().split(" ")){ + if(thisName.startsWith(marker) && !thisName.startsWith(AUTHOR_MARKER_OLD)){ + nameList.add(thisName); + } + // Depreciated, but still supports. Remove this via a new ticket + if(thisName.startsWith(AUTHOR_MARKER_OLD)){ + nameList.add(thisName); + } } + return nameList; - return authorName; } protected String onlyScenarioName(String scenarioName) { @@ -430,4 +414,12 @@ private String createTimeStampedFileName() { ".html"; } + public static void main(String[] args) { + String sss = "A quick brown fox jumps over a lazy dog @ODS-X @Licenc_Y Z"; + for(String st : sss.trim().split(" ")){ + if(st.startsWith("@")){ + System.out.println(st); + } + } + } } diff --git a/core/src/test/java/org/jsmart/zerocode/core/report/ZeroCodeReportGeneratorImplTest.java b/core/src/test/java/org/jsmart/zerocode/core/report/ZeroCodeReportGeneratorImplTest.java index f573f38e5..60dfa5ea3 100644 --- a/core/src/test/java/org/jsmart/zerocode/core/report/ZeroCodeReportGeneratorImplTest.java +++ b/core/src/test/java/org/jsmart/zerocode/core/report/ZeroCodeReportGeneratorImplTest.java @@ -58,84 +58,85 @@ public void testReportFolderPresentInTargetNormalFlow() throws Exception { @Test - public void testAuthorJiraStyle() throws Exception { - String author; + public void testAuthorJiraStyle_LEGACYMARKER() throws Exception { + List authors; // OLD - Deprecated - author = zeroCodeReportGenerator.optionalAuthor("PayPal One touch payment @@Peter@@"); - assertThat(author, is("Peter")); + authors = zeroCodeReportGenerator.optionalAuthors("PayPal One touch payment @@Peter"); + assertThat(authors.get(0), is("@@Peter")); - author = zeroCodeReportGenerator.optionalAuthor("PayPal One touch @@payment @@Peter@@"); - assertThat(author, is("payment ")); + authors = zeroCodeReportGenerator.optionalAuthors("PayPal One touch payment"); + assertThat(authors.size(), is(0)); - author = zeroCodeReportGenerator.optionalAuthor("PayPal One touch payment @@Peter Gibson@@"); - assertThat(author, is("Peter Gibson")); + authors = zeroCodeReportGenerator.optionalAuthors("PayPal One touch @@payment @@Peter"); + assertThat(authors.get(0), is("@@payment")); + assertThat(authors.get(1), is("@@Peter")); + assertThat(authors.size(), is(2)); - author = zeroCodeReportGenerator.optionalAuthor("PayPal One touch payment @@Peter Gibson"); - assertThat(author, is("Peter")); + authors = zeroCodeReportGenerator.optionalAuthors("PayPal One touch payment @@Peter-Gibson"); + assertThat(authors.get(0), is("@@Peter-Gibson")); - author = zeroCodeReportGenerator.optionalAuthor("PayPal One touch payment @@Peter"); - assertThat(author, is("Peter")); - - author = zeroCodeReportGenerator.optionalAuthor("@@Peter, PayPal One touch payment "); - assertThat(author, is("Peter")); - - author = zeroCodeReportGenerator.optionalAuthor("PayPal One touch payment"); - assertThat(author, is("Anonymous")); + authors = zeroCodeReportGenerator.optionalAuthors("PayPal One touch payment @@Peter Gibson"); + assertThat(authors.get(0), is("@@Peter")); + authors = zeroCodeReportGenerator.optionalAuthors("@@Peter- PayPal One touch payment "); + assertThat(authors.get(0), is("@@Peter-")); } @Test public void testAuthorJiraStyle_new() throws Exception { - String author; + List authors; - author = zeroCodeReportGenerator.optionalAuthor("PayPal One touch payment @Peter@"); - assertThat(author, is("Peter")); - - author = zeroCodeReportGenerator.optionalAuthor("PayPal One touch @payment @Peter@"); - assertThat(author, is("payment ")); + // OLD - Deprecated + authors = zeroCodeReportGenerator.optionalAuthors("PayPal One touch payment @Peter"); + assertThat(authors.get(0), is("@Peter")); - author = zeroCodeReportGenerator.optionalAuthor("PayPal One touch payment @Peter Gibson@"); - assertThat(author, is("Peter Gibson")); + authors = zeroCodeReportGenerator.optionalAuthors("PayPal One touch payment"); + assertThat(authors.size(), is(0)); - author = zeroCodeReportGenerator.optionalAuthor("PayPal One touch payment @Peter Gibson"); - assertThat(author, is("Peter")); + authors = zeroCodeReportGenerator.optionalAuthors("PayPal One touch @payment @Peter"); + assertThat(authors.get(0), is("@payment")); + assertThat(authors.get(1), is("@Peter")); + assertThat(authors.size(), is(2)); - author = zeroCodeReportGenerator.optionalAuthor("PayPal One touch payment @Peter"); - assertThat(author, is("Peter")); + authors = zeroCodeReportGenerator.optionalAuthors("PayPal One touch payment @Peter-Gibson"); + assertThat(authors.get(0), is("@Peter-Gibson")); - author = zeroCodeReportGenerator.optionalAuthor("@Peter, PayPal One touch payment "); - assertThat(author, is("Peter")); + authors = zeroCodeReportGenerator.optionalAuthors("PayPal One touch payment @Peter Gibson"); + assertThat(authors.get(0), is("@Peter")); - author = zeroCodeReportGenerator.optionalAuthor("PayPal One touch payment"); - assertThat(author, is("Anonymous")); + authors = zeroCodeReportGenerator.optionalAuthors("@Peter- PayPal One touch payment "); + assertThat(authors.get(0), is("@Peter-")); } @Test public void testCategoryHashTag() throws Exception { - String author; + List categories; - author = zeroCodeReportGenerator.optionalCategory("PayPal One touch payment #Smoke#"); - assertThat(author, is("Smoke")); + categories = zeroCodeReportGenerator.optionalCategories("PayPal One touch payment #Smoke"); + assertThat(categories.get(0), is("#Smoke")); + assertThat(categories.size(), is(1)); - author = zeroCodeReportGenerator.optionalCategory("PayPal One touch #Smoke #PDC#"); - assertThat(author, is("Smoke ")); + categories = zeroCodeReportGenerator.optionalCategories("PayPal One touch #Smoke #PDC"); + assertThat(categories.get(0), is("#Smoke")); + assertThat(categories.get(1), is("#PDC")); + assertThat(categories.size(), is(2)); - author = zeroCodeReportGenerator.optionalCategory("PayPal One touch payment #SIT Smoke#"); - assertThat(author, is("SIT Smoke")); + categories = zeroCodeReportGenerator.optionalCategories("PayPal One touch payment #SIT_Smoke"); + assertThat(categories.get(0), is("#SIT_Smoke")); - author = zeroCodeReportGenerator.optionalCategory("PayPal One touch payment #PDC Gibson"); - assertThat(author, is("PDC")); + categories = zeroCodeReportGenerator.optionalCategories("PayPal One touch payment #PDC-Gibson"); + assertThat(categories.get(0), is("#PDC-Gibson")); - author = zeroCodeReportGenerator.optionalCategory("PayPal One touch payment #PDC"); - assertThat(author, is("PDC")); + categories = zeroCodeReportGenerator.optionalCategories("PayPal One touch payment #PDC"); + assertThat(categories.get(0), is("#PDC")); - author = zeroCodeReportGenerator.optionalCategory("#PDC, PayPal One touch payment "); - assertThat(author, is("PDC")); + categories = zeroCodeReportGenerator.optionalCategories("#PDC, PayPal One touch payment "); + assertThat(categories.get(0), is("#PDC,")); - author = zeroCodeReportGenerator.optionalCategory("PayPal One touch payment"); - assertThat(author, is("Anonymous")); + categories = zeroCodeReportGenerator.optionalCategories("PayPal One touch payment"); + assertThat(categories.size(), is(0)); } From 5fadc27a668b1fc32514714d98a58c800a7d14cc Mon Sep 17 00:00:00 2001 From: nchandra Date: Sun, 28 Jan 2024 13:58:50 +0000 Subject: [PATCH 22/44] ISSUES-603 Secrets with masked string replaced --- .../engine/tokens/ZeroCodeValueTokens.java | 3 ++ .../zerocode/core/utils/TokenUtils.java | 41 +++++++++++-------- 2 files changed, 27 insertions(+), 17 deletions(-) diff --git a/core/src/main/java/org/jsmart/zerocode/core/engine/tokens/ZeroCodeValueTokens.java b/core/src/main/java/org/jsmart/zerocode/core/engine/tokens/ZeroCodeValueTokens.java index 3104c7a16..f73b0b072 100644 --- a/core/src/main/java/org/jsmart/zerocode/core/engine/tokens/ZeroCodeValueTokens.java +++ b/core/src/main/java/org/jsmart/zerocode/core/engine/tokens/ZeroCodeValueTokens.java @@ -32,12 +32,15 @@ public class ZeroCodeValueTokens { public static final String $VALUE = ".$VALUE"; public static final String ABS_PATH = "ABS.PATH:"; public static final String JSON_CONTENT = "JSON.CONTENT:"; + public static final String MASKED = "MASKED:"; + public static final String MASKED_STR = "***masked***"; public static Map globalTokenCache = new HashMap<>(); public static List getKnownTokens() { return asList( + MASKED, PREFIX_ASU, RANDOM_NUMBER, GLOBAL_RANDOM_NUMBER, diff --git a/core/src/main/java/org/jsmart/zerocode/core/utils/TokenUtils.java b/core/src/main/java/org/jsmart/zerocode/core/utils/TokenUtils.java index e54a5036d..a5eee82dd 100644 --- a/core/src/main/java/org/jsmart/zerocode/core/utils/TokenUtils.java +++ b/core/src/main/java/org/jsmart/zerocode/core/utils/TokenUtils.java @@ -19,23 +19,7 @@ import static org.apache.commons.lang.RandomStringUtils.randomAlphabetic; import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric; import static org.apache.commons.lang.StringEscapeUtils.escapeJava; -import static org.jsmart.zerocode.core.engine.tokens.ZeroCodeValueTokens.ABS_PATH; -import static org.jsmart.zerocode.core.engine.tokens.ZeroCodeValueTokens.GLOBAL_RANDOM_NUMBER; -import static org.jsmart.zerocode.core.engine.tokens.ZeroCodeValueTokens.GQL_FILE; -import static org.jsmart.zerocode.core.engine.tokens.ZeroCodeValueTokens.LOCALDATETIME_NOW; -import static org.jsmart.zerocode.core.engine.tokens.ZeroCodeValueTokens.LOCALDATE_TODAY; -import static org.jsmart.zerocode.core.engine.tokens.ZeroCodeValueTokens.RANDOM_NUMBER; -import static org.jsmart.zerocode.core.engine.tokens.ZeroCodeValueTokens.RANDOM_NUMBER_FIXED; -import static org.jsmart.zerocode.core.engine.tokens.ZeroCodeValueTokens.RANDOM_STRING_ALPHA; -import static org.jsmart.zerocode.core.engine.tokens.ZeroCodeValueTokens.RANDOM_STRING_ALPHA_NUMERIC; -import static org.jsmart.zerocode.core.engine.tokens.ZeroCodeValueTokens.RANDOM_UU_ID; -import static org.jsmart.zerocode.core.engine.tokens.ZeroCodeValueTokens.RANDOM_UU_ID_FIXED; -import static org.jsmart.zerocode.core.engine.tokens.ZeroCodeValueTokens.STATIC_ALPHABET; -import static org.jsmart.zerocode.core.engine.tokens.ZeroCodeValueTokens.SYSTEM_ENV; -import static org.jsmart.zerocode.core.engine.tokens.ZeroCodeValueTokens.SYSTEM_PROPERTY; -import static org.jsmart.zerocode.core.engine.tokens.ZeroCodeValueTokens.XML_FILE; -import static org.jsmart.zerocode.core.engine.tokens.ZeroCodeValueTokens.getKnownTokens; -import static org.jsmart.zerocode.core.engine.tokens.ZeroCodeValueTokens.globalTokenCache; +import static org.jsmart.zerocode.core.engine.tokens.ZeroCodeValueTokens.*; public class TokenUtils { @@ -162,6 +146,29 @@ public static List getTestCaseTokens(String aString) { return keyTokens; } + public static String getMaskedTokensReplaced(String aString) { + String regex = "\\$\\{MASKED:([^\\}]*)\\}"; + Matcher maskMatcher = Pattern.compile(regex).matcher(aString); + while(maskMatcher.find()) { + String foundMatch = maskMatcher.group(0); + aString = aString.replace(foundMatch, MASKED_STR); + } + + return aString; + } + + public static String getMaskedTokensRemoved(String aString) { + String regex = "\\$\\{MASKED:([^\\}]*)\\}"; + Matcher maskMatcher = Pattern.compile(regex).matcher(aString); + while(maskMatcher.find()) { + String foundFullMatch = maskMatcher.group(0); + String innerContent = maskMatcher.group(1); + aString = aString.replace(foundFullMatch, innerContent); + } + + return aString; + } + public static String createRandomAlphaString(int length) { return randomAlphabetic(length); } From 079647e0aceec1ae341bc5530295da1c999c2fdb Mon Sep 17 00:00:00 2001 From: nchandra Date: Sun, 28 Jan 2024 14:07:11 +0000 Subject: [PATCH 23/44] ISSUES-603 Mask Method renamed --- .../main/java/org/jsmart/zerocode/core/utils/TokenUtils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/org/jsmart/zerocode/core/utils/TokenUtils.java b/core/src/main/java/org/jsmart/zerocode/core/utils/TokenUtils.java index a5eee82dd..e9e4707c6 100644 --- a/core/src/main/java/org/jsmart/zerocode/core/utils/TokenUtils.java +++ b/core/src/main/java/org/jsmart/zerocode/core/utils/TokenUtils.java @@ -157,7 +157,7 @@ public static String getMaskedTokensReplaced(String aString) { return aString; } - public static String getMaskedTokensRemoved(String aString) { + public static String getMasksRemoved(String aString) { String regex = "\\$\\{MASKED:([^\\}]*)\\}"; Matcher maskMatcher = Pattern.compile(regex).matcher(aString); while(maskMatcher.find()) { From b414c65f4b7447dd10dba923daa44d7eb4e8b8e2 Mon Sep 17 00:00:00 2001 From: Aditya Lahiri Date: Sun, 28 Jan 2024 19:43:17 +0530 Subject: [PATCH 24/44] Changes to support seekFromTimestamp --- .../kafka/consume/ConsumerLocalConfigs.java | 28 ++++-- .../kafka/helper/KafkaConsumerHelper.java | 92 +++++++++++++------ .../core/kafka/receive/KafkaReceiver.java | 4 +- 3 files changed, 85 insertions(+), 39 deletions(-) diff --git a/core/src/main/java/org/jsmart/zerocode/core/kafka/consume/ConsumerLocalConfigs.java b/core/src/main/java/org/jsmart/zerocode/core/kafka/consume/ConsumerLocalConfigs.java index 865992518..20f2cbbf7 100644 --- a/core/src/main/java/org/jsmart/zerocode/core/kafka/consume/ConsumerLocalConfigs.java +++ b/core/src/main/java/org/jsmart/zerocode/core/kafka/consume/ConsumerLocalConfigs.java @@ -23,6 +23,7 @@ public class ConsumerLocalConfigs { private final String protoClassType; private final Boolean cacheByTopic; private final String filterByJsonPath; + private final Long seekToTimestamp; @JsonCreator public ConsumerLocalConfigs( @@ -36,7 +37,8 @@ public ConsumerLocalConfigs( @JsonProperty("pollingTime") Long pollingTime, @JsonProperty("cacheByTopic") Boolean cacheByTopic, @JsonProperty("filterByJsonPath") String filterByJsonPath, - @JsonProperty("seek") String seek) { + @JsonProperty("seek") String seek, + @JsonProperty("seekToTimestamp") Long seekToTimestamp) { this.recordType = recordType; this.protoClassType= protobufMessageClassType; this.fileDumpTo = fileDumpTo; @@ -48,13 +50,14 @@ public ConsumerLocalConfigs( this.cacheByTopic = cacheByTopic; this.filterByJsonPath = filterByJsonPath; this.seek = seek; + this.seekToTimestamp = seekToTimestamp; } - + public ConsumerLocalConfigs( - String recordType, - String fileDumpTo, - Boolean commitAsync, + String recordType, + String fileDumpTo, + Boolean commitAsync, Boolean commitSync, Boolean showRecordsConsumed, Integer maxNoOfRetryPollsOrTimeouts, @@ -62,16 +65,17 @@ public ConsumerLocalConfigs( Boolean cacheByTopic, String filterByJsonPath, String seek) { - this(recordType, null, + this(recordType, null, fileDumpTo, commitAsync, commitSync, showRecordsConsumed, maxNoOfRetryPollsOrTimeouts, - pollingTime, + pollingTime, cacheByTopic, filterByJsonPath, - seek); + seek, + null); } public String getRecordType() { @@ -119,6 +123,10 @@ public String getSeek() { return seek; } + public Long getSeekToTimestamp() { + return seekToTimestamp; + } + @JsonIgnore public String[] getSeekTopicPartitionOffset() { return seek.split(","); @@ -139,7 +147,8 @@ public boolean equals(Object o) { Objects.equals(pollingTime, that.pollingTime) && Objects.equals(filterByJsonPath, that.filterByJsonPath) && Objects.equals(cacheByTopic, that.cacheByTopic) && - Objects.equals(seek, that.seek); + Objects.equals(seek, that.seek) && + Objects.equals(seekToTimestamp, that.seekToTimestamp); } @Override @@ -162,6 +171,7 @@ public String toString() { ", cacheByTopic=" + cacheByTopic + ", filterByJsonPath=" + filterByJsonPath + ", seek=" + seek + + ", seekToTimestamp=" + seekToTimestamp + '}'; } } diff --git a/core/src/main/java/org/jsmart/zerocode/core/kafka/helper/KafkaConsumerHelper.java b/core/src/main/java/org/jsmart/zerocode/core/kafka/helper/KafkaConsumerHelper.java index 1e5a76ae2..66548c0df 100644 --- a/core/src/main/java/org/jsmart/zerocode/core/kafka/helper/KafkaConsumerHelper.java +++ b/core/src/main/java/org/jsmart/zerocode/core/kafka/helper/KafkaConsumerHelper.java @@ -19,20 +19,13 @@ import java.lang.reflect.Method; import java.time.Duration; import java.time.temporal.ChronoUnit; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Properties; -import java.util.Set; +import java.util.*; +import java.util.function.Function; +import java.util.stream.Collectors; import com.jayway.jsonpath.JsonPath; -import org.apache.kafka.clients.consumer.Consumer; -import org.apache.kafka.clients.consumer.ConsumerRecord; -import org.apache.kafka.clients.consumer.ConsumerRecords; -import org.apache.kafka.clients.consumer.KafkaConsumer; +import org.apache.kafka.clients.consumer.*; +import org.apache.kafka.common.PartitionInfo; import org.apache.kafka.common.TopicPartition; import org.apache.kafka.common.header.Header; import org.apache.kafka.common.header.Headers; @@ -135,6 +128,14 @@ public static void validateLocalConfigs(ConsumerLocalConfigs localConfigs) { validateCommitFlags(localCommitSync, localCommitAsync); validateSeekConfig(localConfigs); + validateSeekToTimestamp(localConfigs); + } + } + + private static void validateSeekToTimestamp(ConsumerLocalConfigs localConfigs) { + Long seekToTimestamp = localConfigs.getSeekToTimestamp(); + if (Objects.nonNull(seekToTimestamp) && (seekToTimestamp > System.currentTimeMillis() || seekToTimestamp < 0L)) { + throw new RuntimeException("\n------> 'seekToTimestamp' is not a valid epoch/Unix timestamp"); } } @@ -163,7 +164,8 @@ public static ConsumerLocalConfigs createEffective(ConsumerCommonConfigs consume consumerCommon.getPollingTime(), consumerCommon.getCacheByTopic(), consumerCommon.getFilterByJsonPath(), - consumerCommon.getSeek()); + consumerCommon.getSeek(), + null); } // Handle recordType @@ -210,6 +212,8 @@ public static ConsumerLocalConfigs createEffective(ConsumerCommonConfigs consume effectiveCommitSync = localCommitSync; effectiveCommitAsync = localCommitAsync; } + // this property doesn't make sense in a common context. should always be picked from local config + Long effectiveSeekToTimestamp = consumerLocal.getSeekToTimestamp(); return new ConsumerLocalConfigs( effectiveRecordType, @@ -222,7 +226,8 @@ public static ConsumerLocalConfigs createEffective(ConsumerCommonConfigs consume effectivePollingTime, effectiveConsumerCacheByTopic, filterByJsonPath, - effectiveSeek); + effectiveSeek, + effectiveSeekToTimestamp); } public static ConsumerLocalConfigs readConsumerLocalTestProperties(String requestJsonWithConfigWrapped) { @@ -378,30 +383,61 @@ public static void handleCommitSyncAsync(Consumer consumer, // -------------------------------------------------------- } - public static void handleSeekOffset(ConsumerLocalConfigs effectiveLocal, Consumer consumer) { + public static void handleSeek(ConsumerLocalConfigs effectiveLocal, Consumer consumer, String topicName) { String seek = effectiveLocal.getSeek(); if (!isEmpty(seek)) { - String[] seekParts = effectiveLocal.getSeekTopicPartitionOffset(); - String topic = seekParts[0]; - int partition = parseInt(seekParts[1]); - long offset = parseLong(seekParts[2]); + handleSeekByOffset(effectiveLocal, consumer); + } else if (Objects.nonNull(effectiveLocal.getSeekToTimestamp())) { + handleSeekByTimestamp(effectiveLocal, consumer, topicName); + } + } + + private static void handleSeekByTimestamp(ConsumerLocalConfigs effectiveLocal, Consumer consumer, String topicName) { + if (Objects.nonNull(effectiveLocal.getSeekToTimestamp())) { + List partitionInfos = consumer.partitionsFor(topicName); + + //fetch partitions on topic + List topicPartitions = partitionInfos.stream() + .map(info -> new TopicPartition(info.topic(), info.partition())) + .collect(Collectors.toList()); - TopicPartition topicPartition = new TopicPartition(topic, partition); - Set topicPartitions = new HashSet<>(); - topicPartitions.add(topicPartition); + //fetch offsets for each partition-timestamp pair + Map topicPartitionTimestampMap = topicPartitions.stream() + .collect(Collectors.toMap(Function.identity(), ignore -> effectiveLocal.getSeekToTimestamp())); + Map topicPartitionOffsetAndTimestampMap = consumer.offsetsForTimes(topicPartitionTimestampMap); + //assign to fetched partitions consumer.unsubscribe(); - consumer.assign(topicPartitions); + consumer.assign(topicPartitionOffsetAndTimestampMap.keySet()); - if (offset <= -1) { - consumer.seekToEnd(topicPartitions); - consumer.seek(topicPartition, consumer.position(topicPartition) + offset); - } else { - consumer.seek(topicPartition, offset); + //seek to fetched offsets for partitions + for (Map.Entry topicOffsetEntry : topicPartitionOffsetAndTimestampMap.entrySet()) { + consumer.seek(topicOffsetEntry.getKey(), topicOffsetEntry.getValue().offset()); } } } + private static void handleSeekByOffset(ConsumerLocalConfigs effectiveLocal, Consumer consumer) { + String[] seekParts = effectiveLocal.getSeekTopicPartitionOffset(); + String topic = seekParts[0]; + int partition = parseInt(seekParts[1]); + long offset = parseLong(seekParts[2]); + + TopicPartition topicPartition = new TopicPartition(topic, partition); + Set topicPartitions = new HashSet<>(); + topicPartitions.add(topicPartition); + + consumer.unsubscribe(); + consumer.assign(topicPartitions); + + if (offset <= -1) { + consumer.seekToEnd(topicPartitions); + consumer.seek(topicPartition, consumer.position(topicPartition) + offset); + } else { + consumer.seek(topicPartition, offset); + } + } + private static void validateCommitFlags(Boolean commitSync, Boolean commitAsync) { if ((commitSync != null && commitAsync != null) && commitSync == true && commitAsync == true) { throw new RuntimeException("\n********* Both commitSync and commitAsync can not be true *********\n"); diff --git a/core/src/main/java/org/jsmart/zerocode/core/kafka/receive/KafkaReceiver.java b/core/src/main/java/org/jsmart/zerocode/core/kafka/receive/KafkaReceiver.java index 37f893161..327250242 100644 --- a/core/src/main/java/org/jsmart/zerocode/core/kafka/receive/KafkaReceiver.java +++ b/core/src/main/java/org/jsmart/zerocode/core/kafka/receive/KafkaReceiver.java @@ -25,7 +25,7 @@ import static org.jsmart.zerocode.core.kafka.helper.KafkaConsumerHelper.getMaxTimeOuts; import static org.jsmart.zerocode.core.kafka.helper.KafkaConsumerHelper.getPollTime; import static org.jsmart.zerocode.core.kafka.helper.KafkaConsumerHelper.handleCommitSyncAsync; -import static org.jsmart.zerocode.core.kafka.helper.KafkaConsumerHelper.handleSeekOffset; +import static org.jsmart.zerocode.core.kafka.helper.KafkaConsumerHelper.handleSeek; import static org.jsmart.zerocode.core.kafka.helper.KafkaConsumerHelper.initialPollWaitingForConsumerGroupJoin; import static org.jsmart.zerocode.core.kafka.helper.KafkaConsumerHelper.prepareResult; import static org.jsmart.zerocode.core.kafka.helper.KafkaConsumerHelper.readConsumerLocalTestProperties; @@ -62,7 +62,7 @@ public String receive(String kafkaServers, String topicName, String requestJsonW int noOfTimeOuts = 0; - handleSeekOffset(effectiveLocal, consumer); + handleSeek(effectiveLocal, consumer, topicName); LOGGER.debug("initial polling to trigger ConsumerGroupJoin"); From 365e9ac75be4d24faa31cf56c33f3cf658fc3cc7 Mon Sep 17 00:00:00 2001 From: DohaRamadan <77820526+DohaRamadan@users.noreply.github.com> Date: Sun, 28 Jan 2024 21:20:29 +0200 Subject: [PATCH 25/44] added unit test cases --- .../zerocode/core/utils/TokenUtilsTest.java | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/core/src/test/java/org/jsmart/zerocode/core/utils/TokenUtilsTest.java b/core/src/test/java/org/jsmart/zerocode/core/utils/TokenUtilsTest.java index 9566c4dc9..6c01ac6c8 100644 --- a/core/src/test/java/org/jsmart/zerocode/core/utils/TokenUtilsTest.java +++ b/core/src/test/java/org/jsmart/zerocode/core/utils/TokenUtilsTest.java @@ -10,6 +10,8 @@ import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.CoreMatchers.is; import static org.jsmart.zerocode.core.utils.TokenUtils.absolutePathOf; +import static org.jsmart.zerocode.core.utils.TokenUtils.getMaskedTokensReplaced; +import static org.jsmart.zerocode.core.utils.TokenUtils.getMasksRemoved; import static org.jsmart.zerocode.core.utils.TokenUtils.resolveKnownTokens; import static org.junit.Assert.*; @@ -169,4 +171,48 @@ public void testAbsolutePathOf() { assertThat(absolutePathOf("unit_test_files/jks_files/dummy_key_store.jks"), containsString("zerocode/core/target/test-classes/unit_test_files/jks_files/dummy_key_store.jks")); } + + + @Test + public void testGetMaskedTokensReplaced_multipleOccurrences(){ + assertEquals("This is a ***masked*** message with ***masked*** tokens.", getMaskedTokensReplaced("This is a ${MASKED:secret} message with ${MASKED:masked} tokens.")); + } + + @Test + public void testGetMaskedTokensReplaced_noOccurrences(){ + assertEquals("This string has no masked tokens.", getMaskedTokensReplaced("This string has no masked tokens.")); + } + + @Test + public void testGetMaskedTokensReplaced_emptyString(){ + assertEquals("", getMaskedTokensReplaced("")); + } + + @Test + public void testGetMaskedTokensReplaced_specialCharacters(){ + assertEquals("***masked*** and ***masked***", getMaskedTokensReplaced("${MASKED:abc@123} and ${MASKED:!@#$%^}")); + } + + @Test + public void testGetMaskedTokensRemoved_multipleOccurrences(){ + assertEquals("This is a secret message with masked tokens.", getMasksRemoved("This is a ${MASKED:secret} message with ${MASKED:masked} tokens.")); + } + + @Test + public void testGetMaskedTokensRemoved_noOccurrences(){ + assertEquals("This string has no masked tokens.", getMasksRemoved("This string has no masked tokens.")); + } + + @Test + public void testGetMaskedTokensRemoved_emptyString(){ + assertEquals("", getMasksRemoved("")); + } + + @Test + public void testGetMaskedTokensRemoved_specialCharacters(){ + assertEquals("abc@123 and !@#$%^", getMasksRemoved("${MASKED:abc@123} and ${MASKED:!@#$%^}")); + } + + + } \ No newline at end of file From 3d1ddb8046e57ccf4a9f0db10308eef5399971a7 Mon Sep 17 00:00:00 2001 From: authorjapps Date: Sun, 28 Jan 2024 21:07:54 +0000 Subject: [PATCH 26/44] Removed psvm --- .../zerocode/core/report/ZeroCodeReportGeneratorImpl.java | 8 -------- 1 file changed, 8 deletions(-) diff --git a/core/src/main/java/org/jsmart/zerocode/core/report/ZeroCodeReportGeneratorImpl.java b/core/src/main/java/org/jsmart/zerocode/core/report/ZeroCodeReportGeneratorImpl.java index d356cdde4..e80fb0760 100644 --- a/core/src/main/java/org/jsmart/zerocode/core/report/ZeroCodeReportGeneratorImpl.java +++ b/core/src/main/java/org/jsmart/zerocode/core/report/ZeroCodeReportGeneratorImpl.java @@ -414,12 +414,4 @@ private String createTimeStampedFileName() { ".html"; } - public static void main(String[] args) { - String sss = "A quick brown fox jumps over a lazy dog @ODS-X @Licenc_Y Z"; - for(String st : sss.trim().split(" ")){ - if(st.startsWith("@")){ - System.out.println(st); - } - } - } } From 153a06d19988062b5451d1f0cb01b59373ba1c19 Mon Sep 17 00:00:00 2001 From: nchandra Date: Sun, 28 Jan 2024 22:59:52 +0000 Subject: [PATCH 27/44] ISSUES-603 Mask applied for logging n removed for API exec --- .../ZeroCodeAssertionsProcessor.java | 4 + .../ZeroCodeAssertionsProcessorImpl.java | 74 +++++++++++++++---- .../ZeroCodeMultiStepsScenarioRunnerImpl.java | 23 ++++-- .../zerocode/core/utils/TokenUtils.java | 2 +- .../zerocode/core/utils/TokenUtilsTest.java | 10 +-- 5 files changed, 83 insertions(+), 30 deletions(-) diff --git a/core/src/main/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeAssertionsProcessor.java b/core/src/main/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeAssertionsProcessor.java index 0d5ac829c..c74a8d9b8 100644 --- a/core/src/main/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeAssertionsProcessor.java +++ b/core/src/main/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeAssertionsProcessor.java @@ -22,4 +22,8 @@ public interface ZeroCodeAssertionsProcessor { Step resolveJsonContent(Step thisStep, ScenarioExecutionState scenarioExecutionState); + String fieldMasksRemoved(String resolvedRequestJson); + + String fieldMasksApplied(String resolvedRequestJson); + } diff --git a/core/src/main/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeAssertionsProcessorImpl.java b/core/src/main/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeAssertionsProcessorImpl.java index cafb18f35..e083918fc 100644 --- a/core/src/main/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeAssertionsProcessorImpl.java +++ b/core/src/main/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeAssertionsProcessorImpl.java @@ -8,6 +8,28 @@ import com.google.inject.Inject; import com.google.inject.name.Named; import com.jayway.jsonpath.JsonPath; +import net.minidev.json.JSONArray; +import org.apache.commons.lang.text.StrSubstitutor; +import org.jsmart.zerocode.core.domain.Step; +import org.jsmart.zerocode.core.engine.assertion.FieldAssertionMatcher; +import org.jsmart.zerocode.core.engine.assertion.JsonAsserter; +import org.jsmart.zerocode.core.engine.assertion.array.ArrayIsEmptyAsserterImpl; +import org.jsmart.zerocode.core.engine.assertion.array.ArraySizeAsserterImpl; +import org.jsmart.zerocode.core.engine.assertion.field.FieldContainsStringAsserter; +import org.jsmart.zerocode.core.engine.assertion.field.FieldContainsStringIgnoreCaseAsserter; +import org.jsmart.zerocode.core.engine.assertion.field.FieldHasDateAfterValueAsserter; +import org.jsmart.zerocode.core.engine.assertion.field.FieldHasDateBeforeValueAsserter; +import org.jsmart.zerocode.core.engine.assertion.field.FieldHasEqualNumberValueAsserter; +import org.jsmart.zerocode.core.engine.assertion.field.FieldHasExactValueAsserter; +import org.jsmart.zerocode.core.engine.assertion.field.FieldHasGreaterThanValueAsserter; +import org.jsmart.zerocode.core.engine.assertion.field.FieldHasInEqualNumberValueAsserter; +import org.jsmart.zerocode.core.engine.assertion.field.FieldHasLesserThanValueAsserter; +import org.jsmart.zerocode.core.engine.assertion.field.FieldIsNotNullAsserter; +import org.jsmart.zerocode.core.engine.assertion.field.FieldIsNullAsserter; +import org.jsmart.zerocode.core.engine.assertion.field.FieldIsOneOfValueAsserter; +import org.jsmart.zerocode.core.engine.assertion.field.FieldMatchesCustomAsserter; +import org.jsmart.zerocode.core.engine.assertion.field.FieldMatchesRegexPatternAsserter; + import java.io.IOException; import java.math.BigDecimal; import java.time.LocalDateTime; @@ -19,37 +41,47 @@ import java.util.List; import java.util.Map; import java.util.Properties; -import net.minidev.json.JSONArray; -import org.apache.commons.lang.text.StrSubstitutor; -import org.jsmart.zerocode.core.domain.Step; -import org.jsmart.zerocode.core.engine.assertion.FieldAssertionMatcher; -import org.jsmart.zerocode.core.engine.assertion.JsonAsserter; -import org.jsmart.zerocode.core.engine.assertion.array.ArrayIsEmptyAsserterImpl; -import org.jsmart.zerocode.core.engine.assertion.array.ArraySizeAsserterImpl; -import org.jsmart.zerocode.core.engine.assertion.field.*; -import org.jsmart.zerocode.core.utils.SmartUtils; import static java.lang.Integer.valueOf; import static java.lang.String.format; import static org.apache.commons.lang.StringEscapeUtils.escapeJava; import static org.apache.commons.lang.StringUtils.substringBetween; -import static org.jsmart.zerocode.core.engine.tokens.ZeroCodeAssertionTokens.*; +import static org.jsmart.zerocode.core.engine.tokens.ZeroCodeAssertionTokens.ASSERT_LOCAL_DATETIME_AFTER; +import static org.jsmart.zerocode.core.engine.tokens.ZeroCodeAssertionTokens.ASSERT_LOCAL_DATETIME_BEFORE; +import static org.jsmart.zerocode.core.engine.tokens.ZeroCodeAssertionTokens.ASSERT_PATH_SIZE; +import static org.jsmart.zerocode.core.engine.tokens.ZeroCodeAssertionTokens.ASSERT_VALUE_CONTAINS_STRING; +import static org.jsmart.zerocode.core.engine.tokens.ZeroCodeAssertionTokens.ASSERT_VALUE_CONTAINS_STRING_IGNORE_CASE; +import static org.jsmart.zerocode.core.engine.tokens.ZeroCodeAssertionTokens.ASSERT_VALUE_CUSTOM_ASSERT; +import static org.jsmart.zerocode.core.engine.tokens.ZeroCodeAssertionTokens.ASSERT_VALUE_EMPTY_ARRAY; +import static org.jsmart.zerocode.core.engine.tokens.ZeroCodeAssertionTokens.ASSERT_VALUE_EQUAL_TO_NUMBER; +import static org.jsmart.zerocode.core.engine.tokens.ZeroCodeAssertionTokens.ASSERT_VALUE_GREATER_THAN; +import static org.jsmart.zerocode.core.engine.tokens.ZeroCodeAssertionTokens.ASSERT_VALUE_IS_NOT_NULL; +import static org.jsmart.zerocode.core.engine.tokens.ZeroCodeAssertionTokens.ASSERT_VALUE_IS_NULL; +import static org.jsmart.zerocode.core.engine.tokens.ZeroCodeAssertionTokens.ASSERT_VALUE_IS_ONE_OF; +import static org.jsmart.zerocode.core.engine.tokens.ZeroCodeAssertionTokens.ASSERT_VALUE_LESSER_THAN; +import static org.jsmart.zerocode.core.engine.tokens.ZeroCodeAssertionTokens.ASSERT_VALUE_MATCHES_STRING; +import static org.jsmart.zerocode.core.engine.tokens.ZeroCodeAssertionTokens.ASSERT_VALUE_NOT_EQUAL_TO_NUMBER; +import static org.jsmart.zerocode.core.engine.tokens.ZeroCodeAssertionTokens.ASSERT_VALUE_NOT_NULL; +import static org.jsmart.zerocode.core.engine.tokens.ZeroCodeAssertionTokens.ASSERT_VALUE_NULL; +import static org.jsmart.zerocode.core.engine.tokens.ZeroCodeAssertionTokens.ASSERT_VALUE_ONE_OF; +import static org.jsmart.zerocode.core.engine.tokens.ZeroCodeAssertionTokens.RAW_BODY; import static org.jsmart.zerocode.core.engine.tokens.ZeroCodeValueTokens.$VALUE; import static org.jsmart.zerocode.core.engine.tokens.ZeroCodeValueTokens.JSON_CONTENT; -import static org.jsmart.zerocode.core.engine.tokens.ZeroCodeValueTokens.JSON_PAYLOAD_FILE; -import static org.jsmart.zerocode.core.engine.tokens.ZeroCodeValueTokens.YAML_PAYLOAD_FILE; import static org.jsmart.zerocode.core.utils.FieldTypeConversionUtils.deepTypeCast; import static org.jsmart.zerocode.core.utils.FieldTypeConversionUtils.fieldTypes; import static org.jsmart.zerocode.core.utils.PropertiesProviderUtils.loadAbsoluteProperties; +import static org.jsmart.zerocode.core.utils.SmartUtils.checkDigNeeded; +import static org.jsmart.zerocode.core.utils.SmartUtils.getJsonFilePhToken; import static org.jsmart.zerocode.core.utils.SmartUtils.isValidAbsolutePath; -import static org.jsmart.zerocode.core.utils.SmartUtils.readJsonAsString; -import static org.jsmart.zerocode.core.utils.SmartUtils.readYamlAsString; -import static org.jsmart.zerocode.core.utils.SmartUtils.checkDigNeeded;; -import static org.jsmart.zerocode.core.utils.SmartUtils.getJsonFilePhToken;; +import static org.jsmart.zerocode.core.utils.TokenUtils.getMasksRemoved; +import static org.jsmart.zerocode.core.utils.TokenUtils.getMasksReplaced; import static org.jsmart.zerocode.core.utils.TokenUtils.getTestCaseTokens; import static org.jsmart.zerocode.core.utils.TokenUtils.populateParamMap; import static org.slf4j.LoggerFactory.getLogger; +; +; + public class ZeroCodeAssertionsProcessorImpl implements ZeroCodeAssertionsProcessor { private static final org.slf4j.Logger LOGGER = getLogger(ZeroCodeAssertionsProcessorImpl.class); @@ -380,6 +412,16 @@ public Step resolveJsonContent(Step thisStep, ScenarioExecutionState scenarioExe } } + @Override + public String fieldMasksRemoved(String resolvedRequestJson) { + return getMasksRemoved(resolvedRequestJson); + } + + @Override + public String fieldMasksApplied(String resolvedRequestJson) { + return getMasksReplaced(resolvedRequestJson); + } + private void loadAnnotatedHostProperties() { try { if(isValidAbsolutePath(hostFileName)){ diff --git a/core/src/main/java/org/jsmart/zerocode/core/runner/ZeroCodeMultiStepsScenarioRunnerImpl.java b/core/src/main/java/org/jsmart/zerocode/core/runner/ZeroCodeMultiStepsScenarioRunnerImpl.java index fd9190e76..7808a5fd0 100644 --- a/core/src/main/java/org/jsmart/zerocode/core/runner/ZeroCodeMultiStepsScenarioRunnerImpl.java +++ b/core/src/main/java/org/jsmart/zerocode/core/runner/ZeroCodeMultiStepsScenarioRunnerImpl.java @@ -414,6 +414,13 @@ private String executeApi(String logPrefixRelationshipId, // -------------------------------- url = zeroCodeAssertionsProcessor.resolveStringJson(url, scenarioExecutionState.getResolvedScenarioState()); + // ------------------------------------------------ + // 1) Removed the MASKED wrapper for API execution (For logging) + // 2) Replace the MASKED field with masked content (For API executions) + // ------------------------------------------------ + String resolvedRequestJsonMaskRemoved = zeroCodeAssertionsProcessor.fieldMasksRemoved(resolvedRequestJson); + String resolvedRequestJsonMaskApplied = zeroCodeAssertionsProcessor.fieldMasksApplied(resolvedRequestJson); + final LocalDateTime requestTimeStamp = LocalDateTime.now(); String executionResult; @@ -428,9 +435,9 @@ private String executeApi(String logPrefixRelationshipId, .url(url) .method(operationName) .id(stepId) - .request(prettyPrintJson(resolvedRequestJson)); + .request(prettyPrintJson(resolvedRequestJsonMaskApplied)); - executionResult = apiExecutor.executeHttpApi(url, operationName, resolvedRequestJson); + executionResult = apiExecutor.executeHttpApi(url, operationName, resolvedRequestJsonMaskRemoved); break; case JAVA_CALL: @@ -441,10 +448,10 @@ private String executeApi(String logPrefixRelationshipId, .id(stepId) .url(url) .method(operationName) - .request(prettyPrintJson(resolvedRequestJson)); + .request(prettyPrintJson(resolvedRequestJsonMaskApplied)); url = apiTypeUtils.getQualifiedJavaApi(url); - executionResult = apiExecutor.executeJavaOperation(url, operationName, resolvedRequestJson); + executionResult = apiExecutor.executeJavaOperation(url, operationName, resolvedRequestJsonMaskRemoved); break; case KAFKA_CALL: @@ -459,10 +466,10 @@ private String executeApi(String logPrefixRelationshipId, .url(url) .method(operationName.toUpperCase()) .id(stepId) - .request(prettyPrintJson(resolvedRequestJson)); + .request(prettyPrintJson(resolvedRequestJsonMaskApplied)); String topicName = url.substring(KAFKA_TOPIC.length()); - executionResult = apiExecutor.executeKafkaService(kafkaServers, topicName, operationName, resolvedRequestJson, scenarioExecutionState); + executionResult = apiExecutor.executeKafkaService(kafkaServers, topicName, operationName, resolvedRequestJsonMaskRemoved, scenarioExecutionState); break; case NONE: @@ -473,14 +480,14 @@ private String executeApi(String logPrefixRelationshipId, .id(stepId) .url(url) .method(operationName) - .request(prettyPrintJson(resolvedRequestJson)); + .request(prettyPrintJson(resolvedRequestJsonMaskApplied)); executionResult = prettyPrintJson(resolvedRequestJson); break; default: throw new RuntimeException("Oops! API Type Undecided. If it is intentional, " + - "then keep the value as empty to receive the request in the response"); + "then keep the value as empty to receive the request as response"); } return executionResult; diff --git a/core/src/main/java/org/jsmart/zerocode/core/utils/TokenUtils.java b/core/src/main/java/org/jsmart/zerocode/core/utils/TokenUtils.java index e9e4707c6..367c1ff42 100644 --- a/core/src/main/java/org/jsmart/zerocode/core/utils/TokenUtils.java +++ b/core/src/main/java/org/jsmart/zerocode/core/utils/TokenUtils.java @@ -146,7 +146,7 @@ public static List getTestCaseTokens(String aString) { return keyTokens; } - public static String getMaskedTokensReplaced(String aString) { + public static String getMasksReplaced(String aString) { String regex = "\\$\\{MASKED:([^\\}]*)\\}"; Matcher maskMatcher = Pattern.compile(regex).matcher(aString); while(maskMatcher.find()) { diff --git a/core/src/test/java/org/jsmart/zerocode/core/utils/TokenUtilsTest.java b/core/src/test/java/org/jsmart/zerocode/core/utils/TokenUtilsTest.java index 6c01ac6c8..a4dedeadd 100644 --- a/core/src/test/java/org/jsmart/zerocode/core/utils/TokenUtilsTest.java +++ b/core/src/test/java/org/jsmart/zerocode/core/utils/TokenUtilsTest.java @@ -10,7 +10,7 @@ import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.CoreMatchers.is; import static org.jsmart.zerocode.core.utils.TokenUtils.absolutePathOf; -import static org.jsmart.zerocode.core.utils.TokenUtils.getMaskedTokensReplaced; +import static org.jsmart.zerocode.core.utils.TokenUtils.getMasksReplaced; import static org.jsmart.zerocode.core.utils.TokenUtils.getMasksRemoved; import static org.jsmart.zerocode.core.utils.TokenUtils.resolveKnownTokens; import static org.junit.Assert.*; @@ -175,22 +175,22 @@ public void testAbsolutePathOf() { @Test public void testGetMaskedTokensReplaced_multipleOccurrences(){ - assertEquals("This is a ***masked*** message with ***masked*** tokens.", getMaskedTokensReplaced("This is a ${MASKED:secret} message with ${MASKED:masked} tokens.")); + assertEquals("This is a ***masked*** message with ***masked*** tokens.", getMasksReplaced("This is a ${MASKED:secret} message with ${MASKED:masked} tokens.")); } @Test public void testGetMaskedTokensReplaced_noOccurrences(){ - assertEquals("This string has no masked tokens.", getMaskedTokensReplaced("This string has no masked tokens.")); + assertEquals("This string has no masked tokens.", getMasksReplaced("This string has no masked tokens.")); } @Test public void testGetMaskedTokensReplaced_emptyString(){ - assertEquals("", getMaskedTokensReplaced("")); + assertEquals("", getMasksReplaced("")); } @Test public void testGetMaskedTokensReplaced_specialCharacters(){ - assertEquals("***masked*** and ***masked***", getMaskedTokensReplaced("${MASKED:abc@123} and ${MASKED:!@#$%^}")); + assertEquals("***masked*** and ***masked***", getMasksReplaced("${MASKED:abc@123} and ${MASKED:!@#$%^}")); } @Test From a27729c5f815210c4aa157bc03579c8a5d8718e1 Mon Sep 17 00:00:00 2001 From: authorjapps Date: Wed, 31 Jan 2024 17:42:25 +0000 Subject: [PATCH 28/44] Update BUILDING.md --- BUILDING.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/BUILDING.md b/BUILDING.md index 7866abd7e..5d0da2c86 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -28,6 +28,9 @@ mvn -pl core clean test ## With tests executed(kafka) Some tests require a running Kafka (and some related components like kafka-rest, and kafka-schema-registry). +Location: +https://github.com/authorjapps/zerocode/blob/master/docker/compose/kafka-schema-registry.yml + Download the file, and run(or `cd to the docker/compose` dir and run) ``` docker-compose -f kafka-schema-registry.yml up -d From 0700b3f0cb2390eec193b815d878b2bca9571089 Mon Sep 17 00:00:00 2001 From: Aditya Lahiri Date: Sat, 3 Feb 2024 09:07:33 +0530 Subject: [PATCH 29/44] seekTimestamp added with format 1. Changed epoch seekTimestamp to seekEpoch and added seekTimestamp with format and timestamp 2. Added validations for seekEpoch and seekTimestamp 3. Implemented seekTimestamp feature --- core/pom.xml | 4 ++ .../kafka/consume/ConsumerLocalConfigs.java | 44 ++++++++----- .../core/kafka/consume/SeekTimestamp.java | 16 +++++ .../kafka/helper/KafkaConsumerHelper.java | 63 ++++++++++++++----- .../kafka/receive/ConsumerCommonConfigs.java | 19 +----- .../consume/ConsumerLocalConfigsWrapTest.java | 6 +- .../kafka/helper/KafkaConsumerHelperTest.java | 38 +++++------ pom.xml | 8 +++ 8 files changed, 129 insertions(+), 69 deletions(-) create mode 100644 core/src/main/java/org/jsmart/zerocode/core/kafka/consume/SeekTimestamp.java diff --git a/core/pom.xml b/core/pom.xml index de612cc51..21d12466b 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -116,6 +116,10 @@ com.jayway.jsonpath json-path + + org.projectlombok + lombok + commons-lang commons-lang diff --git a/core/src/main/java/org/jsmart/zerocode/core/kafka/consume/ConsumerLocalConfigs.java b/core/src/main/java/org/jsmart/zerocode/core/kafka/consume/ConsumerLocalConfigs.java index 20f2cbbf7..86b49df10 100644 --- a/core/src/main/java/org/jsmart/zerocode/core/kafka/consume/ConsumerLocalConfigs.java +++ b/core/src/main/java/org/jsmart/zerocode/core/kafka/consume/ConsumerLocalConfigs.java @@ -23,7 +23,9 @@ public class ConsumerLocalConfigs { private final String protoClassType; private final Boolean cacheByTopic; private final String filterByJsonPath; - private final Long seekToTimestamp; + private final String seekEpoch; + private final SeekTimestamp seekTimestamp; + @JsonCreator public ConsumerLocalConfigs( @@ -38,9 +40,10 @@ public ConsumerLocalConfigs( @JsonProperty("cacheByTopic") Boolean cacheByTopic, @JsonProperty("filterByJsonPath") String filterByJsonPath, @JsonProperty("seek") String seek, - @JsonProperty("seekToTimestamp") Long seekToTimestamp) { + @JsonProperty("seekEpoch") String seekEpoch, + @JsonProperty("seekTimestamp") SeekTimestamp seekTimestamp) { this.recordType = recordType; - this.protoClassType= protobufMessageClassType; + this.protoClassType = protobufMessageClassType; this.fileDumpTo = fileDumpTo; this.commitAsync = commitAsync; this.commitSync = commitSync; @@ -50,7 +53,8 @@ public ConsumerLocalConfigs( this.cacheByTopic = cacheByTopic; this.filterByJsonPath = filterByJsonPath; this.seek = seek; - this.seekToTimestamp = seekToTimestamp; + this.seekEpoch = seekEpoch; + this.seekTimestamp = seekTimestamp; } @@ -64,7 +68,9 @@ public ConsumerLocalConfigs( Long pollingTime, Boolean cacheByTopic, String filterByJsonPath, - String seek) { + String seek, + String seekEpoch, + SeekTimestamp seekTimestamp) { this(recordType, null, fileDumpTo, commitAsync, @@ -75,16 +81,17 @@ public ConsumerLocalConfigs( cacheByTopic, filterByJsonPath, seek, - null); + seekEpoch, + seekTimestamp); } public String getRecordType() { return recordType != null ? recordType : RAW; } - - public String getProtoClassType() { - return protoClassType; - } + + public String getProtoClassType() { + return protoClassType; + } public String getFileDumpTo() { @@ -123,8 +130,12 @@ public String getSeek() { return seek; } - public Long getSeekToTimestamp() { - return seekToTimestamp; + public String getSeekEpoch() { + return seekEpoch; + } + + public SeekTimestamp getSeekTimestamp() { + return seekTimestamp; } @JsonIgnore @@ -138,7 +149,7 @@ public boolean equals(Object o) { if (o == null || getClass() != o.getClass()) return false; ConsumerLocalConfigs that = (ConsumerLocalConfigs) o; return Objects.equals(recordType, that.recordType) && - Objects.equals(protoClassType, that.protoClassType) && + Objects.equals(protoClassType, that.protoClassType) && Objects.equals(fileDumpTo, that.fileDumpTo) && Objects.equals(commitAsync, that.commitAsync) && Objects.equals(commitSync, that.commitSync) && @@ -148,13 +159,13 @@ public boolean equals(Object o) { Objects.equals(filterByJsonPath, that.filterByJsonPath) && Objects.equals(cacheByTopic, that.cacheByTopic) && Objects.equals(seek, that.seek) && - Objects.equals(seekToTimestamp, that.seekToTimestamp); + Objects.equals(seekEpoch, that.seekEpoch); } @Override public int hashCode() { - return Objects.hash(recordType, fileDumpTo, commitAsync, commitSync, showRecordsConsumed, maxNoOfRetryPollsOrTimeouts, pollingTime,cacheByTopic, filterByJsonPath, seek); + return Objects.hash(recordType, fileDumpTo, commitAsync, commitSync, showRecordsConsumed, maxNoOfRetryPollsOrTimeouts, pollingTime, cacheByTopic, filterByJsonPath, seek); } @Override @@ -171,7 +182,8 @@ public String toString() { ", cacheByTopic=" + cacheByTopic + ", filterByJsonPath=" + filterByJsonPath + ", seek=" + seek + - ", seekToTimestamp=" + seekToTimestamp + + ", seekEpoch=" + seekEpoch + + ", seekTimestamp=" + seekTimestamp + '}'; } } diff --git a/core/src/main/java/org/jsmart/zerocode/core/kafka/consume/SeekTimestamp.java b/core/src/main/java/org/jsmart/zerocode/core/kafka/consume/SeekTimestamp.java new file mode 100644 index 000000000..5ce72b408 --- /dev/null +++ b/core/src/main/java/org/jsmart/zerocode/core/kafka/consume/SeekTimestamp.java @@ -0,0 +1,16 @@ +package org.jsmart.zerocode.core.kafka.consume; + + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.ToString; + + +@Getter +@ToString +@AllArgsConstructor +public class SeekTimestamp { + + private final String timestamp; + private final String format; +} diff --git a/core/src/main/java/org/jsmart/zerocode/core/kafka/helper/KafkaConsumerHelper.java b/core/src/main/java/org/jsmart/zerocode/core/kafka/helper/KafkaConsumerHelper.java index 66548c0df..820dadfb6 100644 --- a/core/src/main/java/org/jsmart/zerocode/core/kafka/helper/KafkaConsumerHelper.java +++ b/core/src/main/java/org/jsmart/zerocode/core/kafka/helper/KafkaConsumerHelper.java @@ -4,6 +4,7 @@ import static java.lang.Long.parseLong; import static java.util.Optional.ofNullable; import static org.apache.commons.lang3.StringUtils.isEmpty; +import static org.apache.commons.lang3.StringUtils.isNumeric; import static org.jsmart.zerocode.core.kafka.KafkaConstants.AVRO; import static org.jsmart.zerocode.core.kafka.KafkaConstants.DEFAULT_POLLING_TIME_MILLI_SEC; import static org.jsmart.zerocode.core.kafka.KafkaConstants.JSON; @@ -17,6 +18,9 @@ import java.io.InputStream; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; import java.time.Duration; import java.time.temporal.ChronoUnit; import java.util.*; @@ -24,6 +28,7 @@ import java.util.stream.Collectors; import com.jayway.jsonpath.JsonPath; +import lombok.SneakyThrows; import org.apache.kafka.clients.consumer.*; import org.apache.kafka.common.PartitionInfo; import org.apache.kafka.common.TopicPartition; @@ -34,6 +39,7 @@ import org.jsmart.zerocode.core.kafka.KafkaConstants; import org.jsmart.zerocode.core.kafka.consume.ConsumerLocalConfigs; import org.jsmart.zerocode.core.kafka.consume.ConsumerLocalConfigsWrap; +import org.jsmart.zerocode.core.kafka.consume.SeekTimestamp; import org.jsmart.zerocode.core.kafka.receive.ConsumerCommonConfigs; import org.jsmart.zerocode.core.kafka.receive.message.ConsumerJsonRecord; import org.jsmart.zerocode.core.kafka.receive.message.ConsumerJsonRecords; @@ -133,9 +139,26 @@ public static void validateLocalConfigs(ConsumerLocalConfigs localConfigs) { } private static void validateSeekToTimestamp(ConsumerLocalConfigs localConfigs) { - Long seekToTimestamp = localConfigs.getSeekToTimestamp(); - if (Objects.nonNull(seekToTimestamp) && (seekToTimestamp > System.currentTimeMillis() || seekToTimestamp < 0L)) { - throw new RuntimeException("\n------> 'seekToTimestamp' is not a valid epoch/Unix timestamp"); + String seekToTimestamp = localConfigs.getSeekEpoch(); + if (isEmpty(seekToTimestamp)) { + if (isNumeric(seekToTimestamp) && (Long.parseLong(seekToTimestamp) > System.currentTimeMillis() || Long.parseLong(seekToTimestamp) < 0L)) { + throw new RuntimeException("\n------> 'seekEpoch' is not a valid epoch/Unix timestamp"); + } + if (!isEmpty(localConfigs.getSeek()) && Objects.nonNull(localConfigs.getSeekTimestamp())) { + throw new RuntimeException("Only one of 'seek', 'seekEpoch' and 'seekTimestamp' should be provided, but not both. Please fix and rerun"); + } + } + if (Objects.nonNull(localConfigs.getSeekTimestamp())) { + DateFormat dateFormat = new SimpleDateFormat(localConfigs.getSeekTimestamp().getFormat()); + try { + Date date = dateFormat.parse(localConfigs.getSeekTimestamp().getTimestamp()); + long epochMillis = date.toInstant().toEpochMilli(); + if (epochMillis > System.currentTimeMillis() || epochMillis < 0L) { + throw new RuntimeException("\n------> 'seekTimestamp' is not a valid epoch/Unix timestamp " + epochMillis); + } + } catch (ParseException e) { + throw new RuntimeException("Timestamp and format provided in 'seekTimestamp' cannot be parsed ", e); + } } } @@ -164,7 +187,8 @@ public static ConsumerLocalConfigs createEffective(ConsumerCommonConfigs consume consumerCommon.getPollingTime(), consumerCommon.getCacheByTopic(), consumerCommon.getFilterByJsonPath(), - consumerCommon.getSeek(), + null, + null, null); } @@ -190,9 +214,6 @@ public static ConsumerLocalConfigs createEffective(ConsumerCommonConfigs consume // Handle pollingTime String filterByJsonPath = ofNullable(consumerLocal.getFilterByJsonPath()).orElse(consumerCommon.getFilterByJsonPath()); - // Handle pollingTime - String effectiveSeek = ofNullable(consumerLocal.getSeek()).orElse(consumerCommon.getSeek()); - // Handle consumerCache by topic Boolean effectiveConsumerCacheByTopic = ofNullable(consumerLocal.getCacheByTopic()) .orElse(consumerCommon.getCacheByTopic()); @@ -212,8 +233,6 @@ public static ConsumerLocalConfigs createEffective(ConsumerCommonConfigs consume effectiveCommitSync = localCommitSync; effectiveCommitAsync = localCommitAsync; } - // this property doesn't make sense in a common context. should always be picked from local config - Long effectiveSeekToTimestamp = consumerLocal.getSeekToTimestamp(); return new ConsumerLocalConfigs( effectiveRecordType, @@ -226,8 +245,9 @@ public static ConsumerLocalConfigs createEffective(ConsumerCommonConfigs consume effectivePollingTime, effectiveConsumerCacheByTopic, filterByJsonPath, - effectiveSeek, - effectiveSeekToTimestamp); + consumerLocal.getSeek(), + consumerLocal.getSeekEpoch(), + consumerLocal.getSeekTimestamp()); } public static ConsumerLocalConfigs readConsumerLocalTestProperties(String requestJsonWithConfigWrapped) { @@ -387,13 +407,24 @@ public static void handleSeek(ConsumerLocalConfigs effectiveLocal, Consumer cons String seek = effectiveLocal.getSeek(); if (!isEmpty(seek)) { handleSeekByOffset(effectiveLocal, consumer); - } else if (Objects.nonNull(effectiveLocal.getSeekToTimestamp())) { - handleSeekByTimestamp(effectiveLocal, consumer, topicName); + } else if (!isEmpty(effectiveLocal.getSeekEpoch())) { + handleSeekByEpoch(Long.parseLong(effectiveLocal.getSeekEpoch()), consumer, topicName); + } else if (Objects.nonNull(effectiveLocal.getSeekTimestamp())) { + handleSeekByTimestamp(effectiveLocal.getSeekTimestamp(), consumer, topicName); + } + } + + @SneakyThrows + private static void handleSeekByTimestamp(SeekTimestamp seekTimestamp, Consumer consumer, String topicName) { + if (Objects.nonNull(seekTimestamp)) { + DateFormat dateFormat = new SimpleDateFormat(seekTimestamp.getFormat()); + Date date = dateFormat.parse(seekTimestamp.getTimestamp()); + handleSeekByEpoch(date.toInstant().toEpochMilli(), consumer, topicName); } } - private static void handleSeekByTimestamp(ConsumerLocalConfigs effectiveLocal, Consumer consumer, String topicName) { - if (Objects.nonNull(effectiveLocal.getSeekToTimestamp())) { + private static void handleSeekByEpoch(Long epoch, Consumer consumer, String topicName) { + if (Objects.nonNull(epoch)) { List partitionInfos = consumer.partitionsFor(topicName); //fetch partitions on topic @@ -403,7 +434,7 @@ private static void handleSeekByTimestamp(ConsumerLocalConfigs effectiveLocal, C //fetch offsets for each partition-timestamp pair Map topicPartitionTimestampMap = topicPartitions.stream() - .collect(Collectors.toMap(Function.identity(), ignore -> effectiveLocal.getSeekToTimestamp())); + .collect(Collectors.toMap(Function.identity(), ignore -> epoch)); Map topicPartitionOffsetAndTimestampMap = consumer.offsetsForTimes(topicPartitionTimestampMap); //assign to fetched partitions diff --git a/core/src/main/java/org/jsmart/zerocode/core/kafka/receive/ConsumerCommonConfigs.java b/core/src/main/java/org/jsmart/zerocode/core/kafka/receive/ConsumerCommonConfigs.java index 2b6640d4e..d34fe087c 100644 --- a/core/src/main/java/org/jsmart/zerocode/core/kafka/receive/ConsumerCommonConfigs.java +++ b/core/src/main/java/org/jsmart/zerocode/core/kafka/receive/ConsumerCommonConfigs.java @@ -49,11 +49,6 @@ public class ConsumerCommonConfigs { @Named("consumer.filterByJsonPath") private String filterByJsonPath; - // TODO- Remove this from Global properties, as it doesn't make sense - @Inject(optional = true) - @Named("consumer.seek") - private String seek; - public ConsumerCommonConfigs() { } @@ -66,8 +61,7 @@ public ConsumerCommonConfigs(Boolean commitSync, Integer maxNoOfRetryPollsOrTimeouts, Long pollingTime, Boolean cacheByTopic, - String filterByJsonPath, - String seek + String filterByJsonPath ) { this.commitSync = commitSync; @@ -80,7 +74,6 @@ public ConsumerCommonConfigs(Boolean commitSync, this.pollingTime = pollingTime; this.cacheByTopic = cacheByTopic; this.filterByJsonPath = filterByJsonPath; - this.seek = seek; } public ConsumerCommonConfigs(Boolean commitSync, @@ -91,8 +84,7 @@ public ConsumerCommonConfigs(Boolean commitSync, Integer maxNoOfRetryPollsOrTimeouts, Long pollingTime, Boolean cacheByTopic, - String filterByJsonPath, - String seek + String filterByJsonPath ) { this(commitSync, @@ -104,8 +96,7 @@ public ConsumerCommonConfigs(Boolean commitSync, maxNoOfRetryPollsOrTimeouts, pollingTime, cacheByTopic, - filterByJsonPath, - seek); + filterByJsonPath); } public Boolean getCommitSync() { @@ -136,9 +127,6 @@ public String getRecordType() { return recordType; } - public String getSeek() { - return seek; - } public String getProtoClassType() { return protoClassType; } @@ -165,7 +153,6 @@ public String toString() { ", pollingTime=" + pollingTime + ", cacheByTopic=" + cacheByTopic + ", filterByJsonPath=" + filterByJsonPath + - ", seek=" + seek + '}'; } } diff --git a/core/src/test/java/org/jsmart/zerocode/core/kafka/consume/ConsumerLocalConfigsWrapTest.java b/core/src/test/java/org/jsmart/zerocode/core/kafka/consume/ConsumerLocalConfigsWrapTest.java index 4a9de75df..39041a984 100644 --- a/core/src/test/java/org/jsmart/zerocode/core/kafka/consume/ConsumerLocalConfigsWrapTest.java +++ b/core/src/test/java/org/jsmart/zerocode/core/kafka/consume/ConsumerLocalConfigsWrapTest.java @@ -27,7 +27,8 @@ public void testSerDeser() throws IOException { 50L, false, "$.JSON.Path", - "1,0,test-topic")); + "1,0,test-topic", + null, null)); ObjectMapper objectMapper = new ObjectMapperProvider().get(); String json = objectMapper.writeValueAsString(javaObject); @@ -58,7 +59,8 @@ public void testSerDeser_oneFieldOnly() throws IOException { null, false, null, - "1,0,test-topic")); + "1,0,test-topic", + null, null)); String json = objectMapper.writeValueAsString(javaObject); assertEquals("{\n" + diff --git a/core/src/test/java/org/jsmart/zerocode/core/kafka/helper/KafkaConsumerHelperTest.java b/core/src/test/java/org/jsmart/zerocode/core/kafka/helper/KafkaConsumerHelperTest.java index e1b2eefd0..63699055c 100644 --- a/core/src/test/java/org/jsmart/zerocode/core/kafka/helper/KafkaConsumerHelperTest.java +++ b/core/src/test/java/org/jsmart/zerocode/core/kafka/helper/KafkaConsumerHelperTest.java @@ -44,7 +44,7 @@ public class KafkaConsumerHelperTest { public void test_syncAsyncTrueCommon() throws Exception { consumerCommon = new ConsumerCommonConfigs(true, true, "aTestFile", "JSON", true, 3, 50L, - false,"$JSON.Path", ""); + false,"$JSON.Path"); expectedException.expectMessage("Both commitSync and commitAsync can not be true"); ConsumerLocalConfigs consumerEffectiveConfigs = deriveEffectiveConfigs(null, consumerCommon); @@ -52,8 +52,8 @@ public void test_syncAsyncTrueCommon() throws Exception { @Test public void test_syncAsyncTrueLocal() throws Exception { - consumerCommon = new ConsumerCommonConfigs(true, false, "aTestFile", "JSON", true, 3, 50L,false,"$JSON.Path", ""); - consumerLocal = new ConsumerLocalConfigs("RAW", "sTestLocalFile", true, true, false, 3, 50L,false,"$JSON.Path", "1,0,test-topic"); + consumerCommon = new ConsumerCommonConfigs(true, false, "aTestFile", "JSON", true, 3, 50L,false,"$JSON.Path"); + consumerLocal = new ConsumerLocalConfigs("RAW", "sTestLocalFile", true, true, false, 3, 50L,false,"$JSON.Path", "1,0,test-topic", null, null); ConsumerLocalConfigsWrap localConfigsWrap = new ConsumerLocalConfigsWrap(consumerLocal); expectedException.expectMessage("Both commitSync and commitAsync can not be true"); @@ -63,8 +63,8 @@ public void test_syncAsyncTrueLocal() throws Exception { @Test public void test_effectiveConfigsIsLocal() throws Exception { - consumerCommon = new ConsumerCommonConfigs(true, false, "aTestFile", "JSON", true, 3, 50L,false,"$JSON.Path", ""); - consumerLocal = new ConsumerLocalConfigs("RAW", "sTestLocalFile", true, false, false, 3, 150L,false,"$JSON.Path", "1,0,test-topic"); + consumerCommon = new ConsumerCommonConfigs(true, false, "aTestFile", "JSON", true, 3, 50L,false,"$JSON.Path"); + consumerLocal = new ConsumerLocalConfigs("RAW", "sTestLocalFile", true, false, false, 3, 150L,false,"$JSON.Path", "1,0,test-topic", null, null); ConsumerLocalConfigs consumerEffectiveConfigs = deriveEffectiveConfigs(consumerLocal, consumerCommon); @@ -79,7 +79,7 @@ public void test_effectiveConfigsIsLocal() throws Exception { @Test public void test_effectiveConfigsIsCentral() throws Exception { - consumerCommon = new ConsumerCommonConfigs(true, false, "aTestFile", "JSON", true, 3, 50L,false,"$JSON.Path", ""); + consumerCommon = new ConsumerCommonConfigs(true, false, "aTestFile", "JSON", true, 3, 50L,false,"$JSON.Path"); consumerLocal = null; ConsumerLocalConfigs consumerEffectiveConfigs = deriveEffectiveConfigs(consumerLocal, consumerCommon); @@ -94,8 +94,8 @@ public void test_effectiveConfigsIsCentral() throws Exception { @Test public void test_effectiveCommitAsync_true() throws Exception { - consumerCommon = new ConsumerCommonConfigs(true, null, "aTestFile", "JSON", true, 3, 50L,false,"$JSON.Path", ""); - consumerLocal = new ConsumerLocalConfigs("RAW", "sTestLocalFile", true, false, false, 3, 50L,false,"$JSON.Path", "1,0,test-topic"); + consumerCommon = new ConsumerCommonConfigs(true, null, "aTestFile", "JSON", true, 3, 50L,false,"$JSON.Path"); + consumerLocal = new ConsumerLocalConfigs("RAW", "sTestLocalFile", true, false, false, 3, 50L,false,"$JSON.Path", "1,0,test-topic", null, null); ConsumerLocalConfigs consumerEffectiveConfigs = deriveEffectiveConfigs(consumerLocal, consumerCommon); @@ -106,8 +106,8 @@ public void test_effectiveCommitAsync_true() throws Exception { @Test public void test_effectiveCommitSync_true() throws Exception { - consumerCommon = new ConsumerCommonConfigs(null, true, "aTestFile", "JSON", true, 3, 50L,false,"$JSON.Path", ""); - consumerLocal = new ConsumerLocalConfigs("RAW", "sTestLocalFile", null, true, false, 3, 50L,false,"$JSON.Path", "1,0,test-topic"); + consumerCommon = new ConsumerCommonConfigs(null, true, "aTestFile", "JSON", true, 3, 50L,false,"$JSON.Path"); + consumerLocal = new ConsumerLocalConfigs("RAW", "sTestLocalFile", null, true, false, 3, 50L,false,"$JSON.Path", "1,0,test-topic", null, null); ConsumerLocalConfigs consumerEffectiveConfigs = deriveEffectiveConfigs(consumerLocal, consumerCommon); @@ -118,8 +118,8 @@ public void test_effectiveCommitSync_true() throws Exception { @Test public void test_effectiveCommitSyncFromCommon_true() throws Exception { - consumerCommon = new ConsumerCommonConfigs(true, false, "aTestFile", "JSON", true, 3, 50L,false,"$JSON.Path", ""); - consumerLocal = new ConsumerLocalConfigs("RAW", "sTestLocalFile", null, null, false, 3, 50L,false,"$JSON.Path", "1,0,test-topic"); + consumerCommon = new ConsumerCommonConfigs(true, false, "aTestFile", "JSON", true, 3, 50L,false,"$JSON.Path"); + consumerLocal = new ConsumerLocalConfigs("RAW", "sTestLocalFile", null, null, false, 3, 50L,false,"$JSON.Path", "1,0,test-topic", null, null); ConsumerLocalConfigs consumerEffectiveConfigs = deriveEffectiveConfigs(consumerLocal, consumerCommon); @@ -130,8 +130,8 @@ public void test_effectiveCommitSyncFromCommon_true() throws Exception { @Test public void test_effectiveCommitAsyncFromCommon_true() throws Exception { - consumerCommon = new ConsumerCommonConfigs(null, true, "aTestFile", "JSON", true, 3, 50L,false,"$JSON.Path", ""); - consumerLocal = new ConsumerLocalConfigs("RAW", "sTestLocalFile", true, false, false, 3, 150L,false,"$JSON.Path", "1,0,test-topic"); + consumerCommon = new ConsumerCommonConfigs(null, true, "aTestFile", "JSON", true, 3, 50L,false,"$JSON.Path"); + consumerLocal = new ConsumerLocalConfigs("RAW", "sTestLocalFile", true, false, false, 3, 150L,false,"$JSON.Path", "1,0,test-topic", null, null); ConsumerLocalConfigs consumerEffectiveConfigs = deriveEffectiveConfigs(consumerLocal, consumerCommon); @@ -166,7 +166,7 @@ public void should_read_json_with_headers_in_record() throws IOException { public void test_firstPoll_exits_early_on_assignment() { // given - consumerCommon = new ConsumerCommonConfigs(true, false, "aTestFile", "JSON", true, 3, 1000L,false,"$JSON.Path", ""); + consumerCommon = new ConsumerCommonConfigs(true, false, "aTestFile", "JSON", true, 3, 1000L,false,"$JSON.Path"); consumerLocal = null; ConsumerLocalConfigs consumerEffectiveConfigs = deriveEffectiveConfigs(consumerLocal, consumerCommon); Consumer consumer = Mockito.mock(Consumer.class); @@ -185,8 +185,8 @@ public void test_firstPoll_exits_early_on_assignment() { public void test_firstPoll_exits_on_receiving_records() { // given - consumerCommon = new ConsumerCommonConfigs(true, false, "aTestFile", "JSON", true, 3, 5000L,false,"$JSON.Path", ""); - consumerLocal = new ConsumerLocalConfigs("RAW", "sTestLocalFile", true, false, false, 3, 50L,false,"$JSON.Path", "1,0,test-topic"); + consumerCommon = new ConsumerCommonConfigs(true, false, "aTestFile", "JSON", true, 3, 5000L,false,"$JSON.Path"); + consumerLocal = new ConsumerLocalConfigs("RAW", "sTestLocalFile", true, false, false, 3, 50L,false,"$JSON.Path", "1,0,test-topic", null, null); ConsumerLocalConfigs consumerEffectiveConfigs = deriveEffectiveConfigs(consumerLocal, consumerCommon); Consumer consumer = Mockito.mock(Consumer.class); Mockito.when(consumer.assignment()).thenReturn(new HashSet()); @@ -208,8 +208,8 @@ public void test_firstPoll_exits_on_receiving_records() { public void test_firstPoll_throws_after_timeout() throws Exception { // given - consumerCommon = new ConsumerCommonConfigs(true, false, "aTestFile", "JSON", true, 3, null,false,"$JSON.Path", ""); - consumerLocal = new ConsumerLocalConfigs("RAW", "sTestLocalFile", true, false, false, 3, 50L,false,"$JSON.Path", "1,0,test-topic"); + consumerCommon = new ConsumerCommonConfigs(true, false, "aTestFile", "JSON", true, 3, null,false,"$JSON.Path"); + consumerLocal = new ConsumerLocalConfigs("RAW", "sTestLocalFile", true, false, false, 3, 50L,false,"$JSON.Path", "1,0,test-topic", null, null); ConsumerLocalConfigs consumerEffectiveConfigs = deriveEffectiveConfigs(consumerLocal, consumerCommon); Consumer consumer = Mockito.mock(Consumer.class); diff --git a/pom.xml b/pom.xml index e19726b09..f164e7b71 100644 --- a/pom.xml +++ b/pom.xml @@ -94,6 +94,7 @@ false 3.13.0 1.1.8.4 + 1.18.30 @@ -138,6 +139,13 @@ json 20160810 + + org.projectlombok + lombok + ${lombok.version} + provided + + org.apache.velocity velocity From f01e1088076c2d0980eb773ee08305b96d655bdd Mon Sep 17 00:00:00 2001 From: Aditya Lahiri Date: Sun, 4 Feb 2024 14:54:45 +0530 Subject: [PATCH 30/44] added kafka-testing cases for seekEpoch and seekTimestamp --- .../core/kafka/consume/SeekTimestamp.java | 6 +- .../consume/ConsumerLocalConfigsWrapTest.java | 80 +++++++++++++ .../zerocodejavaexec/utils/ExampleUtils.java | 11 ++ .../consume/KafkaConsumeSeekOffsetTest.java | 6 + ...afka_consume_seek_epoch_and_timestamp.json | 105 ++++++++++++++++++ 5 files changed, 206 insertions(+), 2 deletions(-) create mode 100755 kafka-testing/src/test/resources/kafka/consume/test_kafka_consume_seek_epoch_and_timestamp.json diff --git a/core/src/main/java/org/jsmart/zerocode/core/kafka/consume/SeekTimestamp.java b/core/src/main/java/org/jsmart/zerocode/core/kafka/consume/SeekTimestamp.java index 5ce72b408..371ad21bb 100644 --- a/core/src/main/java/org/jsmart/zerocode/core/kafka/consume/SeekTimestamp.java +++ b/core/src/main/java/org/jsmart/zerocode/core/kafka/consume/SeekTimestamp.java @@ -1,14 +1,16 @@ package org.jsmart.zerocode.core.kafka.consume; -import lombok.AllArgsConstructor; +import lombok.Builder; import lombok.Getter; import lombok.ToString; +import lombok.extern.jackson.Jacksonized; @Getter +@Builder @ToString -@AllArgsConstructor +@Jacksonized public class SeekTimestamp { private final String timestamp; diff --git a/core/src/test/java/org/jsmart/zerocode/core/kafka/consume/ConsumerLocalConfigsWrapTest.java b/core/src/test/java/org/jsmart/zerocode/core/kafka/consume/ConsumerLocalConfigsWrapTest.java index 39041a984..4c592f2aa 100644 --- a/core/src/test/java/org/jsmart/zerocode/core/kafka/consume/ConsumerLocalConfigsWrapTest.java +++ b/core/src/test/java/org/jsmart/zerocode/core/kafka/consume/ConsumerLocalConfigsWrapTest.java @@ -15,6 +15,86 @@ public class ConsumerLocalConfigsWrapTest { ObjectMapper objectMapper = new ObjectMapperProvider().get(); + @Test + public void testSerDeser_seekEpoch() throws IOException { + ConsumerLocalConfigsWrap javaObject = new ConsumerLocalConfigsWrap( + new ConsumerLocalConfigs("RAW", + "RAW:/target/ttt", + true, + null, + true, + 3, + 50L, + false, + "$.JSON.Path", + null, + String.valueOf(System.currentTimeMillis()), + null)); + ObjectMapper objectMapper = new ObjectMapperProvider().get(); + + String json = objectMapper.writeValueAsString(javaObject); + assertEquals("{\n" + + " \"consumerLocalConfigs\":\n" + + " {\n" + + " \"recordType\": \"RAW\",\n" + + " \"fileDumpTo\": \"RAW:/target/ttt\",\n" + + " \"commitAsync\": true,\n" + + " \"showRecordsConsumed\": true,\n" + + " \"maxNoOfRetryPollsOrTimeouts\": 3,\n" + + " \"pollingTime\": 50,\n" + + " \"cacheByTopic\": false,\n" + + " \"filterByJsonPath\": \"$.JSON.Path\",\n" + + " \"seekEpoch\": \"1706940293669\"\n" + + " }\n" + + "}", + json, LENIENT); + + ConsumerLocalConfigsWrap javaPojo = objectMapper.readValue(json, ConsumerLocalConfigsWrap.class); + assertThat(javaPojo, is(javaObject)); + } + + @Test + public void testSerDeser_seekTimestamp() throws IOException { + ConsumerLocalConfigsWrap javaObject = new ConsumerLocalConfigsWrap( + new ConsumerLocalConfigs("RAW", + "RAW:/target/ttt", + true, + null, + true, + 3, + 50L, + false, + "$.JSON.Path", + null, + null, + new SeekTimestamp("2024-01-29T19:35:21.959340", "yyyy-MM-dd'T'HH:mm:ss.ssssss"))); + ObjectMapper objectMapper = new ObjectMapperProvider().get(); + + String json = objectMapper.writeValueAsString(javaObject); + assertEquals("{\n" + + " \"consumerLocalConfigs\":\n" + + " {\n" + + " \"recordType\": \"RAW\",\n" + + " \"fileDumpTo\": \"RAW:/target/ttt\",\n" + + " \"commitAsync\": true,\n" + + " \"showRecordsConsumed\": true,\n" + + " \"maxNoOfRetryPollsOrTimeouts\": 3,\n" + + " \"pollingTime\": 50,\n" + + " \"cacheByTopic\": false,\n" + + " \"filterByJsonPath\": \"$.JSON.Path\",\n" + + " \"seekTimestamp\":\n" + + " {\n" + + " \"timestamp\": \"2024-01-29T19:35:21.959340\",\n" + + " \"format\": \"yyyy-MM-dd'T'HH:mm:ss.ssssss\"\n" + + " }\n" + + " }\n" + + "}", + json, LENIENT); + + ConsumerLocalConfigsWrap javaPojo = objectMapper.readValue(json, ConsumerLocalConfigsWrap.class); + assertThat(javaPojo, is(javaObject)); + } + @Test public void testSerDeser() throws IOException { ConsumerLocalConfigsWrap javaObject = new ConsumerLocalConfigsWrap( diff --git a/kafka-testing/src/main/java/org/jsmart/zerocode/zerocodejavaexec/utils/ExampleUtils.java b/kafka-testing/src/main/java/org/jsmart/zerocode/zerocodejavaexec/utils/ExampleUtils.java index 860646189..90be7b93d 100644 --- a/kafka-testing/src/main/java/org/jsmart/zerocode/zerocodejavaexec/utils/ExampleUtils.java +++ b/kafka-testing/src/main/java/org/jsmart/zerocode/zerocodejavaexec/utils/ExampleUtils.java @@ -1,5 +1,16 @@ package org.jsmart.zerocode.zerocodejavaexec.utils; +import org.jsmart.zerocode.core.kafka.consume.SeekTimestamp; + +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; + public class ExampleUtils { + public String seekTimestampToEpoch(SeekTimestamp seekTimestamp) throws ParseException { + DateFormat dateFormat = new SimpleDateFormat(seekTimestamp.getFormat()); + return String.valueOf(dateFormat.parse(seekTimestamp.getTimestamp()).toInstant().toEpochMilli()); + } + } diff --git a/kafka-testing/src/test/java/org/jsmart/zerocode/integration/tests/kafka/consume/KafkaConsumeSeekOffsetTest.java b/kafka-testing/src/test/java/org/jsmart/zerocode/integration/tests/kafka/consume/KafkaConsumeSeekOffsetTest.java index bb48d0f15..690be202b 100644 --- a/kafka-testing/src/test/java/org/jsmart/zerocode/integration/tests/kafka/consume/KafkaConsumeSeekOffsetTest.java +++ b/kafka-testing/src/test/java/org/jsmart/zerocode/integration/tests/kafka/consume/KafkaConsumeSeekOffsetTest.java @@ -26,4 +26,10 @@ public void testKafkaConsume_seekOffset() throws Exception { public void testKafkaConsume_seekOffsetLatest() throws Exception { } + @Test + @Scenario("kafka/consume/test_kafka_consume_seek_epoch_and_timestamp.json") + public void testKafkaConsume_seekEpochAndTimestamp() { + + } + } diff --git a/kafka-testing/src/test/resources/kafka/consume/test_kafka_consume_seek_epoch_and_timestamp.json b/kafka-testing/src/test/resources/kafka/consume/test_kafka_consume_seek_epoch_and_timestamp.json new file mode 100755 index 000000000..b71aac928 --- /dev/null +++ b/kafka-testing/src/test/resources/kafka/consume/test_kafka_consume_seek_epoch_and_timestamp.json @@ -0,0 +1,105 @@ +{ + "scenarioName": "Consume message after timestamp/epoch", + "steps": [ + { + "name": "load_kafka_before_timestamp", + "url": "kafka-topic:demo-seekTime", + "operation": "PRODUCE", + "request": { + "records": [ + { + "key": "${RANDOM.NUMBER}", + "value": "Before Timestamp 1" + }, + { + "key": "${RANDOM.NUMBER}", + "value": "Before Timestamp 2" + } + ] + }, + "assertions": { + "status": "Ok" + } + }, + { + "name": "load_timestamp_and_epoch", + "url": "org.jsmart.zerocode.zerocodejavaexec.utils.ExampleUtils", + "operation": "seekTimestampToEpoch", + "request": { + "timestamp": "${LOCAL.DATETIME.NOW:yyyy-MM-dd'T'HH:mm:ss.SSS}", + "format": "yyyy-MM-dd'T'HH:mm:ss.SSS" + }, + "assertions": {} + }, + { + "name": "load_kafka_after_timestamp", + "url": "kafka-topic:demo-seekTime", + "operation": "PRODUCE", + "request": { + "records": [ + { + "key": "${RANDOM.NUMBER}", + "value": "After Timestamp 1" + }, + { + "key": "${RANDOM.NUMBER}", + "value": "After Timestamp 2" + } + ] + }, + "assertions": { + "status": "Ok" + } + }, + { + "name": "consume_seekEpoch", + "url": "kafka-topic:demo-seekTime", + "operation": "CONSUME", + "request": { + "consumerLocalConfigs": { + "seekEpoch": "${$.load_timestamp_and_epoch.response}", + "commitSync": true, + "recordType": "RAW", + "showRecordsConsumed": true, + "maxNoOfRetryPollsOrTimeouts": 3 + } + }, + "verify": { + "records": [ + { + "value": "After Timestamp 1" + }, + { + "value": "After Timestamp 2" + } + ] + }}, + { + "name": "consume_seekTimestamp", + "url": "kafka-topic:demo-seekTime", + "operation": "CONSUME", + "request": { + "consumerLocalConfigs": { + "seekTimestamp": { + "timestamp": "${$.load_timestamp_and_epoch.request.timestamp}", + "format": "${$.load_timestamp_and_epoch.request.format}" + }, + "commitSync": true, + "recordType": "RAW", + "showRecordsConsumed": true, + "maxNoOfRetryPollsOrTimeouts": 3 + } + }, + "verify": { + "records": [ + { + "value": "After Timestamp 1" + }, + { + "value": "After Timestamp 2" + } + ] + } + } + ] +} From bbf2dc3e5e1ae7407747a730d476e2efb5375ee9 Mon Sep 17 00:00:00 2001 From: nchandra Date: Wed, 7 Feb 2024 07:04:55 +0000 Subject: [PATCH 31/44] ISSUES-603 Masked Integration Test (Vanila) - Green --- .../masked/MaskedSecretsInMemoryTest.java | 27 +++++++++++++++++++ ...rd_or_secrets_masked_in_log_n_console.json | 26 ++++++++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 core/src/test/java/org/jsmart/zerocode/integrationtests/masked/MaskedSecretsInMemoryTest.java create mode 100644 core/src/test/resources/integration_test_files/masked/password_or_secrets_masked_in_log_n_console.json diff --git a/core/src/test/java/org/jsmart/zerocode/integrationtests/masked/MaskedSecretsInMemoryTest.java b/core/src/test/java/org/jsmart/zerocode/integrationtests/masked/MaskedSecretsInMemoryTest.java new file mode 100644 index 000000000..ebf75a7c8 --- /dev/null +++ b/core/src/test/java/org/jsmart/zerocode/integrationtests/masked/MaskedSecretsInMemoryTest.java @@ -0,0 +1,27 @@ +package org.jsmart.zerocode.integrationtests.masked; + +import org.jsmart.zerocode.core.domain.HostProperties; +import org.jsmart.zerocode.core.domain.Scenario; +import org.jsmart.zerocode.core.tests.customrunner.TestOnlyZeroCodeUnitRunner; +import org.junit.Test; +import org.junit.runner.RunWith; + +@HostProperties(host="http://localhost", port=9998, context = "") +@RunWith(TestOnlyZeroCodeUnitRunner.class) +public class MaskedSecretsInMemoryTest { + + /** + * Mock end points are in test/resources: simulators/test_purpose_end_points.json. + * @RunWith(TestOnlyZeroCodeUnitRunner.class) : starts these mocks first before running the tests + */ + + @Test + @Scenario("integration_test_files/masked/password_or_secrets_masked_in_log_n_console.json") + public void testSecretPrinted_masked() throws Exception { + + } + +} + + + diff --git a/core/src/test/resources/integration_test_files/masked/password_or_secrets_masked_in_log_n_console.json b/core/src/test/resources/integration_test_files/masked/password_or_secrets_masked_in_log_n_console.json new file mode 100644 index 000000000..1b66fdff4 --- /dev/null +++ b/core/src/test/resources/integration_test_files/masked/password_or_secrets_masked_in_log_n_console.json @@ -0,0 +1,26 @@ +{ + "scenarioName": "As simple GET API - Inetgration Test - Local Server", + "steps": [ + { + "name": "find_match", + "url": "/api/v1/search/persons", + "method": "GET", + "request": { + "queryParams": { + "lang": "${MASKED:Amazing}", + "city": "Lon" + } + }, + "verify": { + "status": 200, + "body": { + "exactMatches": true, + "name": "Mr Bean", + "lang": "Amazing", + "city": "Lon" + } + } + } + ] +} + From 4e804b37c4c57bf08005a17473b377e787ef0241 Mon Sep 17 00:00:00 2001 From: nchandra Date: Wed, 7 Feb 2024 20:05:59 +0000 Subject: [PATCH 32/44] ISSUES-603 More real-world scenarios tested --- .../ZerocodeCorrelationshipLogger.java | 4 +- .../ZeroCodeMultiStepsScenarioRunnerImpl.java | 4 +- .../masked/MaskedSecretsInMemoryTest.java | 7 ++- ...token_or_secret_masked_reuse_example_.json | 48 +++++++++++++++++++ ...rd_or_secrets_masked_in_log_n_console.json | 7 ++- .../simulators/test_purpose_end_points.json | 13 +++++ 6 files changed, 79 insertions(+), 4 deletions(-) create mode 100644 core/src/test/resources/integration_test_files/masked/bearer_token_or_secret_masked_reuse_example_.json diff --git a/core/src/main/java/org/jsmart/zerocode/core/logbuilder/ZerocodeCorrelationshipLogger.java b/core/src/main/java/org/jsmart/zerocode/core/logbuilder/ZerocodeCorrelationshipLogger.java index 974ab29fa..53c807b7c 100644 --- a/core/src/main/java/org/jsmart/zerocode/core/logbuilder/ZerocodeCorrelationshipLogger.java +++ b/core/src/main/java/org/jsmart/zerocode/core/logbuilder/ZerocodeCorrelationshipLogger.java @@ -16,6 +16,7 @@ import static org.jsmart.zerocode.core.constants.ZeroCodeReportConstants.RESULT_FAIL; import static org.jsmart.zerocode.core.constants.ZeroCodeReportConstants.RESULT_PASS; import static org.jsmart.zerocode.core.constants.ZeroCodeReportConstants.TEST_STEP_CORRELATION_ID; +import static org.jsmart.zerocode.core.utils.TokenUtils.getMasksReplaced; public class ZerocodeCorrelationshipLogger { private static final String DISPLAY_DEMARCATION_ = "\n--------- " + TEST_STEP_CORRELATION_ID + " %s ---------"; @@ -139,11 +140,12 @@ public void print() { buildResponseDelay(); String customLog = responseLogBuilder.getCustomLog(); + String assertionsWithMaskRemoved = getMasksReplaced(responseLogBuilder.getAssertion()); logger.warn(format("%s %s \n*Response delay:%s milli-secs \n%s \n%s \n-done-\n", requestLogBuilder.toString(), responseLogBuilder.toString(), responseDelay, - "---------> Expected Response: <----------\n" + responseLogBuilder.getAssertion(), + "---------> Expected Response: <----------\n" + assertionsWithMaskRemoved, customLog == null ? "" : "---------> Custom Log: <----------\n" +customLog ) ); diff --git a/core/src/main/java/org/jsmart/zerocode/core/runner/ZeroCodeMultiStepsScenarioRunnerImpl.java b/core/src/main/java/org/jsmart/zerocode/core/runner/ZeroCodeMultiStepsScenarioRunnerImpl.java index 7808a5fd0..3bef7ba2d 100644 --- a/core/src/main/java/org/jsmart/zerocode/core/runner/ZeroCodeMultiStepsScenarioRunnerImpl.java +++ b/core/src/main/java/org/jsmart/zerocode/core/runner/ZeroCodeMultiStepsScenarioRunnerImpl.java @@ -482,7 +482,7 @@ private String executeApi(String logPrefixRelationshipId, .method(operationName) .request(prettyPrintJson(resolvedRequestJsonMaskApplied)); - executionResult = prettyPrintJson(resolvedRequestJson); + executionResult = prettyPrintJson(resolvedRequestJsonMaskApplied); break; default: @@ -541,6 +541,8 @@ private int deriveScenarioLoopTimes(ScenarioSpec scenario) { private List compareStepResults(Step thisStep, String actualResult, String expectedResult, String resolvedScenarioState) { List failureResults = new ArrayList<>(); + expectedResult = zeroCodeAssertionsProcessor.fieldMasksRemoved(expectedResult); + // -------------------- // Validators (pyrest) // -------------------- diff --git a/core/src/test/java/org/jsmart/zerocode/integrationtests/masked/MaskedSecretsInMemoryTest.java b/core/src/test/java/org/jsmart/zerocode/integrationtests/masked/MaskedSecretsInMemoryTest.java index ebf75a7c8..2ed676ad1 100644 --- a/core/src/test/java/org/jsmart/zerocode/integrationtests/masked/MaskedSecretsInMemoryTest.java +++ b/core/src/test/java/org/jsmart/zerocode/integrationtests/masked/MaskedSecretsInMemoryTest.java @@ -18,7 +18,12 @@ public class MaskedSecretsInMemoryTest { @Test @Scenario("integration_test_files/masked/password_or_secrets_masked_in_log_n_console.json") public void testSecretPrinted_masked() throws Exception { - + } + + @Test + @Scenario("integration_test_files/masked/bearer_token_or_secret_masked_reuse_example_.json") + public void testSecretPrintedAssertions_masked() throws Exception { + } } diff --git a/core/src/test/resources/integration_test_files/masked/bearer_token_or_secret_masked_reuse_example_.json b/core/src/test/resources/integration_test_files/masked/bearer_token_or_secret_masked_reuse_example_.json new file mode 100644 index 000000000..0ebdd9d53 --- /dev/null +++ b/core/src/test/resources/integration_test_files/masked/bearer_token_or_secret_masked_reuse_example_.json @@ -0,0 +1,48 @@ +{ + "scenarioName": "Masked Secret path as step param", + "steps": [ + { + "name": "get_balance_via_secret_token", + "url": "/home/accounts/123/balance", + "operation": "GET", + "request": { + "headers": { + "Authorization": "Bearer ${MASKED:token1002003004}", + "request-bank-name": "${MASKED:HSBC}", + "secretCode": "${MASKED:Amazing}" + } + + }, + "assertions": { + "status": 200, + "body" : { + "balance" : 3900, + "name" : "${$.get_balance_via_secret_token.request.headers.request-bank-name}", + "current" : true + } + } + }, + { + "name": "find_match", + "url": "/api/v1/search/persons", + "method": "GET", + "request": { + "queryParams": { + "lang": "${$.get_balance_via_secret_token.request.headers.secretCode}", + "city": "${MASKED:Lon}" + } + }, + "verify": { + "status": 200, + "body": { + "exactMatches": true, + "name": "Mr Bean", + "lang": "${$.get_balance_via_secret_token.request.headers.secretCode}", + "city": "${$.find_match.request.queryParams.city}" + } + } + } + + ] +} + diff --git a/core/src/test/resources/integration_test_files/masked/password_or_secrets_masked_in_log_n_console.json b/core/src/test/resources/integration_test_files/masked/password_or_secrets_masked_in_log_n_console.json index 1b66fdff4..00044a409 100644 --- a/core/src/test/resources/integration_test_files/masked/password_or_secrets_masked_in_log_n_console.json +++ b/core/src/test/resources/integration_test_files/masked/password_or_secrets_masked_in_log_n_console.json @@ -9,6 +9,11 @@ "queryParams": { "lang": "${MASKED:Amazing}", "city": "Lon" + }, + "body": { + "api_secret" : "${MASKED:pass123}", + "emotion": "${MASKED:Amazing}", + "state": "Amazing" } }, "verify": { @@ -16,7 +21,7 @@ "body": { "exactMatches": true, "name": "Mr Bean", - "lang": "Amazing", + "lang": "${$.find_match.request.body.emotion}", "city": "Lon" } } diff --git a/core/src/test/resources/simulators/test_purpose_end_points.json b/core/src/test/resources/simulators/test_purpose_end_points.json index 15dc01d6e..2c738d8ff 100644 --- a/core/src/test/resources/simulators/test_purpose_end_points.json +++ b/core/src/test/resources/simulators/test_purpose_end_points.json @@ -1,6 +1,19 @@ { "name": "Mock endpoints Simulator - API Stubs", "apis": [ + { + "name": "Get My Bank Balance", + "operation": "GET", + "url": "/home/accounts/123/balance", + "response": { + "status": 200, + "body": { + "balance": 3900, + "name": "HSBC", + "current": true + } + } + }, { "name": "Get Bank Account by Id", "operation": "GET", From 0c56321b0e92f0e13c7a047c2ea78e8f7abb18f6 Mon Sep 17 00:00:00 2001 From: authorjapps Date: Wed, 7 Feb 2024 20:09:34 +0000 Subject: [PATCH 33/44] Update BUILDING.md --- BUILDING.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/BUILDING.md b/BUILDING.md index 5d0da2c86..e4f8654cb 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -25,6 +25,11 @@ or mvn -pl core clean test ``` +## Runing Only The Integration tests(core) +Right click and run the "integrationtests" package. It picks the tests ending with "*Test.java" +integration_tests_only_running_ + + ## With tests executed(kafka) Some tests require a running Kafka (and some related components like kafka-rest, and kafka-schema-registry). From 1b1a3291363c11ab341659c69014aef17b721174 Mon Sep 17 00:00:00 2001 From: authorjapps Date: Wed, 7 Feb 2024 20:43:12 +0000 Subject: [PATCH 34/44] Doc update for contribution --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index afcd1df1d..04ea15ce4 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,7 @@ Documentation === For a quick introduction to Zerocode and its features, visit the + [Zerocode TDD Doc Site](https://zerocode-tdd-docs.pages.dev) ++ [Wan to contribute or Improve](https://github.com/authorjapps/zerocode/wiki/Documentation-How-To-Fix-Steps)? Steps and guidelines are [here](https://github.com/authorjapps/zerocode/wiki/Documentation-How-To-Fix-Steps) IDE Support By === From 66afc31fc02a5bcc0b1a22f164715f80cb35e82c Mon Sep 17 00:00:00 2001 From: Aditya Lahiri Date: Thu, 8 Feb 2024 09:25:56 +0530 Subject: [PATCH 35/44] fixed test case --- .../core/kafka/consume/ConsumerLocalConfigsWrapTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/test/java/org/jsmart/zerocode/core/kafka/consume/ConsumerLocalConfigsWrapTest.java b/core/src/test/java/org/jsmart/zerocode/core/kafka/consume/ConsumerLocalConfigsWrapTest.java index 4c592f2aa..63e2bf93f 100644 --- a/core/src/test/java/org/jsmart/zerocode/core/kafka/consume/ConsumerLocalConfigsWrapTest.java +++ b/core/src/test/java/org/jsmart/zerocode/core/kafka/consume/ConsumerLocalConfigsWrapTest.java @@ -28,7 +28,7 @@ public void testSerDeser_seekEpoch() throws IOException { false, "$.JSON.Path", null, - String.valueOf(System.currentTimeMillis()), + "1706940293669", null)); ObjectMapper objectMapper = new ObjectMapperProvider().get(); From 822586b196066332e7a1cee74abe777c144d4e5c Mon Sep 17 00:00:00 2001 From: Aditya Lahiri Date: Tue, 13 Feb 2024 07:46:02 +0530 Subject: [PATCH 36/44] removed lombok --- core/pom.xml | 4 - .../core/kafka/consume/SeekTimestamp.java | 38 ++++-- .../kafka/helper/KafkaConsumerHelper.java | 128 ++++++++++-------- pom.xml | 8 -- 4 files changed, 100 insertions(+), 78 deletions(-) diff --git a/core/pom.xml b/core/pom.xml index 21d12466b..de612cc51 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -116,10 +116,6 @@ com.jayway.jsonpath json-path - - org.projectlombok - lombok - commons-lang commons-lang diff --git a/core/src/main/java/org/jsmart/zerocode/core/kafka/consume/SeekTimestamp.java b/core/src/main/java/org/jsmart/zerocode/core/kafka/consume/SeekTimestamp.java index 371ad21bb..6381ee252 100644 --- a/core/src/main/java/org/jsmart/zerocode/core/kafka/consume/SeekTimestamp.java +++ b/core/src/main/java/org/jsmart/zerocode/core/kafka/consume/SeekTimestamp.java @@ -1,18 +1,38 @@ package org.jsmart.zerocode.core.kafka.consume; -import lombok.Builder; -import lombok.Getter; -import lombok.ToString; -import lombok.extern.jackson.Jacksonized; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; - -@Getter -@Builder -@ToString -@Jacksonized +@JsonInclude(JsonInclude.Include.NON_EMPTY) public class SeekTimestamp { private final String timestamp; private final String format; + + + @JsonCreator + public SeekTimestamp( + @JsonProperty("timestamp") String timestamp, + @JsonProperty("format") String format) { + this.timestamp = timestamp; + this.format = format; + } + + public String getTimestamp() { + return timestamp; + } + + public String getFormat() { + return format; + } + + @Override + public String toString() { + return "SeekTimestamp{" + + "timestamp='" + timestamp + '\'' + + ", format='" + format + '\'' + + '}'; + } } diff --git a/core/src/main/java/org/jsmart/zerocode/core/kafka/helper/KafkaConsumerHelper.java b/core/src/main/java/org/jsmart/zerocode/core/kafka/helper/KafkaConsumerHelper.java index 820dadfb6..0ea2d4424 100644 --- a/core/src/main/java/org/jsmart/zerocode/core/kafka/helper/KafkaConsumerHelper.java +++ b/core/src/main/java/org/jsmart/zerocode/core/kafka/helper/KafkaConsumerHelper.java @@ -1,10 +1,32 @@ package org.jsmart.zerocode.core.kafka.helper; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.common.io.Resources; +import com.google.gson.Gson; +import com.google.protobuf.InvalidProtocolBufferException; +import com.google.protobuf.Message; +import com.google.protobuf.MessageOrBuilder; +import com.google.protobuf.util.JsonFormat; +import com.jayway.jsonpath.JsonPath; import static java.lang.Integer.parseInt; import static java.lang.Long.parseLong; import static java.util.Optional.ofNullable; import static org.apache.commons.lang3.StringUtils.isEmpty; import static org.apache.commons.lang3.StringUtils.isNumeric; +import org.apache.kafka.clients.consumer.Consumer; +import org.apache.kafka.clients.consumer.ConsumerRecord; +import org.apache.kafka.clients.consumer.ConsumerRecords; +import org.apache.kafka.clients.consumer.KafkaConsumer; +import org.apache.kafka.clients.consumer.OffsetAndTimestamp; +import org.apache.kafka.common.PartitionInfo; +import org.apache.kafka.common.TopicPartition; +import org.apache.kafka.common.header.Header; +import org.apache.kafka.common.header.Headers; +import org.jsmart.zerocode.core.di.provider.GsonSerDeProvider; +import org.jsmart.zerocode.core.di.provider.ObjectMapperProvider; +import org.jsmart.zerocode.core.kafka.KafkaConstants; import static org.jsmart.zerocode.core.kafka.KafkaConstants.AVRO; import static org.jsmart.zerocode.core.kafka.KafkaConstants.DEFAULT_POLLING_TIME_MILLI_SEC; import static org.jsmart.zerocode.core.kafka.KafkaConstants.JSON; @@ -12,7 +34,16 @@ import static org.jsmart.zerocode.core.kafka.KafkaConstants.PROTO; import static org.jsmart.zerocode.core.kafka.KafkaConstants.RAW; import static org.jsmart.zerocode.core.kafka.common.KafkaCommonUtils.resolveValuePlaceHolders; +import org.jsmart.zerocode.core.kafka.consume.ConsumerLocalConfigs; +import org.jsmart.zerocode.core.kafka.consume.ConsumerLocalConfigsWrap; +import org.jsmart.zerocode.core.kafka.consume.SeekTimestamp; +import org.jsmart.zerocode.core.kafka.receive.ConsumerCommonConfigs; +import org.jsmart.zerocode.core.kafka.receive.message.ConsumerJsonRecord; +import org.jsmart.zerocode.core.kafka.receive.message.ConsumerJsonRecords; +import org.jsmart.zerocode.core.kafka.receive.message.ConsumerRawRecords; import static org.jsmart.zerocode.core.utils.SmartUtils.prettyPrintJson; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.io.IOException; import java.io.InputStream; @@ -23,45 +54,24 @@ import java.text.SimpleDateFormat; import java.time.Duration; import java.time.temporal.ChronoUnit; -import java.util.*; +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Properties; +import java.util.Set; import java.util.function.Function; import java.util.stream.Collectors; -import com.jayway.jsonpath.JsonPath; -import lombok.SneakyThrows; -import org.apache.kafka.clients.consumer.*; -import org.apache.kafka.common.PartitionInfo; -import org.apache.kafka.common.TopicPartition; -import org.apache.kafka.common.header.Header; -import org.apache.kafka.common.header.Headers; -import org.jsmart.zerocode.core.di.provider.GsonSerDeProvider; -import org.jsmart.zerocode.core.di.provider.ObjectMapperProvider; -import org.jsmart.zerocode.core.kafka.KafkaConstants; -import org.jsmart.zerocode.core.kafka.consume.ConsumerLocalConfigs; -import org.jsmart.zerocode.core.kafka.consume.ConsumerLocalConfigsWrap; -import org.jsmart.zerocode.core.kafka.consume.SeekTimestamp; -import org.jsmart.zerocode.core.kafka.receive.ConsumerCommonConfigs; -import org.jsmart.zerocode.core.kafka.receive.message.ConsumerJsonRecord; -import org.jsmart.zerocode.core.kafka.receive.message.ConsumerJsonRecords; -import org.jsmart.zerocode.core.kafka.receive.message.ConsumerRawRecords; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.google.common.io.Resources; -import com.google.gson.Gson; -import com.google.protobuf.InvalidProtocolBufferException; -import com.google.protobuf.Message; -import com.google.protobuf.MessageOrBuilder; -import com.google.protobuf.util.JsonFormat; - public class KafkaConsumerHelper { + public static final String CONSUMER = "CONSUMER"; private static final Logger LOGGER = LoggerFactory.getLogger(KafkaConsumerHelper.class); private static final Gson gson = new GsonSerDeProvider().get(); private static final ObjectMapper objectMapper = new ObjectMapperProvider().get(); - public static final String CONSUMER = "CONSUMER"; public static Map consumerCacheByTopicMap = new HashMap<>(); public static Consumer createConsumer(String bootStrapServers, String consumerPropertyFile, String topic, Boolean consumerToBeCached) { @@ -80,9 +90,9 @@ public static Consumer createConsumer(String bootStrapServers, String consumerPr final Consumer consumer = new KafkaConsumer(properties); consumer.subscribe(Collections.singletonList(topic)); - if(consumerToBeCached == true){ + if (consumerToBeCached) { consumerCacheByTopicMap.forEach((xTopic, xConsumer) -> { - if(!xTopic.equals(topic)){ + if (!xTopic.equals(topic)) { // close the earlier consumer if in the same group for safety. // (even if not in the same group, closing it anyway will not do any harm) // Otherwise rebalance will fail while rejoining/joining the same group for a new consumer @@ -110,18 +120,18 @@ public static Consumer createConsumer(String bootStrapServers, String consumerPr public static ConsumerRecords initialPollWaitingForConsumerGroupJoin(Consumer consumer, ConsumerLocalConfigs effectiveLocalConfigs) { - for (int run = 0; run < 50; run++) { - if (!consumer.assignment().isEmpty()) { - LOGGER.debug("==> WaitingForConsumerGroupJoin - Partition now assigned. No records yet consumed"); - return new ConsumerRecords(new HashMap()); - } - LOGGER.debug("==> WaitingForConsumerGroupJoin - Partition not assigned. Polling once"); - ConsumerRecords records = consumer.poll(Duration.of(getPollTime(effectiveLocalConfigs), ChronoUnit.MILLIS)); - LOGGER.debug("==> WaitingForConsumerGroupJoin - polled records length={}", records.count()); - if (!records.isEmpty()) { - return records; - } + for (int run = 0; run < 50; run++) { + if (!consumer.assignment().isEmpty()) { + LOGGER.debug("==> WaitingForConsumerGroupJoin - Partition now assigned. No records yet consumed"); + return new ConsumerRecords(new HashMap()); } + LOGGER.debug("==> WaitingForConsumerGroupJoin - Partition not assigned. Polling once"); + ConsumerRecords records = consumer.poll(Duration.of(getPollTime(effectiveLocalConfigs), ChronoUnit.MILLIS)); + LOGGER.debug("==> WaitingForConsumerGroupJoin - polled records length={}", records.count()); + if (!records.isEmpty()) { + return records; + } + } throw new RuntimeException("\n********* Kafka Consumer unable to join in time - try increasing consumer polling time setting *********\n"); } @@ -289,7 +299,7 @@ public static void readJson(List jsonRecords, Object key = thisRecord.key(); Object valueObj = thisRecord.value(); Headers headers = thisRecord.headers(); - String keyStr = thisRecord.key() != null ? thisRecord.key().toString() : ""; + String keyStr = thisRecord.key() != null ? thisRecord.key().toString() : ""; String valueStr = consumerLocalConfig != null && KafkaConstants.PROTO.equalsIgnoreCase(consumerLocalConfig.getRecordType()) ? convertProtobufToJson(thisRecord, consumerLocalConfig) : valueObj.toString(); LOGGER.debug("\nRecord Key - {} , Record value - {}, Record partition - {}, Record offset - {}, Headers - {}", key, valueStr, thisRecord.partition(), thisRecord.offset(), headers); @@ -314,7 +324,7 @@ private static String convertProtobufToJson(ConsumerRecord thisRecord, ConsumerL throw new IllegalArgumentException( "[protoClassType] is required consumer config for recordType PROTO."); } - MessageOrBuilder builderOrMessage = (MessageOrBuilder) createMessageOrBuilder( + MessageOrBuilder builderOrMessage = createMessageOrBuilder( consumerLocalConfig.getProtoClassType(), (byte[]) thisRecord.value()); try { return JsonFormat.printer().includingDefaultValueFields().preservingProtoFieldNames().print(builderOrMessage); @@ -326,10 +336,10 @@ private static String convertProtobufToJson(ConsumerRecord thisRecord, ConsumerL private static MessageOrBuilder createMessageOrBuilder(String messageClass, byte[] value) { try { Class msgClass = (Class) Class.forName(messageClass); - Method method = msgClass.getMethod("parseFrom", new Class[]{byte[].class}); + Method method = msgClass.getMethod("parseFrom", byte[].class); return (MessageOrBuilder) method.invoke(null, value); } catch (IllegalAccessException | ClassNotFoundException | NoSuchMethodException | SecurityException - | IllegalArgumentException | InvocationTargetException e) { + | IllegalArgumentException | InvocationTargetException e) { throw new IllegalArgumentException(e); } @@ -341,7 +351,7 @@ public static String prepareResult(ConsumerLocalConfigs testConfigs, String result; - if (testConfigs != null && testConfigs.getShowRecordsConsumed() == false) { + if (testConfigs != null && !testConfigs.getShowRecordsConsumed()) { int size = jsonRecords.size(); result = prettyPrintJson(gson.toJson(new ConsumerRawRecords(size == 0 ? rawRecords.size() : size))); @@ -351,7 +361,7 @@ public static String prepareResult(ConsumerLocalConfigs testConfigs, } else if (testConfigs != null && (JSON.equals(testConfigs.getRecordType()) || PROTO.equalsIgnoreCase(testConfigs.getRecordType()) || AVRO.equalsIgnoreCase(testConfigs.getRecordType()))) { result = prettyPrintJson(objectMapper.writeValueAsString(new ConsumerJsonRecords(jsonRecords))); - }else { + } else { result = "{\"error\" : \"recordType Undecided, Please chose recordType as JSON or RAW\"}"; } @@ -388,10 +398,10 @@ public static void handleCommitSyncAsync(Consumer consumer, effectiveCommitAsync = localCommitAsync; } - if (effectiveCommitSync != null && effectiveCommitSync == true) { + if (effectiveCommitSync != null && effectiveCommitSync) { consumer.commitSync(); - } else if (effectiveCommitAsync != null && effectiveCommitAsync == true) { + } else if (effectiveCommitAsync != null && effectiveCommitAsync) { consumer.commitAsync(); } else { @@ -414,11 +424,15 @@ public static void handleSeek(ConsumerLocalConfigs effectiveLocal, Consumer cons } } - @SneakyThrows private static void handleSeekByTimestamp(SeekTimestamp seekTimestamp, Consumer consumer, String topicName) { if (Objects.nonNull(seekTimestamp)) { DateFormat dateFormat = new SimpleDateFormat(seekTimestamp.getFormat()); - Date date = dateFormat.parse(seekTimestamp.getTimestamp()); + Date date = null; + try { + date = dateFormat.parse(seekTimestamp.getTimestamp()); + } catch (ParseException e) { + throw new RuntimeException("Could not parse timestamp", e); + } handleSeekByEpoch(date.toInstant().toEpochMilli(), consumer, topicName); } } @@ -470,7 +484,7 @@ private static void handleSeekByOffset(ConsumerLocalConfigs effectiveLocal, Cons } private static void validateCommitFlags(Boolean commitSync, Boolean commitAsync) { - if ((commitSync != null && commitAsync != null) && commitSync == true && commitAsync == true) { + if ((commitSync != null && commitAsync != null) && commitSync && commitAsync) { throw new RuntimeException("\n********* Both commitSync and commitAsync can not be true *********\n"); } } @@ -486,7 +500,7 @@ private static void validateSeekConfig(ConsumerLocalConfigs localConfigs) { } private static Consumer getCachedConsumer(String topic, Boolean consumerToBeCached) { - if(consumerToBeCached){ + if (consumerToBeCached) { return consumerCacheByTopicMap.get(topic); } return null; diff --git a/pom.xml b/pom.xml index f164e7b71..e19726b09 100644 --- a/pom.xml +++ b/pom.xml @@ -94,7 +94,6 @@ false 3.13.0 1.1.8.4 - 1.18.30 @@ -139,13 +138,6 @@ json 20160810 - - org.projectlombok - lombok - ${lombok.version} - provided - - org.apache.velocity velocity From 771386e3b71485fee3fa227488e5b5d9cf661ad6 Mon Sep 17 00:00:00 2001 From: nchandra Date: Tue, 13 Feb 2024 11:34:42 +0000 Subject: [PATCH 37/44] Simple Kafka compose without KSQL --- ...token_or_secret_masked_reuse_example_.json | 2 +- docker/compose/kafka-schema-registry-m3.yml | 49 +++++++++++++++++++ 2 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 docker/compose/kafka-schema-registry-m3.yml diff --git a/core/src/test/resources/integration_test_files/masked/bearer_token_or_secret_masked_reuse_example_.json b/core/src/test/resources/integration_test_files/masked/bearer_token_or_secret_masked_reuse_example_.json index 0ebdd9d53..1871b434f 100644 --- a/core/src/test/resources/integration_test_files/masked/bearer_token_or_secret_masked_reuse_example_.json +++ b/core/src/test/resources/integration_test_files/masked/bearer_token_or_secret_masked_reuse_example_.json @@ -1,5 +1,5 @@ { - "scenarioName": "Masked Secret path as step param", + "scenarioName": "Masked Secret path as step param - Reusable Secret or Bearer token", "steps": [ { "name": "get_balance_via_secret_token", diff --git a/docker/compose/kafka-schema-registry-m3.yml b/docker/compose/kafka-schema-registry-m3.yml new file mode 100644 index 000000000..c7224d4c3 --- /dev/null +++ b/docker/compose/kafka-schema-registry-m3.yml @@ -0,0 +1,49 @@ +--- +version: '3' +services: + zookeeper: + image: confluentinc/cp-zookeeper:5.5.1 + environment: + ZOOKEEPER_CLIENT_PORT: 2181 + ZOOKEEPER_TICK_TIME: 2000 + + kafka: + image: confluentinc/cp-kafka:5.5.1 + depends_on: + - zookeeper + ports: + - 9092:9092 + environment: + KAFKA_BROKER_ID: 1 + KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181 + KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:29092,PLAINTEXT_HOST://localhost:9092 + KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT + KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT + KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1 + + schema-registry: + image: confluentinc/cp-schema-registry:5.5.1 + depends_on: + - kafka + - zookeeper + environment: + SCHEMA_REGISTRY_HOST_NAME: schema-registry + SCHEMA_REGISTRY_KAFKASTORE_CONNECTION_URL: zookeeper:2181 + SCHEMA_REGISTRY_LISTENERS: http://0.0.0.0:8081 + ports: + - "8081:8081" + + rest-proxy: + image: confluentinc/cp-kafka-rest:5.5.1 + depends_on: + - zookeeper + - kafka + - schema-registry + environment: + KAFKA_REST_HOST_NAME: rest-proxy + KAFKA_REST_ZOOKEEPER_CONNECT: zookeeper:2181 + KAFKA_REST_BOOTSTRAP_SERVERS: kafka:29092 + KAFKA_REST_LISTENERS: http://0.0.0.0:8082 + KAFKA_REST_SCHEMA_REGISTRY_URL: http://schema-registry:8081 + ports: + - "8082:8082" From 28271a124fd85e4edcf801f7c04793a628bf278b Mon Sep 17 00:00:00 2001 From: Aditya Lahiri Date: Sat, 17 Feb 2024 16:14:24 +0530 Subject: [PATCH 38/44] Java method features enhanced 1. Support for multiple parameters in java method exec 2. Support for static method Exec 3. Minor refactoring changes --- .../javaapi/JavaMethodExecutorImpl.java | 51 +++++++++++++---- .../zerocodejavaexec/SampleMethods.java | 41 ++++++++++++++ .../MultipleArgumentMethodExecTest.java | 16 ++++++ .../StaticMethodExecTest.java | 16 ++++++ .../java_method_multiple_arguments_test.json | 56 +++++++++++++++++++ .../java_static_method_test.json | 24 ++++++++ 6 files changed, 194 insertions(+), 10 deletions(-) create mode 100644 http-testing/src/main/java/org/jsmart/zerocode/zerocodejavaexec/SampleMethods.java create mode 100644 http-testing/src/test/java/org/jsmart/zerocode/testhelp/tests/helloworldjavaexec/MultipleArgumentMethodExecTest.java create mode 100644 http-testing/src/test/java/org/jsmart/zerocode/testhelp/tests/helloworldjavaexec/StaticMethodExecTest.java create mode 100644 http-testing/src/test/resources/helloworldjavaexec/java_method_multiple_arguments_test.json create mode 100644 http-testing/src/test/resources/helloworldjavaexec/java_static_method_test.json diff --git a/core/src/main/java/org/jsmart/zerocode/core/engine/executor/javaapi/JavaMethodExecutorImpl.java b/core/src/main/java/org/jsmart/zerocode/core/engine/executor/javaapi/JavaMethodExecutorImpl.java index f5efb4623..5eddfae9a 100644 --- a/core/src/main/java/org/jsmart/zerocode/core/engine/executor/javaapi/JavaMethodExecutorImpl.java +++ b/core/src/main/java/org/jsmart/zerocode/core/engine/executor/javaapi/JavaMethodExecutorImpl.java @@ -1,18 +1,22 @@ package org.jsmart.zerocode.core.engine.executor.javaapi; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.inject.Inject; import com.google.inject.Injector; -import java.lang.reflect.Method; -import java.util.List; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import static java.lang.Class.forName; import static java.lang.String.format; import static java.util.Arrays.asList; import static org.jsmart.zerocode.core.utils.SmartUtils.prettyPrintJson; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.List; public class JavaMethodExecutorImpl implements JavaMethodExecutor { private static final Logger LOGGER = LoggerFactory.getLogger(JavaMethodExecutorImpl.class); @@ -38,14 +42,17 @@ public String execute(String qualifiedClassName, String methodName, String reque Object result; - if (parameterTypes == null || parameterTypes.size() == 0) { + if (parameterTypes == null || parameterTypes.isEmpty()) { result = executeWithParams(qualifiedClassName, methodName); - } else { + } else if (parameterTypes.size() == 1) { Object request = objectMapper.readValue(requestJson, parameterTypes.get(0)); result = executeWithParams(qualifiedClassName, methodName, request); + } else { + Object[] requestArgs = getRequestArgs(parameterTypes, requestJson); + result = executeWithParams(qualifiedClassName, methodName, requestArgs); } final String resultJson = objectMapper.writeValueAsString(result); @@ -58,6 +65,24 @@ public String execute(String qualifiedClassName, String methodName, String reque } } + private Object[] getRequestArgs(List> parameterTypes, String requestJson) { + List args = new ArrayList<>(); + JsonNode root = null; + try { + root = objectMapper.readTree(requestJson); + } catch (JsonProcessingException e) { + throw new RuntimeException("Could not parse Java method request Json ", e); + } + for (int i = 0; i < parameterTypes.size(); i++) { + try { + args.add(objectMapper.treeToValue(root.get(String.valueOf(i)), parameterTypes.get(i))); + } catch (JsonProcessingException e) { + throw new RuntimeException("Could not convert value " + i + " to type " + parameterTypes.get(i), e); + } + } + return args.toArray(); + } + /* * * @param qualifiedClassName : including package name: e.g. "org.jsmart.zerocode.core.AddService" @@ -67,16 +92,22 @@ public String execute(String qualifiedClassName, String methodName, String reque */ Object executeWithParams(String qualifiedClassName, String methodName, Object... params) { - /** + /* * Refer SOF example: * Q. How do I invoke a Java method when given the method name as a string? * Link: https://stackoverflow.com/questions/160970/how-do-i-invoke-a-java-method-when-given-the-method-name-as-a-string */ try { Method method = findMatchingMethod(qualifiedClassName, methodName); - Object objectToInvokeOn = injector.getInstance(forName(qualifiedClassName)); - return method.invoke(objectToInvokeOn, params); + if (Modifier.isStatic(method.getModifiers())) { + return method.invoke(null, params); + } else { + Object objectToInvokeOn = injector.getInstance(forName(qualifiedClassName)); + return method.invoke(objectToInvokeOn, params); + } + + } catch (Exception e) { String errMsg = format("Java exec(): Invocation failed for method %s in class %s", methodName, qualifiedClassName); LOGGER.error(errMsg + ". Exception - " + e); diff --git a/http-testing/src/main/java/org/jsmart/zerocode/zerocodejavaexec/SampleMethods.java b/http-testing/src/main/java/org/jsmart/zerocode/zerocodejavaexec/SampleMethods.java new file mode 100644 index 000000000..cafad2765 --- /dev/null +++ b/http-testing/src/main/java/org/jsmart/zerocode/zerocodejavaexec/SampleMethods.java @@ -0,0 +1,41 @@ +package org.jsmart.zerocode.zerocodejavaexec; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.google.common.collect.ImmutableMap; + +import java.util.Map; + +public class SampleMethods { + + public static class SamplePOJO { + public String arg1; + public String arg2; + + @JsonCreator + public SamplePOJO(@JsonProperty("arg1") String arg1, @JsonProperty("arg2") String arg2) { + this.arg1 = arg1; + this.arg2 = arg2; + } + } + + public static Map sampleStaticMethod(String arg1, String arg2) { + return ImmutableMap.of("0", arg1, + "1", arg2); + } + + public Map sampleMultiArgMethod1(String arg1, String arg2) { + return ImmutableMap.of("0", arg1, + "1", arg2); + } + + public Map sampleMultiArgMethod2(String arg1, Map arg2) { + return ImmutableMap.of("0", arg1, + "1", arg2); + } + + public Map sampleMultiArgMethod3(String arg1, SamplePOJO arg2) { + return ImmutableMap.of("0", arg1, + "1", arg2); + } +} diff --git a/http-testing/src/test/java/org/jsmart/zerocode/testhelp/tests/helloworldjavaexec/MultipleArgumentMethodExecTest.java b/http-testing/src/test/java/org/jsmart/zerocode/testhelp/tests/helloworldjavaexec/MultipleArgumentMethodExecTest.java new file mode 100644 index 000000000..459dcff03 --- /dev/null +++ b/http-testing/src/test/java/org/jsmart/zerocode/testhelp/tests/helloworldjavaexec/MultipleArgumentMethodExecTest.java @@ -0,0 +1,16 @@ +package org.jsmart.zerocode.testhelp.tests.helloworldjavaexec; + +import org.jsmart.zerocode.core.domain.Scenario; +import org.jsmart.zerocode.core.runner.ZeroCodeUnitRunner; +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(ZeroCodeUnitRunner.class) +public class MultipleArgumentMethodExecTest { + + @Test + @Scenario("helloworldjavaexec/java_method_multiple_arguments_test.json") + public void test_multi_arg_method_exec() throws Exception { + + } +} diff --git a/http-testing/src/test/java/org/jsmart/zerocode/testhelp/tests/helloworldjavaexec/StaticMethodExecTest.java b/http-testing/src/test/java/org/jsmart/zerocode/testhelp/tests/helloworldjavaexec/StaticMethodExecTest.java new file mode 100644 index 000000000..9b8bffd2e --- /dev/null +++ b/http-testing/src/test/java/org/jsmart/zerocode/testhelp/tests/helloworldjavaexec/StaticMethodExecTest.java @@ -0,0 +1,16 @@ +package org.jsmart.zerocode.testhelp.tests.helloworldjavaexec; + +import org.jsmart.zerocode.core.domain.Scenario; +import org.jsmart.zerocode.core.runner.ZeroCodeUnitRunner; +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(ZeroCodeUnitRunner.class) +public class StaticMethodExecTest { + + @Test + @Scenario("helloworldjavaexec/java_static_method_test.json") + public void test_multi_arg_method_exec() throws Exception { + + } +} diff --git a/http-testing/src/test/resources/helloworldjavaexec/java_method_multiple_arguments_test.json b/http-testing/src/test/resources/helloworldjavaexec/java_method_multiple_arguments_test.json new file mode 100644 index 000000000..93fb19f19 --- /dev/null +++ b/http-testing/src/test/resources/helloworldjavaexec/java_method_multiple_arguments_test.json @@ -0,0 +1,56 @@ +{ + "scenarioName": "Call methods with multiple arguments", + "steps": [ + { + "name": "sample method 1", + "url": "org.jsmart.zerocode.zerocodejavaexec.SampleMethods", + "method": "sampleMultiArgMethod1", + "request": { + "0" : "arg1", + "1" : "arg2" + }, + "assertions": { + "0" : "arg1", + "1" : "arg2" + } + }, + { + "name": "sample method 2", + "url": "org.jsmart.zerocode.zerocodejavaexec.SampleMethods", + "method": "sampleMultiArgMethod2", + "request": { + "0" : "arg1", + "1" : { + "key1" : "value1", + "key2" : "value2" + } + }, + "assertions": { + "0" : "arg1", + "1" : { + "key1" : "value1", + "key2" : "value2" + } + } + }, + { + "name": "sample method 3", + "url": "org.jsmart.zerocode.zerocodejavaexec.SampleMethods", + "method": "sampleMultiArgMethod3", + "request": { + "0" : "arg1", + "1" : { + "arg1" : "value1", + "arg2" : "value2" + } + }, + "assertions": { + "0" : "arg1", + "1" : { + "arg1" : "value1", + "arg2" : "value2" + } + } + } + ] +} \ No newline at end of file diff --git a/http-testing/src/test/resources/helloworldjavaexec/java_static_method_test.json b/http-testing/src/test/resources/helloworldjavaexec/java_static_method_test.json new file mode 100644 index 000000000..d326ae98d --- /dev/null +++ b/http-testing/src/test/resources/helloworldjavaexec/java_static_method_test.json @@ -0,0 +1,24 @@ +{ + "scenarioName": "Call static method", + "steps": [ + { + "name": "sample static method 1", + "url": "org.jsmart.zerocode.zerocodejavaexec.SampleMethods", + "method": "sampleStaticMethod", + "request": { + "0" : "arg1", + "1" : "arg2" + }, + "assertions": { + "0" : "arg1", + "1" : "arg2" + } + }, + { + "name": "calling existing method", + "url": "java.lang.System", + "method": "currentTimeMillis", + "assertions": "$NOT.NULL" + } + ] +} \ No newline at end of file From 5514dd2b3b683e1c5cb2e8f41d9a732bb70f3e6f Mon Sep 17 00:00:00 2001 From: Nirmal Chandra Date: Sun, 18 Feb 2024 20:49:29 +0000 Subject: [PATCH 39/44] gpg plugin version updated --- core/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/pom.xml b/core/pom.xml index de612cc51..16abf7860 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -257,7 +257,7 @@ org.apache.maven.plugins maven-gpg-plugin - 1.5 + 3.1.0 sign-artifacts From 89b479878a5eda279c46b1447e59e388fd521b8a Mon Sep 17 00:00:00 2001 From: Nirmal Chandra Date: Sun, 18 Feb 2024 20:51:51 +0000 Subject: [PATCH 40/44] [maven-release-plugin] prepare release zerocode-tdd-parent-1.3.36 --- core/pom.xml | 2 +- http-testing/pom.xml | 2 +- junit5-testing/pom.xml | 2 +- kafka-testing/pom.xml | 2 +- pom.xml | 2 +- zerocode-maven-archetype/pom.xml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/core/pom.xml b/core/pom.xml index 16abf7860..21fd5e9b4 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -4,7 +4,7 @@ zerocode-tdd-parent org.jsmart - 1.3.36-SNAPSHOT + 1.3.36 zerocode-tdd diff --git a/http-testing/pom.xml b/http-testing/pom.xml index 7e2b18472..201142da2 100644 --- a/http-testing/pom.xml +++ b/http-testing/pom.xml @@ -4,7 +4,7 @@ zerocode-tdd-parent org.jsmart - 1.3.36-SNAPSHOT + 1.3.36 org.jsmart diff --git a/junit5-testing/pom.xml b/junit5-testing/pom.xml index 03cbdcdeb..da8a8e19c 100644 --- a/junit5-testing/pom.xml +++ b/junit5-testing/pom.xml @@ -4,7 +4,7 @@ zerocode-tdd-parent org.jsmart - 1.3.36-SNAPSHOT + 1.3.36 zerocode-tdd-jupiter diff --git a/kafka-testing/pom.xml b/kafka-testing/pom.xml index 0a15cbefb..adb2329f1 100644 --- a/kafka-testing/pom.xml +++ b/kafka-testing/pom.xml @@ -4,7 +4,7 @@ zerocode-tdd-parent org.jsmart - 1.3.36-SNAPSHOT + 1.3.36 kafka-testing diff --git a/pom.xml b/pom.xml index e19726b09..1f198a860 100644 --- a/pom.xml +++ b/pom.xml @@ -9,7 +9,7 @@ zerocode-tdd-parent org.jsmart - 1.3.36-SNAPSHOT + 1.3.36 pom ZeroCode TDD Parent diff --git a/zerocode-maven-archetype/pom.xml b/zerocode-maven-archetype/pom.xml index 69716bc33..4aeef6a2c 100644 --- a/zerocode-maven-archetype/pom.xml +++ b/zerocode-maven-archetype/pom.xml @@ -4,7 +4,7 @@ org.jsmart zerocode-tdd-parent - 1.3.36-SNAPSHOT + 1.3.36 zerocode-maven-archetype From b332593bb4cffc65c65f92659ab7829a84e1c5a4 Mon Sep 17 00:00:00 2001 From: Nirmal Chandra Date: Sun, 18 Feb 2024 20:51:55 +0000 Subject: [PATCH 41/44] [maven-release-plugin] prepare for next development iteration --- core/pom.xml | 2 +- http-testing/pom.xml | 2 +- junit5-testing/pom.xml | 2 +- kafka-testing/pom.xml | 2 +- pom.xml | 2 +- zerocode-maven-archetype/pom.xml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/core/pom.xml b/core/pom.xml index 21fd5e9b4..084bd9d37 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -4,7 +4,7 @@ zerocode-tdd-parent org.jsmart - 1.3.36 + 1.3.37-SNAPSHOT zerocode-tdd diff --git a/http-testing/pom.xml b/http-testing/pom.xml index 201142da2..2f2a834d2 100644 --- a/http-testing/pom.xml +++ b/http-testing/pom.xml @@ -4,7 +4,7 @@ zerocode-tdd-parent org.jsmart - 1.3.36 + 1.3.37-SNAPSHOT org.jsmart diff --git a/junit5-testing/pom.xml b/junit5-testing/pom.xml index da8a8e19c..cca01ebde 100644 --- a/junit5-testing/pom.xml +++ b/junit5-testing/pom.xml @@ -4,7 +4,7 @@ zerocode-tdd-parent org.jsmart - 1.3.36 + 1.3.37-SNAPSHOT zerocode-tdd-jupiter diff --git a/kafka-testing/pom.xml b/kafka-testing/pom.xml index adb2329f1..518c91593 100644 --- a/kafka-testing/pom.xml +++ b/kafka-testing/pom.xml @@ -4,7 +4,7 @@ zerocode-tdd-parent org.jsmart - 1.3.36 + 1.3.37-SNAPSHOT kafka-testing diff --git a/pom.xml b/pom.xml index 1f198a860..0f92b0807 100644 --- a/pom.xml +++ b/pom.xml @@ -9,7 +9,7 @@ zerocode-tdd-parent org.jsmart - 1.3.36 + 1.3.37-SNAPSHOT pom ZeroCode TDD Parent diff --git a/zerocode-maven-archetype/pom.xml b/zerocode-maven-archetype/pom.xml index 4aeef6a2c..0ed16767e 100644 --- a/zerocode-maven-archetype/pom.xml +++ b/zerocode-maven-archetype/pom.xml @@ -4,7 +4,7 @@ org.jsmart zerocode-tdd-parent - 1.3.36 + 1.3.37-SNAPSHOT zerocode-maven-archetype From db3111c89f670c2e46a1cca4cbb4400f5678f4d4 Mon Sep 17 00:00:00 2001 From: Nirmal Chandra Date: Sun, 18 Feb 2024 22:02:32 +0000 Subject: [PATCH 42/44] javadoc issues fixed --- .../ZeroCodeAssertionsProcessorImpl.java | 6 +- .../ZeroCodeParameterizedProcessorImpl.java | 17 +++-- .../core/httpclient/BasicHttpClient.java | 71 ++++++++----------- .../core/runner/ZeroCodePackageRunner.java | 3 - .../core/runner/ZeroCodeUnitRunner.java | 4 +- .../zerocode/core/utils/SmartUtils.java | 8 +-- 6 files changed, 45 insertions(+), 64 deletions(-) diff --git a/core/src/main/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeAssertionsProcessorImpl.java b/core/src/main/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeAssertionsProcessorImpl.java index e083918fc..8df167c5a 100644 --- a/core/src/main/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeAssertionsProcessorImpl.java +++ b/core/src/main/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeAssertionsProcessorImpl.java @@ -79,9 +79,6 @@ import static org.jsmart.zerocode.core.utils.TokenUtils.populateParamMap; import static org.slf4j.LoggerFactory.getLogger; -; -; - public class ZeroCodeAssertionsProcessorImpl implements ZeroCodeAssertionsProcessor { private static final org.slf4j.Logger LOGGER = getLogger(ZeroCodeAssertionsProcessorImpl.class); @@ -385,8 +382,7 @@ public List assertAllAndReturnFailed(List a * First the logic checks if dig-deep needed to avoid unwanted recursions. If not needed, the step definition is * returned intact. Otherwise calls the dig deep method to perform the operation. * - * @param thisStep - * @return The effective step definition + * returns: The effective step definition */ @Override public Step resolveJsonContent(Step thisStep, ScenarioExecutionState scenarioExecutionState) { diff --git a/core/src/main/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeParameterizedProcessorImpl.java b/core/src/main/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeParameterizedProcessorImpl.java index 7c899c664..8965f1116 100644 --- a/core/src/main/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeParameterizedProcessorImpl.java +++ b/core/src/main/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeParameterizedProcessorImpl.java @@ -20,30 +20,29 @@ import static org.slf4j.LoggerFactory.getLogger; /** - *

Parameterized Tests Steps

- *

+ * Parameterized Tests Steps + * * Processes the Step for each line in the parameterized/parameterizedCsv section. - *

- *

+ * * Parameters can be * "parameterized": [ * 200, * "Hello", * true * ] - *

+ * * -or- - *

+ * * "parameterizedCsv": [ * "1, 2, 200", * "11, 22, 400", * "21, 31, 500" * ] - *

+ * * In each the above cases, the step will execute 3 times. - *

+ * * For "parameterized" case, ${0} will resolve to 200, "Hello", true respectively for each run. - *

+ * * For "parameterizedCsv" case, ${0}, ${1}, ${2} will resolve to "1", "2", "200" for the first run. * Then it will resolve to "11", "22", "400" for the 2nd run ans so on. */ diff --git a/core/src/main/java/org/jsmart/zerocode/core/httpclient/BasicHttpClient.java b/core/src/main/java/org/jsmart/zerocode/core/httpclient/BasicHttpClient.java index 8ad27d794..07b603e37 100644 --- a/core/src/main/java/org/jsmart/zerocode/core/httpclient/BasicHttpClient.java +++ b/core/src/main/java/org/jsmart/zerocode/core/httpclient/BasicHttpClient.java @@ -69,7 +69,7 @@ public BasicHttpClient(CloseableHttpClient httpclient) { * - org.jsmart.zerocode.core.httpclient.ssl.CorporateProxyNoSslContextHttpClient#createHttpClient() * } * - * @return CloseableHttpClient + * return CloseableHttpClient * @throws Exception */ public CloseableHttpClient createHttpClient() throws Exception { @@ -100,14 +100,13 @@ public CloseableHttpClient createHttpClient() throws Exception { * Override this method in case you want to execute the http call differently via your http client. * Otherwise the framework falls back to this implementation by default. * - * @param httpUrl : path to end point - * @param methodName : e.g. GET, PUT etc - * @param headers : headers, cookies etc - * @param queryParams : key-value query params after the ? in the url - * @param body : json body + * httpUrl : path to end point + * methodName : e.g. GET, PUT etc + * headers : headers, cookies etc + * queryParams : key-value query params after the ? in the url + * body : json body * - * @return : Http response consists of status code, entity, headers, cookies etc - * @throws Exception + * returns : Http response consists of status code, entity, headers, cookies etc */ public Response execute(String httpUrl, String methodName, @@ -151,9 +150,9 @@ public Response execute(String httpUrl, * Once the client executes the http call, then it receives the http response. This method takes care of handling * that. In case you need to handle it differently you can override this method. * - * @param httpResponse : Received Apache http response from the server + * httpResponse : Received Apache http response from the server * - * @return : Effective response with handled http session. + * : Effective response with handled http session. * @throws IOException */ public Response handleResponse(CloseableHttpResponse httpResponse) throws IOException { @@ -178,12 +177,11 @@ public Response handleResponse(CloseableHttpResponse httpResponse) throws IOExce * use the Charset sent by the server e.g. UAT-8 or UTF-16 or UTF-32 etc. * * Note- - * See implementation of java.nio.charset.Charset#defaultCharset. Here the default is UTF-8 if the + * See the implementation of java.nio.charset.Charset#defaultCharset. Here the default is UTF-8 if the * defaultCharset is not set by the JVM, otherwise it picks the JVM provided defaultCharset * - * @param httpResponse - * @return : A http response compatible with Charset received from the http server e.g. UTF-8, UTF-16 etc - * @throws IOException + * httpResponse: + * A http response compatible with Charset received from the http server e.g. UTF-8, UTF-16 etc * */ public Response createCharsetResponse(CloseableHttpResponse httpResponse) throws IOException { @@ -214,9 +212,9 @@ public Response createCharsetResponse(CloseableHttpResponse httpResponse) throws * In case you need to handle it differently you can override this method to change this behaviour to roll your own * feature. * - * @param httpUrl - Url of the target service - * @param queryParams - Query parameters to pass - * @return : Effective url + * httpUrl - Url of the target service + * queryParams - Query parameters to pass + * return : Effective url * */ public String handleUrlAndQueryParams(String httpUrl, Map queryParams) throws URISyntaxException { @@ -231,9 +229,9 @@ public String handleUrlAndQueryParams(String httpUrl, Map queryP * If you want to override any headers, you can do that by overriding the * amendRequestHeaders(headers) method. * - * @param headers - * @param requestBuilder - * @return : An effective Apache http request builder object with processed headers. + * headers + * requestBuilder + * return : An effective Apache http request builder object with processed headers. */ public RequestBuilder handleHeaders(Map headers, RequestBuilder requestBuilder) { Map amendedHeaders = amendRequestHeaders(headers); @@ -246,8 +244,8 @@ public RequestBuilder handleHeaders(Map headers, RequestBuilder * - Add more headers to the http request or * - Amend or modify the headers which were supplied from the JSON test-case request step. * - * @param headers : The headers passed from the JSON test step request - * @return : An effective headers map. + * headers : The headers passed from the JSON test step request + * return : An effective headers map. */ public Map amendRequestHeaders(Map headers) { return headers; @@ -257,8 +255,8 @@ public Map amendRequestHeaders(Map headers) { * Override this method when you want to manipulate the request body passed from your test cases. * Otherwise the framework falls back to this default implementation. * You can override this method via @UseHttpClient(YourCustomHttpClient.class) - * @param body - * @return + * body + * return */ public String handleRequestBody(Object body) { return getContentAsItIsJson(body); @@ -273,10 +271,10 @@ public String handleRequestBody(Object body) { * * You can override this method via @UseHttpClient(YourCustomHttpClient.class) * - * @param httpUrl - * @param methodName - * @param reqBodyAsString - * @return + * httpUrl + * methodName + * reqBodyAsString + * return */ public RequestBuilder createDefaultRequestBuilder(String httpUrl, String methodName, String reqBodyAsString) { RequestBuilder requestBuilder = RequestBuilder @@ -298,11 +296,6 @@ public RequestBuilder createDefaultRequestBuilder(String httpUrl, String methodN * is passed in the request. In case you want to build or prepare the requests differently, * you can override this method via @UseHttpClient(YourCustomHttpClient.class). * - * @param httpUrl - * @param methodName - * @param reqBodyAsString - * @return - * @throws IOException */ public RequestBuilder createFormUrlEncodedRequestBuilder(String httpUrl, String methodName, String reqBodyAsString) throws IOException { RequestBuilder requestBuilder = RequestBuilder @@ -333,11 +326,9 @@ public RequestBuilder createFormUrlEncodedRequestBuilder(String httpUrl, String * * You can override this method via @UseHttpClient(YourCustomHttpClient.class) * - * @param httpUrl - * @param methodName - * @param reqBodyAsString - * @return - * @throws IOException + * httpUrl: The end pint + * methodName: meaningful name of a method + * reqBodyAsString: */ public RequestBuilder createFileUploadRequestBuilder(String httpUrl, String methodName, String reqBodyAsString) throws IOException { Map fileFieldNameValueMap = getFileFieldNameValue(reqBodyAsString); @@ -367,8 +358,8 @@ public RequestBuilder createFileUploadRequestBuilder(String httpUrl, String meth * In case the session is not needed or to be handled differently, then this * method can be overridden to do nothing or to roll your own feature. * - * @param serverResponse - * @param headerKey + * serverResponse + * headerKey */ public void handleHttpSession(Response serverResponse, String headerKey) { /** --------------- diff --git a/core/src/main/java/org/jsmart/zerocode/core/runner/ZeroCodePackageRunner.java b/core/src/main/java/org/jsmart/zerocode/core/runner/ZeroCodePackageRunner.java index 236adc735..f4f493963 100644 --- a/core/src/main/java/org/jsmart/zerocode/core/runner/ZeroCodePackageRunner.java +++ b/core/src/main/java/org/jsmart/zerocode/core/runner/ZeroCodePackageRunner.java @@ -113,7 +113,6 @@ protected List getChildren() { * Returns a {@link Description} for {@code child}, which can be assumed to * be an element of the list returned by {@link ParentRunner#getChildren()} * - * @param child */ @Override protected Description describeChild(ScenarioSpec child) { @@ -163,8 +162,6 @@ protected RunListener createTestUtilityListener() { * Subclasses are responsible for making sure that relevant test events are * reported through {@code notifier} * - * @param child - * @param notifier */ @Override protected void runChild(ScenarioSpec child, RunNotifier notifier) { diff --git a/core/src/main/java/org/jsmart/zerocode/core/runner/ZeroCodeUnitRunner.java b/core/src/main/java/org/jsmart/zerocode/core/runner/ZeroCodeUnitRunner.java index 2da5aeaeb..6c659e247 100644 --- a/core/src/main/java/org/jsmart/zerocode/core/runner/ZeroCodeUnitRunner.java +++ b/core/src/main/java/org/jsmart/zerocode/core/runner/ZeroCodeUnitRunner.java @@ -70,8 +70,8 @@ public class ZeroCodeUnitRunner extends BlockJUnit4ClassRunner { /** * Creates a BlockJUnit4ClassRunner to run {@code klass} * - * @param klass - * @throws InitializationError if the test class is malformed. + * klass: + * InitializationError if the test class is malformed. */ public ZeroCodeUnitRunner(Class klass) throws InitializationError { super(klass); diff --git a/core/src/main/java/org/jsmart/zerocode/core/utils/SmartUtils.java b/core/src/main/java/org/jsmart/zerocode/core/utils/SmartUtils.java index 819746ff0..9d1b1b27b 100644 --- a/core/src/main/java/org/jsmart/zerocode/core/utils/SmartUtils.java +++ b/core/src/main/java/org/jsmart/zerocode/core/utils/SmartUtils.java @@ -245,11 +245,9 @@ public static String getEnvPropertyValue(String envPropertyKey) { } /** - * - * @param thisStep --> Currently executing step - * @param tokenString --> JSON_PAYLAOD_FILE or JSON_CONTENT - * @return if there is a match for the token, then the json traversal will happen - * @throws JsonProcessingException + * thisStep : Currently executing step + * tokenString : JSON_PAYLAOD_FILE or JSON_CONTENT + * if there is a match for the token, then the json traversal will happen */ public static boolean checkDigNeeded(ObjectMapper mapper, Step thisStep, String tokenString) throws JsonProcessingException { String stepJson = mapper.writeValueAsString(thisStep); From 6cc6f944c79a4211eb9f6756cb057500c715fa24 Mon Sep 17 00:00:00 2001 From: Nirmal Chandra Date: Sun, 18 Feb 2024 22:06:56 +0000 Subject: [PATCH 43/44] [maven-release-plugin] prepare release zerocode-tdd-parent-1.3.37 --- core/pom.xml | 2 +- http-testing/pom.xml | 2 +- junit5-testing/pom.xml | 2 +- kafka-testing/pom.xml | 2 +- pom.xml | 2 +- zerocode-maven-archetype/pom.xml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/core/pom.xml b/core/pom.xml index 084bd9d37..129d6dfc1 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -4,7 +4,7 @@ zerocode-tdd-parent org.jsmart - 1.3.37-SNAPSHOT + 1.3.37 zerocode-tdd diff --git a/http-testing/pom.xml b/http-testing/pom.xml index 2f2a834d2..29badd3b3 100644 --- a/http-testing/pom.xml +++ b/http-testing/pom.xml @@ -4,7 +4,7 @@ zerocode-tdd-parent org.jsmart - 1.3.37-SNAPSHOT + 1.3.37 org.jsmart diff --git a/junit5-testing/pom.xml b/junit5-testing/pom.xml index cca01ebde..f2e7ce7cd 100644 --- a/junit5-testing/pom.xml +++ b/junit5-testing/pom.xml @@ -4,7 +4,7 @@ zerocode-tdd-parent org.jsmart - 1.3.37-SNAPSHOT + 1.3.37 zerocode-tdd-jupiter diff --git a/kafka-testing/pom.xml b/kafka-testing/pom.xml index 518c91593..a23dbc17d 100644 --- a/kafka-testing/pom.xml +++ b/kafka-testing/pom.xml @@ -4,7 +4,7 @@ zerocode-tdd-parent org.jsmart - 1.3.37-SNAPSHOT + 1.3.37 kafka-testing diff --git a/pom.xml b/pom.xml index 0f92b0807..57f8941c3 100644 --- a/pom.xml +++ b/pom.xml @@ -9,7 +9,7 @@ zerocode-tdd-parent org.jsmart - 1.3.37-SNAPSHOT + 1.3.37 pom ZeroCode TDD Parent diff --git a/zerocode-maven-archetype/pom.xml b/zerocode-maven-archetype/pom.xml index 0ed16767e..097fde9c2 100644 --- a/zerocode-maven-archetype/pom.xml +++ b/zerocode-maven-archetype/pom.xml @@ -4,7 +4,7 @@ org.jsmart zerocode-tdd-parent - 1.3.37-SNAPSHOT + 1.3.37 zerocode-maven-archetype From d9e68901556f8aa4a6ff7df6ac16f87e6e347bb7 Mon Sep 17 00:00:00 2001 From: Nirmal Chandra Date: Sun, 18 Feb 2024 22:07:00 +0000 Subject: [PATCH 44/44] [maven-release-plugin] prepare for next development iteration --- core/pom.xml | 2 +- http-testing/pom.xml | 2 +- junit5-testing/pom.xml | 2 +- kafka-testing/pom.xml | 2 +- pom.xml | 2 +- zerocode-maven-archetype/pom.xml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/core/pom.xml b/core/pom.xml index 129d6dfc1..8c6275864 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -4,7 +4,7 @@ zerocode-tdd-parent org.jsmart - 1.3.37 + 1.3.38-SNAPSHOT zerocode-tdd diff --git a/http-testing/pom.xml b/http-testing/pom.xml index 29badd3b3..45ffb2bcc 100644 --- a/http-testing/pom.xml +++ b/http-testing/pom.xml @@ -4,7 +4,7 @@ zerocode-tdd-parent org.jsmart - 1.3.37 + 1.3.38-SNAPSHOT org.jsmart diff --git a/junit5-testing/pom.xml b/junit5-testing/pom.xml index f2e7ce7cd..b0ce0a518 100644 --- a/junit5-testing/pom.xml +++ b/junit5-testing/pom.xml @@ -4,7 +4,7 @@ zerocode-tdd-parent org.jsmart - 1.3.37 + 1.3.38-SNAPSHOT zerocode-tdd-jupiter diff --git a/kafka-testing/pom.xml b/kafka-testing/pom.xml index a23dbc17d..1deb71ba5 100644 --- a/kafka-testing/pom.xml +++ b/kafka-testing/pom.xml @@ -4,7 +4,7 @@ zerocode-tdd-parent org.jsmart - 1.3.37 + 1.3.38-SNAPSHOT kafka-testing diff --git a/pom.xml b/pom.xml index 57f8941c3..bca45f22e 100644 --- a/pom.xml +++ b/pom.xml @@ -9,7 +9,7 @@ zerocode-tdd-parent org.jsmart - 1.3.37 + 1.3.38-SNAPSHOT pom ZeroCode TDD Parent diff --git a/zerocode-maven-archetype/pom.xml b/zerocode-maven-archetype/pom.xml index 097fde9c2..ebd9871a8 100644 --- a/zerocode-maven-archetype/pom.xml +++ b/zerocode-maven-archetype/pom.xml @@ -4,7 +4,7 @@ org.jsmart zerocode-tdd-parent - 1.3.37 + 1.3.38-SNAPSHOT zerocode-maven-archetype