Update handlebars code to support Regex.Match (#201) (#202)

* #201

* Handlebars : Linq and JsonPath

* Rename to Regex.Match

* unit test coverage
This commit is contained in:
Stef Heyenrath
2018-09-11 08:42:50 +02:00
committed by GitHub
parent ec39d12cfe
commit da64934c13
11 changed files with 964 additions and 579 deletions

View File

@@ -83,11 +83,13 @@ namespace WireMock.Matchers
// Convert a single object to a Queryable JObject-list with 1 entry.
var queryable1 = new[] { value }.AsQueryable();
// Generate the dynamic linq select statement and generate a dynamic Queryable.
// Generate the DynamicLinq select statement.
string dynamicSelect = JsonUtils.GenerateDynamicLinqStatement(value);
// Execute DynamicLinq Select statement.
var queryable2 = queryable1.Select(dynamicSelect);
// Use the Any(...) method to check if the result matches
// Use the Any(...) method to check if the result matches.
double match = MatchScores.ToScore(_patterns.Select(pattern => queryable2.Any(pattern)));
return MatchBehaviourHelper.Convert(MatchBehaviour, match);

View File

@@ -1,144 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Text.RegularExpressions;
using HandlebarsDotNet;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using WireMock.Utils;
using WireMock.Validation;
namespace WireMock.Transformers
namespace WireMock.Transformers
{
internal static class HandlebarsHelpers
{
public static void Register()
{
Handlebars.RegisterHelper("Regex.Match", (writer, context, arguments) =>
{
(string stringToProcess, string regexPattern, object defaultValue) = ParseRegexArguments(arguments);
HandleBarsRegex.Register();
Match match = Regex.Match(stringToProcess, regexPattern);
HandleBarsJsonPath.Register();
if (match.Success)
{
writer.WriteSafeString(match.Value);
}
else if (defaultValue != null)
{
writer.WriteSafeString(defaultValue);
}
});
Handlebars.RegisterHelper("Regex.Match", (writer, options, context, arguments) =>
{
(string stringToProcess, string regexPattern, object defaultValue) = ParseRegexArguments(arguments);
var regex = new Regex(regexPattern);
var namedGroups = RegexUtils.GetNamedGroups(regex, stringToProcess);
if (namedGroups.Any())
{
options.Template(writer, namedGroups);
}
else if (defaultValue != null)
{
writer.WriteSafeString(defaultValue);
}
});
Handlebars.RegisterHelper("JsonPath.SelectToken", (writer, context, arguments) =>
{
(JObject valueToProcess, string jsonpath) = ParseJsonPathArguments(arguments);
JToken result = null;
try
{
result = valueToProcess.SelectToken(jsonpath);
}
catch (JsonException)
{
// Ignore JsonException and return
return;
}
if (result != null)
{
writer.WriteSafeString(result);
}
});
Handlebars.RegisterHelper("JsonPath.SelectTokens", (writer, options, context, arguments) =>
{
(JObject valueToProcess, string jsonpath) = ParseJsonPathArguments(arguments);
IEnumerable<JToken> values = null;
try
{
values = valueToProcess.SelectTokens(jsonpath);
}
catch (JsonException)
{
// Ignore JsonException and return
return;
}
if (values == null)
{
return;
}
int id = 0;
foreach (JToken value in values)
{
options.Template(writer, new { id, value });
id++;
}
});
}
private static (JObject valueToProcess, string jsonpath) ParseJsonPathArguments(object[] arguments)
{
Check.Condition(arguments, args => args.Length == 2, nameof(arguments));
Check.NotNull(arguments[0], "arguments[0]");
Check.NotNullOrEmpty(arguments[1] as string, "arguments[1]");
JObject valueToProcess;
switch (arguments[0])
{
case string jsonAsString:
valueToProcess = JObject.Parse(jsonAsString);
break;
case JObject jsonAsJObject:
valueToProcess = jsonAsJObject;
break;
default:
throw new NotSupportedException($"The value '{arguments[0]}' with type '{arguments[0]?.GetType()}' cannot be used in Handlebars JsonPath.");
}
return (valueToProcess, arguments[1] as string);
}
private static (string stringToProcess, string regexPattern, object defaultValue) ParseRegexArguments(object[] arguments)
{
Check.Condition(arguments, args => args.Length >= 2, nameof(arguments));
string ParseAsString(object arg)
{
if (arg is string)
{
return arg as string;
}
else
{
throw new NotSupportedException($"The value '{arg}' with type '{arg?.GetType()}' cannot be used in Handlebars Regex.");
}
}
return (ParseAsString(arguments[0]), ParseAsString(arguments[1]), arguments.Length == 3 ? arguments[2] : null);
HandleBarsLinq.Register();
}
}
}

View File

@@ -0,0 +1,75 @@
using System;
using System.Linq;
using HandlebarsDotNet;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using WireMock.Validation;
namespace WireMock.Transformers
{
internal static class HandleBarsJsonPath
{
public static void Register()
{
Handlebars.RegisterHelper("JsonPath.SelectToken", (writer, context, arguments) =>
{
(JObject valueToProcess, string jsonpath) = ParseArguments(arguments);
try
{
var result = valueToProcess.SelectToken(jsonpath);
writer.WriteSafeString(result);
}
catch (JsonException)
{
// Ignore JsonException and return
return;
}
});
Handlebars.RegisterHelper("JsonPath.SelectTokens", (writer, options, context, arguments) =>
{
(JObject valueToProcess, string jsonpath) = ParseArguments(arguments);
try
{
var values = valueToProcess.SelectTokens(jsonpath);
if (values != null)
{
options.Template(writer, values.ToDictionary(value => value.Path, value => value));
}
}
catch (JsonException)
{
// Ignore JsonException and return
return;
}
});
}
private static (JObject valueToProcess, string jsonpath) ParseArguments(object[] arguments)
{
Check.Condition(arguments, args => args.Length == 2, nameof(arguments));
Check.NotNull(arguments[0], "arguments[0]");
Check.NotNullOrEmpty(arguments[1] as string, "arguments[1]");
JObject valueToProcess;
switch (arguments[0])
{
case string jsonAsString:
valueToProcess = JObject.Parse(jsonAsString);
break;
case JObject jsonAsJObject:
valueToProcess = jsonAsJObject;
break;
default:
throw new NotSupportedException($"The value '{arguments[0]}' with type '{arguments[0]?.GetType()}' cannot be used in Handlebars JsonPath.");
}
return (valueToProcess, arguments[1] as string);
}
}
}

View File

@@ -0,0 +1,88 @@
using System;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Linq.Dynamic.Core.Exceptions;
using HandlebarsDotNet;
using Newtonsoft.Json.Linq;
using WireMock.Util;
using WireMock.Validation;
namespace WireMock.Transformers
{
internal static class HandleBarsLinq
{
public static void Register()
{
Handlebars.RegisterHelper("Linq", (writer, context, arguments) =>
{
(JToken valueToProcess, string linqStatement) = ParseArguments(arguments);
try
{
object result = ExecuteDynamicLinq(valueToProcess, linqStatement);
writer.WriteSafeString(result);
}
catch (ParseException)
{
// Ignore ParseException and return
return;
}
});
Handlebars.RegisterHelper("Linq", (writer, options, context, arguments) =>
{
(JToken valueToProcess, string linqStatement) = ParseArguments(arguments);
try
{
var result = ExecuteDynamicLinq(valueToProcess, linqStatement);
options.Template(writer, result);
}
catch (ParseException)
{
// Ignore ParseException and return
return;
}
});
}
private static dynamic ExecuteDynamicLinq(JToken value, string linqStatement)
{
// Convert a single object to a Queryable JObject-list with 1 entry.
var queryable1 = new[] { value }.AsQueryable();
// Generate the DynamicLinq select statement.
string dynamicSelect = JsonUtils.GenerateDynamicLinqStatement(value);
// Execute DynamicLinq Select statement.
var queryable2 = queryable1.Select(dynamicSelect);
// Execute the Select(...) method and get first result with FirstOrDefault().
return queryable2.Select(linqStatement).FirstOrDefault();
}
private static (JToken valueToProcess, string linqStatement) ParseArguments(object[] arguments)
{
Check.Condition(arguments, args => args.Length == 2, nameof(arguments));
Check.NotNull(arguments[0], "arguments[0]");
Check.NotNullOrEmpty(arguments[1] as string, "arguments[1]");
JToken valueToProcess;
switch (arguments[0])
{
case string jsonAsString:
valueToProcess = new JValue(jsonAsString);
break;
case JToken jsonAsJObject:
valueToProcess = jsonAsJObject;
break;
default:
throw new NotSupportedException($"The value '{arguments[0]}' with type '{arguments[0]?.GetType()}' cannot be used in Handlebars Linq.");
}
return (valueToProcess, arguments[1] as string);
}
}
}

View File

@@ -0,0 +1,66 @@
using System;
using System.Linq;
using System.Text.RegularExpressions;
using HandlebarsDotNet;
using WireMock.Utils;
using WireMock.Validation;
namespace WireMock.Transformers
{
internal static class HandleBarsRegex
{
public static void Register()
{
Handlebars.RegisterHelper("Regex.Match", (writer, context, arguments) =>
{
(string stringToProcess, string regexPattern, object defaultValue) = ParseArguments(arguments);
Match match = Regex.Match(stringToProcess, regexPattern);
if (match.Success)
{
writer.WriteSafeString(match.Value);
}
else if (defaultValue != null)
{
writer.WriteSafeString(defaultValue);
}
});
Handlebars.RegisterHelper("Regex.Match", (writer, options, context, arguments) =>
{
(string stringToProcess, string regexPattern, object defaultValue) = ParseArguments(arguments);
var regex = new Regex(regexPattern);
var namedGroups = RegexUtils.GetNamedGroups(regex, stringToProcess);
if (namedGroups.Any())
{
options.Template(writer, namedGroups);
}
else if (defaultValue != null)
{
options.Template(writer, defaultValue);
}
});
}
private static (string stringToProcess, string regexPattern, object defaultValue) ParseArguments(object[] arguments)
{
Check.Condition(arguments, args => args.Length == 2 || args.Length == 3, nameof(arguments));
string ParseAsString(object arg)
{
if (arg is string)
{
return arg as string;
}
else
{
throw new NotSupportedException($"The value '{arg}' with type '{arg?.GetType()}' cannot be used in Handlebars Regex.");
}
}
return (ParseAsString(arguments[0]), ParseAsString(arguments[1]), arguments.Length == 3 ? arguments[2] : null);
}
}
}

View File

@@ -20,7 +20,7 @@ namespace WireMock.Util
}
}
public static string GenerateDynamicLinqStatement(JObject jsonObject)
public static string GenerateDynamicLinqStatement(JToken jsonObject)
{
var lines = new List<string>();
WalkNode(jsonObject, null, null, lines);
@@ -40,7 +40,7 @@ namespace WireMock.Util
}
else
{
ProcessItem(node, path, propertyName, lines);
ProcessItem(node, path ?? "it", propertyName, lines);
}
}

