mirror of
https://github.com/wiremock/WireMock.Net.git
synced 2026-06-07 23:42:48 +02:00
Update Transformer functionality to return value instead of string (#858)
This commit is contained in:
@@ -33,6 +33,7 @@
|
|||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Scriban/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=Scriban/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Sigil/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=Sigil/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Stef/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=Stef/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=templated/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Victoor/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=Victoor/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Webhook/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=Webhook/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Webhooks/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=Webhooks/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
|||||||
@@ -1,36 +1,25 @@
|
|||||||
using System;
|
namespace WireMock.Types;
|
||||||
|
|
||||||
namespace WireMock.Types
|
/// <summary>
|
||||||
|
/// Logic to use when replace a JSON node using the Transformer.
|
||||||
|
/// </summary>
|
||||||
|
public enum ReplaceNodeOptions
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Flags to use when replace a JSON node using the Transformer.
|
/// Try to evaluate a templated value.
|
||||||
|
/// In case this is valid, return the value and if the value can be converted to a primitive type, use that value.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Flags]
|
EvaluateAndTryToConvert = 0,
|
||||||
public enum ReplaceNodeOptions
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Default
|
|
||||||
/// </summary>
|
|
||||||
None = 0
|
|
||||||
|
|
||||||
///// <summary>
|
/// <summary>
|
||||||
///// Replace boolean string value to a real boolean value. (This is used by default to maintain backward compatibility.)
|
/// Try to evaluate a templated value.
|
||||||
///// </summary>
|
/// In case this is valid, return the value, else fallback to the parse behavior.
|
||||||
//Bool = 0b00000001,
|
/// </summary>
|
||||||
|
Evaluate = 1,
|
||||||
|
|
||||||
///// <summary>
|
/// <summary>
|
||||||
///// Replace integer string value to a real integer value.
|
/// Parse templated string to a templated string.
|
||||||
///// </summary>
|
/// (keep a templated string value as string value).
|
||||||
//Integer = 0b00000010,
|
/// </summary>
|
||||||
|
Parse = 2
|
||||||
///// <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,23 +1,22 @@
|
|||||||
namespace WireMock.Types
|
namespace WireMock.Types;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The ResponseMessage Transformers
|
||||||
|
/// </summary>
|
||||||
|
public enum TransformerType
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The ResponseMessage Transformers
|
/// https://github.com/Handlebars-Net/Handlebars.Net
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public enum TransformerType
|
Handlebars,
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// https://github.com/Handlebars-Net/Handlebars.Net
|
|
||||||
/// </summary>
|
|
||||||
Handlebars,
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// https://github.com/scriban/scriban : default
|
/// https://github.com/scriban/scriban : default
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Scriban,
|
Scriban,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// https://github.com/scriban/scriban : DotLiquid
|
/// https://github.com/scriban/scriban : DotLiquid
|
||||||
/// </summary>
|
/// </summary>
|
||||||
ScribanDotLiquid
|
ScribanDotLiquid
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -51,14 +51,14 @@ internal class WebhookSender
|
|||||||
switch (webhookRequest.TransformerType)
|
switch (webhookRequest.TransformerType)
|
||||||
{
|
{
|
||||||
case TransformerType.Handlebars:
|
case TransformerType.Handlebars:
|
||||||
var factoryHandlebars = new HandlebarsContextFactory(_settings.FileSystemHandler, _settings.HandlebarsRegistrationCallback);
|
var factoryHandlebars = new HandlebarsContextFactory(_settings);
|
||||||
transformer = new Transformer(factoryHandlebars);
|
transformer = new Transformer(_settings, factoryHandlebars);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TransformerType.Scriban:
|
case TransformerType.Scriban:
|
||||||
case TransformerType.ScribanDotLiquid:
|
case TransformerType.ScribanDotLiquid:
|
||||||
var factoryDotLiquid = new ScribanContextFactory(_settings.FileSystemHandler, webhookRequest.TransformerType);
|
var factoryDotLiquid = new ScribanContextFactory(_settings.FileSystemHandler, webhookRequest.TransformerType);
|
||||||
transformer = new Transformer(factoryDotLiquid);
|
transformer = new Transformer(_settings, factoryDotLiquid);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -29,5 +29,5 @@ public interface ITransformResponseBuilder : IDelayResponseBuilder
|
|||||||
/// <returns>
|
/// <returns>
|
||||||
/// The <see cref="IResponseBuilder"/>.
|
/// The <see cref="IResponseBuilder"/>.
|
||||||
/// </returns>
|
/// </returns>
|
||||||
IResponseBuilder WithTransformer(TransformerType transformerType = TransformerType.Handlebars, bool transformContentFromBodyAsFile = false, ReplaceNodeOptions options = ReplaceNodeOptions.None);
|
IResponseBuilder WithTransformer(TransformerType transformerType = TransformerType.Handlebars, bool transformContentFromBodyAsFile = false, ReplaceNodeOptions options = ReplaceNodeOptions.Evaluate);
|
||||||
}
|
}
|
||||||
@@ -207,7 +207,7 @@ public partial class Response : IResponseBuilder
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public IResponseBuilder WithTransformer(TransformerType transformerType, bool transformContentFromBodyAsFile = false, ReplaceNodeOptions options = ReplaceNodeOptions.None)
|
public IResponseBuilder WithTransformer(TransformerType transformerType, bool transformContentFromBodyAsFile = false, ReplaceNodeOptions options = ReplaceNodeOptions.Evaluate)
|
||||||
{
|
{
|
||||||
UseTransformer = true;
|
UseTransformer = true;
|
||||||
TransformerType = transformerType;
|
TransformerType = transformerType;
|
||||||
@@ -314,14 +314,14 @@ public partial class Response : IResponseBuilder
|
|||||||
switch (TransformerType)
|
switch (TransformerType)
|
||||||
{
|
{
|
||||||
case TransformerType.Handlebars:
|
case TransformerType.Handlebars:
|
||||||
var factoryHandlebars = new HandlebarsContextFactory(settings.FileSystemHandler, settings.HandlebarsRegistrationCallback);
|
var factoryHandlebars = new HandlebarsContextFactory(settings);
|
||||||
responseMessageTransformer = new Transformer(factoryHandlebars);
|
responseMessageTransformer = new Transformer(settings, factoryHandlebars);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TransformerType.Scriban:
|
case TransformerType.Scriban:
|
||||||
case TransformerType.ScribanDotLiquid:
|
case TransformerType.ScribanDotLiquid:
|
||||||
var factoryDotLiquid = new ScribanContextFactory(settings.FileSystemHandler, TransformerType);
|
var factoryDotLiquid = new ScribanContextFactory(settings.FileSystemHandler, TransformerType);
|
||||||
responseMessageTransformer = new Transformer(factoryDotLiquid);
|
responseMessageTransformer = new Transformer(settings, factoryDotLiquid);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ internal static class WebhookMapper
|
|||||||
|
|
||||||
if (!Enum.TryParse<ReplaceNodeOptions>(model.Request.TransformerReplaceNodeOptions, out var option))
|
if (!Enum.TryParse<ReplaceNodeOptions>(model.Request.TransformerReplaceNodeOptions, out var option))
|
||||||
{
|
{
|
||||||
option = ReplaceNodeOptions.None;
|
option = ReplaceNodeOptions.Evaluate;
|
||||||
}
|
}
|
||||||
webhook.Request.TransformerReplaceNodeOptions = option;
|
webhook.Request.TransformerReplaceNodeOptions = option;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -250,7 +250,7 @@ public partial class WireMockServer
|
|||||||
|
|
||||||
if (!Enum.TryParse<ReplaceNodeOptions>(responseModel.TransformerReplaceNodeOptions, out var option))
|
if (!Enum.TryParse<ReplaceNodeOptions>(responseModel.TransformerReplaceNodeOptions, out var option))
|
||||||
{
|
{
|
||||||
option = ReplaceNodeOptions.None;
|
option = ReplaceNodeOptions.Evaluate;
|
||||||
}
|
}
|
||||||
responseBuilder = responseBuilder.WithTransformer(
|
responseBuilder = responseBuilder.WithTransformer(
|
||||||
transformerType,
|
transformerType,
|
||||||
|
|||||||
@@ -10,272 +10,279 @@ using WireMock.Logging;
|
|||||||
using WireMock.Matchers;
|
using WireMock.Matchers;
|
||||||
using WireMock.RegularExpressions;
|
using WireMock.RegularExpressions;
|
||||||
using WireMock.Types;
|
using WireMock.Types;
|
||||||
|
using System.Globalization;
|
||||||
#if USE_ASPNETCORE
|
#if USE_ASPNETCORE
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace WireMock.Settings
|
namespace WireMock.Settings;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// WireMockServerSettings
|
||||||
|
/// </summary>
|
||||||
|
public class WireMockServerSettings
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// WireMockServerSettings
|
/// Gets or sets the http port.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class WireMockServerSettings
|
[PublicAPI]
|
||||||
{
|
public int? Port { get; set; }
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the http port.
|
|
||||||
/// </summary>
|
|
||||||
[PublicAPI]
|
|
||||||
public int? Port { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the use SSL.
|
/// Gets or sets the use SSL.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
// ReSharper disable once InconsistentNaming
|
// ReSharper disable once InconsistentNaming
|
||||||
[PublicAPI]
|
[PublicAPI]
|
||||||
public bool? UseSSL { get; set; }
|
public bool? UseSSL { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Defines on which scheme (http/https) to host. (This overrides the <c>UseSSL</c> value).
|
/// Defines on which scheme (http/https) to host. (This overrides the <c>UseSSL</c> value).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[PublicAPI]
|
[PublicAPI]
|
||||||
public HostingScheme? HostingScheme { get; set; }
|
public HostingScheme? HostingScheme { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets whether to start admin interface.
|
/// Gets or sets whether to start admin interface.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[PublicAPI]
|
[PublicAPI]
|
||||||
public bool? StartAdminInterface { get; set; }
|
public bool? StartAdminInterface { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets if the static mappings should be read at startup.
|
/// Gets or sets if the static mappings should be read at startup.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[PublicAPI]
|
[PublicAPI]
|
||||||
public bool? ReadStaticMappings { get; set; }
|
public bool? ReadStaticMappings { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Watch the static mapping files + folder for changes when running.
|
/// Watch the static mapping files + folder for changes when running.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[PublicAPI]
|
[PublicAPI]
|
||||||
public bool? WatchStaticMappings { get; set; }
|
public bool? WatchStaticMappings { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A value indicating whether subdirectories within the static mappings path should be monitored.
|
/// A value indicating whether subdirectories within the static mappings path should be monitored.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[PublicAPI]
|
[PublicAPI]
|
||||||
public bool? WatchStaticMappingsInSubdirectories { get; set; }
|
public bool? WatchStaticMappingsInSubdirectories { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets if the proxy and record settings.
|
/// Gets or sets if the proxy and record settings.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[PublicAPI]
|
[PublicAPI]
|
||||||
public ProxyAndRecordSettings? ProxyAndRecordSettings { get; set; }
|
public ProxyAndRecordSettings? ProxyAndRecordSettings { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the urls.
|
/// Gets or sets the urls.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[PublicAPI]
|
[PublicAPI]
|
||||||
public string[]? Urls { get; set; }
|
public string[]? Urls { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// StartTimeout
|
/// StartTimeout
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[PublicAPI]
|
[PublicAPI]
|
||||||
public int StartTimeout { get; set; } = 10000;
|
public int StartTimeout { get; set; } = 10000;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Allow Partial Mapping (default set to false).
|
/// Allow Partial Mapping (default set to false).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[PublicAPI]
|
[PublicAPI]
|
||||||
public bool? AllowPartialMapping { get; set; }
|
public bool? AllowPartialMapping { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The username needed for __admin access.
|
/// The username needed for __admin access.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[PublicAPI]
|
[PublicAPI]
|
||||||
public string? AdminUsername { get; set; }
|
public string? AdminUsername { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The password needed for __admin access.
|
/// The password needed for __admin access.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[PublicAPI]
|
[PublicAPI]
|
||||||
public string? AdminPassword { get; set; }
|
public string? AdminPassword { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The AzureAD Tenant needed for __admin access.
|
/// The AzureAD Tenant needed for __admin access.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[PublicAPI]
|
[PublicAPI]
|
||||||
public string? AdminAzureADTenant { get; set; }
|
public string? AdminAzureADTenant { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The AzureAD Audience / Resource for __admin access.
|
/// The AzureAD Audience / Resource for __admin access.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[PublicAPI]
|
[PublicAPI]
|
||||||
public string? AdminAzureADAudience { get; set; }
|
public string? AdminAzureADAudience { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The RequestLog expiration in hours (optional).
|
/// The RequestLog expiration in hours (optional).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[PublicAPI]
|
[PublicAPI]
|
||||||
public int? RequestLogExpirationDuration { get; set; }
|
public int? RequestLogExpirationDuration { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The MaxRequestLog count (optional).
|
/// The MaxRequestLog count (optional).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[PublicAPI]
|
[PublicAPI]
|
||||||
public int? MaxRequestLogCount { get; set; }
|
public int? MaxRequestLogCount { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Action which is called (with the IAppBuilder or IApplicationBuilder) before the internal WireMockMiddleware is initialized. [Optional]
|
/// Action which is called (with the IAppBuilder or IApplicationBuilder) before the internal WireMockMiddleware is initialized. [Optional]
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[PublicAPI]
|
[PublicAPI]
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public Action<object>? PreWireMockMiddlewareInit { get; set; }
|
public Action<object>? PreWireMockMiddlewareInit { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Action which is called (with the IAppBuilder or IApplicationBuilder) after the internal WireMockMiddleware is initialized. [Optional]
|
/// Action which is called (with the IAppBuilder or IApplicationBuilder) after the internal WireMockMiddleware is initialized. [Optional]
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[PublicAPI]
|
[PublicAPI]
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public Action<object>? PostWireMockMiddlewareInit { get; set; }
|
public Action<object>? PostWireMockMiddlewareInit { get; set; }
|
||||||
|
|
||||||
#if USE_ASPNETCORE
|
#if USE_ASPNETCORE
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Action which is called with IServiceCollection when ASP.NET Core DI is being configured. [Optional]
|
/// Action which is called with IServiceCollection when ASP.NET Core DI is being configured. [Optional]
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[PublicAPI]
|
[PublicAPI]
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public Action<IServiceCollection>? AdditionalServiceRegistration { get; set; }
|
public Action<IServiceCollection>? AdditionalServiceRegistration { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Policies to use when using CORS. By default CORS is disabled. [Optional]
|
/// Policies to use when using CORS. By default CORS is disabled. [Optional]
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[PublicAPI]
|
[PublicAPI]
|
||||||
public CorsPolicyOptions? CorsPolicyOptions { get; set; }
|
public CorsPolicyOptions? CorsPolicyOptions { get; set; }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The IWireMockLogger which logs Debug, Info, Warning or Error
|
/// The IWireMockLogger which logs Debug, Info, Warning or Error
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[PublicAPI]
|
[PublicAPI]
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public IWireMockLogger Logger { get; set; } = null!;
|
public IWireMockLogger Logger { get; set; } = null!;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handler to interact with the file system to read and write static mapping files.
|
/// Handler to interact with the file system to read and write static mapping files.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[PublicAPI]
|
[PublicAPI]
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public IFileSystemHandler FileSystemHandler { get; set; } = null!;
|
public IFileSystemHandler FileSystemHandler { get; set; } = null!;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Action which can be used to add additional Handlebars registrations. [Optional]
|
/// Action which can be used to add additional Handlebars registrations. [Optional]
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[PublicAPI]
|
[PublicAPI]
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public Action<IHandlebars, IFileSystemHandler>? HandlebarsRegistrationCallback { get; set; }
|
public Action<IHandlebars, IFileSystemHandler>? HandlebarsRegistrationCallback { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Allow the usage of CSharpCodeMatcher (default is not allowed).
|
/// Allow the usage of CSharpCodeMatcher (default is not allowed).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[PublicAPI]
|
[PublicAPI]
|
||||||
public bool? AllowCSharpCodeMatcher { get; set; }
|
public bool? AllowCSharpCodeMatcher { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Allow a Body for all HTTP Methods. (default set to false).
|
/// Allow a Body for all HTTP Methods. (default set to false).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[PublicAPI]
|
[PublicAPI]
|
||||||
public bool? AllowBodyForAllHttpMethods { get; set; }
|
public bool? AllowBodyForAllHttpMethods { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Allow only a HttpStatus Code in the response which is defined. (default set to false).
|
/// Allow only a HttpStatus Code in the response which is defined. (default set to false).
|
||||||
/// - false : also null, 0, empty or invalid HttpStatus codes are allowed.
|
/// - false : also null, 0, empty or invalid HttpStatus codes are allowed.
|
||||||
/// - true : only codes defined in <see cref="System.Net.HttpStatusCode"/> are allowed.
|
/// - true : only codes defined in <see cref="System.Net.HttpStatusCode"/> are allowed.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[PublicAPI]
|
[PublicAPI]
|
||||||
public bool? AllowOnlyDefinedHttpStatusCodeInResponse { get; set; }
|
public bool? AllowOnlyDefinedHttpStatusCodeInResponse { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Set to true to disable Json deserialization when processing requests. (default set to false).
|
/// Set to true to disable Json deserialization when processing requests. (default set to false).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[PublicAPI]
|
[PublicAPI]
|
||||||
public bool? DisableJsonBodyParsing { get; set; }
|
public bool? DisableJsonBodyParsing { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Disable support for GZip and Deflate request body decompression. (default set to false).
|
/// Disable support for GZip and Deflate request body decompression. (default set to false).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[PublicAPI]
|
[PublicAPI]
|
||||||
public bool? DisableRequestBodyDecompressing { get; set; }
|
public bool? DisableRequestBodyDecompressing { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handle all requests synchronously. (default set to false).
|
/// Handle all requests synchronously. (default set to false).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[PublicAPI]
|
[PublicAPI]
|
||||||
public bool? HandleRequestsSynchronously { get; set; }
|
public bool? HandleRequestsSynchronously { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Throw an exception when the <see cref="IMatcher"/> fails because of invalid input. (default set to false).
|
/// Throw an exception when the <see cref="IMatcher"/> fails because of invalid input. (default set to false).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[PublicAPI]
|
[PublicAPI]
|
||||||
public bool? ThrowExceptionWhenMatcherFails { get; set; }
|
public bool? ThrowExceptionWhenMatcherFails { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// If https is used, these settings can be used to configure the CertificateSettings in case a custom certificate instead the default .NET certificate should be used.
|
/// If https is used, these settings can be used to configure the CertificateSettings in case a custom certificate instead the default .NET certificate should be used.
|
||||||
///
|
///
|
||||||
/// X509StoreName and X509StoreLocation should be defined
|
/// X509StoreName and X509StoreLocation should be defined
|
||||||
/// OR
|
/// OR
|
||||||
/// X509CertificateFilePath and X509CertificatePassword should be defined
|
/// X509CertificateFilePath and X509CertificatePassword should be defined
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[PublicAPI]
|
[PublicAPI]
|
||||||
public WireMockCertificateSettings? CertificateSettings { get; set; }
|
public WireMockCertificateSettings? CertificateSettings { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Defines if custom CertificateSettings are defined
|
/// Defines if custom CertificateSettings are defined
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[PublicAPI]
|
[PublicAPI]
|
||||||
public bool CustomCertificateDefined => CertificateSettings?.IsDefined == true;
|
public bool CustomCertificateDefined => CertificateSettings?.IsDefined == true;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Defines the global IWebhookSettings to use.
|
/// Defines the global IWebhookSettings to use.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[PublicAPI]
|
[PublicAPI]
|
||||||
public WebhookSettings? WebhookSettings { get; set; }
|
public WebhookSettings? WebhookSettings { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Use the <see cref="RegexExtended"/> instead of the default <see cref="Regex"/> (default set to true).
|
/// Use the <see cref="RegexExtended"/> instead of the default <see cref="Regex"/> (default set to true).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[PublicAPI]
|
[PublicAPI]
|
||||||
public bool? UseRegexExtended { get; set; } = true;
|
public bool? UseRegexExtended { get; set; } = true;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Save unmatched requests to a file using the <see cref="IFileSystemHandler"/> (default set to false).
|
/// Save unmatched requests to a file using the <see cref="IFileSystemHandler"/> (default set to false).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[PublicAPI]
|
[PublicAPI]
|
||||||
public bool? SaveUnmatchedRequests { get; set; }
|
public bool? SaveUnmatchedRequests { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Don't save the response-string in the LogEntry when WithBody(Func{IRequestMessage, string}) or WithBody(Func{IRequestMessage, Task{string}}) is used. (default set to false).
|
/// Don't save the response-string in the LogEntry when WithBody(Func{IRequestMessage, string}) or WithBody(Func{IRequestMessage, Task{string}}) is used. (default set to false).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[PublicAPI]
|
[PublicAPI]
|
||||||
public bool? DoNotSaveDynamicResponseInLogEntry { get; set; }
|
public bool? DoNotSaveDynamicResponseInLogEntry { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// See <seealso cref="QueryParameterMultipleValueSupport"/>.
|
/// See <seealso cref="QueryParameterMultipleValueSupport"/>.
|
||||||
///
|
///
|
||||||
/// Default value = "All".
|
/// Default value = "All".
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[PublicAPI]
|
[PublicAPI]
|
||||||
public QueryParameterMultipleValueSupport? QueryParameterMultipleValueSupport { get; set; }
|
public QueryParameterMultipleValueSupport? QueryParameterMultipleValueSupport { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Custom matcher mappings for static mappings
|
/// Custom matcher mappings for static mappings
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[PublicAPI, JsonIgnore]
|
[PublicAPI, JsonIgnore]
|
||||||
public IDictionary<string, Func<MatcherModel, IMatcher>>? CustomMatcherMappings { get; set; }
|
public IDictionary<string, Func<MatcherModel, IMatcher>>? CustomMatcherMappings { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The <see cref="JsonSerializerSettings"/> used when the a JSON response is generated.
|
/// The <see cref="JsonSerializerSettings"/> used when the a JSON response is generated.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[PublicAPI, JsonIgnore]
|
[PublicAPI, JsonIgnore]
|
||||||
public JsonSerializerSettings? JsonSerializerSettings { get; set; }
|
public JsonSerializerSettings? JsonSerializerSettings { get; set; }
|
||||||
}
|
|
||||||
|
/// <summary>
|
||||||
|
/// The Culture to use.
|
||||||
|
/// Currently used for:
|
||||||
|
/// - Handlebars Transformer
|
||||||
|
/// </summary>
|
||||||
|
public CultureInfo Culture { get; set; } = CultureInfo.CurrentCulture;
|
||||||
}
|
}
|
||||||
@@ -1,8 +1,11 @@
|
|||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Linq;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Stef.Validation;
|
using Stef.Validation;
|
||||||
using WireMock.Logging;
|
using WireMock.Logging;
|
||||||
using WireMock.Types;
|
using WireMock.Types;
|
||||||
|
using WireMock.Util;
|
||||||
|
|
||||||
namespace WireMock.Settings;
|
namespace WireMock.Settings;
|
||||||
|
|
||||||
@@ -55,7 +58,8 @@ public static class WireMockServerSettingsParser
|
|||||||
WatchStaticMappingsInSubdirectories = parser.GetBoolValue("WatchStaticMappingsInSubdirectories"),
|
WatchStaticMappingsInSubdirectories = parser.GetBoolValue("WatchStaticMappingsInSubdirectories"),
|
||||||
HostingScheme = parser.GetEnumValue<HostingScheme>(nameof(WireMockServerSettings.HostingScheme)),
|
HostingScheme = parser.GetEnumValue<HostingScheme>(nameof(WireMockServerSettings.HostingScheme)),
|
||||||
DoNotSaveDynamicResponseInLogEntry = parser.GetBoolValue(nameof(WireMockServerSettings.DoNotSaveDynamicResponseInLogEntry)),
|
DoNotSaveDynamicResponseInLogEntry = parser.GetBoolValue(nameof(WireMockServerSettings.DoNotSaveDynamicResponseInLogEntry)),
|
||||||
QueryParameterMultipleValueSupport = parser.GetEnumValue<QueryParameterMultipleValueSupport>(nameof(WireMockServerSettings.QueryParameterMultipleValueSupport))
|
QueryParameterMultipleValueSupport = parser.GetEnumValue<QueryParameterMultipleValueSupport>(nameof(WireMockServerSettings.QueryParameterMultipleValueSupport)),
|
||||||
|
Culture = parser.GetValue(nameof(WireMockServerSettings.Culture), strings => CultureInfoUtils.Parse(strings.FirstOrDefault()), CultureInfo.CurrentCulture)
|
||||||
};
|
};
|
||||||
|
|
||||||
#if USE_ASPNETCORE
|
#if USE_ASPNETCORE
|
||||||
|
|||||||
@@ -1,27 +1,26 @@
|
|||||||
using System;
|
|
||||||
using HandlebarsDotNet;
|
using HandlebarsDotNet;
|
||||||
using HandlebarsDotNet.Helpers.Attributes;
|
using HandlebarsDotNet.Helpers.Attributes;
|
||||||
using HandlebarsDotNet.Helpers.Enums;
|
using HandlebarsDotNet.Helpers.Enums;
|
||||||
using HandlebarsDotNet.Helpers.Helpers;
|
using HandlebarsDotNet.Helpers.Helpers;
|
||||||
|
using Stef.Validation;
|
||||||
using WireMock.Handlers;
|
using WireMock.Handlers;
|
||||||
|
|
||||||
namespace WireMock.Transformers.Handlebars
|
namespace WireMock.Transformers.Handlebars;
|
||||||
|
|
||||||
|
internal class FileHelpers : BaseHelpers, IHelpers
|
||||||
{
|
{
|
||||||
internal class FileHelpers : BaseHelpers, IHelpers
|
private readonly IFileSystemHandler _fileSystemHandler;
|
||||||
|
|
||||||
|
public FileHelpers(IHandlebars context, IFileSystemHandler fileSystemHandler) : base(context)
|
||||||
{
|
{
|
||||||
private readonly IFileSystemHandler _fileSystemHandler;
|
_fileSystemHandler = Guard.NotNull(fileSystemHandler);
|
||||||
|
}
|
||||||
|
|
||||||
public FileHelpers(IHandlebars context, IFileSystemHandler fileSystemHandler) : base(context)
|
[HandlebarsWriter(WriterType.String, usage: HelperUsage.Both, passContext: true, name: "File")]
|
||||||
{
|
public string Read(Context context, string path)
|
||||||
_fileSystemHandler = fileSystemHandler ?? throw new ArgumentNullException(nameof(fileSystemHandler));
|
{
|
||||||
}
|
var templateFunc = Context.Compile(path);
|
||||||
|
string transformed = templateFunc(context.Value);
|
||||||
[HandlebarsWriter(WriterType.String, usage: HelperUsage.Both, passContext: true, name: "File")]
|
return _fileSystemHandler.ReadResponseBodyAsString(transformed);
|
||||||
public string Read(Context context, string path)
|
|
||||||
{
|
|
||||||
var templateFunc = Context.Compile(path);
|
|
||||||
string transformed = templateFunc(context.Value);
|
|
||||||
return _fileSystemHandler.ReadResponseBodyAsString(transformed);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,18 +1,35 @@
|
|||||||
using HandlebarsDotNet;
|
using HandlebarsDotNet;
|
||||||
|
using HandlebarsDotNet.Helpers.Extensions;
|
||||||
|
using Stef.Validation;
|
||||||
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; }
|
||||||
|
|
||||||
|
public IFileSystemHandler FileSystemHandler { get; }
|
||||||
|
|
||||||
|
public HandlebarsContext(IHandlebars handlebars, IFileSystemHandler fileSystemHandler)
|
||||||
{
|
{
|
||||||
public IHandlebars Handlebars { get; set; }
|
Handlebars = Guard.NotNull(handlebars);
|
||||||
|
FileSystemHandler = Guard.NotNull(fileSystemHandler);
|
||||||
|
}
|
||||||
|
|
||||||
public IFileSystemHandler FileSystemHandler { get; set; }
|
public string ParseAndRender(string text, object model)
|
||||||
|
{
|
||||||
|
var template = Handlebars.Compile(text);
|
||||||
|
return template(model);
|
||||||
|
}
|
||||||
|
|
||||||
public string ParseAndRender(string text, object model)
|
public object? ParseAndEvaluate(string text, object model)
|
||||||
|
{
|
||||||
|
if (Handlebars.TryEvaluate(text, model, out var result) && result is not UndefinedBindingResult)
|
||||||
{
|
{
|
||||||
var template = Handlebars.Compile(text);
|
return result;
|
||||||
return template(model);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return ParseAndRender(text, model);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,33 +1,30 @@
|
|||||||
using System;
|
|
||||||
using HandlebarsDotNet;
|
using HandlebarsDotNet;
|
||||||
using Stef.Validation;
|
using Stef.Validation;
|
||||||
using WireMock.Handlers;
|
using WireMock.Settings;
|
||||||
|
|
||||||
namespace WireMock.Transformers.Handlebars;
|
namespace WireMock.Transformers.Handlebars;
|
||||||
|
|
||||||
internal class HandlebarsContextFactory : ITransformerContextFactory
|
internal class HandlebarsContextFactory : ITransformerContextFactory
|
||||||
{
|
{
|
||||||
private readonly IFileSystemHandler _fileSystemHandler;
|
private readonly WireMockServerSettings _settings;
|
||||||
private readonly Action<IHandlebars, IFileSystemHandler>? _action;
|
|
||||||
|
|
||||||
public HandlebarsContextFactory(IFileSystemHandler fileSystemHandler, Action<IHandlebars, IFileSystemHandler>? action)
|
public HandlebarsContextFactory(WireMockServerSettings settings)
|
||||||
{
|
{
|
||||||
_fileSystemHandler = Guard.NotNull(fileSystemHandler);
|
_settings = Guard.NotNull(settings);
|
||||||
_action = action;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ITransformerContext Create()
|
public ITransformerContext Create()
|
||||||
{
|
{
|
||||||
var handlebars = HandlebarsDotNet.Handlebars.Create();
|
var config = new HandlebarsConfiguration
|
||||||
|
|
||||||
WireMockHandlebarsHelpers.Register(handlebars, _fileSystemHandler);
|
|
||||||
|
|
||||||
_action?.Invoke(handlebars, _fileSystemHandler);
|
|
||||||
|
|
||||||
return new HandlebarsContext
|
|
||||||
{
|
{
|
||||||
Handlebars = handlebars,
|
FormatProvider = _settings.Culture
|
||||||
FileSystemHandler = _fileSystemHandler
|
|
||||||
};
|
};
|
||||||
|
var handlebars = HandlebarsDotNet.Handlebars.Create(config);
|
||||||
|
|
||||||
|
WireMockHandlebarsHelpers.Register(handlebars, _settings.FileSystemHandler);
|
||||||
|
|
||||||
|
_settings.HandlebarsRegistrationCallback?.Invoke(handlebars, _settings.FileSystemHandler);
|
||||||
|
|
||||||
|
return new HandlebarsContext(handlebars, _settings.FileSystemHandler);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,9 +1,8 @@
|
|||||||
using HandlebarsDotNet;
|
using HandlebarsDotNet;
|
||||||
|
|
||||||
namespace WireMock.Transformers.Handlebars
|
namespace WireMock.Transformers.Handlebars;
|
||||||
|
|
||||||
|
interface IHandlebarsContext : ITransformerContext
|
||||||
{
|
{
|
||||||
interface IHandlebarsContext : ITransformerContext
|
IHandlebars Handlebars { get; }
|
||||||
{
|
|
||||||
IHandlebars Handlebars { get; set; }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,11 +1,12 @@
|
|||||||
using WireMock.Handlers;
|
using WireMock.Handlers;
|
||||||
|
|
||||||
namespace WireMock.Transformers
|
namespace WireMock.Transformers;
|
||||||
|
|
||||||
|
internal interface ITransformerContext
|
||||||
{
|
{
|
||||||
interface ITransformerContext
|
IFileSystemHandler FileSystemHandler { get; }
|
||||||
{
|
|
||||||
IFileSystemHandler FileSystemHandler { get; set; }
|
|
||||||
|
|
||||||
string ParseAndRender(string text, object model);
|
string ParseAndRender(string text, object model);
|
||||||
}
|
|
||||||
|
object? ParseAndEvaluate(string text, object model);
|
||||||
}
|
}
|
||||||
@@ -3,25 +3,30 @@ using Stef.Validation;
|
|||||||
using WireMock.Handlers;
|
using WireMock.Handlers;
|
||||||
using WireMock.Types;
|
using WireMock.Types;
|
||||||
|
|
||||||
namespace WireMock.Transformers.Scriban
|
namespace WireMock.Transformers.Scriban;
|
||||||
|
|
||||||
|
internal class ScribanContext : ITransformerContext
|
||||||
{
|
{
|
||||||
internal class ScribanContext : ITransformerContext
|
private readonly TransformerType _transformerType;
|
||||||
|
|
||||||
|
public IFileSystemHandler FileSystemHandler { get; }
|
||||||
|
|
||||||
|
public ScribanContext(IFileSystemHandler fileSystemHandler, TransformerType transformerType)
|
||||||
{
|
{
|
||||||
private readonly TransformerType _transformerType;
|
FileSystemHandler = Guard.NotNull(fileSystemHandler);
|
||||||
|
_transformerType = transformerType;
|
||||||
|
}
|
||||||
|
|
||||||
public IFileSystemHandler FileSystemHandler { get; set; }
|
public string ParseAndRender(string text, object model)
|
||||||
|
{
|
||||||
|
var template = _transformerType == TransformerType.ScribanDotLiquid ? Template.ParseLiquid(text) : Template.Parse(text);
|
||||||
|
|
||||||
public ScribanContext(IFileSystemHandler fileSystemHandler, TransformerType transformerType)
|
return template.Render(model, member => member.Name);
|
||||||
{
|
}
|
||||||
FileSystemHandler = Guard.NotNull(fileSystemHandler);
|
|
||||||
_transformerType = transformerType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string ParseAndRender(string text, object model)
|
public object? ParseAndEvaluate(string text, object model)
|
||||||
{
|
{
|
||||||
var template = _transformerType == TransformerType.ScribanDotLiquid ? Template.ParseLiquid(text) : Template.Parse(text);
|
// In case of Scriban, call ParseAndRender.
|
||||||
|
return ParseAndRender(text, model);
|
||||||
return template.Render(model, member => member.Name);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,22 +2,21 @@ using WireMock.Handlers;
|
|||||||
using WireMock.Types;
|
using WireMock.Types;
|
||||||
using Stef.Validation;
|
using Stef.Validation;
|
||||||
|
|
||||||
namespace WireMock.Transformers.Scriban
|
namespace WireMock.Transformers.Scriban;
|
||||||
|
|
||||||
|
internal class ScribanContextFactory : ITransformerContextFactory
|
||||||
{
|
{
|
||||||
internal class ScribanContextFactory : ITransformerContextFactory
|
private readonly IFileSystemHandler _fileSystemHandler;
|
||||||
|
private readonly TransformerType _transformerType;
|
||||||
|
|
||||||
|
public ScribanContextFactory(IFileSystemHandler fileSystemHandler, TransformerType transformerType)
|
||||||
{
|
{
|
||||||
private readonly IFileSystemHandler _fileSystemHandler;
|
_fileSystemHandler = Guard.NotNull(fileSystemHandler);
|
||||||
private readonly TransformerType _transformerType;
|
_transformerType = Guard.Condition(transformerType, t => t is TransformerType.Scriban or TransformerType.ScribanDotLiquid);
|
||||||
|
}
|
||||||
|
|
||||||
public ScribanContextFactory(IFileSystemHandler fileSystemHandler, TransformerType transformerType)
|
public ITransformerContext Create()
|
||||||
{
|
{
|
||||||
_fileSystemHandler = Guard.NotNull(fileSystemHandler);
|
return new ScribanContext(_fileSystemHandler, _transformerType);
|
||||||
_transformerType = Guard.Condition(transformerType, t => t == TransformerType.Scriban || t == TransformerType.ScribanDotLiquid);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ITransformerContext Create()
|
|
||||||
{
|
|
||||||
return new ScribanContext(_fileSystemHandler, _transformerType);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,9 +1,11 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using System.Linq;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using Stef.Validation;
|
using Stef.Validation;
|
||||||
using System;
|
using WireMock.Settings;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using WireMock.Types;
|
using WireMock.Types;
|
||||||
using WireMock.Util;
|
using WireMock.Util;
|
||||||
|
|
||||||
@@ -11,11 +13,19 @@ namespace WireMock.Transformers;
|
|||||||
|
|
||||||
internal class Transformer : ITransformer
|
internal class Transformer : ITransformer
|
||||||
{
|
{
|
||||||
|
private static readonly Type[] SupportedTypes = { typeof(bool), typeof(long), typeof(int), typeof(double), typeof(Guid), typeof(DateTime), typeof(TimeSpan), typeof(Uri) };
|
||||||
|
|
||||||
|
private readonly JsonSerializer _jsonSerializer;
|
||||||
private readonly ITransformerContextFactory _factory;
|
private readonly ITransformerContextFactory _factory;
|
||||||
|
|
||||||
public Transformer(ITransformerContextFactory factory)
|
public Transformer(WireMockServerSettings settings, ITransformerContextFactory factory)
|
||||||
{
|
{
|
||||||
_factory = Guard.NotNull(factory);
|
_factory = Guard.NotNull(factory);
|
||||||
|
|
||||||
|
_jsonSerializer = new JsonSerializer
|
||||||
|
{
|
||||||
|
Culture = Guard.NotNull(settings).Culture
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public IBodyData? TransformBody(
|
public IBodyData? TransformBody(
|
||||||
@@ -109,7 +119,7 @@ internal class Transformer : ITransformer
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IBodyData? TransformBodyData(ITransformerContext transformerContext, ReplaceNodeOptions options, TransformModel model, IBodyData original, bool useTransformerForBodyAsFile)
|
private IBodyData? TransformBodyData(ITransformerContext transformerContext, ReplaceNodeOptions options, TransformModel model, IBodyData original, bool useTransformerForBodyAsFile)
|
||||||
{
|
{
|
||||||
return original.DetectedBodyType switch
|
return original.DetectedBodyType switch
|
||||||
{
|
{
|
||||||
@@ -139,33 +149,33 @@ internal class Transformer : ITransformer
|
|||||||
return newHeaders;
|
return newHeaders;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IBodyData TransformBodyAsJson(ITransformerContext handlebarsContext, ReplaceNodeOptions options, object model, IBodyData original)
|
private IBodyData TransformBodyAsJson(ITransformerContext transformerContext, ReplaceNodeOptions options, object model, IBodyData original)
|
||||||
{
|
{
|
||||||
JToken? jToken = null;
|
JToken? jToken = null;
|
||||||
switch (original.BodyAsJson)
|
switch (original.BodyAsJson)
|
||||||
{
|
{
|
||||||
case JObject bodyAsJObject:
|
case JObject bodyAsJObject:
|
||||||
jToken = bodyAsJObject.DeepClone();
|
jToken = bodyAsJObject.DeepClone();
|
||||||
WalkNode(handlebarsContext, options, jToken, model);
|
WalkNode(transformerContext, options, jToken, model);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case JArray bodyAsJArray:
|
case JArray bodyAsJArray:
|
||||||
jToken = bodyAsJArray.DeepClone();
|
jToken = bodyAsJArray.DeepClone();
|
||||||
WalkNode(handlebarsContext, options, jToken, model);
|
WalkNode(transformerContext, options, jToken, model);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Array bodyAsArray:
|
case Array bodyAsArray:
|
||||||
jToken = JArray.FromObject(bodyAsArray);
|
jToken = JArray.FromObject(bodyAsArray, _jsonSerializer);
|
||||||
WalkNode(handlebarsContext, options, jToken, model);
|
WalkNode(transformerContext, options, jToken, model);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case string bodyAsString:
|
case string bodyAsString:
|
||||||
jToken = ReplaceSingleNode(handlebarsContext, options, bodyAsString, model);
|
jToken = ReplaceSingleNode(transformerContext, options, bodyAsString, model);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case not null:
|
case not null:
|
||||||
jToken = JObject.FromObject(original.BodyAsJson);
|
jToken = JObject.FromObject(original.BodyAsJson, _jsonSerializer);
|
||||||
WalkNode(handlebarsContext, options, jToken, model);
|
WalkNode(transformerContext, options, jToken, model);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -178,9 +188,9 @@ internal class Transformer : ITransformer
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static JToken ReplaceSingleNode(ITransformerContext handlebarsContext, ReplaceNodeOptions options, string stringValue, object model)
|
private JToken ReplaceSingleNode(ITransformerContext transformerContext, ReplaceNodeOptions options, string stringValue, object model)
|
||||||
{
|
{
|
||||||
string transformedString = handlebarsContext.ParseAndRender(stringValue, model);
|
string transformedString = transformerContext.ParseAndRender(stringValue, model);
|
||||||
|
|
||||||
if (!string.Equals(stringValue, transformedString))
|
if (!string.Equals(stringValue, transformedString))
|
||||||
{
|
{
|
||||||
@@ -202,7 +212,7 @@ internal class Transformer : ITransformer
|
|||||||
return stringValue;
|
return stringValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void WalkNode(ITransformerContext handlebarsContext, ReplaceNodeOptions options, JToken node, object model)
|
private void WalkNode(ITransformerContext transformerContext, ReplaceNodeOptions options, JToken node, object model)
|
||||||
{
|
{
|
||||||
switch (node.Type)
|
switch (node.Type)
|
||||||
{
|
{
|
||||||
@@ -210,7 +220,7 @@ internal class Transformer : ITransformer
|
|||||||
// In case of Object, loop all children. Do a ToArray() to avoid `Collection was modified` exceptions.
|
// In case of Object, loop all children. Do a ToArray() to avoid `Collection was modified` exceptions.
|
||||||
foreach (var child in node.Children<JProperty>().ToArray())
|
foreach (var child in node.Children<JProperty>().ToArray())
|
||||||
{
|
{
|
||||||
WalkNode(handlebarsContext, options, child.Value, model);
|
WalkNode(transformerContext, options, child.Value, model);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -218,7 +228,7 @@ internal class Transformer : ITransformer
|
|||||||
// In case of Array, loop all items. Do a ToArray() to avoid `Collection was modified` exceptions.
|
// In case of Array, loop all items. Do a ToArray() to avoid `Collection was modified` exceptions.
|
||||||
foreach (var child in node.Children().ToArray())
|
foreach (var child in node.Children().ToArray())
|
||||||
{
|
{
|
||||||
WalkNode(handlebarsContext, options, child, model);
|
WalkNode(transformerContext, options, child, model);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -230,8 +240,8 @@ internal class Transformer : ITransformer
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
string transformed = handlebarsContext.ParseAndRender(stringValue!, model);
|
var transformed = transformerContext.ParseAndEvaluate(stringValue, model);
|
||||||
if (!string.Equals(stringValue, transformed))
|
if (!Equals(stringValue, transformed))
|
||||||
{
|
{
|
||||||
ReplaceNodeValue(options, node, transformed);
|
ReplaceNodeValue(options, node, transformed);
|
||||||
}
|
}
|
||||||
@@ -240,44 +250,88 @@ internal class Transformer : ITransformer
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ReSharper disable once UnusedParameter.Local
|
// ReSharper disable once UnusedParameter.Local
|
||||||
private static void ReplaceNodeValue(ReplaceNodeOptions options, JToken node, string transformedString)
|
private void ReplaceNodeValue(ReplaceNodeOptions options, JToken node, object? transformedValue)
|
||||||
{
|
{
|
||||||
StringUtils.TryParseQuotedString(transformedString, out var result, out _);
|
switch (transformedValue)
|
||||||
if (bool.TryParse(result, out var valueAsBoolean) || bool.TryParse(transformedString, out valueAsBoolean))
|
|
||||||
{
|
{
|
||||||
node.Replace(valueAsBoolean);
|
case JValue jValue:
|
||||||
return;
|
node.Replace(jValue);
|
||||||
}
|
return;
|
||||||
|
|
||||||
JToken value;
|
case string transformedString:
|
||||||
try
|
if (TryConvert(transformedString, out var convertedFromStringValue))
|
||||||
{
|
{
|
||||||
// Try to convert this string into a JsonObject
|
node.Replace(JToken.FromObject(convertedFromStringValue, _jsonSerializer));
|
||||||
value = JToken.Parse(transformedString);
|
}
|
||||||
}
|
else
|
||||||
catch (JsonException)
|
{
|
||||||
{
|
node.Replace(ParseAsJObject(transformedString));
|
||||||
// Ignore JsonException and just keep string value and convert to JToken
|
}
|
||||||
value = transformedString;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
node.Replace(value);
|
case WireMockList<string> strings:
|
||||||
|
switch (strings.Count)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
node.Replace(ParseAsJObject(strings[0]));
|
||||||
|
return;
|
||||||
|
|
||||||
|
case > 1:
|
||||||
|
node.Replace(JToken.FromObject(strings.ToArray(), _jsonSerializer));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case { }:
|
||||||
|
if (TryConvert(transformedValue, out var convertedValue))
|
||||||
|
{
|
||||||
|
node.Replace(JToken.FromObject(convertedValue, _jsonSerializer));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
|
||||||
|
default: // It's null, skip it. Maybe remove it ?
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IBodyData TransformBodyAsString(ITransformerContext handlebarsContext, object model, IBodyData original)
|
private static JToken ParseAsJObject(string stringValue)
|
||||||
|
{
|
||||||
|
return JsonUtils.TryParseAsJObject(stringValue, out var parsedAsjObject) ? parsedAsjObject : stringValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool TryConvert(object? transformedValue, [NotNullWhen(true)] out object? convertedValue)
|
||||||
|
{
|
||||||
|
foreach (var supportedType in SupportedTypes)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
convertedValue = Convert.ChangeType(transformedValue, supportedType);
|
||||||
|
return convertedValue is not null;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// Ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
convertedValue = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IBodyData TransformBodyAsString(ITransformerContext transformerContext, object model, IBodyData original)
|
||||||
{
|
{
|
||||||
return new BodyData
|
return new BodyData
|
||||||
{
|
{
|
||||||
Encoding = original.Encoding,
|
Encoding = original.Encoding,
|
||||||
DetectedBodyType = original.DetectedBodyType,
|
DetectedBodyType = original.DetectedBodyType,
|
||||||
DetectedBodyTypeFromContentType = original.DetectedBodyTypeFromContentType,
|
DetectedBodyTypeFromContentType = original.DetectedBodyTypeFromContentType,
|
||||||
BodyAsString = handlebarsContext.ParseAndRender(original.BodyAsString!, model)
|
BodyAsString = transformerContext.ParseAndRender(original.BodyAsString!, model)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IBodyData TransformBodyAsFile(ITransformerContext handlebarsContext, object model, IBodyData original, bool useTransformerForBodyAsFile)
|
private static IBodyData TransformBodyAsFile(ITransformerContext transformerContext, object model, IBodyData original, bool useTransformerForBodyAsFile)
|
||||||
{
|
{
|
||||||
string transformedBodyAsFilename = handlebarsContext.ParseAndRender(original.BodyAsFile!, model);
|
string transformedBodyAsFilename = transformerContext.ParseAndRender(original.BodyAsFile!, model);
|
||||||
|
|
||||||
if (!useTransformerForBodyAsFile)
|
if (!useTransformerForBodyAsFile)
|
||||||
{
|
{
|
||||||
@@ -289,12 +343,12 @@ internal class Transformer : ITransformer
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
string text = handlebarsContext.FileSystemHandler.ReadResponseBodyAsString(transformedBodyAsFilename);
|
string text = transformerContext.FileSystemHandler.ReadResponseBodyAsString(transformedBodyAsFilename);
|
||||||
return new BodyData
|
return new BodyData
|
||||||
{
|
{
|
||||||
DetectedBodyType = BodyType.String,
|
DetectedBodyType = BodyType.String,
|
||||||
DetectedBodyTypeFromContentType = original.DetectedBodyTypeFromContentType,
|
DetectedBodyTypeFromContentType = original.DetectedBodyTypeFromContentType,
|
||||||
BodyAsString = handlebarsContext.ParseAndRender(text, model),
|
BodyAsString = transformerContext.ParseAndRender(text, model),
|
||||||
BodyAsFile = transformedBodyAsFilename
|
BodyAsFile = transformedBodyAsFilename
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
using System;
|
||||||
|
using System.Globalization;
|
||||||
|
|
||||||
|
namespace WireMock.Util;
|
||||||
|
|
||||||
|
internal static class CultureInfoUtils
|
||||||
|
{
|
||||||
|
public static CultureInfo Parse(string? value)
|
||||||
|
{
|
||||||
|
if (value is null)
|
||||||
|
{
|
||||||
|
return CultureInfo.CurrentCulture;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
#if !NETSTANDARD1_3
|
||||||
|
if (int.TryParse(value, out var culture))
|
||||||
|
{
|
||||||
|
return new CultureInfo(culture);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (string.Equals(value, nameof(CultureInfo.CurrentCulture), StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
return CultureInfo.CurrentCulture;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.Equals(value, nameof(CultureInfo.InvariantCulture), StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
return CultureInfo.InvariantCulture;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new CultureInfo(value);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return CultureInfo.CurrentCulture;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -87,8 +87,8 @@
|
|||||||
<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="Nullable" Version="1.3.1">
|
<PackageReference Include="Nullable" Version="1.3.1">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
@@ -163,13 +163,13 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Handlebars.Net.Helpers" Version="2.3.10" />
|
<PackageReference Include="Handlebars.Net.Helpers" Version="2.3.11" />
|
||||||
<PackageReference Include="Handlebars.Net.Helpers.DynamicLinq" Version="2.3.10" />
|
<PackageReference Include="Handlebars.Net.Helpers.DynamicLinq" Version="2.3.11" />
|
||||||
<PackageReference Include="Handlebars.Net.Helpers.Humanizer" Version="2.3.10" />
|
<PackageReference Include="Handlebars.Net.Helpers.Humanizer" Version="2.3.11" />
|
||||||
<PackageReference Include="Handlebars.Net.Helpers.Json" Version="2.3.10" />
|
<PackageReference Include="Handlebars.Net.Helpers.Json" Version="2.3.11" />
|
||||||
<PackageReference Include="Handlebars.Net.Helpers.Random" Version="2.3.10" />
|
<PackageReference Include="Handlebars.Net.Helpers.Random" Version="2.3.11" />
|
||||||
<PackageReference Include="Handlebars.Net.Helpers.XPath" Version="2.3.10" />
|
<PackageReference Include="Handlebars.Net.Helpers.XPath" Version="2.3.11" />
|
||||||
<PackageReference Include="Handlebars.Net.Helpers.Xeger" Version="2.3.10" />
|
<PackageReference Include="Handlebars.Net.Helpers.Xeger" Version="2.3.11" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ public class ResponseWithHandlebarsJsonPathTests
|
|||||||
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
|
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
JObject j = JObject.FromObject(response.Message.BodyData.BodyAsJson);
|
JObject j = JObject.FromObject(response.Message.BodyData.BodyAsJson!);
|
||||||
Check.That(j["x"].Value<long>()).Equals(99);
|
Check.That(j["x"].Value<long>()).Equals(99);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ public class ResponseWithHandlebarsRandomTests
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
[InlineData(ReplaceNodeOptions.None, JTokenType.Integer)]
|
[InlineData(ReplaceNodeOptions.Evaluate, JTokenType.Integer)]
|
||||||
//[InlineData(ReplaceNodeOptions.Bool, JTokenType.String)]
|
//[InlineData(ReplaceNodeOptions.Bool, JTokenType.String)]
|
||||||
//[InlineData(ReplaceNodeOptions.Integer, JTokenType.Integer)]
|
//[InlineData(ReplaceNodeOptions.Integer, JTokenType.Integer)]
|
||||||
//[InlineData(ReplaceNodeOptions.Bool | ReplaceNodeOptions.Integer, JTokenType.Integer)]
|
//[InlineData(ReplaceNodeOptions.Bool | ReplaceNodeOptions.Integer, JTokenType.Integer)]
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ using WireMock.Settings;
|
|||||||
using WireMock.Types;
|
using WireMock.Types;
|
||||||
using WireMock.Util;
|
using WireMock.Util;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
using System.Globalization;
|
||||||
|
using CultureAwareTesting.xUnit;
|
||||||
#if NET452
|
#if NET452
|
||||||
using Microsoft.Owin;
|
using Microsoft.Owin;
|
||||||
#else
|
#else
|
||||||
@@ -24,6 +26,7 @@ namespace WireMock.Net.Tests.ResponseBuilders;
|
|||||||
|
|
||||||
public class ResponseWithTransformerTests
|
public class ResponseWithTransformerTests
|
||||||
{
|
{
|
||||||
|
private readonly Mock<IFileSystemHandler> _filesystemHandlerMock;
|
||||||
private readonly WireMockServerSettings _settings = new();
|
private readonly WireMockServerSettings _settings = new();
|
||||||
private const string ClientIp = "::1";
|
private const string ClientIp = "::1";
|
||||||
|
|
||||||
@@ -33,10 +36,10 @@ public class ResponseWithTransformerTests
|
|||||||
{
|
{
|
||||||
_mappingMock = new Mock<IMapping>();
|
_mappingMock = new Mock<IMapping>();
|
||||||
|
|
||||||
var filesystemHandlerMock = new Mock<IFileSystemHandler>(MockBehavior.Strict);
|
_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]
|
||||||
@@ -333,7 +336,7 @@ public class ResponseWithTransformerTests
|
|||||||
// Assert
|
// Assert
|
||||||
Check.That(response.Message.BodyData!.BodyAsString).Equals("test");
|
Check.That(response.Message.BodyData!.BodyAsString).Equals("test");
|
||||||
Check.That(response.Message.Headers).ContainsKey("x");
|
Check.That(response.Message.Headers).ContainsKey("x");
|
||||||
Check.That(response.Message.Headers["x"]).Contains("text/plain");
|
Check.That(response.Message.Headers!["x"]).Contains("text/plain");
|
||||||
Check.That(response.Message.Headers["x"]).Contains("http://localhost/foo");
|
Check.That(response.Message.Headers["x"]).Contains("http://localhost/foo");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -358,7 +361,7 @@ public class ResponseWithTransformerTests
|
|||||||
// Assert
|
// Assert
|
||||||
Check.That(response.Message.BodyData!.BodyAsString).Equals("test");
|
Check.That(response.Message.BodyData!.BodyAsString).Equals("test");
|
||||||
Check.That(response.Message.Headers).ContainsKey("x");
|
Check.That(response.Message.Headers).ContainsKey("x");
|
||||||
Check.That(response.Message.Headers["x"]).Contains("text/plain");
|
Check.That(response.Message.Headers!["x"]).Contains("text/plain");
|
||||||
Check.That(response.Message.Headers["x"]).Contains("http://localhost/foo");
|
Check.That(response.Message.Headers["x"]).Contains("http://localhost/foo");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -394,7 +397,7 @@ public class ResponseWithTransformerTests
|
|||||||
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 = "{ \"id\": 42, \"things\": [ { \"name\": \"RequiredThing\" }, { \"name\": \"WireMock\" } ] }";
|
||||||
var bodyData = new BodyData
|
var bodyData = new BodyData
|
||||||
{
|
{
|
||||||
BodyAsJson = JsonConvert.DeserializeObject(jsonString),
|
BodyAsJson = JsonConvert.DeserializeObject(jsonString),
|
||||||
@@ -411,7 +414,49 @@ public class ResponseWithTransformerTests
|
|||||||
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
|
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
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\"}");
|
||||||
|
}
|
||||||
|
|
||||||
|
[CulturedTheory("en-US")]
|
||||||
|
[InlineData(TransformerType.Handlebars, "{ \"id\": 42 }", "{\"x\":\"test 42\",\"y\":42}")]
|
||||||
|
[InlineData(TransformerType.Scriban, "{ \"id\": 42 }", "{\"x\":\"test 42\",\"y\":42}")]
|
||||||
|
[InlineData(TransformerType.ScribanDotLiquid, "{ \"id\": 42 }", "{\"x\":\"test 42\",\"y\":42}")]
|
||||||
|
[InlineData(TransformerType.Handlebars, "{ \"id\": true }", "{\"x\":\"test True\",\"y\":true}")]
|
||||||
|
[InlineData(TransformerType.Scriban, "{ \"id\": true }", "{\"x\":\"test True\",\"y\":true}")]
|
||||||
|
[InlineData(TransformerType.ScribanDotLiquid, "{ \"id\": true }", "{\"x\":\"test True\",\"y\":true}")]
|
||||||
|
[InlineData(TransformerType.Handlebars, "{ \"id\": 0.005 }", "{\"x\":\"test 0.005\",\"y\":0.005}")]
|
||||||
|
[InlineData(TransformerType.Scriban, "{ \"id\": 0.005 }", "{\"x\":\"test 0.005\",\"y\":0.005}")]
|
||||||
|
[InlineData(TransformerType.ScribanDotLiquid, "{ \"id\": 0.005 }", "{\"x\":\"test 0.005\",\"y\":0.005}")]
|
||||||
|
public async Task Response_ProvideResponse_Transformer_WithBodyAsJson_KeepType(TransformerType transformerType, string jsonString, string expected)
|
||||||
|
{
|
||||||
|
// Assign
|
||||||
|
var culture = CultureInfo.CreateSpecificCulture("en-US");
|
||||||
|
var settings = new WireMockServerSettings
|
||||||
|
{
|
||||||
|
FileSystemHandler = _filesystemHandlerMock.Object,
|
||||||
|
Culture = culture
|
||||||
|
};
|
||||||
|
var jsonSettings = new JsonSerializerSettings
|
||||||
|
{
|
||||||
|
Culture = culture
|
||||||
|
};
|
||||||
|
var bodyData = new BodyData
|
||||||
|
{
|
||||||
|
BodyAsJson = JsonConvert.DeserializeObject(jsonString, jsonSettings),
|
||||||
|
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 { x = "test {{request.BodyAsJson.id}}", y = "{{request.BodyAsJson.id}}" })
|
||||||
|
.WithTransformer(transformerType);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, settings).ConfigureAwait(false);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
JsonConvert.SerializeObject(response.Message.BodyData!.BodyAsJson).Should().Be(expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
@@ -431,7 +476,7 @@ public class ResponseWithTransformerTests
|
|||||||
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
|
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
JsonConvert.SerializeObject(response.Message.BodyData.BodyAsJson).Should().Be("[{\"x\":\"test\"}]");
|
JsonConvert.SerializeObject(response.Message.BodyData!.BodyAsJson).Should().Be("[{\"x\":\"test\"}]");
|
||||||
}
|
}
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
@@ -452,7 +497,7 @@ public class ResponseWithTransformerTests
|
|||||||
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
|
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
JsonConvert.SerializeObject(response.Message.BodyData.BodyAsJson).Should().Be("[{\"x\":\"test\"}]");
|
JsonConvert.SerializeObject(response.Message.BodyData!.BodyAsJson).Should().Be("[{\"x\":\"test\"}]");
|
||||||
}
|
}
|
||||||
|
|
||||||
//[Theory]
|
//[Theory]
|
||||||
@@ -488,15 +533,15 @@ public class ResponseWithTransformerTests
|
|||||||
[InlineData(TransformerType.Handlebars, "\"a\"", "\"a\"")]
|
[InlineData(TransformerType.Handlebars, "\"a\"", "\"a\"")]
|
||||||
[InlineData(TransformerType.Handlebars, "\" \"", "\" \"")]
|
[InlineData(TransformerType.Handlebars, "\" \"", "\" \"")]
|
||||||
[InlineData(TransformerType.Handlebars, "\"'\"", "\"'\"")]
|
[InlineData(TransformerType.Handlebars, "\"'\"", "\"'\"")]
|
||||||
[InlineData(TransformerType.Handlebars, "\"false\"", "false")] // bool is special
|
[InlineData(TransformerType.Handlebars, "\"false\"", "\"false\"")]
|
||||||
[InlineData(TransformerType.Handlebars, "false", "false")]
|
[InlineData(TransformerType.Handlebars, "false", "false")]
|
||||||
[InlineData(TransformerType.Handlebars, "\"true\"", "true")] // bool is special
|
[InlineData(TransformerType.Handlebars, "\"true\"", "\"true\"")]
|
||||||
[InlineData(TransformerType.Handlebars, "true", "true")]
|
[InlineData(TransformerType.Handlebars, "true", "true")]
|
||||||
[InlineData(TransformerType.Handlebars, "\"-42\"", "-42")] // todo
|
[InlineData(TransformerType.Handlebars, "\"-42\"", "\"-42\"")]
|
||||||
[InlineData(TransformerType.Handlebars, "-42", "-42")]
|
[InlineData(TransformerType.Handlebars, "-42", "-42")]
|
||||||
[InlineData(TransformerType.Handlebars, "\"2147483647\"", "2147483647")] // todo
|
[InlineData(TransformerType.Handlebars, "\"2147483647\"", "\"2147483647\"")]
|
||||||
[InlineData(TransformerType.Handlebars, "2147483647", "2147483647")]
|
[InlineData(TransformerType.Handlebars, "2147483647", "2147483647")]
|
||||||
[InlineData(TransformerType.Handlebars, "\"9223372036854775807\"", "9223372036854775807")] // todo
|
[InlineData(TransformerType.Handlebars, "\"9223372036854775807\"", "\"9223372036854775807\"")]
|
||||||
[InlineData(TransformerType.Handlebars, "9223372036854775807", "9223372036854775807")]
|
[InlineData(TransformerType.Handlebars, "9223372036854775807", "9223372036854775807")]
|
||||||
public async Task Response_ProvideResponse_Transformer_WithBodyAsJson_And_ReplaceNodeOptionsKeep(TransformerType transformerType, string value, string expected)
|
public async Task Response_ProvideResponse_Transformer_WithBodyAsJson_And_ReplaceNodeOptionsKeep(TransformerType transformerType, string value, string expected)
|
||||||
{
|
{
|
||||||
@@ -511,50 +556,13 @@ public class ResponseWithTransformerTests
|
|||||||
|
|
||||||
var responseBuilder = Response.Create()
|
var responseBuilder = Response.Create()
|
||||||
.WithBodyAsJson(new { text = "{{request.bodyAsJson.x}}" })
|
.WithBodyAsJson(new { text = "{{request.bodyAsJson.x}}" })
|
||||||
.WithTransformer(transformerType, false, ReplaceNodeOptions.None);
|
.WithTransformer(transformerType, false, ReplaceNodeOptions.Evaluate);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
|
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
JsonConvert.SerializeObject(response.Message.BodyData.BodyAsJson).Should().Be($"{{\"text\":{expected}}}");
|
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(_mappingMock.Object, request, _settings).ConfigureAwait(false);
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
JsonConvert.SerializeObject(response.Message.BodyData.BodyAsJson).Should().Be($"{{\"text\":{expected}}}");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
@@ -581,7 +589,7 @@ public class ResponseWithTransformerTests
|
|||||||
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
|
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Check.That(JsonConvert.SerializeObject(response.Message.BodyData.BodyAsJson)).Equals("[\"first\",\"/foo_array\",\"test 1\",\"test 2\",\"last\"]");
|
Check.That(JsonConvert.SerializeObject(response.Message.BodyData!.BodyAsJson)).Equals("[\"first\",\"/foo_array\",\"test 1\",\"test 2\",\"last\"]");
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
@@ -598,7 +606,7 @@ public class ResponseWithTransformerTests
|
|||||||
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
|
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Check.That(response.Message.BodyData.BodyAsFile).Equals(@"c:\1\test.xml");
|
Check.That(response.Message.BodyData!.BodyAsFile).Equals(@"c:\1\test.xml");
|
||||||
}
|
}
|
||||||
|
|
||||||
[Theory(Skip = @"Does not work in Scriban --> c:\\[""1""]\\test.xml")]
|
[Theory(Skip = @"Does not work in Scriban --> c:\\[""1""]\\test.xml")]
|
||||||
@@ -617,7 +625,7 @@ public class ResponseWithTransformerTests
|
|||||||
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
|
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Check.That(response.Message.BodyData.BodyAsFile).Equals(@"c:\1\test.xml");
|
Check.That(response.Message.BodyData!.BodyAsFile).Equals(@"c:\1\test.xml");
|
||||||
}
|
}
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
@@ -642,7 +650,7 @@ public class ResponseWithTransformerTests
|
|||||||
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
|
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Check.That(response.Message.BodyData.BodyAsFile).Equals(@"c:\1\test.xml");
|
Check.That(response.Message.BodyData!.BodyAsFile).Equals(@"c:\1\test.xml");
|
||||||
Check.That(response.Message.BodyData.DetectedBodyType).Equals(BodyType.String);
|
Check.That(response.Message.BodyData.DetectedBodyType).Equals(BodyType.String);
|
||||||
Check.That(response.Message.BodyData!.BodyAsString).Equals("<xml MyUniqueNumber=\"1\"></xml>");
|
Check.That(response.Message.BodyData!.BodyAsString).Equals("<xml MyUniqueNumber=\"1\"></xml>");
|
||||||
}
|
}
|
||||||
@@ -671,14 +679,15 @@ public class ResponseWithTransformerTests
|
|||||||
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
|
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Check.That(JsonConvert.SerializeObject(response.Message.BodyData.BodyAsJson)).Equals("\"test\"");
|
Check.That(JsonConvert.SerializeObject(response.Message.BodyData!.BodyAsJson)).Equals("\"test\"");
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact(Skip = "todo...")]
|
[Fact(Skip = "todo...")]
|
||||||
|
//[Fact]
|
||||||
public async Task Response_ProvideResponse_Handlebars_WithBodyAsJson_ResultAsTemplatedString()
|
public async Task Response_ProvideResponse_Handlebars_WithBodyAsJson_ResultAsTemplatedString()
|
||||||
{
|
{
|
||||||
// Assign
|
// Assign
|
||||||
string jsonString = "{ \"name\": \"WireMock\" }";
|
string jsonString = "{ \"name\": \"WireMock\", \"id\": 12345 }";
|
||||||
var bodyData = new BodyData
|
var bodyData = new BodyData
|
||||||
{
|
{
|
||||||
BodyAsJson = JsonConvert.DeserializeObject(jsonString),
|
BodyAsJson = JsonConvert.DeserializeObject(jsonString),
|
||||||
@@ -688,14 +697,14 @@ public class ResponseWithTransformerTests
|
|||||||
var request = new RequestMessage(new UrlDetails("http://localhost/foo_object"), "POST", ClientIp, bodyData);
|
var request = new RequestMessage(new UrlDetails("http://localhost/foo_object"), "POST", ClientIp, bodyData);
|
||||||
|
|
||||||
var responseBuilder = Response.Create()
|
var responseBuilder = Response.Create()
|
||||||
.WithBodyAsJson("{{{request.BodyAsJson}}}")
|
.WithBodyAsJson("{{{request.BodyAsJson.name}}}")
|
||||||
.WithTransformer();
|
.WithTransformer();
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
|
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Check.That(JsonConvert.SerializeObject(response.Message.BodyData.BodyAsJson)).Equals("{\"name\":\"WireMock\"}");
|
Check.That(JsonConvert.SerializeObject(response.Message.BodyData!.BodyAsJson)).Equals("{\"name\":\"WireMock\"}");
|
||||||
}
|
}
|
||||||
|
|
||||||
[Theory(Skip = "{{{ }}} Does not work in Scriban")]
|
[Theory(Skip = "{{{ }}} Does not work in Scriban")]
|
||||||
@@ -721,7 +730,7 @@ public class ResponseWithTransformerTests
|
|||||||
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
|
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Check.That(JsonConvert.SerializeObject(response.Message.BodyData.BodyAsJson)).Equals("{\"name\":\"WireMock\"}");
|
Check.That(JsonConvert.SerializeObject(response.Message.BodyData!.BodyAsJson)).Equals("{\"name\":\"WireMock\"}");
|
||||||
}
|
}
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
@@ -749,7 +758,7 @@ public class ResponseWithTransformerTests
|
|||||||
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
|
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
response.Message.BodyData.BodyAsString.Should().Be(text);
|
response.Message.BodyData!.BodyAsString.Should().Be(text);
|
||||||
response.Message.BodyData.Encoding.Should().Be(enc);
|
response.Message.BodyData.Encoding.Should().Be(enc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,52 +1,59 @@
|
|||||||
using System;
|
|
||||||
using FluentAssertions;
|
using FluentAssertions;
|
||||||
using HandlebarsDotNet;
|
|
||||||
using Moq;
|
using Moq;
|
||||||
using WireMock.Handlers;
|
using WireMock.Handlers;
|
||||||
|
using WireMock.Settings;
|
||||||
using WireMock.Transformers.Handlebars;
|
using WireMock.Transformers.Handlebars;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace WireMock.Net.Tests.Transformers.Handlebars
|
namespace WireMock.Net.Tests.Transformers.Handlebars;
|
||||||
|
|
||||||
|
public class HandlebarsContextFactoryTests
|
||||||
{
|
{
|
||||||
public class HandlebarsContextFactoryTests
|
private readonly Mock<IFileSystemHandler> _fileSystemHandlerMock = new();
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Create_WithNullAction_DoesNotInvokeAction()
|
||||||
{
|
{
|
||||||
private readonly Mock<IFileSystemHandler> _fileSystemHandlerMock = new Mock<IFileSystemHandler>();
|
// Arrange
|
||||||
|
var settings = new WireMockServerSettings
|
||||||
[Fact]
|
|
||||||
public void Create_WithNullAction_DoesNotInvokeAction()
|
|
||||||
{
|
{
|
||||||
// Arrange
|
FileSystemHandler = _fileSystemHandlerMock.Object
|
||||||
var sut = new HandlebarsContextFactory(_fileSystemHandlerMock.Object, null);
|
};
|
||||||
|
var sut = new HandlebarsContextFactory(settings);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var result = sut.Create();
|
var result = sut.Create();
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
result.Should().NotBeNull();
|
result.Should().NotBeNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Create_WithAction_InvokesAction()
|
public void Create_WithAction_InvokesAction()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
int num = 0;
|
||||||
|
var settings = new WireMockServerSettings
|
||||||
{
|
{
|
||||||
// Arrange
|
FileSystemHandler = _fileSystemHandlerMock.Object,
|
||||||
int num = 0;
|
HandlebarsRegistrationCallback = (ctx, fs) =>
|
||||||
Action<IHandlebars, IFileSystemHandler> action = (ctx, fs) =>
|
|
||||||
{
|
{
|
||||||
ctx.Should().NotBeNull();
|
ctx.Should().NotBeNull();
|
||||||
fs.Should().NotBeNull();
|
fs.Should().NotBeNull();
|
||||||
|
|
||||||
num++;
|
num++;
|
||||||
};
|
}
|
||||||
var sut = new HandlebarsContextFactory(_fileSystemHandlerMock.Object, action);
|
};
|
||||||
|
|
||||||
// Act
|
var sut = new HandlebarsContextFactory(settings);
|
||||||
var result = sut.Create();
|
|
||||||
|
|
||||||
// Assert
|
// Act
|
||||||
result.Should().NotBeNull();
|
var result = sut.Create();
|
||||||
|
|
||||||
// Verify
|
// Assert
|
||||||
num.Should().Be(1);
|
result.Should().NotBeNull();
|
||||||
}
|
|
||||||
|
// Verify
|
||||||
|
num.Should().Be(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -20,6 +20,10 @@
|
|||||||
<GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
|
<GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup Condition="'$(TargetFramework)' == 'net452' or '$(TargetFramework)' == 'net461'">
|
||||||
|
<DefineConstants>NETFRAMEWORK</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\..\src\WireMock.Net.Abstractions\WireMock.Net.Abstractions.csproj" />
|
<ProjectReference Include="..\..\src\WireMock.Net.Abstractions\WireMock.Net.Abstractions.csproj" />
|
||||||
<ProjectReference Include="..\..\src\WireMock.Net.FluentAssertions\WireMock.Net.FluentAssertions.csproj" />
|
<ProjectReference Include="..\..\src\WireMock.Net.FluentAssertions\WireMock.Net.FluentAssertions.csproj" />
|
||||||
@@ -35,8 +39,10 @@
|
|||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
|
<PackageReference Include="CultureAwareTesting.xUnit" Version="0.0.1" />
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.4.0" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.4.0" />
|
||||||
<PackageReference Include="xunit" Version="2.4.1" />
|
<PackageReference Include="xunit" Version="2.4.1" />
|
||||||
|
<PackageReference Include="xunit.core" Version="2.4.1" />
|
||||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
|
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
|||||||
Reference in New Issue
Block a user