Skip to content

Commit

Permalink
Merge pull request #8 from DavitRekhviashvili/master
Browse files Browse the repository at this point in the history
QueryParamCollection upgrade by QueryStringBuilder
  • Loading branch information
svangio authored Jul 5, 2022
2 parents c15d269 + 9704905 commit baa6a91
Show file tree
Hide file tree
Showing 5 changed files with 159 additions and 18 deletions.
30 changes: 12 additions & 18 deletions src/TBC.OpenAPI.SDK.Core/Models/QueryParamCollection.cs
Original file line number Diff line number Diff line change
@@ -1,38 +1,32 @@
using System.Collections.Specialized;
using System.Net;
using System.Linq;
using System.Web;
using System.Text;
using TBC.OpenAPI.SDK.Core.QueryStringHelper;

namespace TBC.OpenAPI.SDK.Core.Models
{
public sealed class QueryParamCollection : Dictionary<string, ParamValue>
{
{
public string ToQueryString()
{
var query = new NameValueCollection();

var queryStringBulder = QueryStringBuilder.StartBuild();
foreach (var item in this)
{
var value = item.Value;
if (value?.Value is not null)
if (item.Value?.Value is not null)
{
query.Add(item.Key, value.ToString());
queryStringBulder.AddParameter(item.Key, item.Value.Value);
}
else
if (value?.Values is not null)
else if (item.Value?.Values is not null)
{
foreach (var v in value.Values)
foreach (var v in item.Value.Values)
{
query.Add(item.Key, v.ToString());
queryStringBulder.AddParameter(item.Key, v.ToString());
}
}
}

if (!query.HasKeys())
return string.Empty;

var segments = query.AllKeys.SelectMany(key => query.GetValues(key),
(key, value) => $"{WebUtility.UrlEncode(key)}={WebUtility.UrlEncode(value)}");

return "?" + string.Join("&", segments);
return queryStringBulder.Finish().GetBuildedQuery();
}
}
}
14 changes: 14 additions & 0 deletions src/TBC.OpenAPI.SDK.Core/QueryStringHelper/IAddParameterable.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Text;

namespace TBC.OpenAPI.SDK.Core.QueryStringHelper
{
internal interface IAddParameterable
{

IAddParameterable AddParameter(string name, string value);
IFinisher Finish();

}
}
11 changes: 11 additions & 0 deletions src/TBC.OpenAPI.SDK.Core/QueryStringHelper/IFinisher.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using System;
using System.Collections.Generic;
using System.Text;

namespace TBC.OpenAPI.SDK.Core.QueryStringHelper
{
internal interface IFinisher
{
string GetBuildedQuery();
}
}
41 changes: 41 additions & 0 deletions src/TBC.OpenAPI.SDK.Core/QueryStringHelper/QueryStringBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Text.Encodings.Web;

namespace TBC.OpenAPI.SDK.Core.QueryStringHelper
{
internal class QueryStringBuilder:IAddParameterable, IFinisher
{
protected StringBuilder sb = new StringBuilder();
private QueryStringBuilder(string startingString)
{
sb.Append(startingString);
}
public static IAddParameterable StartBuild(string rootaddress = null)
{
return new QueryStringBuilder(rootaddress == null?"?":$"{rootaddress}?");
}
public IAddParameterable AddParameter(string name, string value)
{
if (!string.IsNullOrWhiteSpace(value) && !string.IsNullOrWhiteSpace(name))
{
sb.Append($"{UrlEncoder.Default.Encode(name)}={UrlEncoder.Default.Encode(value)}&");
}

return this;
}
public IFinisher Finish()
{
if(sb[sb.Length - 1] == '&' || sb[sb.Length - 1] == '?')
{
sb.Remove(sb.Length - 1, 1);
}
return this;
}
public string GetBuildedQuery()
{
return sb.ToString();
}
}
}
81 changes: 81 additions & 0 deletions tests/TBC.OpenAPI.SDK.Core.Tests/ComponentTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TBC.OpenAPI.SDK.Core.Models;
using Xunit;
using FluentAssertions;
using System.Net;
using System.Web;
using System.Text.Encodings.Web;

namespace TBC.OpenAPI.SDK.Core.Tests
{
public class ComponentTests
{
[Theory]
[InlineData("name", "Shota Rustaveli")]
[InlineData("name", "Shota&Rustaveli")]
[InlineData("name", "Shota?Rustaveli")]
[InlineData("name?", "ShotaRustaveli")]
[InlineData("name&", "ShotaRustaveli")]
[InlineData("name!", "ShotaRustaveli")]
[InlineData("(name)", "ShotaRustaveli")]
[InlineData("name", "Shota! Rustaveli")]
[InlineData("name", "Shota.Rustaveli")]
[InlineData("name", "Shota_Rustaveli")]
[InlineData("name", "Shota-Rustaveli")]
[InlineData("name", "Shota(Rustaveli)")]
[InlineData("name", "შოთა რუსთაველი")]
public void QueryParamCollection_ToQueryString_UrlEncode_RespondShouldBePositive(string key, string value)
{
//Arrange
QueryParamCollection col = new QueryParamCollection();
col.Add("paramKey", "paramValue");
col.Add(key, value);

//act
var result = col.ToQueryString();

//assert
result.Should().NotBeNullOrEmpty();
var shouldBe = $"?paramKey=paramValue&{UrlEncoder.Default.Encode(key)}={UrlEncoder.Default.Encode(value)}";
result.Should().Be(shouldBe);
}

[Theory]
[InlineData("", "Shota Rustaveli")]
[InlineData("Name", null)]
[InlineData("Name", "")]
[InlineData("", "")]
public void QueryParamCollection_ToQueryString_IfHaveNullKeyOrValue_PositiveCases(string key, string value)
{
//Arrange
QueryParamCollection col = new QueryParamCollection();
col.Add(key, value);

//act
var result = col.ToQueryString();

//assert
var shouldBe = "";
result.Should().Be(shouldBe);
}

[Theory]
[InlineData(null, "Shota Rustaveli")]
[InlineData(null, null)]
public void QueryParamCollection_ToQueryString_IfHaveNullKeyOrValue_ThrowException(string key, string value)
{
//Arrange
QueryParamCollection col = new QueryParamCollection();

//act
Action result = ()=> col.Add(key, value);

//assert
result.Should().Throw<ArgumentNullException>();
}
}
}

0 comments on commit baa6a91

Please sign in to comment.