View File

@@ -0,0 +1,324 @@
using System;
using System.Threading.Tasks;
using Newtonsoft.Json.Linq;
using NFluent;
using WireMock.Models;
using WireMock.ResponseBuilders;
using WireMock.Util;
using Xunit;
namespace WireMock.Net.Tests.ResponseBuilderTests
{
public class ResponseWithHandlebarsJsonPathTests
{
private const string ClientIp = "::1";
[Fact]
public async Task Response_ProvideResponse_Handlebars_JsonPath_SelectToken_Object_ResponseBodyAsJson()
{
// Assign
var body = new BodyData
{
BodyAsString = @"{
""Stores"": [
""Lambton Quay"",
""Willis Street""
],
""Manufacturers"": [
{
""Name"": ""Acme Co"",
""Products"": [
{
""Name"": ""Anvil"",
""Price"": 50
}
]
},
{
""Name"": ""Contoso"",
""Products"": [
{
""Name"": ""Elbow Grease"",
""Price"": 99.95
},
{
""Name"": ""Headlight Fluid"",
""Price"": 4
}
]
}
]
}"
};
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body);
var response = Response.Create()
.WithHeader("Content-Type", "application/json")
.WithBodyAsJson(new { x = "{{JsonPath.SelectToken request.body \"$.Manufacturers[?(@.Name == 'Acme Co')]\"}}" })
.WithTransformer();
// Act
var responseMessage = await response.ProvideResponseAsync(request);
// Assert
JObject j = JObject.FromObject(responseMessage.BodyAsJson);
Check.That(j["x"]).IsNotNull();
Check.That(j["x"]["Name"].ToString()).Equals("Acme Co");
}
[Fact]
public async Task Response_ProvideResponse_Handlebars_JsonPath_SelectToken_Number_ResponseBodyAsJson()
{
// Assign
var body = new BodyData { BodyAsString = "{ \"Price\": 99 }" };
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body);
var response = Response.Create()
.WithHeader("Content-Type", "application/json")
.WithBodyAsJson(new { x = "{{JsonPath.SelectToken request.body \"..Price\"}}" })
.WithTransformer();
// Act
var responseMessage = await response.ProvideResponseAsync(request);
// Assert
JObject j = JObject.FromObject(responseMessage.BodyAsJson);
Check.That(j["x"].Value<long>()).Equals(99);
}
[Fact]
public async Task Response_ProvideResponse_Handlebars_JsonPath_SelectToken_Request_BodyAsString()
{
// Assign
var body = new BodyData
{
BodyAsString = @"{
""Stores"": [
""Lambton Quay"",
""Willis Street""
],
""Manufacturers"": [
{
""Name"": ""Acme Co"",
""Products"": [
{
""Name"": ""Anvil"",
""Price"": 50
}
]
},
{
""Name"": ""Contoso"",
""Products"": [
{
""Name"": ""Elbow Grease"",
""Price"": 99.95
},
{
""Name"": ""Headlight Fluid"",
""Price"": 4
}
]
}
]
}"
};
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body);
var response = Response.Create()
.WithHeader("Content-Type", "application/json")
.WithBody("{{JsonPath.SelectToken request.body \"$.Manufacturers[?(@.Name == 'Acme Co')]\"}}")
.WithTransformer();
// Act
var responseMessage = await response.ProvideResponseAsync(request);
// Assert
Check.That(responseMessage.Body).Equals("{\r\n \"Name\": \"Acme Co\",\r\n \"Products\": [\r\n {\r\n \"Name\": \"Anvil\",\r\n \"Price\": 50\r\n }\r\n ]\r\n}");
}
[Fact]
public async Task Response_ProvideResponse_Handlebars_JsonPath_SelectToken_Request_BodyAsJObject()
{
// Assign
var body = new BodyData
{
BodyAsJson = JObject.Parse(@"{
'Stores': [
'Lambton Quay',
'Willis Street'
],
'Manufacturers': [
{
'Name': 'Acme Co',
'Products': [
{
'Name': 'Anvil',
'Price': 50
}
]
},
{
'Name': 'Contoso',
'Products': [
{
'Name': 'Elbow Grease',
'Price': 99.95
},
{
'Name': 'Headlight Fluid',
'Price': 4
}
]
}
]
}")
};
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body);
var response = Response.Create()
.WithHeader("Content-Type", "application/json")
.WithBody("{{JsonPath.SelectToken request.bodyAsJson \"$.Manufacturers[?(@.Name == 'Acme Co')]\"}}")
.WithTransformer();
// Act
var responseMessage = await response.ProvideResponseAsync(request);
// Assert
Check.That(responseMessage.Body).Equals("{\r\n \"Name\": \"Acme Co\",\r\n \"Products\": [\r\n {\r\n \"Name\": \"Anvil\",\r\n \"Price\": 50\r\n }\r\n ]\r\n}");
}
[Fact]
public async Task Response_ProvideResponse_Handlebars_JsonPath_SelectTokens_Request_BodyAsString()
{
// Assign
var body = new BodyData
{
BodyAsString = @"{
""Stores"": [
""Lambton Quay"",
""Willis Street""
],
""Manufacturers"": [
{
""Name"": ""Acme Co"",
""Products"": [
{
""Name"": ""Anvil"",
""Price"": 50
}
]
},
{
""Name"": ""Contoso"",
""Products"": [
{
""Name"": ""Elbow Grease"",
""Price"": 99.95
},
{
""Name"": ""Headlight Fluid"",
""Price"": 4
}
]
}
]
}"
};
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body);
var response = Response.Create()
.WithHeader("Content-Type", "application/json")
.WithBody("{{#JsonPath.SelectTokens request.body \"$..Products[?(@.Price >= 50)].Name\"}}{{#each this}}%{{@index}}:{{this}}%{{/each}}{{/JsonPath.SelectTokens}}")
.WithTransformer();
// Act
var responseMessage = await response.ProvideResponseAsync(request);
// Assert
Check.That(responseMessage.Body).Equals("%0:Anvil%%1:Elbow Grease%");
}
[Fact]
public async Task Response_ProvideResponse_Handlebars_JsonPath_SelectTokens_Request_BodyAsJObject()
{
// Assign
var body = new BodyData
{
BodyAsJson = JObject.Parse(@"{
'Stores': [
'Lambton Quay',
'Willis Street'
],
'Manufacturers': [
{
'Name': 'Acme Co',
'Products': [
{
'Name': 'Anvil',
'Price': 50
}
]
},
{
'Name': 'Contoso',
'Products': [
{
'Name': 'Elbow Grease',
'Price': 99.95
},
{
'Name': 'Headlight Fluid',
'Price': 4
}
]
}
]
}")
};
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body);
var response = Response.Create()
.WithHeader("Content-Type", "application/json")
.WithBody("{{#JsonPath.SelectTokens request.bodyAsJson \"$..Products[?(@.Price >= 50)].Name\"}}{{#each this}}%{{@index}}:{{this}}%{{/each}}{{/JsonPath.SelectTokens}}")
.WithTransformer();
// Act
var responseMessage = await response.ProvideResponseAsync(request);
// Assert
Check.That(responseMessage.Body).Equals("%0:Anvil%%1:Elbow Grease%");
}
[Fact]
public void Response_ProvideResponse_Handlebars_JsonPath_SelectTokens_Throws()
{
// Assign
var body = new BodyData
{
BodyAsJson = JObject.Parse(@"{
'Stores': [
'Lambton Quay',
'Willis Street'
]
}")
};
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body);
var response = Response.Create()
.WithHeader("Content-Type", "application/json")
.WithBody("{{#JsonPath.SelectTokens request.body \"$..Products[?(@.Price >= 50)].Name\"}}{{id}} {{value}},{{/JsonPath.SelectTokens}}")
.WithTransformer();
// Act
Check.ThatAsyncCode(() => response.ProvideResponseAsync(request)).Throws<ArgumentNullException>();
}
}
}

