diff --git a/examples/WireMock.Net.ConsoleApplication/Program.cs b/examples/WireMock.Net.ConsoleApplication/Program.cs index 10944199..99f5a9e2 100644 --- a/examples/WireMock.Net.ConsoleApplication/Program.cs +++ b/examples/WireMock.Net.ConsoleApplication/Program.cs @@ -33,7 +33,8 @@ namespace WireMock.Net.ConsoleApplication .WithStatusCode(200) .WithHeader("Content-Type", "application/json") .WithHeader("Transformed-Postman-Token", "token is {{request.headers.Postman-Token}}") - .WithBody(@"{""msg"": ""Hello world! : {{request.url}} : {{request.path}} : {{request.query.start}} : {{request.query.stop.[0]}}""") + .WithBody(@"{""msg"": ""Hello world! : {{request.url}} : {{request.path}} : + bykey={{request.query.start}} : bykey={{request.query.stop}} byidx0={{request.query.stop.[0]}} byidx1={{request.query.stop.[1]}}""") .WithTransformer() .WithDelay(TimeSpan.FromMilliseconds(100)) ); diff --git a/src/WireMock/Matchers/Request/RequestMessageParamMatcher.cs b/src/WireMock/Matchers/Request/RequestMessageParamMatcher.cs index 4a8049ca..8197fb02 100644 --- a/src/WireMock/Matchers/Request/RequestMessageParamMatcher.cs +++ b/src/WireMock/Matchers/Request/RequestMessageParamMatcher.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using JetBrains.Annotations; +using WireMock.Util; using WireMock.Validation; namespace WireMock.Matchers.Request @@ -21,7 +22,7 @@ namespace WireMock.Matchers.Request /// private readonly IEnumerable _values; - private readonly Func>, bool> _func; + private readonly Func>, bool> _func; /// /// Initializes a new instance of the class. @@ -47,7 +48,7 @@ namespace WireMock.Matchers.Request /// /// The func. /// - public RequestMessageParamMatcher([NotNull] Func>, bool> func) + public RequestMessageParamMatcher([NotNull] Func>, bool> func) { Check.NotNull(func, nameof(func)); _func = func; @@ -64,7 +65,7 @@ namespace WireMock.Matchers.Request { if (_func != null) { - return _func(requestMessage.Parameters); + return _func(requestMessage.Query); } return requestMessage.GetParameter(_key).Intersect(_values).Count() == _values.Count(); diff --git a/src/WireMock/RequestBuilders/IParamsRequestBuilder.cs b/src/WireMock/RequestBuilders/IParamsRequestBuilder.cs index 243fe89b..b445688b 100644 --- a/src/WireMock/RequestBuilders/IParamsRequestBuilder.cs +++ b/src/WireMock/RequestBuilders/IParamsRequestBuilder.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using JetBrains.Annotations; using WireMock.Matchers.Request; +using WireMock.Util; namespace WireMock.RequestBuilders { @@ -33,6 +34,6 @@ namespace WireMock.RequestBuilders /// /// The . /// - IRequestMatcher WithParam([NotNull] Func>, bool> func); + IRequestMatcher WithParam([NotNull] Func>, bool> func); } } \ No newline at end of file diff --git a/src/WireMock/RequestBuilders/Request.cs b/src/WireMock/RequestBuilders/Request.cs index 85f21bac..91929786 100644 --- a/src/WireMock/RequestBuilders/Request.cs +++ b/src/WireMock/RequestBuilders/Request.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using WireMock.Matchers; using WireMock.Matchers.Request; +using WireMock.Util; namespace WireMock.RequestBuilders { @@ -299,7 +300,7 @@ namespace WireMock.RequestBuilders /// /// The . /// - public IRequestMatcher WithParam(Func>, bool> func) + public IRequestMatcher WithParam(Func>, bool> func) { _requestMatchers.Add(new RequestMessageParamMatcher(func)); return this; diff --git a/src/WireMock/RequestMessage.cs b/src/WireMock/RequestMessage.cs index 2cb5f6ae..9625ce5b 100644 --- a/src/WireMock/RequestMessage.cs +++ b/src/WireMock/RequestMessage.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using JetBrains.Annotations; using WireMock.Extensions; +using WireMock.Util; using WireMock.Validation; namespace WireMock @@ -12,6 +13,41 @@ namespace WireMock /// public class RequestMessage { + /// + /// Gets the url. + /// + public string Url { get; private set; } + + /// + /// Gets the path. + /// + public string Path { get; } + + /// + /// Gets the verb. + /// + public string Verb { get; } + + /// + /// Gets the headers. + /// + public IDictionary Headers { get; } + + /// + /// Gets the query. + /// + public IDictionary> Query { get; } = new Dictionary>(); + + /// + /// Gets the bodyAsBytes. + /// + public byte[] BodyAsBytes { get; } + + /// + /// Gets the body. + /// + public string Body { get; } + /// /// Initializes a new instance of the class. /// @@ -40,85 +76,30 @@ namespace WireMock query = query.Substring(1); } - Parameters = query.Split('&').Aggregate( - new Dictionary>(), + Query = query.Split('&').Aggregate( + new Dictionary>(), (dict, term) => { var key = term.Split('=')[0]; if (!dict.ContainsKey(key)) { - dict.Add(key, new List()); + dict.Add(key, new WireMockList()); } dict[key].Add(term.Split('=')[1]); return dict; }); - - var tmpDictionary = new Dictionary(); - foreach (var parameter in Parameters.Where(p => p.Value.Any())) - { - if (parameter.Value.Count == 1) - { - tmpDictionary.Add(parameter.Key, parameter.Value.First()); - } - else - { - tmpDictionary.Add(parameter.Key, parameter.Value); - } - } - Query = tmpDictionary.ToExpandoObject(); } } /// - /// Gets the url. - /// - public string Url { get; private set; } - - /// - /// Gets the path. - /// - public string Path { get; } - - /// - /// Gets the verb. - /// - public string Verb { get; } - - /// - /// Gets the headers. - /// - public IDictionary Headers { get; } - - /// - /// Gets the query parameters. - /// - public IDictionary> Parameters { get; } = new Dictionary>(); - - /// - /// Gets the query as object. - /// - [PublicAPI] - public dynamic Query { get; } - - /// - /// Gets the bodyAsBytes. - /// - public byte[] BodyAsBytes { get; } - - /// - /// Gets the body. - /// - public string Body { get; } - - /// - /// The get parameter. + /// The get a query parameter. /// /// The key. - /// The parameter.s + /// The query parameter. public List GetParameter(string key) { - return Parameters.ContainsKey(key) ? Parameters[key] : new List(); + return Query.ContainsKey(key) ? Query[key] : new WireMockList(); } } } \ No newline at end of file diff --git a/src/WireMock/Util/WireMockList.cs b/src/WireMock/Util/WireMockList.cs new file mode 100644 index 00000000..4f84d8b1 --- /dev/null +++ b/src/WireMock/Util/WireMockList.cs @@ -0,0 +1,42 @@ +using System.Collections.Generic; +using System.Linq; + +namespace WireMock.Util +{ + /// + /// A special List which overrides the ToString() to return first value. + /// + /// The generic type + /// + public class WireMockList : List + { + /// + /// Initializes a new instance of the class. + /// + public WireMockList() + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The collection whose elements are copied to the new list. + public WireMockList(IEnumerable collection) : base(collection) + { + } + + /// + /// Returns a that represents this instance. + /// + /// + /// A that represents this instance. + /// + public override string ToString() + { + if (this != null && this.Any()) + return this.First().ToString(); + + return base.ToString(); + } + } +} \ No newline at end of file diff --git a/test/WireMock.Net.Tests/ResponseTests.cs b/test/WireMock.Net.Tests/ResponseTests.cs index e6f9a880..017ec565 100644 --- a/test/WireMock.Net.Tests/ResponseTests.cs +++ b/test/WireMock.Net.Tests/ResponseTests.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Text; using System.Threading.Tasks; using NFluent; @@ -13,14 +12,16 @@ namespace WireMock.Net.Tests public class ResponseTests { [Test] - public async Task Response_ProvideResponse_Handlebars_body() + public async Task Response_ProvideResponse_Handlebars_UrlPathVerb() { // given string bodyAsString = "abc"; byte[] body = Encoding.UTF8.GetBytes(bodyAsString); var request = new RequestMessage(new Uri("http://localhost/foo"), "POST", body, bodyAsString); - var response = Response.Create().WithBody("test {{request.url}} {{request.path}} {{request.verb}}").WithTransformer(); + var response = Response.Create() + .WithBody("test {{request.url}} {{request.path}} {{request.verb}}") + .WithTransformer(); // act var responseMessage = await response.ProvideResponse(request); @@ -30,7 +31,26 @@ namespace WireMock.Net.Tests } [Test] - public async Task Response_ProvideResponse_Handlebars_headers() + public async Task Response_ProvideResponse_Handlebars_Query() + { + // given + string bodyAsString = "abc"; + byte[] body = Encoding.UTF8.GetBytes(bodyAsString); + var request = new RequestMessage(new Uri("http://localhost/foo?a=1&a=2&b=5"), "POST", body, bodyAsString); + + var response = Response.Create() + .WithBody("test keya={{request.query.a}} idx={{request.query.a.[0]}} idx={{request.query.a.[1]}} keyb={{request.query.b}}") + .WithTransformer(); + + // act + var responseMessage = await response.ProvideResponse(request); + + // then + Check.That(responseMessage.Body).Equals("test keya=1 idx=1 idx=2 keyb=5"); + } + + [Test] + public async Task Response_ProvideResponse_Handlebars_Headers() { // given string bodyAsString = "abc";