Compare commits

...

7 Commits

Author SHA1 Message Date
Stef Heyenrath
561bb75f9f 1.0.19.0 2019-06-15 10:36:52 +02:00
Stef Heyenrath
f764881622 QueryStringParserTests 2019-06-15 10:26:39 +02:00
Stef Heyenrath
fdc433f0ce QueryStringParser 2019-06-15 10:22:28 +02:00
Stef Heyenrath
c76bb94b4c 1.0.18.0 2019-06-10 17:52:05 +02:00
Stef Heyenrath
d7b6e03cb2 --WireMockLogger WireMockConsoleLogger (#282) 2019-06-10 17:46:04 +02:00
Stef Heyenrath
9031541b91 1.0.17.0 2019-06-05 16:05:26 +02:00
Stef Heyenrath
bd030594d5 Add support for HandleBars File (to read a file) (#278)
* HandleBarsFileFragment

* 1.0.17

* {{File}}
2019-06-05 16:00:25 +02:00
24 changed files with 546 additions and 62 deletions

View File

@@ -1,3 +1,14 @@
# 1.0.19.0 (15 June 2019)
- [#279](https://github.com/WireMock-Net/WireMock.Net/issues/279) - How to simulate disconnect? [question]
- [#283](https://github.com/WireMock-Net/WireMock.Net/issues/283) - Support equal-sign in query [bug]
# 1.0.18.0 (10 June 2019)
- [#282](https://github.com/WireMock-Net/WireMock.Net/pull/282) - WireMock.Net.Standalone : Add --WireMockLogger commandline argument [feature] contributed by [StefH](https://github.com/StefH)
# 1.0.17.0 (05 June 2019)
- [#278](https://github.com/WireMock-Net/WireMock.Net/pull/278) - Add support for HandleBars File (to read a file) [feature] contributed by [StefH](https://github.com/StefH)
- [#276](https://github.com/WireMock-Net/WireMock.Net/issues/276) - No server response in Postman and Receive Failure in Fiddler [invalid]
# 1.0.16.0 (16 May 2019)
- [#274](https://github.com/WireMock-Net/WireMock.Net/pull/274) - Sign Assembly [feature] contributed by [StefH](https://github.com/StefH)
- [#160](https://github.com/WireMock-Net/WireMock.Net/issues/160) - Feature: Sign 'WireMock.Net' [feature]

View File

@@ -4,7 +4,7 @@
</PropertyGroup>
<PropertyGroup>
<VersionPrefix>1.0.16</VersionPrefix>
<VersionPrefix>1.0.19</VersionPrefix>
</PropertyGroup>
<Choose>

View File

@@ -1,3 +1,3 @@
https://github.com/StefH/GitHubReleaseNotes
GitHubReleaseNotes.exe --output CHANGELOG.md --skip-empty-releases --version 1.0.16.0
GitHubReleaseNotes.exe --output CHANGELOG.md --skip-empty-releases --version 1.0.19.0

View File

@@ -50,6 +50,12 @@ namespace WireMock.Net.ConsoleApplication
return File.ReadAllBytes(Path.GetFileName(path) == path ? Path.Combine(GetMappingFolder(), path) : path);
}
/// <inheritdoc cref="IFileSystemHandler.ReadResponseBodyAsFile"/>
public string ReadResponseBodyAsString(string path)
{
return File.ReadAllText(Path.GetFileName(path) == path ? Path.Combine(GetMappingFolder(), path) : path);
}
/// <inheritdoc cref="IFileSystemHandler.FileExists"/>
public bool FileExists(string path)
{

View File

@@ -438,6 +438,15 @@ namespace WireMock.Net.ConsoleApplication
.WithBody("<xml>ok</xml>")
);
server.Given(Request.Create()
.WithPath("/services/query/")
.WithParam("q", "SELECT Id from User where username='user@gmail.com'")
.UsingGet())
.RespondWith(Response.Create()
.WithStatusCode(200)
.WithHeader("Content-Type", "application/json")
.WithBodyAsJson(new { Id = "5bdf076c-5654-4b3e-842c-7caf1fabf8c9" }));
System.Console.WriteLine("Press any key to stop the server");
System.Console.ReadKey();
server.Stop();

View File

@@ -2,7 +2,7 @@
"profiles": {
"WireMock.Net.StandAlone.NETCoreApp": {
"commandName": "Project",
"commandLineArgs": "--Urls http://*:9091"
"commandLineArgs": "--Urls http://*:9091 --WireMockLogger WireMockConsoleLogger"
}
}
}

View File

@@ -50,7 +50,7 @@ namespace WireMock.Net.StandAlone
AdminUsername = parser.GetStringValue("AdminUsername"),
AdminPassword = parser.GetStringValue("AdminPassword"),
MaxRequestLogCount = parser.GetIntValue("MaxRequestLogCount"),
RequestLogExpirationDuration = parser.GetIntValue("RequestLogExpirationDuration"),
RequestLogExpirationDuration = parser.GetIntValue("RequestLogExpirationDuration")
};
if (logger != null)
@@ -58,6 +58,11 @@ namespace WireMock.Net.StandAlone
settings.Logger = logger;
}
if (parser.GetStringValue("WireMockLogger") == "WireMockConsoleLogger")
{
settings.Logger = new WireMockConsoleLogger();
}
if (parser.Contains("Port"))
{
settings.Port = parser.GetIntValue("Port");
@@ -82,9 +87,7 @@ namespace WireMock.Net.StandAlone
settings.Logger.Debug("WireMock.Net server arguments [{0}]", string.Join(", ", args.Select(a => $"'{a}'")));
FluentMockServer server = Start(settings);
return server;
return Start(settings);
}
}
}

View File

@@ -49,12 +49,19 @@ namespace WireMock.Handlers
void WriteMappingFile([NotNull] string path, [NotNull] string text);
/// <summary>
/// Read a response body file as text.
/// Read a response body file as byte[].
/// </summary>
/// <param name="path">The path or filename from the file to read.</param>
/// <returns>The file content as bytes.</returns>
byte[] ReadResponseBodyAsFile([NotNull] string path);
/// <summary>
/// Read a response body file as text.
/// </summary>
/// <param name="path">The path or filename from the file to read.</param>
/// <returns>The file content as text.</returns>
string ReadResponseBodyAsString([NotNull] string path);
/// <summary>
/// Delete a file.
/// </summary>

View File

@@ -68,6 +68,16 @@ namespace WireMock.Handlers
return File.ReadAllBytes(Path.GetFileName(path) == path ? Path.Combine(GetMappingFolder(), path) : path);
}
/// <inheritdoc cref="IFileSystemHandler.ReadResponseBodyAsString"/>
public string ReadResponseBodyAsString(string path)
{
Check.NotNullOrEmpty(path, nameof(path));
// In case the path is a filename, the path will be adjusted to the MappingFolder.
// Else the path will just be as-is.
return File.ReadAllText(Path.GetFileName(path) == path ? Path.Combine(GetMappingFolder(), path) : path);
}
/// <inheritdoc cref="IFileSystemHandler.FileExists"/>
public bool FileExists(string filename)
{

View File

@@ -4,7 +4,6 @@ using System.Collections.ObjectModel;
using System.Linq;
using WireMock.Matchers;
using WireMock.Matchers.Request;
using WireMock.Util;
using WireMock.Validation;
namespace WireMock.RequestBuilders

View File

@@ -171,40 +171,7 @@ namespace WireMock
Headers = headers?.ToDictionary(header => header.Key, header => new WireMockList<string>(header.Value));
Cookies = cookies;
RawQuery = WebUtility.UrlDecode(urlDetails.Url.Query);
Query = ParseQuery(RawQuery);
}
private static IDictionary<string, WireMockList<string>> ParseQuery(string queryString)
{
if (string.IsNullOrEmpty(queryString))
{
return null;
}
if (queryString.StartsWith("?"))
{
queryString = queryString.Substring(1);
}
return queryString.Split(new[] { '&' }, StringSplitOptions.RemoveEmptyEntries)
.Aggregate(new Dictionary<string, WireMockList<string>>(),
(dict, term) =>
{
string[] parts = term.Split(new[] { '=' }, StringSplitOptions.RemoveEmptyEntries);
string key = parts[0];
if (!dict.ContainsKey(key))
{
dict.Add(key, new WireMockList<string>());
}
if (parts.Length == 2)
{
string[] values = parts[1].Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries);
dict[key].AddRange(values);
}
return dict;
});
Query = QueryStringParser.Parse(RawQuery);
}
/// <summary>

View File

@@ -21,7 +21,8 @@ namespace WireMock.ResponseBuilders
/// </summary>
public class Response : IResponseBuilder
{
private readonly IFileSystemHandler _fileSystemHandler = new LocalFileSystemHandler();
private readonly IFileSystemHandler _fileSystemHandler;
private readonly ResponseMessageTransformer _responseMessageTransformer;
private HttpClient _httpClientForProxy;
/// <summary>
@@ -93,6 +94,9 @@ namespace WireMock.ResponseBuilders
private Response(ResponseMessage responseMessage)
{
ResponseMessage = responseMessage;
_fileSystemHandler = new LocalFileSystemHandler();
_responseMessageTransformer = new ResponseMessageTransformer(_fileSystemHandler);
}
/// <summary>
@@ -417,7 +421,7 @@ namespace WireMock.ResponseBuilders
if (UseTransformer)
{
return ResponseMessageTransformer.Transform(requestMessage, ResponseMessage);
return _responseMessageTransformer.Transform(requestMessage, ResponseMessage);
}
// Just return normal defined ResponseMessage

View File

@@ -1,11 +1,11 @@
using JetBrains.Annotations;
using Newtonsoft.Json;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using Newtonsoft.Json;
using WireMock.Exceptions;
using WireMock.Handlers;
using WireMock.Logging;
@@ -185,7 +185,7 @@ namespace WireMock.Server
private FluentMockServer(IFluentMockServerSettings settings)
{
settings.Logger = settings.Logger ?? new WireMockConsoleLogger();
settings.Logger = settings.Logger ?? new WireMockNullLogger();
_logger = settings.Logger;
_fileSystemHandler = settings.FileSystemHandler ?? new LocalFileSystemHandler();

View File

@@ -1,6 +1,6 @@
using System;
using JetBrains.Annotations;
using JetBrains.Annotations;
using Newtonsoft.Json;
using System;
using WireMock.Handlers;
using WireMock.Logging;

View File

@@ -24,7 +24,7 @@ namespace WireMock.Settings
bool? UseSSL { get; set; }
/// <summary>
/// Gets or sets wether to start admin interface.
/// Gets or sets whether to start admin interface.
/// </summary>
[PublicAPI]
bool? StartAdminInterface { get; set; }

View File

@@ -0,0 +1,41 @@
using HandlebarsDotNet;
using System;
using WireMock.Handlers;
using WireMock.Validation;
namespace WireMock.Transformers
{
internal static class HandleBarsFile
{
public static void Register(IHandlebars handlebarsContext, IFileSystemHandler fileSystemHandler)
{
handlebarsContext.RegisterHelper("File", (writer, context, arguments) =>
{
string value = ParseArgumentAndReadFileFragment(handlebarsContext, context, fileSystemHandler, arguments);
writer.Write(value);
});
handlebarsContext.RegisterHelper("File", (writer, options, context, arguments) =>
{
string value = ParseArgumentAndReadFileFragment(handlebarsContext, context, fileSystemHandler, arguments);
options.Template(writer, value);
});
}
private static string ParseArgumentAndReadFileFragment(IHandlebars handlebarsContext, dynamic context, IFileSystemHandler fileSystemHandler, object[] arguments)
{
Check.Condition(arguments, args => args.Length == 1, nameof(arguments));
Check.NotNull(arguments[0], "arguments[0]");
switch (arguments[0])
{
case string path:
var templateFunc = handlebarsContext.Compile(path);
string transformed = templateFunc(context);
return fileSystemHandler.ReadResponseBodyAsString(transformed);
}
throw new NotSupportedException($"The value '{arguments[0]}' with type '{arguments[0]?.GetType()}' cannot be used in Handlebars File.");
}
}
}

View File

@@ -1,10 +1,11 @@
using HandlebarsDotNet;
using WireMock.Handlers;
namespace WireMock.Transformers
{
internal static class HandlebarsHelpers
{
public static void Register(IHandlebars handlebarsContext)
public static void Register(IHandlebars handlebarsContext, IFileSystemHandler fileSystemHandler)
{
HandleBarsRegex.Register(handlebarsContext);
@@ -15,6 +16,8 @@ namespace WireMock.Transformers
HandleBarsRandom.Register(handlebarsContext);
HandleBarsXeger.Register(handlebarsContext);
HandleBarsFile.Register(handlebarsContext, fileSystemHandler);
}
}
}

View File

@@ -1,14 +1,17 @@
using HandlebarsDotNet;
using JetBrains.Annotations;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using WireMock.Handlers;
using WireMock.Util;
using WireMock.Validation;
namespace WireMock.Transformers
{
internal static class ResponseMessageTransformer
internal class ResponseMessageTransformer
{
private static readonly HandlebarsConfiguration HandlebarsConfiguration = new HandlebarsConfiguration
{
@@ -17,12 +20,14 @@ namespace WireMock.Transformers
private static readonly IHandlebars HandlebarsContext = Handlebars.Create(HandlebarsConfiguration);
static ResponseMessageTransformer()
public ResponseMessageTransformer([NotNull] IFileSystemHandler fileSystemHandler)
{
HandlebarsHelpers.Register(HandlebarsContext);
Check.NotNull(fileSystemHandler, nameof(fileSystemHandler));
HandlebarsHelpers.Register(HandlebarsContext, fileSystemHandler);
}
public static ResponseMessage Transform(RequestMessage requestMessage, ResponseMessage original)
public ResponseMessage Transform(RequestMessage requestMessage, ResponseMessage original)
{
var responseMessage = new ResponseMessage { StatusCode = original.StatusCode };
@@ -90,14 +95,14 @@ namespace WireMock.Transformers
};
}
private static void WalkNode(JToken node, object template)
private static void WalkNode(JToken node, object context)
{
if (node.Type == JTokenType.Object)
{
// In case of Object, loop all children. Do a ToArray() to avoid `Collection was modified` exceptions.
foreach (JProperty child in node.Children<JProperty>().ToArray())
{
WalkNode(child.Value, template);
WalkNode(child.Value, context);
}
}
else if (node.Type == JTokenType.Array)
@@ -105,7 +110,7 @@ namespace WireMock.Transformers
// In case of Array, loop all items. Do a ToArray() to avoid `Collection was modified` exceptions.
foreach (JToken child in node.Children().ToArray())
{
WalkNode(child, template);
WalkNode(child, context);
}
}
else if (node.Type == JTokenType.String)
@@ -118,7 +123,7 @@ namespace WireMock.Transformers
}
var templateForStringValue = HandlebarsContext.Compile(stringValue);
string transformedString = templateForStringValue(template);
string transformedString = templateForStringValue(context);
if (!string.Equals(stringValue, transformedString))
{
ReplaceNodeValue(node, transformedString);

View File

@@ -0,0 +1,41 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace WireMock.Util
{
/// <summary>
/// Based on https://stackoverflow.com/questions/659887/get-url-parameters-from-a-string-in-net
/// </summary>
internal static class QueryStringParser
{
public static IDictionary<string, WireMockList<string>> Parse(string queryString)
{
if (string.IsNullOrEmpty(queryString))
{
return new Dictionary<string, WireMockList<string>>();
}
string[] JoinParts(string[] parts)
{
if (parts.Length > 2)
{
return new[] { string.Join("=", parts, 1, parts.Length - 1) };
}
if (parts.Length > 1)
{
return parts[1].Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries); // support "?key=1,2"
}
return new string[0];
}
return queryString.TrimStart('?')
.Split(new[] { '&', ';' }, StringSplitOptions.RemoveEmptyEntries) // Support "?key=value;key=anotherValue" and "?key=value&key=anotherValue"
.Select(parameter => parameter.Split(new[] { '=' }, StringSplitOptions.RemoveEmptyEntries))
.GroupBy(parts => parts[0], JoinParts)
.ToDictionary(grouping => grouping.Key, grouping => new WireMockList<string>(grouping.SelectMany(x => x)));
}
}
}

View File

@@ -62,7 +62,7 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="System.Linq.Dynamic.Core" Version="1.0.12" />
<PackageReference Include="RandomDataGenerator.Net" Version="1.0.7" />
<PackageReference Include="RandomDataGenerator.Net" Version="1.0.8" />
<PackageReference Include="JmesPath.Net" Version="1.0.125" />
</ItemGroup>

View File

@@ -0,0 +1,102 @@
using Moq;
using Newtonsoft.Json.Linq;
using NFluent;
using System;
using System.Threading.Tasks;
using WireMock.Handlers;
using WireMock.Models;
using WireMock.ResponseBuilders;
using WireMock.Transformers;
using Xunit;
namespace WireMock.Net.Tests.ResponseBuilders
{
public class ResponseWithHandlebarsFileTests
{
private readonly Mock<IFileSystemHandler> _filesystemHandlerMock;
private const string ClientIp = "::1";
public ResponseWithHandlebarsFileTests()
{
_filesystemHandlerMock = new Mock<IFileSystemHandler>(MockBehavior.Strict);
_filesystemHandlerMock.Setup(fs => fs.ReadResponseBodyAsString(It.IsAny<string>())).Returns("abc");
}
[Fact]
public async Task Response_ProvideResponseAsync_Handlebars_File()
{
// Assign
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "GET", ClientIp);
var response = Response.Create()
.WithBodyAsJson(new
{
Data = "{{File \"x.json\"}}"
})
.WithTransformer();
response.SetPrivateFieldValue("_fileSystemHandler", _filesystemHandlerMock.Object);
response.SetPrivateFieldValue("_responseMessageTransformer", new ResponseMessageTransformer(_filesystemHandlerMock.Object));
// Act
var responseMessage = await response.ProvideResponseAsync(request);
// Assert
JObject j = JObject.FromObject(responseMessage.BodyData.BodyAsJson);
Check.That(j["Data"].Value<string>()).Equals("abc");
// Verify
_filesystemHandlerMock.Verify(fs => fs.ReadResponseBodyAsString("x.json"), Times.Once);
_filesystemHandlerMock.VerifyNoOtherCalls();
}
[Fact]
public async Task Response_ProvideResponseAsync_Handlebars_File_Replace()
{
// Assign
var request = new RequestMessage(new UrlDetails("http://localhost:1234?id=x"), "GET", ClientIp);
var response = Response.Create()
.WithBodyAsJson(new
{
Data = "{{File \"{{request.query.id}}.json\"}}"
})
.WithTransformer();
response.SetPrivateFieldValue("_fileSystemHandler", _filesystemHandlerMock.Object);
response.SetPrivateFieldValue("_responseMessageTransformer", new ResponseMessageTransformer(_filesystemHandlerMock.Object));
// Act
var responseMessage = await response.ProvideResponseAsync(request);
// Assert
JObject j = JObject.FromObject(responseMessage.BodyData.BodyAsJson);
Check.That(j["Data"].Value<string>()).Equals("abc");
// Verify
_filesystemHandlerMock.Verify(fs => fs.ReadResponseBodyAsString("x.json"), Times.Once);
_filesystemHandlerMock.VerifyNoOtherCalls();
}
[Fact]
public void Response_ProvideResponseAsync_Handlebars_File_WithMissingArgument_ThrowsArgumentOutOfRangeException()
{
// Assign
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "GET", ClientIp);
var response = Response.Create()
.WithBodyAsJson(new
{
Data = "{{File}}"
})
.WithTransformer();
// Act
Check.ThatAsyncCode(() => response.ProvideResponseAsync(request)).Throws<ArgumentOutOfRangeException>();
// Verify
_filesystemHandlerMock.Verify(fs => fs.ReadResponseBodyAsString(It.IsAny<string>()), Times.Never);
_filesystemHandlerMock.VerifyNoOtherCalls();
}
}
}

View File

@@ -1,4 +1,5 @@
using System.Reflection;
using System;
using System.Reflection;
namespace WireMock.Net.Tests
{
@@ -10,5 +11,53 @@ namespace WireMock.Net.Tests
return (T)field.GetValue(obj);
}
/// <summary>
/// Set a _private_ Field Value on a given Object
/// </summary>
/// <typeparam name="T">Type of the Property</typeparam>
/// <param name="obj">Object from where the Property Value is returned</param>
/// <param name="propertyName">Property name as string.</param>
/// <param name="value">the value to set</param>
public static void SetPrivateFieldValue<T>(this object obj, string propertyName, T value)
{
if (obj == null)
{
throw new ArgumentNullException(nameof(obj));
}
Type t = obj.GetType();
FieldInfo fi = null;
while (fi == null && t != null)
{
fi = t.GetField(propertyName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
t = t.BaseType;
}
if (fi == null)
{
throw new ArgumentOutOfRangeException(nameof(propertyName), $"Field {propertyName} was not found in Type {obj.GetType().FullName}");
}
fi.SetValue(obj, value);
}
/// <summary>
/// Sets a _private_ Property Value from a given Object.
/// </summary>
/// <typeparam name="T">Type of the Property</typeparam>
/// <param name="obj">Object from where the Property Value is set</param>
/// <param name="propertyName">Property name as string.</param>
/// <param name="value">Value to set.</param>
public static void SetPrivatePropertyValue<T>(this object obj, string propertyName, T value)
{
Type t = obj.GetType();
if (t.GetProperty(propertyName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance) == null)
{
throw new ArgumentOutOfRangeException(nameof(propertyName), $"Property {propertyName} was not found in Type {obj.GetType().FullName}");
}
t.InvokeMember(propertyName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.SetProperty | BindingFlags.Instance, null, obj, new object[] { value });
}
}
}

View File

@@ -0,0 +1,224 @@
using FluentAssertions;
using System.Collections.Generic;
using WireMock.Util;
using Xunit;
namespace WireMock.Net.Tests.Util
{
public class QueryStringParserTests
{
[Fact]
public void Parse_WithNullString()
{
// Assign
string query = null;
// Act
var result = QueryStringParser.Parse(query);
// Assert
result.Should().Equal(new Dictionary<string, WireMockList<string>>());
}
[Fact]
public void Parse_WithEmptyString()
{
// Assign
string query = "";
// Act
var result = QueryStringParser.Parse(query);
// Assert
result.Should().Equal(new Dictionary<string, WireMockList<string>>());
}
[Fact]
public void Parse_WithQuestionMark()
{
// Assign
string query = "?";
// Act
var result = QueryStringParser.Parse(query);
// Assert
result.Should().Equal(new Dictionary<string, WireMockList<string>>());
}
[Fact]
public void Parse_With1Param()
{
// Assign
string query = "?key=bla/blub.xml";
// Act
var result = QueryStringParser.Parse(query);
// Assert
result.Count.Should().Be(1);
result["key"].Should().Equal(new WireMockList<string>("bla/blub.xml"));
}
[Fact]
public void Parse_With2Params()
{
// Assign
string query = "?x=1&y=2";
// Act
var result = QueryStringParser.Parse(query);
// Assert
result.Count.Should().Be(2);
result["x"].Should().Equal(new WireMockList<string>("1"));
result["y"].Should().Equal(new WireMockList<string>("2"));
}
[Fact]
public void Parse_With1ParamNoValue()
{
// Assign
string query = "?empty";
// Act
var result = QueryStringParser.Parse(query);
// Assert
result.Count.Should().Be(1);
result["empty"].Should().Equal(new WireMockList<string>());
}
[Fact]
public void Parse_With1ParamNoValueWithEqualSign()
{
// Assign
string query = "?empty=";
// Act
var result = QueryStringParser.Parse(query);
// Assert
result.Count.Should().Be(1);
result["empty"].Should().Equal(new WireMockList<string>());
}
[Fact]
public void Parse_With1ParamAndJustAndSign()
{
// Assign
string query = "?key=1&";
// Act
var result = QueryStringParser.Parse(query);
// Assert
result.Count.Should().Be(1);
result["key"].Should().Equal(new WireMockList<string>("1"));
}
[Fact]
public void Parse_With2ParamsAndWhereOneHasAQuestion()
{
// Assign
string query = "?key=value?&b=c";
// Act
var result = QueryStringParser.Parse(query);
// Assert
result.Count.Should().Be(2);
result["key"].Should().Equal(new WireMockList<string>("value?"));
result["b"].Should().Equal(new WireMockList<string>("c"));
}
[Fact]
public void Parse_With1ParamWithEqualSign()
{
// Assign
string query = "?key=value=what";
// Act
var result = QueryStringParser.Parse(query);
// Assert
result.Count.Should().Be(1);
result["key"].Should().Equal(new WireMockList<string>("value=what"));
}
[Fact]
public void Parse_WithMultipleParamWithSameKeySeparatedBySemiColon()
{
// Assign
string query = "?key=value;key=anotherValue";
// Act
var result = QueryStringParser.Parse(query);
// Assert
result.Count.Should().Be(1);
result["key"].Should().Equal(new WireMockList<string>(new[] { "value", "anotherValue" }));
}
[Fact]
public void Parse_With1ParamContainingComma()
{
// Assign
string query = "?key=1,2&key=3";
// Act
var result = QueryStringParser.Parse(query);
// Assert
result.Count.Should().Be(1);
result["key"].Should().Equal(new WireMockList<string>(new[] { "1", "2", "3" }));
}
[Fact]
public void Parse_WithMultipleParamWithSameKey()
{
// Assign
string query = "?key=value&key=anotherValue";
// Act
var result = QueryStringParser.Parse(query);
// Assert
result.Count.Should().Be(1);
result["key"].Should().Equal(new WireMockList<string>(new[] { "value", "anotherValue" }));
}
[Fact]
public void Parse_With1ParamContainingSpacesAndEqualSign()
{
// Assign
string query = "?q=SELECT Id from User where username='user@gmail.com'";
// Act
var result = QueryStringParser.Parse(query);
// Assert
result.Count.Should().Be(1);
result["q"].Should().Equal(new WireMockList<string>("SELECT Id from User where username='user@gmail.com'"));
}
[Fact]
public void Parse_WithComplex()
{
// Assign
string query = "?q=energy+edge&rls=com.microsoft:en-au&ie=UTF-8&oe=UTF-8&startIndex=&startPage=1%22";
// Act
var result = QueryStringParser.Parse(query);
// Assert
result.Count.Should().Be(6);
result["q"].Should().Equal(new WireMockList<string>("energy+edge"));
result["rls"].Should().Equal(new WireMockList<string>("com.microsoft:en-au"));
result["ie"].Should().Equal(new WireMockList<string>("UTF-8"));
result["oe"].Should().Equal(new WireMockList<string>("UTF-8"));
result["startIndex"].Should().Equal(new WireMockList<string>());
result["startPage"].Should().Equal(new WireMockList<string>("1%22"));
}
}
}

View File

@@ -34,8 +34,10 @@
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="FluentAssertions" Version="5.7.0" />
<PackageReference Include="System.Threading" Version="4.3.0" />
<PackageReference Include="RestEase" Version="1.4.7" />
<PackageReference Include="RandomDataGenerator.Net" Version="1.0.8" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" />
<PackageReference Include="MimeKitLite" Version="2.0.7" />
<PackageReference Include="Moq" Version="4.10.1" />
@@ -50,6 +52,7 @@
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<!--<PackageReference Include="StrongNamer" Version="0.0.8" />-->
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net452'">