View File

@@ -0,0 +1,225 @@
using System;
using System.Threading.Tasks;
using Newtonsoft.Json.Linq;
using NFluent;
using WireMock.Models;
using WireMock.ResponseBuilders;
using WireMock.Util;
using Xunit;
namespace WireMock.Net.Tests.ResponseBuilderTests
{
public class ResponseWithHandlebarsLinqTests
{
[Fact]
public async Task Response_ProvideResponse_Handlebars_Linq1_String0()
{
// Assign
var body = new BodyData { };
var request = new RequestMessage(new UrlDetails("http://localhost:1234/pathtest"), "POST", "::1", body);
var response = Response.Create()
.WithHeader("Content-Type", "application/json")
.WithBodyAsJson(new { x = "{{Linq request.Path 'it'}}" })
.WithTransformer();
// Act
var responseMessage = await response.ProvideResponseAsync(request);
// Assert
JObject j = JObject.FromObject(responseMessage.BodyAsJson);
Check.That(j["x"]).IsNotNull();
Check.That(j["x"].ToString()).Equals("/pathtest");
}
[Fact]
public async Task Response_ProvideResponse_Handlebars_Linq1_String1()
{
// Assign
var body = new BodyData
{
BodyAsJson = new JObject
{
{ "Id", new JValue(9) },
{ "Name", new JValue("Test") }
}
};
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", "::1", body);
var response = Response.Create()
.WithHeader("Content-Type", "application/json")
.WithBodyAsJson(new { x = "{{Linq request.bodyAsJson 'it.Name + \"_123\"' }}" })
.WithTransformer();
// Act
var responseMessage = await response.ProvideResponseAsync(request);
// Assert
JObject j = JObject.FromObject(responseMessage.BodyAsJson);
Check.That(j["x"]).IsNotNull();
Check.That(j["x"].ToString()).Equals("Test_123");
}
[Fact]
public async Task Response_ProvideResponse_Handlebars_Linq1_String2()
{
// Assign
var body = new BodyData
{
BodyAsJson = new JObject
{
{ "Id", new JValue(9) },
{ "Name", new JValue("Test") }
}
};
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", "::1", body);
var response = Response.Create()
.WithHeader("Content-Type", "application/json")
.WithBodyAsJson(new { x = "{{Linq request.bodyAsJson 'new(it.Name + \"_123\" as N, it.Id as I)' }}" })
.WithTransformer();
// Act
var responseMessage = await response.ProvideResponseAsync(request);
// Assert
JObject j = JObject.FromObject(responseMessage.BodyAsJson);
Check.That(j["x"]).IsNotNull();
Check.That(j["x"].ToString()).Equals("{ N = Test_123, I = 9 }");
}
[Fact]
public async Task Response_ProvideResponse_Handlebars_Linq2_Object()
{
// Assign
var body = new BodyData
{
BodyAsJson = new JObject
{
{ "Id", new JValue(9) },
{ "Name", new JValue("Test") }
}
};
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", "::1", body);
var response = Response.Create()
.WithHeader("Content-Type", "application/json")
.WithBodyAsJson(new { x = "{{#Linq request.bodyAsJson 'new(it.Name + \"_123\" as N, it.Id as I)' }}{{this}}{{/Linq}}" })
.WithTransformer();
// Act
var responseMessage = await response.ProvideResponseAsync(request);
// Assert
JObject j = JObject.FromObject(responseMessage.BodyAsJson);
Check.That(j["x"]).IsNotNull();
Check.That(j["x"].ToString()).Equals("{ N = Test_123, I = 9 }");
}
[Fact]
public void Response_ProvideResponse_Handlebars_Linq_Throws_NotSupportedException()
{
// Assign
var body = new BodyData { BodyAsJson = new { x = "x" }};
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", "::1", body);
var response = Response.Create()
.WithBodyAsJson(new { x = "{{Linq request.bodyAsJson 1}}" })
.WithTransformer();
// Act
Check.ThatAsyncCode(() => response.ProvideResponseAsync(request)).Throws<NotSupportedException>();
}
[Fact]
public void Response_ProvideResponse_Handlebars_Linq1_Throws_ArgumentNullException()
{
// Assign
var body = new BodyData { };
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", "::1", body);
var response = Response.Create()
.WithBodyAsJson(new { x = "{{Linq request.body 'Name'}}" })
.WithTransformer();
// Act
Check.ThatAsyncCode(() => response.ProvideResponseAsync(request)).Throws<ArgumentNullException>();
}
[Fact]
public void Response_ProvideResponse_Handlebars_Linq1_Throws_ArgumentException()
{
// Assign
var body = new BodyData { };
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", "::1", body);
var response = Response.Create()
.WithBodyAsJson(new { x = "{{Linq request.bodyAsJson}} ''" })
.WithTransformer();
// Act
Check.ThatAsyncCode(() => response.ProvideResponseAsync(request)).Throws<ArgumentException>();
}
[Fact]
public async void Response_ProvideResponse_Handlebars_Linq1_ParseError_Returns_Empty()
{
// Assign
var body = new BodyData
{
BodyAsJson = new JObject
{
{ "Id", new JValue(9) },
{ "Name", new JValue("Test") }
}
};
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", "::1", body);
var response = Response.Create()
.WithBodyAsJson(new { x = "{{Linq request.bodyAsJson '---' }}" })
.WithTransformer();
// Act
var responseMessage = await response.ProvideResponseAsync(request);
// Assert
JObject j = JObject.FromObject(responseMessage.BodyAsJson);
Check.That(j["x"].ToString()).IsEmpty();
}
[Fact]
public async void Response_ProvideResponse_Handlebars_Linq2_ParseError_Returns_Empty()
{
// Assign
var body = new BodyData
{
BodyAsJson = new JObject
{
{ "Id", new JValue(9) },
{ "Name", new JValue("Test") }
}
};
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", "::1", body);
var response = Response.Create()
.WithBodyAsJson(new { x = "{{#Linq request.bodyAsJson '---' }}{{this}}{{/Linq}}" })
.WithTransformer();
// Act
var responseMessage = await response.ProvideResponseAsync(request);
// Assert
JObject j = JObject.FromObject(responseMessage.BodyAsJson);
Check.That(j["x"].ToString()).IsEmpty();
}
}
}

