Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix logic for QueryParameterMultipleValueSupport #854

Merged
merged 8 commits into from
Dec 3, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ public RequestMessageBodyMatcher(Func<object?, bool> func)
/// Initializes a new instance of the <see cref="RequestMessageBodyMatcher"/> class.
/// </summary>
/// <param name="func">The function.</param>
public RequestMessageBodyMatcher(Func<IBodyData, bool> func)
public RequestMessageBodyMatcher(Func<IBodyData?, bool> func)
{
BodyDataFunc = Guard.NotNull(func);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ public RequestMessageParamMatcher(MatchBehaviour matchBehaviour, string key, boo
/// <param name="key">The key.</param>
/// <param name="ignoreCase">Defines if the key should be matched using case-ignore.</param>
/// <param name="values">The values.</param>
public RequestMessageParamMatcher(MatchBehaviour matchBehaviour, string key, bool ignoreCase, string[]? values) : this(matchBehaviour, key, ignoreCase, values?.Select(value => new ExactMatcher(matchBehaviour, ignoreCase, false, MatchOperator.And, value)).Cast<IStringMatcher>().ToArray())
public RequestMessageParamMatcher(MatchBehaviour matchBehaviour, string key, bool ignoreCase, params string[]? values) :
this(matchBehaviour, key, ignoreCase, values?.Select(value => new ExactMatcher(matchBehaviour, ignoreCase, false, MatchOperator.And, value)).Cast<IStringMatcher>().ToArray())
{
}

Expand All @@ -64,7 +65,7 @@ public RequestMessageParamMatcher(MatchBehaviour matchBehaviour, string key, boo
/// <param name="key">The key.</param>
/// <param name="ignoreCase">Defines if the key should be matched using case-ignore.</param>
/// <param name="matchers">The matchers.</param>
public RequestMessageParamMatcher(MatchBehaviour matchBehaviour, string key, bool ignoreCase, IStringMatcher[]? matchers)
public RequestMessageParamMatcher(MatchBehaviour matchBehaviour, string key, bool ignoreCase, params IStringMatcher[]? matchers)
{
MatchBehaviour = matchBehaviour;
Key = Guard.NotNull(key);
Expand Down Expand Up @@ -95,7 +96,7 @@ private double IsMatch(IRequestMessage requestMessage)
return MatchScores.ToScore(requestMessage.Query != null && Funcs.Any(f => f(requestMessage.Query)));
}

var valuesPresentInRequestMessage = ((RequestMessage)requestMessage).GetParameter(Key!, IgnoreCase ?? false);
var valuesPresentInRequestMessage = ((RequestMessage)requestMessage).GetParameter(Key, IgnoreCase ?? false);
if (valuesPresentInRequestMessage == null)
{
// Key is not present at all, just return Mismatch
Expand Down
2 changes: 1 addition & 1 deletion src/WireMock.Net/Owin/Mappers/OwinRequestMapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ public async Task<RequestMessage> MapAsync(IRequest request, IWireMockMiddleware
body = await BodyParser.ParseAsync(bodyParserSettings).ConfigureAwait(false);
}

return new RequestMessage(urlDetails, method, clientIP, body, headers, cookies) { DateTime = DateTime.UtcNow };
return new RequestMessage(options, urlDetails, method, clientIP, body, headers, cookies) { DateTime = DateTime.UtcNow };
}

private static (UrlDetails UrlDetails, string ClientIP) ParseRequest(IRequest request)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
using FluentAssertions;
using NFluent;
using WireMock.Matchers;
using WireMock.Matchers.Request;
using WireMock.Models;
using WireMock.Owin;
using WireMock.Types;
using Xunit;

namespace WireMock.Net.Tests.RequestMatchers
Expand Down Expand Up @@ -172,5 +175,25 @@ public void RequestMessageParamMatcher_GetMatchingScore_KeyWithValuePresentInUrl
// Assert
Check.That(score).IsEqualTo(1.0d);
}

// Issue #849
[Fact]
public void RequestMessageParamMatcher_With1ParamContainingComma_Using_QueryParameterMultipleValueSupport_NoComma()
{
// Assign
var options = new WireMockMiddlewareOptions
{
QueryParameterMultipleValueSupport = QueryParameterMultipleValueSupport.NoComma
};
var requestMessage = new RequestMessage(options, new UrlDetails("http://localhost?query=SELECT id, value FROM table WHERE id = 1&test=42"), "GET", "127.0.0.1");
var matcher = new RequestMessageParamMatcher(MatchBehaviour.AcceptOnMatch, "query", false, "SELECT id, value FROM table WHERE id = 1");

// Act
var result = new RequestMatchResult();
double score = matcher.GetMatchingScore(requestMessage, result);

// Assert
score.Should().Be(1.0);
}
}
}
18 changes: 17 additions & 1 deletion test/WireMock.Net.Tests/Util/QueryStringParserTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ public void Parse_WithMultipleParamWithSameKey()
}

[Fact]
public void Parse_With1ParamContainingSpacesAndEqualSign()
public void Parse_With1ParamContainingSpacesSingleQuoteAndEqualSign()
{
// Assign
string query = "?q=SELECT Id from User where username='user@gmail.com'";
Expand All @@ -287,6 +287,22 @@ public void Parse_With1ParamContainingSpacesAndEqualSign()
result["q"].Should().Equal(new WireMockList<string>("SELECT Id from User where username='user@gmail.com'"));
}

// Issue #849
[Fact]
public void Parse_With1ParamContainingComma_Using_QueryParameterMultipleValueSupport_NoComma()
{
// Assign
string query = "?query=SELECT id, value FROM table WHERE id = 1&test=42";

// Act
var result = QueryStringParser.Parse(query, QueryParameterMultipleValueSupport.NoComma);

// Assert
result.Count.Should().Be(2);
result["query"].Should().Equal(new WireMockList<string>("SELECT id, value FROM table WHERE id = 1"));
result["test"].Should().Equal(new WireMockList<string>("42"));
}

[Fact]
public void Parse_WithComplex()
{
Expand Down
46 changes: 46 additions & 0 deletions test/WireMock.Net.Tests/WireMockServerTests.WithParam.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
using System;
using System.Net;
using System.Threading.Tasks;
using FluentAssertions;
using WireMock.RequestBuilders;
using WireMock.ResponseBuilders;
using WireMock.Server;
using WireMock.Settings;
using WireMock.Types;
using Xunit;

namespace WireMock.Net.Tests;

public partial class WireMockServerTests
{
[Theory]
[InlineData("SELECT id, value FROM table WHERE id = 1")]
[InlineData("select id, name, value from table where id in (1, 2, 3, 4, 5)")]
public async Task WireMockServer_WithParam_QueryParameterMultipleValueSupport_NoComma_Should_Ignore_Comma(string queryValue)
{
// Arrange
var settings = new WireMockServerSettings
{
QueryParameterMultipleValueSupport = QueryParameterMultipleValueSupport.NoComma
};
var server = WireMockServer.Start(settings);
server.Given(
Request.Create()
.UsingGet()
.WithPath("/foo")
.WithParam("query", queryValue)
)
.RespondWith(
Response.Create().WithStatusCode(200)
);

// Act
var requestUri = new Uri($"http://localhost:{server.Port}/foo?query={queryValue}");
var response = await server.CreateClient().GetAsync(requestUri).ConfigureAwait(false);

// Assert
response.StatusCode.Should().Be(HttpStatusCode.OK);

server.Stop();
}
}