mirror of
https://github.com/wiremock/WireMock.Net.git
synced 2026-04-21 08:21:53 +02:00
Add ReplaceNodeOption flag (#710)
This commit is contained in:
@@ -1,19 +1,17 @@
|
|||||||
using Newtonsoft.Json;
|
|
||||||
using HandlebarsDotNet;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Newtonsoft.Json;
|
||||||
using WireMock.Logging;
|
using WireMock.Logging;
|
||||||
using WireMock.Matchers;
|
using WireMock.Matchers;
|
||||||
using WireMock.RequestBuilders;
|
using WireMock.RequestBuilders;
|
||||||
using WireMock.ResponseBuilders;
|
using WireMock.ResponseBuilders;
|
||||||
using WireMock.Server;
|
using WireMock.Server;
|
||||||
using WireMock.Settings;
|
using WireMock.Settings;
|
||||||
using WireMock.Util;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using WireMock.Types;
|
using WireMock.Types;
|
||||||
|
using WireMock.Util;
|
||||||
|
|
||||||
namespace WireMock.Net.ConsoleApplication
|
namespace WireMock.Net.ConsoleApplication
|
||||||
{
|
{
|
||||||
@@ -359,7 +357,7 @@ namespace WireMock.Net.ConsoleApplication
|
|||||||
.WithHeader("Transformed-Postman-Token", "token is {{request.headers.Postman-Token}}")
|
.WithHeader("Transformed-Postman-Token", "token is {{request.headers.Postman-Token}}")
|
||||||
.WithHeader("xyz_{{request.headers.Postman-Token}}", "token is {{request.headers.Postman-Token}}")
|
.WithHeader("xyz_{{request.headers.Postman-Token}}", "token is {{request.headers.Postman-Token}}")
|
||||||
.WithBody(@"{""msg"": ""Hello world CATCH-ALL on /*, {{request.path}}, add={{Math.Add request.query.start.[0] 42}} bykey={{request.query.start}}, bykey={{request.query.stop}}, byidx0={{request.query.stop.[0]}}, byidx1={{request.query.stop.[1]}}"" }")
|
.WithBody(@"{""msg"": ""Hello world CATCH-ALL on /*, {{request.path}}, add={{Math.Add request.query.start.[0] 42}} bykey={{request.query.start}}, bykey={{request.query.stop}}, byidx0={{request.query.stop.[0]}}, byidx1={{request.query.stop.[1]}}"" }")
|
||||||
.WithTransformer(TransformerType.Handlebars)
|
.WithTransformer(TransformerType.Handlebars, true, ReplaceNodeOptions.None)
|
||||||
.WithDelay(TimeSpan.FromMilliseconds(100))
|
.WithDelay(TimeSpan.FromMilliseconds(100))
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace WireMock.Admin.Mappings
|
namespace WireMock.Admin.Mappings
|
||||||
{
|
{
|
||||||
@@ -64,10 +64,15 @@ namespace WireMock.Admin.Mappings
|
|||||||
public string TransformerType { get; set; }
|
public string TransformerType { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Use the Handlerbars transformer for the content from the referenced BodyAsFile.
|
/// Use the Handlebars transformer for the content from the referenced BodyAsFile.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool? UseTransformerForBodyAsFile { get; set; }
|
public bool? UseTransformerForBodyAsFile { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The ReplaceNodeOptions to use when transforming a JSON node.
|
||||||
|
/// </summary>
|
||||||
|
public string TransformerReplaceNodeOptions { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the headers.
|
/// Gets or sets the headers.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using WireMock.Types;
|
||||||
|
|
||||||
namespace WireMock.Admin.Mappings
|
namespace WireMock.Admin.Mappings
|
||||||
{
|
{
|
||||||
@@ -42,5 +43,10 @@ namespace WireMock.Admin.Mappings
|
|||||||
/// Gets the type of the transformer.
|
/// Gets the type of the transformer.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string TransformerType { get; set; }
|
public string TransformerType { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The ReplaceNodeOptions to use when transforming a JSON node.
|
||||||
|
/// </summary>
|
||||||
|
public string TransformerReplaceNodeOptions { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,13 +1,13 @@
|
|||||||
namespace WireMock.Models
|
namespace WireMock.Models
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// IWebhook
|
/// IWebhook
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IWebhook
|
public interface IWebhook
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Request
|
/// Request
|
||||||
/// </summary>
|
/// </summary>
|
||||||
IWebhookRequest Request { get; set; }
|
IWebhookRequest Request { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,42 +1,47 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using WireMock.Types;
|
using WireMock.Types;
|
||||||
using WireMock.Util;
|
using WireMock.Util;
|
||||||
|
|
||||||
namespace WireMock.Models
|
namespace WireMock.Models
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// IWebhookRequest
|
/// IWebhookRequest
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IWebhookRequest
|
public interface IWebhookRequest
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The Webhook Url.
|
/// The Webhook Url.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
string Url { get; set; }
|
string Url { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The method to use.
|
/// The method to use.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
string Method { get; set; }
|
string Method { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The Headers to send.
|
/// The Headers to send.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
IDictionary<string, WireMockList<string>> Headers { get; }
|
IDictionary<string, WireMockList<string>> Headers { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The body to send.
|
/// The body to send.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
IBodyData BodyData { get; set; }
|
IBodyData BodyData { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Use Transformer.
|
/// Use Transformer.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
bool? UseTransformer { get; set; }
|
bool? UseTransformer { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The transformer type.
|
/// The transformer type.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
TransformerType TransformerType { get; set; }
|
TransformerType TransformerType { get; set; }
|
||||||
}
|
|
||||||
|
/// <summary>
|
||||||
|
/// The ReplaceNodeOptions to use when transforming a JSON node.
|
||||||
|
/// </summary>
|
||||||
|
ReplaceNodeOptions TransformerReplaceNodeOptions { get; set; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
36
src/WireMock.Net.Abstractions/Types/ReplaceNodeOptions.cs
Normal file
36
src/WireMock.Net.Abstractions/Types/ReplaceNodeOptions.cs
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace WireMock.Types
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Flags to use when replace a JSON node using the Transformer.
|
||||||
|
/// </summary>
|
||||||
|
[Flags]
|
||||||
|
public enum ReplaceNodeOptions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Default
|
||||||
|
/// </summary>
|
||||||
|
None = 0
|
||||||
|
|
||||||
|
///// <summary>
|
||||||
|
///// Replace boolean string value to a real boolean value. (This is used by default to maintain backward compatibility.)
|
||||||
|
///// </summary>
|
||||||
|
//Bool = 0b00000001,
|
||||||
|
|
||||||
|
///// <summary>
|
||||||
|
///// Replace integer string value to a real integer value.
|
||||||
|
///// </summary>
|
||||||
|
//Integer = 0b00000010,
|
||||||
|
|
||||||
|
///// <summary>
|
||||||
|
///// Replace long string value to a real long value.
|
||||||
|
///// </summary>
|
||||||
|
//Long = 0b00000100,
|
||||||
|
|
||||||
|
///// <summary>
|
||||||
|
///// Replace all string values to a real values.
|
||||||
|
///// </summary>
|
||||||
|
//All = Bool | Integer | Long
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
@@ -55,7 +55,7 @@ namespace WireMock.Http
|
|||||||
throw new NotImplementedException($"TransformerType '{request.TransformerType}' is not supported.");
|
throw new NotImplementedException($"TransformerType '{request.TransformerType}' is not supported.");
|
||||||
}
|
}
|
||||||
|
|
||||||
(bodyData, headers) = responseMessageTransformer.Transform(originalRequestMessage, originalResponseMessage, request.BodyData, request.Headers);
|
(bodyData, headers) = responseMessageTransformer.Transform(originalRequestMessage, originalResponseMessage, request.BodyData, request.Headers, request.TransformerReplaceNodeOptions);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using WireMock.Types;
|
using WireMock.Types;
|
||||||
using WireMock.Util;
|
using WireMock.Util;
|
||||||
|
|
||||||
@@ -26,5 +26,8 @@ namespace WireMock.Models
|
|||||||
|
|
||||||
/// <inheritdoc cref="IWebhookRequest.TransformerType"/>
|
/// <inheritdoc cref="IWebhookRequest.TransformerType"/>
|
||||||
public TransformerType TransformerType { get; set; }
|
public TransformerType TransformerType { get; set; }
|
||||||
|
|
||||||
|
/// <inheritdoc cref="IWebhookRequest.TransformerReplaceNodeOptions"/>
|
||||||
|
public ReplaceNodeOptions TransformerReplaceNodeOptions { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,13 +1,13 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using WireMock.Logging;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Stef.Validation;
|
||||||
|
using WireMock.Logging;
|
||||||
using WireMock.Matchers;
|
using WireMock.Matchers;
|
||||||
using WireMock.Http;
|
using WireMock.Http;
|
||||||
using WireMock.Owin.Mappers;
|
using WireMock.Owin.Mappers;
|
||||||
using WireMock.Serialization;
|
using WireMock.Serialization;
|
||||||
using WireMock.Types;
|
using WireMock.Types;
|
||||||
using Stef.Validation;
|
|
||||||
using WireMock.ResponseBuilders;
|
using WireMock.ResponseBuilders;
|
||||||
using WireMock.Settings;
|
using WireMock.Settings;
|
||||||
#if !USE_ASPNETCORE
|
#if !USE_ASPNETCORE
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using WireMock.Types;
|
using WireMock.Types;
|
||||||
|
|
||||||
namespace WireMock.ResponseBuilders
|
namespace WireMock.ResponseBuilders
|
||||||
{
|
{
|
||||||
@@ -13,7 +13,15 @@ namespace WireMock.ResponseBuilders
|
|||||||
/// <returns>
|
/// <returns>
|
||||||
/// The <see cref="IResponseBuilder"/>.
|
/// The <see cref="IResponseBuilder"/>.
|
||||||
/// </returns>
|
/// </returns>
|
||||||
IResponseBuilder WithTransformer(bool transformContentFromBodyAsFile = false);
|
IResponseBuilder WithTransformer(bool transformContentFromBodyAsFile);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use the Handlebars.Net ResponseMessage transformer.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>
|
||||||
|
/// The <see cref="IResponseBuilder"/>.
|
||||||
|
/// </returns>
|
||||||
|
IResponseBuilder WithTransformer(ReplaceNodeOptions options);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Use a specific ResponseMessage transformer.
|
/// Use a specific ResponseMessage transformer.
|
||||||
@@ -21,6 +29,6 @@ namespace WireMock.ResponseBuilders
|
|||||||
/// <returns>
|
/// <returns>
|
||||||
/// The <see cref="IResponseBuilder"/>.
|
/// The <see cref="IResponseBuilder"/>.
|
||||||
/// </returns>
|
/// </returns>
|
||||||
IResponseBuilder WithTransformer(TransformerType transformerType, bool transformContentFromBodyAsFile = false);
|
IResponseBuilder WithTransformer(TransformerType transformerType = TransformerType.Handlebars, bool transformContentFromBodyAsFile = false, ReplaceNodeOptions options = ReplaceNodeOptions.None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -8,6 +8,7 @@ using System.Text;
|
|||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
|
using Stef.Validation;
|
||||||
using WireMock.Proxy;
|
using WireMock.Proxy;
|
||||||
using WireMock.ResponseProviders;
|
using WireMock.ResponseProviders;
|
||||||
using WireMock.Settings;
|
using WireMock.Settings;
|
||||||
@@ -16,7 +17,6 @@ using WireMock.Transformers.Handlebars;
|
|||||||
using WireMock.Transformers.Scriban;
|
using WireMock.Transformers.Scriban;
|
||||||
using WireMock.Types;
|
using WireMock.Types;
|
||||||
using WireMock.Util;
|
using WireMock.Util;
|
||||||
using Stef.Validation;
|
|
||||||
|
|
||||||
namespace WireMock.ResponseBuilders
|
namespace WireMock.ResponseBuilders
|
||||||
{
|
{
|
||||||
@@ -68,10 +68,15 @@ namespace WireMock.ResponseBuilders
|
|||||||
public TransformerType TransformerType { get; private set; }
|
public TransformerType TransformerType { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a value indicating whether to use the Handlerbars transformer for the content from the referenced BodyAsFile.
|
/// Gets a value indicating whether to use the Handlebars transformer for the content from the referenced BodyAsFile.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool UseTransformerForBodyAsFile { get; private set; }
|
public bool UseTransformerForBodyAsFile { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the ReplaceNodeOptions to use when transforming a JSON node.
|
||||||
|
/// </summary>
|
||||||
|
public ReplaceNodeOptions TransformerReplaceNodeOptions { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the response message.
|
/// Gets the response message.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -330,20 +335,26 @@ namespace WireMock.ResponseBuilders
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc cref="ITransformResponseBuilder.WithTransformer(bool)"/>
|
/// <inheritdoc cref="ITransformResponseBuilder.WithTransformer(bool)"/>
|
||||||
public IResponseBuilder WithTransformer(bool transformContentFromBodyAsFile = false)
|
public IResponseBuilder WithTransformer(bool transformContentFromBodyAsFile)
|
||||||
{
|
{
|
||||||
UseTransformer = true;
|
return WithTransformer(TransformerType.Handlebars, transformContentFromBodyAsFile);
|
||||||
TransformerType = TransformerType.Handlebars;
|
|
||||||
UseTransformerForBodyAsFile = transformContentFromBodyAsFile;
|
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc cref="ITransformResponseBuilder.WithTransformer(TransformerType, bool)"/>
|
/// <inheritdoc cref="ITransformResponseBuilder.WithTransformer(ReplaceNodeOptions)"/>
|
||||||
public IResponseBuilder WithTransformer(TransformerType transformerType, bool transformContentFromBodyAsFile = false)
|
public IResponseBuilder WithTransformer(ReplaceNodeOptions options)
|
||||||
|
{
|
||||||
|
return WithTransformer(TransformerType.Handlebars, false, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma warning disable CS1574
|
||||||
|
/// <inheritdoc cref="ITransformResponseBuilder.WithTransformer(TransformerType, bool, ReplaceNodeOptions)"/>
|
||||||
|
#pragma warning restore CS1574
|
||||||
|
public IResponseBuilder WithTransformer(TransformerType transformerType, bool transformContentFromBodyAsFile = false, ReplaceNodeOptions options = ReplaceNodeOptions.None)
|
||||||
{
|
{
|
||||||
UseTransformer = true;
|
UseTransformer = true;
|
||||||
TransformerType = transformerType;
|
TransformerType = transformerType;
|
||||||
UseTransformerForBodyAsFile = transformContentFromBodyAsFile;
|
UseTransformerForBodyAsFile = transformContentFromBodyAsFile;
|
||||||
|
TransformerReplaceNodeOptions = options;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -458,7 +469,7 @@ namespace WireMock.ResponseBuilders
|
|||||||
throw new NotImplementedException($"TransformerType '{TransformerType}' is not supported.");
|
throw new NotImplementedException($"TransformerType '{TransformerType}' is not supported.");
|
||||||
}
|
}
|
||||||
|
|
||||||
return (responseMessageTransformer.Transform(requestMessage, responseMessage, UseTransformerForBodyAsFile), null);
|
return (responseMessageTransformer.Transform(requestMessage, responseMessage, UseTransformerForBodyAsFile, TransformerReplaceNodeOptions), null);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!UseTransformer && ResponseMessage.BodyData?.BodyAsFileIsCached == true)
|
if (!UseTransformer && ResponseMessage.BodyData?.BodyAsFileIsCached == true)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Stef.Validation;
|
||||||
using WireMock.Admin.Mappings;
|
using WireMock.Admin.Mappings;
|
||||||
using WireMock.Matchers.Request;
|
using WireMock.Matchers.Request;
|
||||||
using WireMock.RequestBuilders;
|
using WireMock.RequestBuilders;
|
||||||
@@ -16,7 +16,7 @@ namespace WireMock.Serialization
|
|||||||
|
|
||||||
public MappingConverter(MatcherMapper mapper)
|
public MappingConverter(MatcherMapper mapper)
|
||||||
{
|
{
|
||||||
_mapper = mapper ?? throw new ArgumentNullException(nameof(mapper));
|
_mapper = Guard.NotNull(mapper, nameof(mapper));
|
||||||
}
|
}
|
||||||
|
|
||||||
public MappingModel ToMappingModel(IMapping mapping)
|
public MappingModel ToMappingModel(IMapping mapping)
|
||||||
@@ -130,6 +130,7 @@ namespace WireMock.Serialization
|
|||||||
mappingModel.Response.UseTransformer = null;
|
mappingModel.Response.UseTransformer = null;
|
||||||
mappingModel.Response.TransformerType = null;
|
mappingModel.Response.TransformerType = null;
|
||||||
mappingModel.Response.UseTransformerForBodyAsFile = null;
|
mappingModel.Response.UseTransformerForBodyAsFile = null;
|
||||||
|
mappingModel.Response.TransformerReplaceNodeOptions = null;
|
||||||
mappingModel.Response.BodyEncoding = null;
|
mappingModel.Response.BodyEncoding = null;
|
||||||
mappingModel.Response.ProxyUrl = response.ProxyAndRecordSettings.Url;
|
mappingModel.Response.ProxyUrl = response.ProxyAndRecordSettings.Url;
|
||||||
mappingModel.Response.Fault = null;
|
mappingModel.Response.Fault = null;
|
||||||
@@ -150,6 +151,7 @@ namespace WireMock.Serialization
|
|||||||
{
|
{
|
||||||
mappingModel.Response.UseTransformer = response.UseTransformer;
|
mappingModel.Response.UseTransformer = response.UseTransformer;
|
||||||
mappingModel.Response.TransformerType = response.TransformerType.ToString();
|
mappingModel.Response.TransformerType = response.TransformerType.ToString();
|
||||||
|
mappingModel.Response.TransformerReplaceNodeOptions = response.TransformerReplaceNodeOptions.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (response.UseTransformerForBodyAsFile)
|
if (response.UseTransformerForBodyAsFile)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using WireMock.Admin.Mappings;
|
using WireMock.Admin.Mappings;
|
||||||
@@ -31,6 +31,13 @@ namespace WireMock.Serialization
|
|||||||
transformerType = TransformerType.Handlebars;
|
transformerType = TransformerType.Handlebars;
|
||||||
}
|
}
|
||||||
webhook.Request.TransformerType = transformerType;
|
webhook.Request.TransformerType = transformerType;
|
||||||
|
|
||||||
|
if (!Enum.TryParse<ReplaceNodeOptions>(model.Request.TransformerReplaceNodeOptions, out var option))
|
||||||
|
{
|
||||||
|
option = ReplaceNodeOptions.None;
|
||||||
|
}
|
||||||
|
|
||||||
|
webhook.Request.TransformerReplaceNodeOptions = option;
|
||||||
}
|
}
|
||||||
|
|
||||||
IEnumerable<string> contentTypeHeader = null;
|
IEnumerable<string> contentTypeHeader = null;
|
||||||
@@ -76,7 +83,8 @@ namespace WireMock.Serialization
|
|||||||
Method = webhook.Request.Method,
|
Method = webhook.Request.Method,
|
||||||
Headers = webhook.Request.Headers?.ToDictionary(x => x.Key, x => x.Value.ToString()),
|
Headers = webhook.Request.Headers?.ToDictionary(x => x.Key, x => x.Value.ToString()),
|
||||||
UseTransformer = webhook.Request.UseTransformer,
|
UseTransformer = webhook.Request.UseTransformer,
|
||||||
TransformerType = webhook.Request.UseTransformer == true ? webhook.Request.TransformerType.ToString() : null
|
TransformerType = webhook.Request.UseTransformer == true ? webhook.Request.TransformerType.ToString() : null,
|
||||||
|
TransformerReplaceNodeOptions = webhook.Request.TransformerReplaceNodeOptions.ToString()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -93,6 +101,7 @@ namespace WireMock.Serialization
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
// Empty
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ using System.Threading.Tasks;
|
|||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
|
using Stef.Validation;
|
||||||
using WireMock.Admin.Mappings;
|
using WireMock.Admin.Mappings;
|
||||||
using WireMock.Admin.Scenarios;
|
using WireMock.Admin.Scenarios;
|
||||||
using WireMock.Admin.Settings;
|
using WireMock.Admin.Settings;
|
||||||
@@ -24,7 +25,6 @@ using WireMock.Serialization;
|
|||||||
using WireMock.Settings;
|
using WireMock.Settings;
|
||||||
using WireMock.Types;
|
using WireMock.Types;
|
||||||
using WireMock.Util;
|
using WireMock.Util;
|
||||||
using Stef.Validation;
|
|
||||||
|
|
||||||
namespace WireMock.Server
|
namespace WireMock.Server
|
||||||
{
|
{
|
||||||
@@ -785,7 +785,15 @@ namespace WireMock.Server
|
|||||||
{
|
{
|
||||||
transformerType = TransformerType.Handlebars;
|
transformerType = TransformerType.Handlebars;
|
||||||
}
|
}
|
||||||
responseBuilder = responseBuilder.WithTransformer(transformerType, responseModel.UseTransformerForBodyAsFile == true);
|
|
||||||
|
if (!Enum.TryParse<ReplaceNodeOptions>(responseModel.TransformerReplaceNodeOptions, out var option))
|
||||||
|
{
|
||||||
|
option = ReplaceNodeOptions.None;
|
||||||
|
}
|
||||||
|
responseBuilder = responseBuilder.WithTransformer(
|
||||||
|
transformerType,
|
||||||
|
responseModel.UseTransformerForBodyAsFile == true,
|
||||||
|
option);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(responseModel.ProxyUrl))
|
if (!string.IsNullOrEmpty(responseModel.ProxyUrl))
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
using HandlebarsDotNet;
|
using HandlebarsDotNet;
|
||||||
using WireMock.Handlers;
|
using WireMock.Handlers;
|
||||||
|
|
||||||
namespace WireMock.Transformers.Handlebars
|
namespace WireMock.Transformers.Handlebars
|
||||||
{
|
{
|
||||||
internal class HandlebarsContext : IHandlebarsContext
|
internal class HandlebarsContext : IHandlebarsContext
|
||||||
{
|
{
|
||||||
public IHandlebars Handlebars { get; set; }
|
public IHandlebars Handlebars { get; set; }
|
||||||
|
|
||||||
public IFileSystemHandler FileSystemHandler { get; set; }
|
public IFileSystemHandler FileSystemHandler { get; set; }
|
||||||
|
|
||||||
public string ParseAndRender(string text, object model)
|
public string ParseAndRender(string text, object model)
|
||||||
{
|
{
|
||||||
var template = Handlebars.Compile(text);
|
var template = Handlebars.Compile(text);
|
||||||
return template(model);
|
return template(model);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,13 +1,14 @@
|
|||||||
using System.Collections.Generic;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using WireMock.Types;
|
using WireMock.Types;
|
||||||
using WireMock.Util;
|
using WireMock.Util;
|
||||||
|
|
||||||
namespace WireMock.Transformers
|
namespace WireMock.Transformers
|
||||||
{
|
{
|
||||||
interface ITransformer
|
interface ITransformer
|
||||||
{
|
{
|
||||||
ResponseMessage Transform(RequestMessage requestMessage, ResponseMessage original, bool useTransformerForBodyAsFile);
|
ResponseMessage Transform(RequestMessage requestMessage, ResponseMessage original, bool useTransformerForBodyAsFile, ReplaceNodeOptions options);
|
||||||
|
|
||||||
(IBodyData BodyData, IDictionary<string, WireMockList<string>> Headers) Transform(RequestMessage originalRequestMessage, ResponseMessage originalResponseMessage, IBodyData bodyData, IDictionary<string, WireMockList<string>> headers);
|
(IBodyData BodyData, IDictionary<string, WireMockList<string>> Headers) Transform(RequestMessage originalRequestMessage, ResponseMessage originalResponseMessage, IBodyData bodyData, IDictionary<string, WireMockList<string>> headers, ReplaceNodeOptions options);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -18,7 +18,7 @@ namespace WireMock.Transformers
|
|||||||
_factory = factory ?? throw new ArgumentNullException(nameof(factory));
|
_factory = factory ?? throw new ArgumentNullException(nameof(factory));
|
||||||
}
|
}
|
||||||
|
|
||||||
public (IBodyData BodyData, IDictionary<string, WireMockList<string>> Headers) Transform(RequestMessage originalRequestMessage, ResponseMessage originalResponseMessage, IBodyData bodyData, IDictionary<string, WireMockList<string>> headers)
|
public (IBodyData BodyData, IDictionary<string, WireMockList<string>> Headers) Transform(RequestMessage originalRequestMessage, ResponseMessage originalResponseMessage, IBodyData bodyData, IDictionary<string, WireMockList<string>> headers, ReplaceNodeOptions options)
|
||||||
{
|
{
|
||||||
var transformerContext = _factory.Create();
|
var transformerContext = _factory.Create();
|
||||||
|
|
||||||
@@ -31,13 +31,13 @@ namespace WireMock.Transformers
|
|||||||
IBodyData newBodyData = null;
|
IBodyData newBodyData = null;
|
||||||
if (bodyData?.DetectedBodyType != null)
|
if (bodyData?.DetectedBodyType != null)
|
||||||
{
|
{
|
||||||
newBodyData = TransformBodyData(transformerContext, model, bodyData, false);
|
newBodyData = TransformBodyData(transformerContext, options, model, bodyData, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (newBodyData, TransformHeaders(transformerContext, model, headers));
|
return (newBodyData, TransformHeaders(transformerContext, model, headers));
|
||||||
}
|
}
|
||||||
|
|
||||||
public ResponseMessage Transform(RequestMessage requestMessage, ResponseMessage original, bool useTransformerForBodyAsFile)
|
public ResponseMessage Transform(RequestMessage requestMessage, ResponseMessage original, bool useTransformerForBodyAsFile, ReplaceNodeOptions options)
|
||||||
{
|
{
|
||||||
var transformerContext = _factory.Create();
|
var transformerContext = _factory.Create();
|
||||||
|
|
||||||
@@ -50,7 +50,7 @@ namespace WireMock.Transformers
|
|||||||
|
|
||||||
if (original.BodyData?.DetectedBodyType != null)
|
if (original.BodyData?.DetectedBodyType != null)
|
||||||
{
|
{
|
||||||
responseMessage.BodyData = TransformBodyData(transformerContext, model, original.BodyData, useTransformerForBodyAsFile);
|
responseMessage.BodyData = TransformBodyData(transformerContext, options, model, original.BodyData, useTransformerForBodyAsFile);
|
||||||
|
|
||||||
if (original.BodyData.DetectedBodyType == BodyType.String)
|
if (original.BodyData.DetectedBodyType == BodyType.String)
|
||||||
{
|
{
|
||||||
@@ -77,12 +77,12 @@ namespace WireMock.Transformers
|
|||||||
return responseMessage;
|
return responseMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IBodyData TransformBodyData(ITransformerContext transformerContext, object model, IBodyData original, bool useTransformerForBodyAsFile)
|
private static IBodyData TransformBodyData(ITransformerContext transformerContext, ReplaceNodeOptions options, object model, IBodyData original, bool useTransformerForBodyAsFile)
|
||||||
{
|
{
|
||||||
switch (original?.DetectedBodyType)
|
switch (original?.DetectedBodyType)
|
||||||
{
|
{
|
||||||
case BodyType.Json:
|
case BodyType.Json:
|
||||||
return TransformBodyAsJson(transformerContext, model, original);
|
return TransformBodyAsJson(transformerContext, options, model, original);
|
||||||
|
|
||||||
case BodyType.File:
|
case BodyType.File:
|
||||||
return TransformBodyAsFile(transformerContext, model, original, useTransformerForBodyAsFile);
|
return TransformBodyAsFile(transformerContext, model, original, useTransformerForBodyAsFile);
|
||||||
@@ -114,28 +114,28 @@ namespace WireMock.Transformers
|
|||||||
return newHeaders;
|
return newHeaders;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IBodyData TransformBodyAsJson(ITransformerContext handlebarsContext, object model, IBodyData original)
|
private static IBodyData TransformBodyAsJson(ITransformerContext handlebarsContext, ReplaceNodeOptions options, object model, IBodyData original)
|
||||||
{
|
{
|
||||||
JToken jToken;
|
JToken jToken;
|
||||||
switch (original.BodyAsJson)
|
switch (original.BodyAsJson)
|
||||||
{
|
{
|
||||||
case JObject bodyAsJObject:
|
case JObject bodyAsJObject:
|
||||||
jToken = bodyAsJObject.DeepClone();
|
jToken = bodyAsJObject.DeepClone();
|
||||||
WalkNode(handlebarsContext, jToken, model);
|
WalkNode(handlebarsContext, options, jToken, model);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Array bodyAsArray:
|
case Array bodyAsArray:
|
||||||
jToken = JArray.FromObject(bodyAsArray);
|
jToken = JArray.FromObject(bodyAsArray);
|
||||||
WalkNode(handlebarsContext, jToken, model);
|
WalkNode(handlebarsContext, options, jToken, model);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case string bodyAsString:
|
case string bodyAsString:
|
||||||
jToken = ReplaceSingleNode(handlebarsContext, bodyAsString, model);
|
jToken = ReplaceSingleNode(handlebarsContext, options, bodyAsString, model);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
jToken = JObject.FromObject(original.BodyAsJson);
|
jToken = JObject.FromObject(original.BodyAsJson);
|
||||||
WalkNode(handlebarsContext, jToken, model);
|
WalkNode(handlebarsContext, options, jToken, model);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -148,7 +148,7 @@ namespace WireMock.Transformers
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static JToken ReplaceSingleNode(ITransformerContext handlebarsContext, string stringValue, object model)
|
private static JToken ReplaceSingleNode(ITransformerContext handlebarsContext, ReplaceNodeOptions options, string stringValue, object model)
|
||||||
{
|
{
|
||||||
string transformedString = handlebarsContext.ParseAndRender(stringValue, model);
|
string transformedString = handlebarsContext.ParseAndRender(stringValue, model);
|
||||||
|
|
||||||
@@ -158,7 +158,7 @@ namespace WireMock.Transformers
|
|||||||
JObject dummy = JObject.Parse($"{{ \"{property}\": null }}");
|
JObject dummy = JObject.Parse($"{{ \"{property}\": null }}");
|
||||||
JToken node = dummy[property];
|
JToken node = dummy[property];
|
||||||
|
|
||||||
ReplaceNodeValue(node, transformedString);
|
ReplaceNodeValue(options, node, transformedString);
|
||||||
|
|
||||||
return dummy[property];
|
return dummy[property];
|
||||||
}
|
}
|
||||||
@@ -166,44 +166,47 @@ namespace WireMock.Transformers
|
|||||||
return stringValue;
|
return stringValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void WalkNode(ITransformerContext handlebarsContext, JToken node, object model)
|
private static void WalkNode(ITransformerContext handlebarsContext, ReplaceNodeOptions options, JToken node, object model)
|
||||||
{
|
{
|
||||||
if (node.Type == JTokenType.Object)
|
switch (node.Type)
|
||||||
{
|
{
|
||||||
// In case of Object, loop all children. Do a ToArray() to avoid `Collection was modified` exceptions.
|
case JTokenType.Object:
|
||||||
foreach (JProperty child in node.Children<JProperty>().ToArray())
|
// In case of Object, loop all children. Do a ToArray() to avoid `Collection was modified` exceptions.
|
||||||
{
|
foreach (var child in node.Children<JProperty>().ToArray())
|
||||||
WalkNode(handlebarsContext, child.Value, model);
|
{
|
||||||
}
|
WalkNode(handlebarsContext, options, child.Value, model);
|
||||||
}
|
}
|
||||||
else if (node.Type == JTokenType.Array)
|
break;
|
||||||
{
|
|
||||||
// In case of Array, loop all items. Do a ToArray() to avoid `Collection was modified` exceptions.
|
|
||||||
foreach (JToken child in node.Children().ToArray())
|
|
||||||
{
|
|
||||||
WalkNode(handlebarsContext, child, model);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (node.Type == JTokenType.String)
|
|
||||||
{
|
|
||||||
// In case of string, try to transform the value.
|
|
||||||
string stringValue = node.Value<string>();
|
|
||||||
if (string.IsNullOrEmpty(stringValue))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
string transformedString = handlebarsContext.ParseAndRender(stringValue, model);
|
case JTokenType.Array:
|
||||||
if (!string.Equals(stringValue, transformedString))
|
// In case of Array, loop all items. Do a ToArray() to avoid `Collection was modified` exceptions.
|
||||||
{
|
foreach (var child in node.Children().ToArray())
|
||||||
ReplaceNodeValue(node, transformedString);
|
{
|
||||||
}
|
WalkNode(handlebarsContext, options, child, model);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case JTokenType.String:
|
||||||
|
// In case of string, try to transform the value.
|
||||||
|
string stringValue = node.Value<string>();
|
||||||
|
if (string.IsNullOrEmpty(stringValue))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
string transformed = handlebarsContext.ParseAndRender(stringValue, model);
|
||||||
|
if (!string.Equals(stringValue, transformed))
|
||||||
|
{
|
||||||
|
ReplaceNodeValue(options, node, transformed);
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void ReplaceNodeValue(JToken node, string stringValue)
|
private static void ReplaceNodeValue(ReplaceNodeOptions options, JToken node, string transformedString)
|
||||||
{
|
{
|
||||||
if (bool.TryParse(stringValue, out bool valueAsBoolean))
|
StringUtils.TryParseQuotedString(transformedString, out var result, out _);
|
||||||
|
if (bool.TryParse(result, out var valueAsBoolean) || bool.TryParse(transformedString, out valueAsBoolean))
|
||||||
{
|
{
|
||||||
node.Replace(valueAsBoolean);
|
node.Replace(valueAsBoolean);
|
||||||
return;
|
return;
|
||||||
@@ -213,12 +216,12 @@ namespace WireMock.Transformers
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Try to convert this string into a JsonObject
|
// Try to convert this string into a JsonObject
|
||||||
value = JToken.Parse(stringValue);
|
value = JToken.Parse(transformedString);
|
||||||
}
|
}
|
||||||
catch (JsonException)
|
catch (JsonException)
|
||||||
{
|
{
|
||||||
// Ignore JsonException and just keep string value and convert to JToken
|
// Ignore JsonException and just keep string value and convert to JToken
|
||||||
value = stringValue;
|
value = transformedString;
|
||||||
}
|
}
|
||||||
|
|
||||||
node.Replace(value);
|
node.Replace(value);
|
||||||
@@ -248,18 +251,15 @@ namespace WireMock.Transformers
|
|||||||
BodyAsFile = transformedBodyAsFilename
|
BodyAsFile = transformedBodyAsFilename
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
string text = handlebarsContext.FileSystemHandler.ReadResponseBodyAsString(transformedBodyAsFilename);
|
|
||||||
|
|
||||||
return new BodyData
|
string text = handlebarsContext.FileSystemHandler.ReadResponseBodyAsString(transformedBodyAsFilename);
|
||||||
{
|
return new BodyData
|
||||||
DetectedBodyType = BodyType.String,
|
{
|
||||||
DetectedBodyTypeFromContentType = original.DetectedBodyTypeFromContentType,
|
DetectedBodyType = BodyType.String,
|
||||||
BodyAsString = handlebarsContext.ParseAndRender(text, model),
|
DetectedBodyTypeFromContentType = original.DetectedBodyTypeFromContentType,
|
||||||
BodyAsFile = transformedBodyAsFilename
|
BodyAsString = handlebarsContext.ParseAndRender(text, model),
|
||||||
};
|
BodyAsFile = transformedBodyAsFilename
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -10,6 +10,33 @@ namespace WireMock.Util
|
|||||||
{
|
{
|
||||||
internal static class JsonUtils
|
internal static class JsonUtils
|
||||||
{
|
{
|
||||||
|
public static bool TryParseAsComplexObject(string strInput, out JToken token)
|
||||||
|
{
|
||||||
|
token = null;
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(strInput))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
strInput = strInput.Trim();
|
||||||
|
if ((!strInput.StartsWith("{") || !strInput.EndsWith("}")) && (!strInput.StartsWith("[") || !strInput.EndsWith("]")))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Try to convert this string into a JToken
|
||||||
|
token = JToken.Parse(strInput);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static string Serialize<T>(T value)
|
public static string Serialize<T>(T value)
|
||||||
{
|
{
|
||||||
return JsonConvert.SerializeObject(value, JsonSerializationConstants.JsonSerializerSettingsIncludeNullValues);
|
return JsonConvert.SerializeObject(value, JsonSerializationConstants.JsonSerializerSettingsIncludeNullValues);
|
||||||
|
|||||||
42
src/WireMock.Net/Util/StringUtils.cs
Normal file
42
src/WireMock.Net/Util/StringUtils.cs
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
using System.Linq;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
|
namespace WireMock.Util
|
||||||
|
{
|
||||||
|
internal static class StringUtils
|
||||||
|
{
|
||||||
|
public static bool TryParseQuotedString(string value, out string result, out char quote)
|
||||||
|
{
|
||||||
|
result = null;
|
||||||
|
quote = '\0';
|
||||||
|
|
||||||
|
if (value == null || value.Length < 2)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
quote = value[0]; // This can be single or a double quote
|
||||||
|
if (quote != '"' && quote != '\'')
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value.Last() != quote)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
result = Regex.Unescape(value.Substring(1, value.Length - 2));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// Ignore Exception, just continue and return false.
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -83,7 +83,7 @@
|
|||||||
<PackageReference Include="Microsoft.AspNet.WebApi.OwinSelfHost" Version="5.2.6" />
|
<PackageReference Include="Microsoft.AspNet.WebApi.OwinSelfHost" Version="5.2.6" />
|
||||||
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
|
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
|
||||||
<PackageReference Include="Scriban.Signed" Version="2.1.4" />
|
<PackageReference Include="Scriban.Signed" Version="2.1.4" />
|
||||||
<PackageReference Include="Mapster" Version="7.2.0" />
|
<!--<PackageReference Include="Mapster" Version="7.2.0" />-->
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup Condition=" '$(TargetFramework)' == 'net46' ">
|
<ItemGroup Condition=" '$(TargetFramework)' == 'net46' ">
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
using FluentAssertions;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using FluentAssertions;
|
||||||
using WireMock.RequestBuilders;
|
using WireMock.RequestBuilders;
|
||||||
using WireMock.ResponseBuilders;
|
using WireMock.ResponseBuilders;
|
||||||
using WireMock.Server;
|
using WireMock.Server;
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ using WireMock.Handlers;
|
|||||||
using WireMock.Models;
|
using WireMock.Models;
|
||||||
using WireMock.ResponseBuilders;
|
using WireMock.ResponseBuilders;
|
||||||
using WireMock.Settings;
|
using WireMock.Settings;
|
||||||
|
using WireMock.Types;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace WireMock.Net.Tests.ResponseBuilders
|
namespace WireMock.Net.Tests.ResponseBuilders
|
||||||
@@ -15,15 +16,14 @@ namespace WireMock.Net.Tests.ResponseBuilders
|
|||||||
{
|
{
|
||||||
private const string ClientIp = "::1";
|
private const string ClientIp = "::1";
|
||||||
|
|
||||||
private readonly Mock<IFileSystemHandler> _filesystemHandlerMock;
|
|
||||||
private readonly WireMockServerSettings _settings = new WireMockServerSettings();
|
private readonly WireMockServerSettings _settings = new WireMockServerSettings();
|
||||||
|
|
||||||
public ResponseWithHandlebarsRandomTests()
|
public ResponseWithHandlebarsRandomTests()
|
||||||
{
|
{
|
||||||
_filesystemHandlerMock = new Mock<IFileSystemHandler>(MockBehavior.Strict);
|
var filesystemHandlerMock = new Mock<IFileSystemHandler>(MockBehavior.Strict);
|
||||||
_filesystemHandlerMock.Setup(fs => fs.ReadResponseBodyAsString(It.IsAny<string>())).Returns("abc");
|
filesystemHandlerMock.Setup(fs => fs.ReadResponseBodyAsString(It.IsAny<string>())).Returns("abc");
|
||||||
|
|
||||||
_settings.FileSystemHandler = _filesystemHandlerMock.Object;
|
_settings.FileSystemHandler = filesystemHandlerMock.Object;
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
@@ -73,6 +73,31 @@ namespace WireMock.Net.Tests.ResponseBuilders
|
|||||||
Check.That(j["Value"].Type).IsEqualTo(JTokenType.Boolean);
|
Check.That(j["Value"].Type).IsEqualTo(JTokenType.Boolean);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(ReplaceNodeOptions.None, JTokenType.Integer)]
|
||||||
|
//[InlineData(ReplaceNodeOptions.Bool, JTokenType.String)]
|
||||||
|
//[InlineData(ReplaceNodeOptions.Integer, JTokenType.Integer)]
|
||||||
|
//[InlineData(ReplaceNodeOptions.Bool | ReplaceNodeOptions.Integer, JTokenType.Integer)]
|
||||||
|
public async Task Response_ProvideResponseAsync_Handlebars_Random1_Integer(ReplaceNodeOptions options, JTokenType expected)
|
||||||
|
{
|
||||||
|
// Assign
|
||||||
|
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "GET", ClientIp);
|
||||||
|
|
||||||
|
var responseBuilder = Response.Create()
|
||||||
|
.WithBodyAsJson(new
|
||||||
|
{
|
||||||
|
Value = "{{Random Type=\"Integer\"}}"
|
||||||
|
})
|
||||||
|
.WithTransformer(options);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var response = await responseBuilder.ProvideResponseAsync(request, _settings).ConfigureAwait(false);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
JObject j = JObject.FromObject(response.Message.BodyData.BodyAsJson);
|
||||||
|
Check.That(j["Value"].Type).IsEqualTo(expected);
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task Response_ProvideResponseAsync_Handlebars_Random1_Guid()
|
public async Task Response_ProvideResponseAsync_Handlebars_Random1_Guid()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -23,17 +23,16 @@ namespace WireMock.Net.Tests.ResponseBuilders
|
|||||||
{
|
{
|
||||||
public class ResponseWithTransformerTests
|
public class ResponseWithTransformerTests
|
||||||
{
|
{
|
||||||
private readonly Mock<IFileSystemHandler> _filesystemHandlerMock;
|
|
||||||
private readonly WireMockServerSettings _settings = new WireMockServerSettings();
|
private readonly WireMockServerSettings _settings = new WireMockServerSettings();
|
||||||
|
|
||||||
private const string ClientIp = "::1";
|
private const string ClientIp = "::1";
|
||||||
|
|
||||||
public ResponseWithTransformerTests()
|
public ResponseWithTransformerTests()
|
||||||
{
|
{
|
||||||
_filesystemHandlerMock = new Mock<IFileSystemHandler>(MockBehavior.Strict);
|
var filesystemHandlerMock = new Mock<IFileSystemHandler>(MockBehavior.Strict);
|
||||||
_filesystemHandlerMock.Setup(fs => fs.ReadResponseBodyAsString(It.IsAny<string>())).Returns("abc");
|
filesystemHandlerMock.Setup(fs => fs.ReadResponseBodyAsString(It.IsAny<string>())).Returns("abc");
|
||||||
|
|
||||||
_settings.FileSystemHandler = _filesystemHandlerMock.Object;
|
_settings.FileSystemHandler = filesystemHandlerMock.Object;
|
||||||
}
|
}
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
@@ -366,7 +365,7 @@ namespace WireMock.Net.Tests.ResponseBuilders
|
|||||||
public async Task Response_ProvideResponse_Transformer_WithBodyAsJson_ResultAsObject(TransformerType transformerType)
|
public async Task Response_ProvideResponse_Transformer_WithBodyAsJson_ResultAsObject(TransformerType transformerType)
|
||||||
{
|
{
|
||||||
// Assign
|
// Assign
|
||||||
string jsonString = "{ \"things\": [ { \"name\": \"RequiredThing\" }, { \"name\": \"Wiremock\" } ] }";
|
string jsonString = "{ \"things\": [ { \"name\": \"RequiredThing\" }, { \"name\": \"WireMock\" } ] }";
|
||||||
var bodyData = new BodyData
|
var bodyData = new BodyData
|
||||||
{
|
{
|
||||||
BodyAsJson = JsonConvert.DeserializeObject(jsonString),
|
BodyAsJson = JsonConvert.DeserializeObject(jsonString),
|
||||||
@@ -386,6 +385,108 @@ namespace WireMock.Net.Tests.ResponseBuilders
|
|||||||
Check.That(JsonConvert.SerializeObject(response.Message.BodyData.BodyAsJson)).Equals("{\"x\":\"test /foo_object\"}");
|
Check.That(JsonConvert.SerializeObject(response.Message.BodyData.BodyAsJson)).Equals("{\"x\":\"test /foo_object\"}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//[Theory]
|
||||||
|
//[InlineData(TransformerType.Handlebars, "a")]
|
||||||
|
//[InlineData(TransformerType.Handlebars, "42")]
|
||||||
|
//[InlineData(TransformerType.Handlebars, "{")]
|
||||||
|
//[InlineData(TransformerType.Handlebars, "]")]
|
||||||
|
//[InlineData(TransformerType.Handlebars, " ")]
|
||||||
|
//public async Task Response_ProvideResponse_Transformer_WithBodyAsJsonWithExtraQuotes_AndSpecialOption_MakesAString_ResultAsObject(TransformerType transformerType, string text)
|
||||||
|
//{
|
||||||
|
// string jsonString = $"{{ \"x\": \"{text}\" }}";
|
||||||
|
// var bodyData = new BodyData
|
||||||
|
// {
|
||||||
|
// BodyAsJson = JsonConvert.DeserializeObject(jsonString),
|
||||||
|
// DetectedBodyType = BodyType.Json,
|
||||||
|
// Encoding = Encoding.UTF8
|
||||||
|
// };
|
||||||
|
// var request = new RequestMessage(new UrlDetails("http://localhost/foo_object"), "POST", ClientIp, bodyData);
|
||||||
|
|
||||||
|
// var responseBuilder = Response.Create()
|
||||||
|
// .WithBodyAsJson(new { text = "\"{{request.bodyAsJson.x}}\"" })
|
||||||
|
// .WithTransformer(transformerType, false, ReplaceNodeOptions.Default);
|
||||||
|
|
||||||
|
// // Act
|
||||||
|
// var response = await responseBuilder.ProvideResponseAsync(request, _settings).ConfigureAwait(false);
|
||||||
|
|
||||||
|
// // Assert
|
||||||
|
// JsonConvert.SerializeObject(response.Message.BodyData.BodyAsJson).Should().Be($"{{\"text\":\"{text}\"}}");
|
||||||
|
//}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(TransformerType.Handlebars, "\"\"", "\"\"")]
|
||||||
|
[InlineData(TransformerType.Handlebars, "\"a\"", "\"a\"")]
|
||||||
|
[InlineData(TransformerType.Handlebars, "\" \"", "\" \"")]
|
||||||
|
[InlineData(TransformerType.Handlebars, "\"'\"", "\"'\"")]
|
||||||
|
[InlineData(TransformerType.Handlebars, "\"false\"", "false")] // bool is special
|
||||||
|
[InlineData(TransformerType.Handlebars, "false", "false")]
|
||||||
|
[InlineData(TransformerType.Handlebars, "\"true\"", "true")] // bool is special
|
||||||
|
[InlineData(TransformerType.Handlebars, "true", "true")]
|
||||||
|
[InlineData(TransformerType.Handlebars, "\"-42\"", "-42")] // todo
|
||||||
|
[InlineData(TransformerType.Handlebars, "-42", "-42")]
|
||||||
|
[InlineData(TransformerType.Handlebars, "\"2147483647\"", "2147483647")] // todo
|
||||||
|
[InlineData(TransformerType.Handlebars, "2147483647", "2147483647")]
|
||||||
|
[InlineData(TransformerType.Handlebars, "\"9223372036854775807\"", "9223372036854775807")] // todo
|
||||||
|
[InlineData(TransformerType.Handlebars, "9223372036854775807", "9223372036854775807")]
|
||||||
|
public async Task Response_ProvideResponse_Transformer_WithBodyAsJson_And_ReplaceNodeOptionsKeep(TransformerType transformerType, string value, string expected)
|
||||||
|
{
|
||||||
|
string jsonString = $"{{ \"x\": {value} }}";
|
||||||
|
var bodyData = new BodyData
|
||||||
|
{
|
||||||
|
BodyAsJson = JsonConvert.DeserializeObject(jsonString),
|
||||||
|
DetectedBodyType = BodyType.Json,
|
||||||
|
Encoding = Encoding.UTF8
|
||||||
|
};
|
||||||
|
var request = new RequestMessage(new UrlDetails("http://localhost/foo_object"), "POST", ClientIp, bodyData);
|
||||||
|
|
||||||
|
var responseBuilder = Response.Create()
|
||||||
|
.WithBodyAsJson(new { text = "{{request.bodyAsJson.x}}" })
|
||||||
|
.WithTransformer(transformerType, false, ReplaceNodeOptions.None);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var response = await responseBuilder.ProvideResponseAsync(request, _settings).ConfigureAwait(false);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
JsonConvert.SerializeObject(response.Message.BodyData.BodyAsJson).Should().Be($"{{\"text\":{expected}}}");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(TransformerType.Handlebars, "\"\"", "\"\"")]
|
||||||
|
[InlineData(TransformerType.Handlebars, "\"a\"", "\"a\"")]
|
||||||
|
[InlineData(TransformerType.Handlebars, "\" \"", "\" \"")]
|
||||||
|
[InlineData(TransformerType.Handlebars, "\"'\"", "\"'\"")]
|
||||||
|
[InlineData(TransformerType.Handlebars, "\"false\"", "false")] // bool is special
|
||||||
|
[InlineData(TransformerType.Handlebars, "false", "false")]
|
||||||
|
[InlineData(TransformerType.Handlebars, "\"true\"", "true")] // bool is special
|
||||||
|
[InlineData(TransformerType.Handlebars, "true", "true")]
|
||||||
|
[InlineData(TransformerType.Handlebars, "\"-42\"", "\"-42\"")]
|
||||||
|
[InlineData(TransformerType.Handlebars, "-42", "\"-42\"")]
|
||||||
|
[InlineData(TransformerType.Handlebars, "\"2147483647\"", "\"2147483647\"")]
|
||||||
|
[InlineData(TransformerType.Handlebars, "2147483647", "\"2147483647\"")]
|
||||||
|
[InlineData(TransformerType.Handlebars, "\"9223372036854775807\"", "\"9223372036854775807\"")]
|
||||||
|
[InlineData(TransformerType.Handlebars, "9223372036854775807", "\"9223372036854775807\"")]
|
||||||
|
public async Task Response_ProvideResponse_Transformer_WithBodyAsJsonWithExtraQuotes_AlwaysMakesString(TransformerType transformerType, string value, string expected)
|
||||||
|
{
|
||||||
|
string jsonString = $"{{ \"x\": {value} }}";
|
||||||
|
var bodyData = new BodyData
|
||||||
|
{
|
||||||
|
BodyAsJson = JsonConvert.DeserializeObject(jsonString),
|
||||||
|
DetectedBodyType = BodyType.Json,
|
||||||
|
Encoding = Encoding.UTF8
|
||||||
|
};
|
||||||
|
var request = new RequestMessage(new UrlDetails("http://localhost/foo_object"), "POST", ClientIp, bodyData);
|
||||||
|
|
||||||
|
var responseBuilder = Response.Create()
|
||||||
|
.WithBodyAsJson(new { text = "\"{{request.bodyAsJson.x}}\"" })
|
||||||
|
.WithTransformer(transformerType);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var response = await responseBuilder.ProvideResponseAsync(request, _settings).ConfigureAwait(false);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
JsonConvert.SerializeObject(response.Message.BodyData.BodyAsJson).Should().Be($"{{\"text\":{expected}}}");
|
||||||
|
}
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
[InlineData(TransformerType.Handlebars)]
|
[InlineData(TransformerType.Handlebars)]
|
||||||
//[InlineData(TransformerType.Scriban)] Scriban cannot access dynamic Json Objects
|
//[InlineData(TransformerType.Scriban)] Scriban cannot access dynamic Json Objects
|
||||||
|
|||||||
104
test/WireMock.Net.Tests/Util/StringUtilsTests.cs
Normal file
104
test/WireMock.Net.Tests/Util/StringUtilsTests.cs
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
using FluentAssertions;
|
||||||
|
using WireMock.Util;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace WireMock.Net.Tests.Util
|
||||||
|
{
|
||||||
|
public class StringUtilsTests
|
||||||
|
{
|
||||||
|
[Theory]
|
||||||
|
[InlineData("'s")]
|
||||||
|
[InlineData("\"s")]
|
||||||
|
public void StringUtils_TryParseQuotedString_With_UnexpectedUnclosedString_Returns_False(string input)
|
||||||
|
{
|
||||||
|
// Act
|
||||||
|
bool valid = StringUtils.TryParseQuotedString(input, out var result, out var quote);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
valid.Should().BeFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData("")]
|
||||||
|
[InlineData(null)]
|
||||||
|
[InlineData("x")]
|
||||||
|
public void StringUtils_TryParseQuotedString_With_InvalidStringLength_Returns_False(string input)
|
||||||
|
{
|
||||||
|
// Act
|
||||||
|
bool valid = StringUtils.TryParseQuotedString(input, out var result, out var quote);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
valid.Should().BeFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData("xx")]
|
||||||
|
[InlineData(" ")]
|
||||||
|
public void StringUtils_TryParseQuotedString_With_InvalidStringQuoteCharacter_Returns_False(string input)
|
||||||
|
{
|
||||||
|
// Act
|
||||||
|
bool valid = StringUtils.TryParseQuotedString(input, out var result, out var quote);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
valid.Should().BeFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void StringUtils_TryParseQuotedString_With_UnexpectedUnrecognizedEscapeSequence_Returns_False()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
string input = new string(new[] { '"', '\\', 'u', '?', '"' });
|
||||||
|
|
||||||
|
// Act
|
||||||
|
bool valid = StringUtils.TryParseQuotedString(input, out var result, out var quote);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
valid.Should().BeFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData("''", "")]
|
||||||
|
[InlineData("'s'", "s")]
|
||||||
|
[InlineData("'\\\\'", "\\")]
|
||||||
|
[InlineData("'\\n'", "\n")]
|
||||||
|
public void StringUtils_TryParseQuotedString_SingleQuotedString(string input, string expectedResult)
|
||||||
|
{
|
||||||
|
// Act
|
||||||
|
bool valid = StringUtils.TryParseQuotedString(input, out var result, out var quote);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
valid.Should().BeTrue();
|
||||||
|
result.Should().Be(expectedResult);
|
||||||
|
quote.Should().Be('\'');
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData("\"\"", "")]
|
||||||
|
[InlineData("\"\\\\\"", "\\")]
|
||||||
|
[InlineData("\"\\n\"", "\n")]
|
||||||
|
[InlineData("\"\\\\n\"", "\\n")]
|
||||||
|
[InlineData("\"\\\\new\"", "\\new")]
|
||||||
|
[InlineData("\"[]\"", "[]")]
|
||||||
|
[InlineData("\"()\"", "()")]
|
||||||
|
[InlineData("\"(\\\"\\\")\"", "(\"\")")]
|
||||||
|
[InlineData("\"/\"", "/")]
|
||||||
|
[InlineData("\"a\"", "a")]
|
||||||
|
[InlineData("\"This \\\"is\\\" a test.\"", "This \"is\" a test.")]
|
||||||
|
[InlineData(@"""This \""is\"" b test.""", @"This ""is"" b test.")]
|
||||||
|
[InlineData("\"ab\\\"cd\"", "ab\"cd")]
|
||||||
|
[InlineData("\"\\\"\"", "\"")]
|
||||||
|
[InlineData("\"\\\"\\\"\"", "\"\"")]
|
||||||
|
[InlineData("\"AB YZ 19 \uD800\udc05 \u00e4\"", "AB YZ 19 \uD800\udc05 \u00e4")]
|
||||||
|
[InlineData("\"\\\\\\\\192.168.1.1\\\\audio\\\\new\"", "\\\\192.168.1.1\\audio\\new")]
|
||||||
|
public void StringUtils_TryParseQuotedString_DoubleQuotedString(string input, string expectedResult)
|
||||||
|
{
|
||||||
|
// Act
|
||||||
|
bool valid = StringUtils.TryParseQuotedString(input, out var result, out var quote);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
valid.Should().BeTrue();
|
||||||
|
result.Should().Be(expectedResult);
|
||||||
|
quote.Should().Be('"');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user