View File

@@ -0,0 +1,144 @@
using System;
using NFluent;
using WireMock.Models;
using WireMock.ResponseBuilders;
using WireMock.Util;
using Xunit;
namespace WireMock.Net.Tests.ResponseBuilderTests
{
public class ResponseWithHandlebarsRegexTests
{
private const string ClientIp = "::1";
[Fact]
public async void Response_ProvideResponse_Handlebars_RegexMatch()
{
// Assign
var body = new BodyData { BodyAsString = "abc" };
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body);
var response = Response.Create()
.WithBody("{{Regex.Match request.body \"^(?<x>\\w+)$\"}}")
.WithTransformer();
// Act
var responseMessage = await response.ProvideResponseAsync(request);
// assert
Check.That(responseMessage.Body).Equals("abc");
}
[Fact]
public async void Response_ProvideResponse_Handlebars_RegexMatch_NoMatch()
{
// Assign
var body = new BodyData { BodyAsString = "abc" };
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body);
var response = Response.Create()
.WithBody("{{Regex.Match request.body \"^?0$\"}}")
.WithTransformer();
// Act
var responseMessage = await response.ProvideResponseAsync(request);
// assert
Check.That(responseMessage.Body).Equals("");
}
[Fact]
public async void Response_ProvideResponse_Handlebars_RegexMatch_NoMatch_WithDefaultValue()
{
// Assign
var body = new BodyData { BodyAsString = "abc" };
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body);
var response = Response.Create()
.WithBody("{{Regex.Match request.body \"^?0$\" \"d\"}}")
.WithTransformer();
// Act
var responseMessage = await response.ProvideResponseAsync(request);
// assert
Check.That(responseMessage.Body).Equals("d");
}
[Fact]
public async void Response_ProvideResponse_Handlebars_RegexMatch2()
{
// Assign
var body = new BodyData { BodyAsString = "https://localhost:5000/" };
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body);
var response = Response.Create()
.WithBody("{{#Regex.Match request.body \"^(?<proto>\\w+)://[^/]+?(?<port>\\d+)/?\"}}{{this.port}}-{{this.proto}}{{/Regex.Match}}")
.WithTransformer();
// Act
var responseMessage = await response.ProvideResponseAsync(request);
// assert
Check.That(responseMessage.Body).Equals("5000-https");
}
[Fact]
public async void Response_ProvideResponse_Handlebars_RegexMatch2_NoMatch()
{
// Assign
var body = new BodyData { BodyAsString = "{{\\test" };
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body);
var response = Response.Create()
.WithBody("{{#Regex.Match request.body \"^(?<proto>\\w+)://[^/]+?(?<port>\\d+)/?\"}}{{this}}{{/Regex.Match}}")
.WithTransformer();
// Act
var responseMessage = await response.ProvideResponseAsync(request);
// assert
Check.That(responseMessage.Body).Equals("");
}
[Fact]
public async void Response_ProvideResponse_Handlebars_RegexMatch2_NoMatch_WithDefaultValue()
{
// Assign
var body = new BodyData { BodyAsString = "{{\\test" };
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body);
var response = Response.Create()
.WithBody("{{#Regex.Match request.body \"^(?<proto>\\w+)://[^/]+?(?<port>\\d+)/?\" \"x\"}}{{this}}{{/Regex.Match}}")
.WithTransformer();
// Act
var responseMessage = await response.ProvideResponseAsync(request);
// assert
Check.That(responseMessage.Body).Equals("x");
}
[Fact]
public void Response_ProvideResponse_Handlebars_RegexMatch2_Throws()
{
// Assign
var body = new BodyData { BodyAsString = "{{\\test" };
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body);
var response = Response.Create()
.WithBody("{{#Regex.Match request.bodyAsJson \"^(?<proto>\\w+)://[^/]+?(?<port>\\d+)/?\"}}{{/Regex.Match}}")
.WithTransformer();
// Act and Assert
Check.ThatAsyncCode(() => response.ProvideResponseAsync(request)).Throws<NotSupportedException>();
}
}
}

