mirror of
https://github.com/wiremock/WireMock.Net.git
synced 2026-02-14 22:37:41 +01:00
Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
43d481435c | ||
|
|
ea1be6641a | ||
|
|
93613885c1 | ||
|
|
caee5895eb | ||
|
|
101d755a00 | ||
|
|
368fdd4c7d |
12
CHANGELOG.md
12
CHANGELOG.md
@@ -1,3 +1,15 @@
|
||||
# 1.1.3.0 (22 January 2020)
|
||||
- [#403](https://github.com/WireMock-Net/WireMock.Net/pull/403) - Fix for invalid cast exception contributed by [kashifsoofi](https://github.com/kashifsoofi)
|
||||
- [#402](https://github.com/WireMock-Net/WireMock.Net/issues/402) - Invalid Cast Exception [bug]
|
||||
|
||||
# 1.1.2.0 (09 January 2020)
|
||||
- [#399](https://github.com/WireMock-Net/WireMock.Net/pull/399) - ResponseModel.StatusCode is deserialized as either string or long. [bug] contributed by [vitaliydavydiak](https://github.com/vitaliydavydiak)
|
||||
- [#400](https://github.com/WireMock-Net/WireMock.Net/issues/400) - StatusCode not built correctly when loaded from mapping file. [bug]
|
||||
|
||||
# 1.1.1.0 (09 January 2020)
|
||||
- [#398](https://github.com/WireMock-Net/WireMock.Net/pull/398) - Feature/xpath transformer [feature] contributed by [kashifsoofi](https://github.com/kashifsoofi)
|
||||
- [#397](https://github.com/WireMock-Net/WireMock.Net/issues/397) - Question/Feature: Add support for selecting XPath in response template [feature]
|
||||
|
||||
# 1.1.0.0 (27 December 2019)
|
||||
- [#363](https://github.com/WireMock-Net/WireMock.Net/pull/363) - WireMock.Net version 1.1.x contributed by [StefH](https://github.com/StefH)
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<VersionPrefix>1.1.0</VersionPrefix>
|
||||
<VersionPrefix>1.1.3</VersionPrefix>
|
||||
</PropertyGroup>
|
||||
|
||||
<Choose>
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
https://github.com/StefH/GitHubReleaseNotes
|
||||
|
||||
GitHubReleaseNotes.exe --output CHANGELOG.md --skip-empty-releases --exclude-labels question invalid doc --version 1.1.0.0
|
||||
GitHubReleaseNotes.exe --output CHANGELOG.md --skip-empty-releases --exclude-labels question invalid doc --version 1.1.3.0
|
||||
@@ -17,7 +17,7 @@ namespace WireMock.Net.StandAlone
|
||||
/// </summary>
|
||||
/// <param name="settings">The FluentMockServerSettings</param>
|
||||
[PublicAPI]
|
||||
public static WireMockServer Start([NotNull] FluentMockServerSettings settings)
|
||||
public static WireMockServer Start([NotNull] IWireMockServerSettings settings)
|
||||
{
|
||||
Check.NotNull(settings, nameof(settings));
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace WireMock.Net.StandAlone
|
||||
{
|
||||
Check.NotNull(args, nameof(args));
|
||||
|
||||
var settings = (FluentMockServerSettings) WireMockServerSettingsParser.ParseArguments(args);
|
||||
var settings = WireMockServerSettingsParser.ParseArguments(args);
|
||||
|
||||
settings.Logger.Debug("WireMock.Net server arguments [{0}]", string.Join(", ", args.Select(a => $"'{a}'")));
|
||||
|
||||
|
||||
@@ -808,15 +808,13 @@ namespace WireMock.Server
|
||||
return responseBuilder.WithProxy(proxyAndRecordSettings);
|
||||
}
|
||||
|
||||
switch (responseModel.StatusCode)
|
||||
if (responseModel.StatusCode is string)
|
||||
{
|
||||
case int statusCodeAsInteger:
|
||||
responseBuilder = responseBuilder.WithStatusCode(statusCodeAsInteger);
|
||||
break;
|
||||
|
||||
case string statusCodeAsString:
|
||||
responseBuilder = responseBuilder.WithStatusCode(statusCodeAsString);
|
||||
break;
|
||||
responseBuilder = responseBuilder.WithStatusCode((string) responseModel.StatusCode);
|
||||
}
|
||||
else
|
||||
{
|
||||
responseBuilder = responseBuilder.WithStatusCode(Convert.ToInt32(responseModel.StatusCode));
|
||||
}
|
||||
|
||||
if (responseModel.Headers != null)
|
||||
|
||||
@@ -17,6 +17,8 @@ namespace WireMock.Transformers
|
||||
|
||||
HandleBarsXeger.Register(handlebarsContext);
|
||||
|
||||
HandleBarsXPath.Register(handlebarsContext);
|
||||
|
||||
HandleBarsFile.Register(handlebarsContext, fileSystemHandler);
|
||||
}
|
||||
}
|
||||
|
||||
102
src/WireMock.Net/Transformers/HandleBarsXPath.cs
Normal file
102
src/WireMock.Net/Transformers/HandleBarsXPath.cs
Normal file
@@ -0,0 +1,102 @@
|
||||
using HandlebarsDotNet;
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Xml;
|
||||
using System.Xml.XPath;
|
||||
using WireMock.Validation;
|
||||
#if !NETSTANDARD1_3
|
||||
using Wmhelp.XPath2;
|
||||
#endif
|
||||
|
||||
namespace WireMock.Transformers
|
||||
{
|
||||
internal static class HandleBarsXPath
|
||||
{
|
||||
public static void Register(IHandlebars handlebarsContext)
|
||||
{
|
||||
handlebarsContext.RegisterHelper("XPath.SelectSingleNode", (writer, context, arguments) =>
|
||||
{
|
||||
(XPathNavigator nav, string xpath) = ParseArguments(arguments);
|
||||
|
||||
try
|
||||
{
|
||||
#if NETSTANDARD1_3
|
||||
var result = nav.SelectSingleNode(xpath);
|
||||
#else
|
||||
var result = nav.XPath2SelectSingleNode(xpath);
|
||||
#endif
|
||||
writer.WriteSafeString(result.OuterXml);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// Ignore Exception
|
||||
}
|
||||
});
|
||||
|
||||
handlebarsContext.RegisterHelper("XPath.SelectNodes", (writer, context, arguments) =>
|
||||
{
|
||||
(XPathNavigator nav, string xpath) = ParseArguments(arguments);
|
||||
|
||||
try
|
||||
{
|
||||
#if NETSTANDARD1_3
|
||||
var result = nav.Select(xpath);
|
||||
#else
|
||||
var result = nav.XPath2SelectNodes(xpath);
|
||||
#endif
|
||||
var resultXml = new StringBuilder();
|
||||
foreach (XPathNavigator node in result)
|
||||
{
|
||||
resultXml.Append(node.OuterXml);
|
||||
}
|
||||
|
||||
writer.WriteSafeString(resultXml);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// Ignore Exception
|
||||
}
|
||||
});
|
||||
|
||||
handlebarsContext.RegisterHelper("XPath.Evaluate", (writer, context, arguments) =>
|
||||
{
|
||||
(XPathNavigator nav, string xpath) = ParseArguments(arguments);
|
||||
|
||||
try
|
||||
{
|
||||
#if NETSTANDARD1_3
|
||||
var result = nav.Evaluate(xpath);
|
||||
#else
|
||||
var result = nav.XPath2Evaluate(xpath);
|
||||
#endif
|
||||
writer.WriteSafeString(result);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// Ignore Exception
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static (XPathNavigator nav, string xpath) ParseArguments(object[] arguments)
|
||||
{
|
||||
Check.Condition(arguments, args => args.Length == 2, nameof(arguments));
|
||||
Check.NotNull(arguments[0], "arguments[0]");
|
||||
Check.NotNullOrEmpty(arguments[1] as string, "arguments[1]");
|
||||
|
||||
XPathNavigator nav;
|
||||
|
||||
switch (arguments[0])
|
||||
{
|
||||
case string stringValue:
|
||||
nav = new XmlDocument { InnerXml = stringValue }.CreateNavigator();
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new NotSupportedException($"The value '{arguments[0]}' with type '{arguments[0]?.GetType()}' cannot be used in Handlebars XPath.");
|
||||
}
|
||||
|
||||
return (nav, (string)arguments[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,166 @@
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml;
|
||||
using NFluent;
|
||||
using WireMock.Models;
|
||||
using WireMock.ResponseBuilders;
|
||||
using WireMock.Settings;
|
||||
using WireMock.Types;
|
||||
using WireMock.Util;
|
||||
using Xunit;
|
||||
#if !NETSTANDARD1_3
|
||||
using Wmhelp.XPath2;
|
||||
#endif
|
||||
|
||||
namespace WireMock.Net.Tests.ResponseBuilders
|
||||
{
|
||||
public class ResponseWithHandlebarsXPathTests
|
||||
{
|
||||
private readonly WireMockServerSettings _settings = new WireMockServerSettings();
|
||||
private const string ClientIp = "::1";
|
||||
|
||||
[Fact]
|
||||
public async Task Response_ProvideResponse_Handlebars_XPath_SelectSingleNode_Request_BodyAsString()
|
||||
{
|
||||
// Assign
|
||||
var body = new BodyData
|
||||
{
|
||||
BodyAsString = @"<todo-list>
|
||||
<todo-item id='a1'>abc</todo-item>
|
||||
<todo-item id='a2'>def</todo-item>
|
||||
<todo-item id='a3'>xyz</todo-item>
|
||||
</todo-list>",
|
||||
DetectedBodyType = BodyType.String
|
||||
};
|
||||
|
||||
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body);
|
||||
|
||||
var response = Response.Create()
|
||||
.WithHeader("Content-Type", "application/xml")
|
||||
.WithBody("<response>{{XPath.SelectSingleNode request.body \"/todo-list/todo-item[1]\"}}</response>")
|
||||
.WithTransformer();
|
||||
|
||||
// Act
|
||||
var responseMessage = await response.ProvideResponseAsync(request, _settings);
|
||||
|
||||
// Assert
|
||||
var nav = new XmlDocument { InnerXml = responseMessage.BodyData.BodyAsString }.CreateNavigator();
|
||||
var node = nav.XPath2SelectSingleNode("/response/todo-item");
|
||||
Check.That(node.Value).Equals("abc");
|
||||
Check.That(node.GetAttribute("id", "")).Equals("a1");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Response_ProvideResponse_Handlebars_XPath_SelectSingleNode_Text_Request_BodyAsString()
|
||||
{
|
||||
// Assign
|
||||
var body = new BodyData
|
||||
{
|
||||
BodyAsString = @"<todo-list>
|
||||
<todo-item id='a1'>abc</todo-item>
|
||||
<todo-item id='a2'>def</todo-item>
|
||||
<todo-item id='a3'>xyz</todo-item>
|
||||
</todo-list>",
|
||||
DetectedBodyType = BodyType.String
|
||||
};
|
||||
|
||||
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body);
|
||||
|
||||
var response = Response.Create()
|
||||
.WithHeader("Content-Type", "application/xml")
|
||||
.WithBody("{{XPath.SelectSingleNode request.body \"/todo-list/todo-item[1]/text()\"}}")
|
||||
.WithTransformer();
|
||||
|
||||
// Act
|
||||
var responseMessage = await response.ProvideResponseAsync(request, _settings);
|
||||
|
||||
// Assert
|
||||
Check.That(responseMessage.BodyData.BodyAsString).IsEqualTo("abc");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Response_ProvideResponse_Handlebars_XPath_SelectNodes_Request_BodyAsString()
|
||||
{
|
||||
// Assign
|
||||
var body = new BodyData
|
||||
{
|
||||
BodyAsString = @"<todo-list>
|
||||
<todo-item id='a1'>abc</todo-item>
|
||||
<todo-item id='a2'>def</todo-item>
|
||||
<todo-item id='a3'>xyz</todo-item>
|
||||
</todo-list>",
|
||||
DetectedBodyType = BodyType.String
|
||||
};
|
||||
|
||||
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body);
|
||||
|
||||
var response = Response.Create()
|
||||
.WithHeader("Content-Type", "application/xml")
|
||||
.WithBody("<response>{{XPath.SelectNodes request.body \"/todo-list/todo-item\"}}</response>")
|
||||
.WithTransformer();
|
||||
|
||||
// Act
|
||||
var responseMessage = await response.ProvideResponseAsync(request, _settings);
|
||||
|
||||
// Assert
|
||||
var nav = new XmlDocument { InnerXml = responseMessage.BodyData.BodyAsString }.CreateNavigator();
|
||||
var nodes = nav.XPath2SelectNodes("/response/todo-item");
|
||||
Check.That(nodes.Count + 1).IsEqualTo(3);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Response_ProvideResponse_Handlebars_XPath_Evaluate_Request_BodyAsString()
|
||||
{
|
||||
// Assign
|
||||
var body = new BodyData
|
||||
{
|
||||
BodyAsString = @"<todo-list>
|
||||
<todo-item id='a1'>abc</todo-item>
|
||||
<todo-item id='a2'>def</todo-item>
|
||||
<todo-item id='a3'>xyz</todo-item>
|
||||
</todo-list>",
|
||||
DetectedBodyType = BodyType.String
|
||||
};
|
||||
|
||||
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body);
|
||||
|
||||
var response = Response.Create()
|
||||
.WithHeader("Content-Type", "application/xml")
|
||||
.WithBody("{{XPath.Evaluate request.body \"boolean(/todo-list[count(todo-item) = 3])\"}}")
|
||||
.WithTransformer();
|
||||
|
||||
// Act
|
||||
var responseMessage = await response.ProvideResponseAsync(request, _settings);
|
||||
|
||||
// Assert
|
||||
Check.That(responseMessage.BodyData.BodyAsString).IsEqualIgnoringCase("True");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Response_ProvideResponse_Handlebars_XPath_Evaluate_Attribute_Request_BodyAsString()
|
||||
{
|
||||
// Assign
|
||||
var body = new BodyData
|
||||
{
|
||||
BodyAsString = @"<todo-list>
|
||||
<todo-item id='a1'>abc</todo-item>
|
||||
<todo-item id='a2'>def</todo-item>
|
||||
<todo-item id='a3'>xyz</todo-item>
|
||||
</todo-list>",
|
||||
DetectedBodyType = BodyType.String
|
||||
};
|
||||
|
||||
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body);
|
||||
|
||||
var response = Response.Create()
|
||||
.WithHeader("Content-Type", "application/xml")
|
||||
.WithBody("{{XPath.Evaluate request.body \"string(/todo-list/todo-item[1]/@id)\"}}")
|
||||
.WithTransformer();
|
||||
|
||||
// Act
|
||||
var responseMessage = await response.ProvideResponseAsync(request, _settings);
|
||||
|
||||
// Assert
|
||||
Check.That(responseMessage.BodyData.BodyAsString).IsEqualTo("a1");
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user