mirror of
https://github.com/wiremock/WireMock.Net.git
synced 2026-03-11 21:12:16 +01:00
C# code generator improvements (#933)
* Escape quotes in generated C# strings * Handle response with JSON body in C# code generator
This commit is contained in:
@@ -5,6 +5,7 @@ using System.Net;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Stef.Validation;
|
||||
using WireMock.Admin.Mappings;
|
||||
using WireMock.Constants;
|
||||
@@ -143,13 +144,26 @@ internal class MappingConverter
|
||||
}
|
||||
}
|
||||
|
||||
if (response.ResponseMessage.BodyData is { })
|
||||
if (response.ResponseMessage.BodyData is { } bodyData)
|
||||
{
|
||||
switch (response.ResponseMessage.BodyData.DetectedBodyType)
|
||||
{
|
||||
case BodyType.String:
|
||||
case BodyType.FormUrlEncoded:
|
||||
sb.AppendLine($" .WithBody(\"{response.ResponseMessage.BodyData.BodyAsString}\")");
|
||||
sb.AppendLine($" .WithBody(\"{EscapeCSharpString(bodyData.BodyAsString)}\")");
|
||||
break;
|
||||
case BodyType.Json:
|
||||
if (bodyData.BodyAsJson is string bodyStringValue)
|
||||
{
|
||||
sb.AppendLine($" .WithBody(\"{EscapeCSharpString(bodyStringValue)}\")");
|
||||
}
|
||||
else
|
||||
{
|
||||
var serializedBody = JsonConvert.SerializeObject(bodyData.BodyAsJson);
|
||||
var deserializedBody = JToken.Parse(serializedBody);
|
||||
sb.AppendLine($" .WithBodyAsJson({ConvertJsonToAnonymousObjectDefinition(deserializedBody, 2)})");
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -173,6 +187,50 @@ internal class MappingConverter
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
private string ConvertJsonToAnonymousObjectDefinition(JToken token, int ind = 0)
|
||||
{
|
||||
string FormatObject(JObject jObject)
|
||||
{
|
||||
var indStr = new string(' ', 4 * ind);
|
||||
var indStrSub = new string(' ', 4 * (ind + 1));
|
||||
var items = jObject.Properties().Select(x => ConvertJsonToAnonymousObjectDefinition(x, ind + 1));
|
||||
return $"new\r\n{indStr}{{\r\n{indStrSub}{string.Join($",\r\n{indStrSub}", items)}\r\n{indStr}}}";
|
||||
}
|
||||
|
||||
string FormatArray(JArray jArray, int ind)
|
||||
{
|
||||
var hasComplexItems = jArray.FirstOrDefault() is JObject or JArray;
|
||||
var items = jArray.Select(x => ConvertJsonToAnonymousObjectDefinition(x, hasComplexItems ? ind + 1 : ind));
|
||||
if (hasComplexItems)
|
||||
{
|
||||
var indStr = new string(' ', 4 * ind);
|
||||
var indStrSub = new string(' ', 4 * (ind + 1));
|
||||
return $"new []\r\n{indStr}{{\r\n{indStrSub}{string.Join($",\r\n{indStrSub}", items)}\r\n{indStr}}}";
|
||||
}
|
||||
|
||||
return $"new [] {{ {string.Join(", ", items)} }}";
|
||||
}
|
||||
|
||||
return token switch
|
||||
{
|
||||
JArray jArray => FormatArray(jArray, ind),
|
||||
JObject jObject => FormatObject(jObject),
|
||||
JProperty jProperty => $"{jProperty.Name} = {ConvertJsonToAnonymousObjectDefinition(jProperty.Value, ind)}",
|
||||
JValue jValue => jValue.Type switch
|
||||
{
|
||||
JTokenType.None => "null",
|
||||
JTokenType.Integer => jValue.Value?.ToString() ?? "null",
|
||||
JTokenType.Float => jValue.Value?.ToString() ?? "null",
|
||||
JTokenType.String => $"\"{EscapeCSharpString(jValue.Value?.ToString())}\"",
|
||||
JTokenType.Boolean => jValue.Value?.ToString().ToLower() ?? "null",
|
||||
JTokenType.Null => "null",
|
||||
JTokenType.Undefined => "null",
|
||||
_ => $"UNHANDLED_CASE: {jValue.Type}"
|
||||
},
|
||||
_ => $"UNHANDLED_CASE: {token}"
|
||||
};
|
||||
}
|
||||
|
||||
public MappingModel ToMappingModel(IMapping mapping)
|
||||
{
|
||||
var request = (Request)mapping.RequestMatcher;
|
||||
@@ -445,9 +503,11 @@ internal class MappingConverter
|
||||
|
||||
private static string ToValueArguments(string[]? values, string defaultValue = "")
|
||||
{
|
||||
return values is { } ? string.Join(", ", values.Select(v => $"\"{v}\"")) : $"\"{defaultValue}\"";
|
||||
return values is { } ? string.Join(", ", values.Select(v => $"\"{EscapeCSharpString(v)}\"")) : $"\"{EscapeCSharpString(defaultValue)}\"";
|
||||
}
|
||||
|
||||
private static string? EscapeCSharpString(string? value) => value?.Replace("\"", "\\\"");
|
||||
|
||||
private static WebProxyModel? MapWebProxy(WebProxySettings? settings)
|
||||
{
|
||||
return settings != null ? new WebProxyModel
|
||||
|
||||
@@ -16,11 +16,13 @@ server
|
||||
.UsingMethod("POST")
|
||||
.WithPath("/foo2")
|
||||
.WithParam("p2", "abc")
|
||||
.WithHeader("h1", "W/\"234f2q3r\"", true)
|
||||
)
|
||||
.WithGuid("1b731398-4a5b-457f-a6e3-d65e541c428f")
|
||||
.RespondWith(Response.Create()
|
||||
.WithStatusCode("201")
|
||||
.WithHeader("hk", "hv")
|
||||
.WithHeader("ETag", "W/\"168d8e\"")
|
||||
.WithBody("2")
|
||||
);
|
||||
|
||||
@@ -32,5 +34,32 @@ server
|
||||
.WithGuid("f74fd144-df53-404f-8e35-da22a640bd5f")
|
||||
.RespondWith(Response.Create()
|
||||
.WithStatusCode(208)
|
||||
.WithBodyAsJson(new
|
||||
{
|
||||
a = 1,
|
||||
b = 1.2,
|
||||
d = true,
|
||||
e = false,
|
||||
f = new [] { 1, 2, 3, 4 },
|
||||
g = new
|
||||
{
|
||||
z1 = 1,
|
||||
z2 = 2,
|
||||
z3 = new [] { "a", "b", "c" },
|
||||
z4 = new []
|
||||
{
|
||||
new
|
||||
{
|
||||
a = 1,
|
||||
b = 2
|
||||
},
|
||||
new
|
||||
{
|
||||
a = 2,
|
||||
b = 3
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
|
||||
@@ -740,6 +740,7 @@ public class WireMockAdminApiTests
|
||||
Request.Create()
|
||||
.WithPath("/foo2")
|
||||
.WithParam("p2", "abc")
|
||||
.WithHeader("h1", "W/\"234f2q3r\"")
|
||||
.UsingPost()
|
||||
)
|
||||
.WithGuid(guid2)
|
||||
@@ -747,6 +748,7 @@ public class WireMockAdminApiTests
|
||||
Response.Create()
|
||||
.WithStatusCode("201")
|
||||
.WithHeader("hk", "hv")
|
||||
.WithHeader("ETag", "W/\"168d8e\"")
|
||||
.WithBody("2")
|
||||
);
|
||||
|
||||
@@ -760,7 +762,7 @@ public class WireMockAdminApiTests
|
||||
.RespondWith(
|
||||
Response.Create()
|
||||
.WithStatusCode(HttpStatusCode.AlreadyReported)
|
||||
.WithBodyAsJson(new { x = 1 })
|
||||
.WithBodyAsJson(new { a = 1, b=1.2, d=true, e=false, f=new[]{1,2,3,4}, g= new{z1=1, z2=2, z3=new []{"a","b","c"}, z4=new[]{new {a=1, b=2},new {a=2, b=3}}} })
|
||||
);
|
||||
|
||||
// Act
|
||||
|
||||
Reference in New Issue
Block a user