View File

@@ -8,7 +8,6 @@ using Microsoft.Owin;
using Microsoft.AspNetCore.Http;
#endif
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using NFluent;
using WireMock.Models;
using WireMock.ResponseBuilders;
@@ -186,444 +185,6 @@ namespace WireMock.Net.Tests.ResponseBuilderTests
Check.That(responseMessage.Body).Equals("test http://localhost:1234 1234 http localhost");
}
[Fact]
public async Task Response_ProvideResponse_Handlebars_JsonPath_SelectToken_Object_ResponseBodyAsJson()
{
// Assign
var body = new BodyData
{
BodyAsString = @"{
""Stores"": [
""Lambton Quay"",
""Willis Street""
],
""Manufacturers"": [
{
""Name"": ""Acme Co"",
""Products"": [
{
""Name"": ""Anvil"",
""Price"": 50
}
]
},
{
""Name"": ""Contoso"",
""Products"": [
{
""Name"": ""Elbow Grease"",
""Price"": 99.95
},
{
""Name"": ""Headlight Fluid"",
""Price"": 4
}
]
}
]
}"
};
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body);
var response = Response.Create()
.WithHeader("Content-Type", "application/json")
.WithBodyAsJson(new { x = "{{JsonPath.SelectToken request.body \"$.Manufacturers[?(@.Name == 'Acme Co')]\"}}" })
.WithTransformer();
// Act
var responseMessage = await response.ProvideResponseAsync(request);
// Assert
JObject j = JObject.FromObject(responseMessage.BodyAsJson);
Check.That(j["x"]).IsNotNull();
Check.That(j["x"]["Name"].ToString()).Equals("Acme Co");
}
[Fact]
public async Task Response_ProvideResponse_Handlebars_JsonPath_SelectToken_Number_ResponseBodyAsJson()
{
// Assign
var body = new BodyData { BodyAsString = "{ \"Price\": 99 }" };
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body);
var response = Response.Create()
.WithHeader("Content-Type", "application/json")
.WithBodyAsJson(new { x = "{{JsonPath.SelectToken request.body \"..Price\"}}" })
.WithTransformer();
// Act
var responseMessage = await response.ProvideResponseAsync(request);
// Assert
JObject j = JObject.FromObject(responseMessage.BodyAsJson);
Check.That(j["x"].Value<long>()).Equals(99);
}
[Fact]
public async Task Response_ProvideResponse_Handlebars_JsonPath_SelectToken_Request_BodyAsString()
{
// Assign
var body = new BodyData
{
BodyAsString = @"{
""Stores"": [
""Lambton Quay"",
""Willis Street""
],
""Manufacturers"": [
{
""Name"": ""Acme Co"",
""Products"": [
{
""Name"": ""Anvil"",
""Price"": 50
}
]
},
{
""Name"": ""Contoso"",
""Products"": [
{
""Name"": ""Elbow Grease"",
""Price"": 99.95
},
{
""Name"": ""Headlight Fluid"",
""Price"": 4
}
]
}
]
}"
};
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body);
var response = Response.Create()
.WithHeader("Content-Type", "application/json")
.WithBody("{{JsonPath.SelectToken request.body \"$.Manufacturers[?(@.Name == 'Acme Co')]\"}}")
.WithTransformer();
// Act
var responseMessage = await response.ProvideResponseAsync(request);
// Assert
Check.That(responseMessage.Body).Equals("{\r\n \"Name\": \"Acme Co\",\r\n \"Products\": [\r\n {\r\n \"Name\": \"Anvil\",\r\n \"Price\": 50\r\n }\r\n ]\r\n}");
}
[Fact]
public async Task Response_ProvideResponse_Handlebars_JsonPath_SelectToken_Request_BodyAsJObject()
{
// Assign
var body = new BodyData
{
BodyAsJson = JObject.Parse(@"{
'Stores': [
'Lambton Quay',
'Willis Street'
],
'Manufacturers': [
{
'Name': 'Acme Co',
'Products': [
{
'Name': 'Anvil',
'Price': 50
}
]
},
{
'Name': 'Contoso',
'Products': [
{
'Name': 'Elbow Grease',
'Price': 99.95
},
{
'Name': 'Headlight Fluid',
'Price': 4
}
]
}
]
}")
};
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body);
var response = Response.Create()
.WithHeader("Content-Type", "application/json")
.WithBody("{{JsonPath.SelectToken request.bodyAsJson \"$.Manufacturers[?(@.Name == 'Acme Co')]\"}}")
.WithTransformer();
// Act
var responseMessage = await response.ProvideResponseAsync(request);
// Assert
Check.That(responseMessage.Body).Equals("{\r\n \"Name\": \"Acme Co\",\r\n \"Products\": [\r\n {\r\n \"Name\": \"Anvil\",\r\n \"Price\": 50\r\n }\r\n ]\r\n}");
}
[Fact]
public async Task Response_ProvideResponse_Handlebars_JsonPath_SelectTokens_Request_BodyAsString()
{
// Assign
var body = new BodyData
{
BodyAsString = @"{
""Stores"": [
""Lambton Quay"",
""Willis Street""
],
""Manufacturers"": [
{
""Name"": ""Acme Co"",
""Products"": [
{
""Name"": ""Anvil"",
""Price"": 50
}
]
},
{
""Name"": ""Contoso"",
""Products"": [
{
""Name"": ""Elbow Grease"",
""Price"": 99.95
},
{
""Name"": ""Headlight Fluid"",
""Price"": 4
}
]
}
]
}"
};
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body);
var response = Response.Create()
.WithHeader("Content-Type", "application/json")
.WithBody("{{#JsonPath.SelectTokens request.body \"$..Products[?(@.Price >= 50)].Name\"}}{{id}} {{value}},{{/JsonPath.SelectTokens}}")
.WithTransformer();
// Act
var responseMessage = await response.ProvideResponseAsync(request);
// Assert
Check.That(responseMessage.Body).Equals("0 Anvil,1 Elbow Grease,");
}
[Fact]
public async Task Response_ProvideResponse_Handlebars_JsonPath_SelectTokens_Request_BodyAsJObject()
{
// Assign
var body = new BodyData
{
BodyAsJson = JObject.Parse(@"{
'Stores': [
'Lambton Quay',
'Willis Street'
],
'Manufacturers': [
{
'Name': 'Acme Co',
'Products': [
{
'Name': 'Anvil',
'Price': 50
}
]
},
{
'Name': 'Contoso',
'Products': [
{
'Name': 'Elbow Grease',
'Price': 99.95
},
{
'Name': 'Headlight Fluid',
'Price': 4
}
]
}
]
}")
};
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body);
var response = Response.Create()
.WithHeader("Content-Type", "application/json")
.WithBody("{{#JsonPath.SelectTokens request.bodyAsJson \"$..Products[?(@.Price >= 50)].Name\"}}{{id}} {{value}},{{/JsonPath.SelectTokens}}")
.WithTransformer();
// Act
var responseMessage = await response.ProvideResponseAsync(request);
// Assert
Check.That(responseMessage.Body).Equals("0 Anvil,1 Elbow Grease,");
}
[Fact]
public void Response_ProvideResponse_Handlebars_JsonPath_SelectTokens_Throws()
{
// Assign
var body = new BodyData
{
BodyAsJson = JObject.Parse(@"{
'Stores': [
'Lambton Quay',
'Willis Street'
]
}")
};
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body);
var response = Response.Create()
.WithHeader("Content-Type", "application/json")
.WithBody("{{#JsonPath.SelectTokens request.body \"$..Products[?(@.Price >= 50)].Name\"}}{{id}} {{value}},{{/JsonPath.SelectTokens}}")
.WithTransformer();
// Act
Check.ThatAsyncCode(() => response.ProvideResponseAsync(request)).Throws<ArgumentNullException>();
}
[Fact]
public async void Response_ProvideResponse_Handlebars_RegexMatch1()
{
// Assign
var body = new BodyData { BodyAsString = "abc" };
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body);
var response = Response.Create()
.WithBody("{{Regex.Match request.body \"^(?<x>\\w+)$\"}}")
.WithTransformer();
// Act
var responseMessage = await response.ProvideResponseAsync(request);
// assert
Check.That(responseMessage.Body).Equals("abc");
}
[Fact]
public async void Response_ProvideResponse_Handlebars_RegexMatch1_NoMatch()
{
// Assign
var body = new BodyData { BodyAsString = "abc" };
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body);
var response = Response.Create()
.WithBody("{{Regex.Match request.body \"^?0$\"}}")
.WithTransformer();
// Act
var responseMessage = await response.ProvideResponseAsync(request);
// assert
Check.That(responseMessage.Body).Equals("");
}
[Fact]
public async void Response_ProvideResponse_Handlebars_RegexMatch1_NoMatch_WithDefaultValue()
{
// Assign
var body = new BodyData { BodyAsString = "abc" };
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body);
var response = Response.Create()
.WithBody("{{Regex.Match request.body \"^?0$\" \"d\"}}")
.WithTransformer();
// Act
var responseMessage = await response.ProvideResponseAsync(request);
// assert
Check.That(responseMessage.Body).Equals("d");
}
[Fact]
public async void Response_ProvideResponse_Handlebars_RegexMatch2()
{
// Assign
var body = new BodyData { BodyAsString = "https://localhost:5000/" };
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body);
var response = Response.Create()
.WithBody("{{#Regex.Match request.body \"^(?<proto>\\w+)://[^/]+?(?<port>\\d+)/?\"}}{{this.port}}-{{this.proto}}{{/Regex.Match}}")
.WithTransformer();
// Act
var responseMessage = await response.ProvideResponseAsync(request);
// assert
Check.That(responseMessage.Body).Equals("5000-https");
}
[Fact]
public async void Response_ProvideResponse_Handlebars_RegexMatch2_NoMatch()
{
// Assign
var body = new BodyData { BodyAsString = "{{\\test" };
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body);
var response = Response.Create()
.WithBody("{{#Regex.Match request.body \"^(?<proto>\\w+)://[^/]+?(?<port>\\d+)/?\"}}{{this}}{{/Regex.Match}}")
.WithTransformer();
// Act
var responseMessage = await response.ProvideResponseAsync(request);
// assert
Check.That(responseMessage.Body).Equals("");
}
[Fact]
public async void Response_ProvideResponse_Handlebars_RegexMatch2_NoMatch_WithDefaultValue()
{
// Assign
var body = new BodyData { BodyAsString = "{{\\test" };
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body);
var response = Response.Create()
.WithBody("{{#Regex.Match request.body \"^(?<proto>\\w+)://[^/]+?(?<port>\\d+)/?\" \"x\"}}{{this}}{{/Regex.Match}}")
.WithTransformer();
// Act
var responseMessage = await response.ProvideResponseAsync(request);
// assert
Check.That(responseMessage.Body).Equals("x");
}
[Fact]
public void Response_ProvideResponse_Handlebars_RegexMatch_Throws()
{
// Assign
var body = new BodyData { BodyAsString = "{{\\test" };
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body);
var response = Response.Create()
.WithBody("{{#Regex.Match request.bodyAsJson \"^(?<proto>\\w+)://[^/]+?(?<port>\\d+)/?\"}}{{/Regex.Match}}")
.WithTransformer();
// Act and Assert
Check.ThatAsyncCode(() => response.ProvideResponseAsync(request)).Throws<NotSupportedException>();
}
[Fact]
public async Task Response_ProvideResponse_Handlebars_WithBodyAsJson_ResultAsArray()
{

View File

@@ -11,7 +11,37 @@ namespace WireMock.Net.Tests.Util
public class JsonUtilsTests
{
[Fact]
public void JsonUtils_GenerateDynamicLinqStatement()
public void JsonUtils_ParseJTokenToObject()
{
// Assign
object value = "test";
// Act
string result = JsonUtils.ParseJTokenToObject<string>(value);
// Assert
Check.That(result).IsEqualTo(default(string));
}
[Fact]
public void JsonUtils_GenerateDynamicLinqStatement_JToken()
{
// Assign
JToken j = "Test";
// Act
string line = JsonUtils.GenerateDynamicLinqStatement(j);
// Assert
var queryable = new[] { j }.AsQueryable().Select(line);
bool result = queryable.Any("it == \"Test\"");
Check.That(result).IsTrue();
Check.That(line).IsEqualTo("string(it)");
}
[Fact]
public void JsonUtils_GenerateDynamicLinqStatement_JObject()
{
// Assign
var j = new JObject
@@ -39,7 +69,7 @@ namespace WireMock.Net.Tests.Util
string line = JsonUtils.GenerateDynamicLinqStatement(j);
// Assert
var queryable = new[] {j}.AsQueryable().Select(line);
var queryable = new[] { j }.AsQueryable().Select(line);
bool result = queryable.Any("Id > 4");
Check.That(result).IsTrue();