Skip to content

Commit 2c24610

Browse files
committed
allow a custom pattern to be specified for isDateTime
1 parent f520c49 commit 2c24610

File tree

4 files changed

+116
-3
lines changed

4 files changed

+116
-3
lines changed
Lines changed: 73 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,78 @@
11
<Namespace Name="Org.XmlUnit.Placeholder">
22
<Docs>
33
<summary>Keyword based Configuration Experiment.</summary>
4-
<remarks>Experimental support for configuring parts of the test
5-
engine by using ${xmlunit.KEYWORD} sequences inside the control
6-
document.</remarks>
4+
<remarks>
5+
<para>Experimental support for configuring parts of the test
6+
engine by using <c>${xmlunit.KEYWORD}</c> sequences inside the
7+
control document.</para>
8+
9+
<para>This namepace and the whole package are considered
10+
experimental and any API may change between releases of
11+
XMLUnit.</para>
12+
13+
<para>The placeholder feature allows a placeholder sequence of
14+
<c>${xmlunit.KEYWORD(args...)}</c> to be used as nested text in
15+
elements or as attribute values of the control document and
16+
trigger special handling based on the keyword.</para>
17+
18+
<para>The "special handling" is controlled by an instance of
19+
<see cref="IPlaceholderHandler"/> per keyword. The class <see
20+
cref="PlaceholderDifferenceEvaluator"/> loads all
21+
implementations from the current assembly via reflection.</para>
22+
23+
<para>The placeholder sequence can take any number of string
24+
values as arguments in the form
25+
<c>${xmlunit.KEYWORD(args1,arg2)}</c> - if no arguments are used
26+
the parentheses can be omitted completely. Arguments are not
27+
quoted, whitespace inside of the argument list is
28+
significant. All separators (by default <c>${</c>, <c>}</c>,
29+
<c>(</c>, <c>)</c>, and <c>,</c>) can be configured
30+
explicitly.</para>
31+
32+
<para>Keywords currently supported by built-in handlers
33+
are:</para>
34+
<list type="bullet">
35+
36+
<item><c>${xmlunit.ignore}</c> which makes XMLUnit ignore the
37+
nested text or attribute completely. This is handled by <see
38+
cref="IgnorePlaceholderHandler"/>.</item>
39+
40+
<item><c>${xmlunit.isNumber}</c> makes the comparison pass if
41+
the textual content of the element or attributes looks like a
42+
number. This is handled by <see
43+
cref="IsNumberPlaceholderHandler"/>.</item>
44+
45+
<item><c>${xmlunit.matchesRegex}</c> makes the comparison pass
46+
if the textual content of the element or attribute matches the
47+
regular expression specified as the first (and only) argument.
48+
If there is no argument at all, the comparison will fail. This
49+
is handled by <see
50+
cref="MatchesRegexPlaceholderHandler"/>.</item>
51+
52+
<item><c>${xmlunit.isDateTime}</c> makes the comparison pass
53+
if the textual content of the element or attributes looks like
54+
a date or datetime in the current locale or parsed by ISO
55+
rules. An optional argument can be used to specify a pattern
56+
unserstood by <see cref="DateTime.ParseExact"/> to use when
57+
trying to parse the test. This is handled by <see
58+
cref="IsDateTimePlaceholderHandler"/>.</item>
59+
60+
</list
61+
62+
<para>The default delimiters of <c>${</c> and <c>}</c> can be
63+
overwritten using custom regular expressions.</para>
64+
65+
<para>The easiest way to activate the placeholder feature is to
66+
use one of the methods in <see cref="PlaceholderSupport"/> to
67+
add it to a <see cref="org.xmlunit.builder.DiffBuilder"/> or
68+
<c>org.xmlunit.matchers.CompareMatcher</c> instance. The
69+
alternative approach is to create an instance of <see
70+
cref="PlaceholderDifferenceEvaluator"/> as a <see
71+
cref="org.xmlunit.diff.DifferenceEvaluator"/> and add it to the
72+
builder yourself.</para>
73+
74+
</remarks>
75+
76+
777
</Docs>
878
</Namespace>

src/main/net-placeholders/IsDateTimePlaceholderHandler.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,25 @@ public class IsDateTimePlaceholderHandler : IPlaceholderHandler
3939
/// <inheritdoc/>
4040
public ComparisonResult Evaluate(string testText, params string[] args)
4141
{
42+
if (args != null && args.Length == 1) {
43+
return CanParse(args[0], testText)
44+
? ComparisonResult.EQUAL
45+
: ComparisonResult.DIFFERENT;
46+
}
4247
DateTime _;
4348
var result = DateTime.TryParse(testText, out _);
4449
return result
4550
? ComparisonResult.EQUAL
4651
: ComparisonResult.DIFFERENT;
4752
}
53+
54+
private bool CanParse(string pattern, string testText) {
55+
try {
56+
var _ = DateTime.ParseExact(testText, pattern, CultureInfo.InvariantCulture);
57+
return true;
58+
} catch (FormatException) {
59+
return false;
60+
}
61+
}
4862
}
4963
}

src/tests/net-placeholders/IsDateTimePlaceholderHandlerTests.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,5 +62,14 @@ public void ShouldGetKeyword()
6262

6363
Assert.AreEqual(expected, keyword);
6464
}
65+
66+
[Test]
67+
public void ShouldParseExplicitPattern() {
68+
Assert.AreEqual(ComparisonResult.EQUAL,
69+
placeholderHandler.Evaluate("31 01 2020 12:34", "dd MM yyyy HH:mm"));
70+
Assert.AreEqual(ComparisonResult.DIFFERENT,
71+
placeholderHandler.Evaluate("abc", "dd MM yyyy HH:mm"));
72+
}
73+
6574
}
6675
}

src/tests/net-placeholders/PlaceholderDifferenceEvaluatorTest.cs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,16 @@ public void HasIsDateTimePlaceholder_Attribute_IsDateTime() {
407407
Assert.IsFalse(diff.HasDifferences());
408408
}
409409

410+
[Test]
411+
public void IsDateTimePlaceholder_Attribute_IsDateTime_CustomFormat() {
412+
string control = "<elem1 attr='${xmlunit.isDateTime(dd.MM.yyyy)}'/>";
413+
string test = "<elem1 attr='05.09.2020'/>";
414+
var diff = DiffBuilder.Compare(control).WithTest(test)
415+
.WithDifferenceEvaluator(new PlaceholderDifferenceEvaluator().Evaluate).Build();
416+
417+
Assert.IsFalse(diff.HasDifferences());
418+
}
419+
410420
[Test]
411421
public void HasIsDateTimePlaceholder_Element_NotDateTime() {
412422
string control = "<elem1>${xmlunit.isDateTime}</elem1>";
@@ -426,5 +436,15 @@ public void HasIsDateTimePlaceholder_Element_IsDateTime() {
426436

427437
Assert.IsFalse(diff.HasDifferences());
428438
}
439+
440+
[Test]
441+
public void IsDateTimePlaceholder_Element_IsDateTime_CustomFormat() {
442+
string control = "<elem1>${xmlunit.isDateTime(dd.MM.yyyy)}</elem1>";
443+
string test = "<elem1>09.05.2020</elem1>";
444+
var diff = DiffBuilder.Compare(control).WithTest(test)
445+
.WithDifferenceEvaluator(new PlaceholderDifferenceEvaluator().Evaluate).Build();
446+
447+
Assert.IsFalse(diff.HasDifferences());
448+
}
429449
}
430450
}

0 commit comments

Comments
 (0)