// Copyright © WireMock.Net using System.Collections.Generic; using FluentAssertions; using WireMock.Types; using WireMock.Util; using Xunit; namespace WireMock.Net.Tests.Util; public class QueryStringParserTests { public static IEnumerable QueryStringTestData => new List { new object?[] { null, false, false, null }, new object?[] { string.Empty, false, true, new Dictionary() }, new object?[] { "test", false, true, new Dictionary() }, new object?[] { "&", false, true, new Dictionary() }, new object?[] { "&&", false, true, new Dictionary() }, new object?[] { "a=", false, true, new Dictionary { { "a", "" } } }, new object?[] { "&a", false, true, new Dictionary() }, new object?[] { "&a=", false, true, new Dictionary { { "a", "" } } }, new object?[] { "&key1=value1", false, true, new Dictionary { { "key1", "value1" } } }, new object?[] { "key1=value1", false, true, new Dictionary { { "key1", "value1" } } }, new object?[] { "key1=value1&key2=value2", false, true, new Dictionary { { "key1", "value1" }, { "key2", "value2" } } }, new object?[] { "key1=value1&key2=value2&", false, true, new Dictionary { { "key1", "value1" }, { "key2", "value2" } } }, new object?[] { "key1=value1&&key2=value2", false, true, new Dictionary { { "key1", "value1" }, { "key2", "value2" } } }, new object?[] { "&key1=value1&key2=value2&&", false, true, new Dictionary { { "key1", "value1" }, { "key2", "value2" } } }, }; [Theory] [MemberData(nameof(QueryStringTestData))] public void TryParse_Should_Parse_QueryString(string queryString, bool caseIgnore, bool expectedResult, IDictionary expectedOutput) { // Act var result = QueryStringParser.TryParse(queryString, caseIgnore, out var actual); // Assert result.Should().Be(expectedResult); actual.Should().BeEquivalentTo(expectedOutput); } [Fact] public void TryParse_Should_Parse_QueryStringWithUrlEncodedValues() { // Arrange var key = "x"; var value = "rNaCP7hv8UOmS%2FJcujdvLw%3D%3D"; // Act var result = QueryStringParser.TryParse($"{key}={value}", true, out var actual); // Assert result.Should().BeTrue(); actual.Should().BeEquivalentTo(new Dictionary { { "x", "rNaCP7hv8UOmS/JcujdvLw==" } }); } [Fact] public void Parse_WithNullString() { // Assign string? query = null; // Act var result = QueryStringParser.Parse(query); // Assert result.Should().Equal(new Dictionary>()); } [Fact] public void Parse_WithEmptyString() { // Assign string query = ""; // Act var result = QueryStringParser.Parse(query); // Assert result.Should().Equal(new Dictionary>()); } [Fact] public void Parse_WithQuestionMark() { // Assign string query = "?"; // Act var result = QueryStringParser.Parse(query); // Assert result.Should().Equal(new Dictionary>()); } [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("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("1")); result["y"].Should().Equal(new WireMockList("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()); } [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("")); } [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("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("value?")); result["b"].Should().Equal(new WireMockList("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("value=what")); } [Fact] public void Parse_With1ParamWithTwoEqualSigns() { // Assign string query = "?key=value==what"; // Act var result = QueryStringParser.Parse(query); // Assert result.Count.Should().Be(1); result["key"].Should().Equal(new WireMockList("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("value", "anotherValue")); } [Fact] public void Parse_WithMultipleParamWithSameKeySeparatedByAmp() { // Assign string query = "?key=1&key=2"; // Act var result = QueryStringParser.Parse(query); // Assert result.Count.Should().Be(1); result["key"].Should().Equal(new WireMockList("1", "2")); } [Fact] public void Parse_With1ParamContainingComma_When_SupportMultiValueUsingComma_Is_True() { // Assign string query = "?key=1,2,3"; // Act var result = QueryStringParser.Parse(query); // Assert result.Count.Should().Be(1); result["key"].Should().Equal(new WireMockList("1", "2", "3")); } [Fact] public void Parse_With1ParamContainingCommaAndAmpCombined_When_SupportMultiValueUsingComma_Is_Comma() { // 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("1", "2", "3")); } [Fact] public void Parse_With1ParamContainingComma_SupportMultiValueUsingComma_Is_AmpersandAndSemiColon() { // Assign string query = "?$filter=startswith(name,'testName')"; // Act var result = QueryStringParser.Parse(query, QueryParameterMultipleValueSupport.AmpersandAndSemiColon); // Assert result.Count.Should().Be(1); result["$filter"].Should().Equal(new WireMockList("startswith(name,'testName')")); } [Fact] public void Parse_With1ParamContainingEscapedAnd() { // Assign string query = "?winkel=C%26A"; // Act var result = QueryStringParser.Parse(query); // Assert result.Count.Should().Be(1); result["winkel"].Should().Equal(new WireMockList("C&A")); } [Fact] public void Parse_With1ParamContainingParentheses() { // Assign string query = "?Transaction=(123)"; // Act var result = QueryStringParser.Parse(query); // Assert result.Count.Should().Be(1); result["Transaction"].Should().Equal(new WireMockList("(123)")); } [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("value", "anotherValue")); } [Fact] public void Parse_With1ParamContainingSpacesSingleQuoteAndEqualSign() { // 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("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("SELECT id, value FROM table WHERE id = 1")); result["test"].Should().Equal(new WireMockList("42")); } [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&x"; // Act var result = QueryStringParser.Parse(query); // Assert result.Count.Should().Be(7); result["q"].Should().Equal(new WireMockList("energy edge")); result["rls"].Should().Equal(new WireMockList("com.microsoft:en-au")); result["ie"].Should().Equal(new WireMockList("UTF-8")); result["oe"].Should().Equal(new WireMockList("UTF-8")); result["startIndex"].Should().Equal(new WireMockList("")); result["startPage"].Should().Equal(new WireMockList("1\"")); result["x"].Should().Equal(new WireMockList()); } }