diff --git a/core/src/main/java/org/jsmart/zerocode/core/engine/assertion/field/FieldHasDateAfterValueAsserter.java b/core/src/main/java/org/jsmart/zerocode/core/engine/assertion/field/FieldHasDateAfterValueAsserter.java index 5f8ef7f91..06d650b01 100644 --- a/core/src/main/java/org/jsmart/zerocode/core/engine/assertion/field/FieldHasDateAfterValueAsserter.java +++ b/core/src/main/java/org/jsmart/zerocode/core/engine/assertion/field/FieldHasDateAfterValueAsserter.java @@ -2,13 +2,13 @@ package org.jsmart.zerocode.core.engine.assertion.field; import java.time.LocalDateTime; -import java.time.format.DateTimeFormatter; import java.time.format.DateTimeParseException; import org.jsmart.zerocode.core.engine.assertion.JsonAsserter; import org.jsmart.zerocode.core.engine.assertion.FieldAssertionMatcher; 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.utils.DateTimeUtils.parseLocalDateTime; public class FieldHasDateAfterValueAsserter implements JsonAsserter { private final String path; @@ -40,8 +40,7 @@ public FieldAssertionMatcher actualEqualsToExpected(Object result) { } else { LocalDateTime resultDT = null; try { - resultDT = LocalDateTime.parse((String) result, - DateTimeFormatter.ISO_DATE_TIME); + resultDT = parseLocalDateTime((String) result); areEqual = resultDT.isAfter(expected); } catch (DateTimeParseException ex) { areEqual = false; diff --git a/core/src/main/java/org/jsmart/zerocode/core/engine/assertion/field/FieldHasDateBeforeValueAsserter.java b/core/src/main/java/org/jsmart/zerocode/core/engine/assertion/field/FieldHasDateBeforeValueAsserter.java index 5665660be..dc4b8fa15 100644 --- a/core/src/main/java/org/jsmart/zerocode/core/engine/assertion/field/FieldHasDateBeforeValueAsserter.java +++ b/core/src/main/java/org/jsmart/zerocode/core/engine/assertion/field/FieldHasDateBeforeValueAsserter.java @@ -2,13 +2,13 @@ package org.jsmart.zerocode.core.engine.assertion.field; import java.time.LocalDateTime; -import java.time.format.DateTimeFormatter; import java.time.format.DateTimeParseException; import org.jsmart.zerocode.core.engine.assertion.JsonAsserter; import org.jsmart.zerocode.core.engine.assertion.FieldAssertionMatcher; 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.utils.DateTimeUtils.parseLocalDateTime; public class FieldHasDateBeforeValueAsserter implements JsonAsserter { private final String path; @@ -40,8 +40,7 @@ public FieldAssertionMatcher actualEqualsToExpected(Object result) { } else { LocalDateTime resultDT = null; try { - resultDT = LocalDateTime.parse((String) result, - DateTimeFormatter.ISO_DATE_TIME); + resultDT = parseLocalDateTime((String) result); areEqual = resultDT.isBefore(expected); } catch (DateTimeParseException ex) { areEqual = false; 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 6260cf201..d57649aaf 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 @@ -31,8 +31,6 @@ import java.io.IOException; import java.math.BigDecimal; -import java.time.LocalDateTime; -import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; @@ -71,6 +69,7 @@ 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.DateTimeUtils.parseLocalDateTime; 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; @@ -437,10 +436,6 @@ private boolean isPropertyKey(String runTimeToken) { return propertyKeys.contains(runTimeToken); } - private LocalDateTime parseLocalDateTime(String value) { - return LocalDateTime.parse(value, DateTimeFormatter.ISO_DATE_TIME); - } - boolean isPathValueJson(Object jsonPathValue) { return jsonPathValue instanceof LinkedHashMap || jsonPathValue instanceof List; } diff --git a/core/src/main/java/org/jsmart/zerocode/core/utils/DateTimeUtils.java b/core/src/main/java/org/jsmart/zerocode/core/utils/DateTimeUtils.java new file mode 100644 index 000000000..f60d22e46 --- /dev/null +++ b/core/src/main/java/org/jsmart/zerocode/core/utils/DateTimeUtils.java @@ -0,0 +1,29 @@ +package org.jsmart.zerocode.core.utils; + +import java.time.LocalDateTime; +import java.time.OffsetDateTime; +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; + +public class DateTimeUtils { + + public static LocalDateTime parseLocalDateTime(String value) { + try { + return ZonedDateTime.parse(value, DateTimeFormatter.RFC_1123_DATE_TIME) + .withZoneSameInstant(ZoneId.systemDefault()) + .toLocalDateTime(); + } catch (DateTimeParseException ignored) { + } + + try { + return OffsetDateTime.parse(value, DateTimeFormatter.ISO_DATE_TIME) + .atZoneSameInstant(ZoneId.systemDefault()) + .toLocalDateTime(); + } catch (DateTimeParseException ignored) { + } + + return LocalDateTime.parse(value, DateTimeFormatter.ISO_DATE_TIME); + } +} 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 c62ab4eb8..65ace38ad 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 @@ -30,12 +30,14 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.TimeZone; 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; import static org.jsmart.zerocode.core.utils.HelperJsonUtils.readJsonPath; +import static org.jsmart.zerocode.core.utils.DateTimeUtils.parseLocalDateTime; 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; @@ -977,6 +979,46 @@ public void testDateAfterBefore_both() throws Exception { assertThat(failedReports.size(), is(0)); } + @Test + public void testDateAfterBefore_withTimeZoneOffsetsAndHttpDate() throws Exception { + TimeZone defaultTimeZone = TimeZone.getDefault(); + TimeZone.setDefault(TimeZone.getTimeZone("UTC")); + try { + String resolvedAssertions = + "{\n" + + " \"status\": 200,\n" + + " \"body\": {\n" + + " \"projectDetails\": {\n" + + " \"startDateTime\": \"$LOCAL.DATETIME.BEFORE:2019-06-15T10:00:00.000Z\",\n" + + " \"endDateTime\": \"$LOCAL.DATETIME.AFTER:2019-06-15T10:00:00.000Z\",\n" + + " \"lastModified\": \"$LOCAL.DATETIME.BEFORE:Sat, 06 Jul 2019 17:07:15 GMT\"\n" + + " }\n" + + " }\n" + + "}"; + + List asserters = jsonPreProcessor.createJsonAsserters(resolvedAssertions); + assertThat(asserters.size(), is(4)); + + String mockTestResponse = + "{\n" + + " \"status\": 200,\n" + + " \"body\": {\n" + + " \"projectDetails\": {\n" + + " \"startDateTime\": \"2019-06-15T11:30:00.000+02:00\",\n" + + " \"endDateTime\": \"2019-06-15T12:30:00.000+02:00\",\n" + + " \"lastModified\": \"Sat, 06 Jul 2019 16:07:15 GMT\"\n" + + " }\n" + + " }\n" + + "}"; + + List failedReports = + jsonPreProcessor.assertAllAndReturnFailed(asserters, mockTestResponse); + assertThat(failedReports.size(), is(0)); + } finally { + TimeZone.setDefault(defaultTimeZone); + } + } + @Test public void testDateAfterBefore_fail_both() throws Exception { ScenarioSpec scenarioSpec = @@ -1018,12 +1060,12 @@ public void testDateAfterBefore_fail_both() throws Exception { failedReports.get(0).toString(), is( "Assertion jsonPath '$.body.projectDetails.startDateTime' with actual value '2017-04-14T11:49:56.000Z' " - + "did not match the expected value 'Date Before:2016-09-14T09:49:34'")); + + "did not match the expected value 'Date Before:" + parseLocalDateTime("2016-09-14T09:49:34.000Z") + "'")); assertThat( failedReports.get(1).toString(), is( "Assertion jsonPath '$.body.projectDetails.endDateTime' with actual value '2018-11-12T09:39:34.000Z' " - + "did not match the expected value 'Date After:2019-09-14T09:49:34'")); + + "did not match the expected value 'Date After:" + parseLocalDateTime("2019-09-14T09:49:34.000Z") + "'")); } @Test @@ -1063,7 +1105,7 @@ public void testDateAfterBefore_fail_afterSameDate() throws Exception { failedReports.get(0).toString(), is( "Assertion jsonPath '$.body.projectDetails.startDateTime' with actual value '2015-09-14T09:49:34.000Z' " - + "did not match the expected value 'Date After:2015-09-14T09:49:34'")); + + "did not match the expected value 'Date After:" + parseLocalDateTime("2015-09-14T09:49:34.000Z") + "'")); } @Test @@ -1103,7 +1145,7 @@ public void testDateAfterBefore_fail_beforeSameDate() throws Exception { failedReports.get(0).toString(), is( "Assertion jsonPath '$.body.projectDetails.startDateTime' with actual value '2015-09-14T09:49:34.000Z' " - + "did not match the expected value 'Date Before:2015-09-14T09:49:34'")); + + "did not match the expected value 'Date Before:" + parseLocalDateTime("2015-09-14T09:49:34.000Z") + "'")); } @Test