diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 7c2b7113..cb8e2825 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -20,6 +20,12 @@ element/attribute. This allows placeholders like PR [#178](https://github.com/xmlunit/xmlunit/issues/178) by [@Jazzyekim](https://github.com/Jazzyekim). +* add a new `${xmlunit.isDateTime}` placeholder + inspired by [#xmlunit.net/31](https://github.com/xmlunit/xmlunit.net/pull/31) and + [#xmlunit.net/32](https://github.com/xmlunit/xmlunit.net/pull/32) by + [MilkyWare](https://github.com/MilkyWare) + Issue [#174](https://github.com/xmlunit/xmlunit/issues/174) + ## XMLUnit for Java 2.6.4 - /Released 2020-03-08/ * the dependencies on JAXB implementation and its transitive diff --git a/xmlunit-placeholders/src/main/java/org/xmlunit/placeholder/IsDateTimePlaceholderHandler.java b/xmlunit-placeholders/src/main/java/org/xmlunit/placeholder/IsDateTimePlaceholderHandler.java new file mode 100644 index 00000000..512f86a4 --- /dev/null +++ b/xmlunit-placeholders/src/main/java/org/xmlunit/placeholder/IsDateTimePlaceholderHandler.java @@ -0,0 +1,83 @@ +/* + This file is licensed to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +package org.xmlunit.placeholder; + +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import org.xmlunit.diff.ComparisonResult; + +/** + * Handler for the {@code isDateTime} placeholder keyword. + * @since 2.7.0 + */ +public class IsDateTimePlaceholderHandler implements PlaceholderHandler { + private static final String PLACEHOLDER_NAME = "isDateTime"; + + private static final List ISO_PATTERNS = Collections.unmodifiableList(Arrays.asList( + "yyyy-MM-dd", + "yyyy-MM-dd'T'HH:mm:ss", + "yyyy-MM-dd'T'HH:mm:ss.SSS", + "yyyy-MM-dd'T'HH:mm:ssZ", + "yyyy-MM-dd'T'HH:mm:ss.SSSZ", + "yyyy-MM-dd'T'HH:mm:ssXXX", + "yyyy-MM-dd'T'HH:mm:ss.SSSXXX", + "yyyy-MM-dd HH:mm:ss", + "yyyy-MM-dd HH:mm:ss.SSS", + "yyyy-MM-dd HH:mm:ssZ", + "yyyy-MM-dd HH:mm:ss.SSSZ", + "yyyy-MM-dd HH:mm:ssXXX", + "yyyy-MM-dd HH:mm:ss.SSSXXX" + )); + + @Override + public String getKeyword() { + return PLACEHOLDER_NAME; + } + + @Override + public ComparisonResult evaluate(final String testText, final String... param) { + return canParse(testText) + ? ComparisonResult.EQUAL + : ComparisonResult.DIFFERENT; + } + + private boolean canParse(final String testText) { + if (testText == null || "".equals(testText)) { + return false; + } + if (canParse(DateFormat.getDateInstance(DateFormat.SHORT), testText) || + canParse(DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT), testText)) { + return true; + } + for (final String pattern : ISO_PATTERNS) { + if (canParse(new SimpleDateFormat(pattern), testText)) { + return true; + } + } + return false; + } + + private boolean canParse(final DateFormat fmt, final String testText) { + try { + return null != fmt.parse(testText); + } catch (ParseException ex) { + return false; + } + } +} diff --git a/xmlunit-placeholders/src/main/resources/META-INF/services/org.xmlunit.placeholder.PlaceholderHandler b/xmlunit-placeholders/src/main/resources/META-INF/services/org.xmlunit.placeholder.PlaceholderHandler index 2e339b52..300f3c83 100644 --- a/xmlunit-placeholders/src/main/resources/META-INF/services/org.xmlunit.placeholder.PlaceholderHandler +++ b/xmlunit-placeholders/src/main/resources/META-INF/services/org.xmlunit.placeholder.PlaceholderHandler @@ -1,3 +1,4 @@ org.xmlunit.placeholder.IgnorePlaceholderHandler org.xmlunit.placeholder.IsNumberPlaceholderHandler -org.xmlunit.placeholder.MatchesRegexPlaceholderHandler \ No newline at end of file +org.xmlunit.placeholder.MatchesRegexPlaceholderHandler +org.xmlunit.placeholder.IsDateTimePlaceholderHandler diff --git a/xmlunit-placeholders/src/test/java/org/xmlunit/placeholder/IsDateTimePlaceholderHandlerTest.java b/xmlunit-placeholders/src/test/java/org/xmlunit/placeholder/IsDateTimePlaceholderHandlerTest.java new file mode 100644 index 00000000..99d686a4 --- /dev/null +++ b/xmlunit-placeholders/src/test/java/org/xmlunit/placeholder/IsDateTimePlaceholderHandlerTest.java @@ -0,0 +1,68 @@ +/* + This file is licensed to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +package org.xmlunit.placeholder; + +import java.util.Locale; + +import org.junit.Test; +import org.xmlunit.diff.ComparisonResult; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.junit.Assert.assertThat; + +public class IsDateTimePlaceholderHandlerTest { + + private PlaceholderHandler placeholderHandler = new IsDateTimePlaceholderHandler(); + + @Test + public void shouldGetKeyword() { + String expected = "isDateTime"; + String keyword = placeholderHandler.getKeyword(); + + assertThat(keyword, equalTo(expected)); + } + + @Test + public void shouldAcceptABunchOfStrings() { + final Locale l = Locale.getDefault(); + try { + Locale.setDefault(Locale.US); + for (final String s : new String[] { + "2020-01-01", + "01/01/2020", + "01/01/2020", + "2020-01-01T15:00", + "2020-01-01 15:00:00Z", + "01/01/2020 15:00", + }) { + final ComparisonResult comparisonResult = placeholderHandler.evaluate(s); + assertThat(comparisonResult, equalTo(ComparisonResult.EQUAL)); + } + } finally { + Locale.setDefault(l); + } + } + + @Test + public void shouldRejectNullAndEmpty() { + assertThat(placeholderHandler.evaluate(null), equalTo(ComparisonResult.DIFFERENT)); + assertThat(placeholderHandler.evaluate(""), equalTo(ComparisonResult.DIFFERENT)); + } + + @Test + public void shouldRejectExtraContent() { + assertThat(placeholderHandler.evaluate("This is a test date 2020-01-01"), + equalTo(ComparisonResult.DIFFERENT)); + } +} diff --git a/xmlunit-placeholders/src/test/java/org/xmlunit/placeholder/PlaceholderDifferenceEvaluatorTest.java b/xmlunit-placeholders/src/test/java/org/xmlunit/placeholder/PlaceholderDifferenceEvaluatorTest.java index ae06c7a7..f9d4304c 100644 --- a/xmlunit-placeholders/src/test/java/org/xmlunit/placeholder/PlaceholderDifferenceEvaluatorTest.java +++ b/xmlunit-placeholders/src/test/java/org/xmlunit/placeholder/PlaceholderDifferenceEvaluatorTest.java @@ -415,4 +415,40 @@ public void hasMalformedPlaceholder_Attribute() { assertTrue(diff.hasDifferences()); } + + @Test + public void isDateTimePlaceholder_Attribute_NotDateTime() { + String control = ""; + String test = ""; + Diff diff = PlaceholderSupport.withPlaceholderSupport(DiffBuilder.compare(control).withTest(test)).build(); + + assertTrue(diff.hasDifferences()); + } + + @Test + public void isDateTimePlaceholder_Attribute_IsDateTime() { + String control = ""; + String test = ""; + Diff diff = PlaceholderSupport.withPlaceholderSupport(DiffBuilder.compare(control).withTest(test)).build(); + + assertFalse(diff.hasDifferences()); + } + + @Test + public void isDateTimePlaceholder_Element_NotDateTime() { + String control = "${xmlunit.isDateTime}"; + String test = "abc"; + Diff diff = PlaceholderSupport.withPlaceholderSupport(DiffBuilder.compare(control).withTest(test)).build(); + + assertTrue(diff.hasDifferences()); + } + + @Test + public void isDateTimePlaceholder_Element_IsDateTime() { + String control = "${xmlunit.isDateTime}"; + String test = "2020-01-01 15:00:00Z"; + Diff diff = PlaceholderSupport.withPlaceholderSupport(DiffBuilder.compare(control).withTest(test)).build(); + + assertFalse(diff.hasDifferences()); + } }