diff --git a/src/WireMock.Net/Matchers/JSONPathMatcher.cs b/src/WireMock.Net/Matchers/JSONPathMatcher.cs index fda66f49..94d76cca 100644 --- a/src/WireMock.Net/Matchers/JSONPathMatcher.cs +++ b/src/WireMock.Net/Matchers/JSONPathMatcher.cs @@ -123,7 +123,12 @@ public class JsonPathMatcher : IStringMatcher, IObjectMatcher { var array = ConvertJTokenToJArrayIfNeeded(jToken); - return MatchScores.ToScore(_patterns.Select(pattern => array.SelectToken(pattern.GetPattern())?.Any() == true).ToArray(), MatchOperator); + // The SelectToken method can accept a string path to a child token ( i.e. "Manufacturers[0].Products[0].Price"). In that case it will return a JValue (some type) which does not implement the IEnumerable interface. + // Using ?.Any() == true relays that we use a JSONPath queries and the SelectToken will return a JObject ( implements the IEnumerable interface). + // So the current code works only when the JSONPath is expression and not when we pass a valid string path to child. + // My suggestion is to roll back to != null to cover the both cases. + + return MatchScores.ToScore(_patterns.Select(pattern => array.SelectToken(pattern.GetPattern()) != null ).ToArray(), MatchOperator); } // https://github.com/WireMock-Net/WireMock.Net/issues/965 @@ -149,4 +154,4 @@ public class JsonPathMatcher : IStringMatcher, IObjectMatcher return jToken; } -} \ No newline at end of file +} diff --git a/test/WireMock.Net.Tests/Matchers/JsonPathMatcherTests.cs b/test/WireMock.Net.Tests/Matchers/JsonPathMatcherTests.cs index d0a8e46c..33a21a28 100644 --- a/test/WireMock.Net.Tests/Matchers/JsonPathMatcherTests.cs +++ b/test/WireMock.Net.Tests/Matchers/JsonPathMatcherTests.cs @@ -200,4 +200,128 @@ public class JsonPathMatcherTests // Assert Check.That(match).IsEqualTo(0.0); } -} \ No newline at end of file + + [Fact] + public void JsonPathMatcher_IsMatch_ArrayOneLevel() + { + // Arrange + var matcher = new JsonPathMatcher("$.arr[0].line1"); + + // Act + double match = matcher.IsMatch(JObject.Parse(@"{ + ""name"": ""PathSelectorTest"", + ""test"": ""test"", + ""test2"": ""test2"", + ""arr"": [{ + ""line1"": ""line1"", + }] + }")); + + // Assert + Check.That(match).IsEqualTo(1.0); + } + + [Fact] + public void JsonPathMatcher_IsMatch_ObjectMatch() + { + // Arrange + var matcher = new JsonPathMatcher("$.test"); + + // Act + double match = matcher.IsMatch(JObject.Parse(@"{ + ""name"": ""PathSelectorTest"", + ""test"": ""test"", + ""test2"": ""test2"", + ""arr"": [ + { + ""line1"": ""line1"", + } + ] + }")); + + // Assert + Check.That(match).IsEqualTo(1.0); + } + + [Fact] + public void JsonPathMatcher_IsMatch_DoesntMatch() + { + // Arrange + var matcher = new JsonPathMatcher("$.test3"); + + // Act + double match = matcher.IsMatch(JObject.Parse(@"{ + ""name"": ""PathSelectorTest"", + ""test"": ""test"", + ""test2"": ""test2"", + ""arr"": [ + { + ""line1"": ""line1"", + } + ] + }")); + + // Assert + Check.That(match).IsEqualTo(0.0); + } + + [Fact] + public void JsonPathMatcher_IsMatch_DoesntMatchInArray() + { + // Arrange + var matcher = new JsonPathMatcher("$arr[0].line1"); + + // Act + double match = matcher.IsMatch(JObject.Parse(@"{ + ""name"": ""PathSelectorTest"", + ""test"": ""test"", + ""test2"": ""test2"", + ""arr"": [] + }")); + + // Assert + Check.That(match).IsEqualTo(0.0); + } + + [Fact] + public void JsonPathMatcher_IsMatch_DoesntMatchNoObjectsInArray() + { + // Arrange + var matcher = new JsonPathMatcher("$arr[2].line1"); + + // Act + double match = matcher.IsMatch(JObject.Parse(@"{ + ""name"": ""PathSelectorTest"", + ""test"": ""test"", + ""test2"": ""test2"", + ""arr"": [] + }")); + + // Assert + Check.That(match).IsEqualTo(0.0); + } + + [Fact] + public void JsonPathMatcher_IsMatch_NestedArrays() + { + // Arrange + var matcher = new JsonPathMatcher("$.arr[0].sub[0].subline1"); + + // Act + double match = matcher.IsMatch(JObject.Parse(@"{ + ""name"": ""PathSelectorTest"", + ""test"": ""test"", + ""test2"": ""test2"", + ""arr"": [{ + ""line1"": ""line1"", + ""sub"":[ + { + ""subline1"":""subline1"" + }] + }] + }")); + + // Assert + Check.That(match).IsEqualTo(1.0); + } +}