#269 Clean up QueryString APIs, add tests.

This commit is contained in:
Chris R 2015-05-06 10:55:20 -07:00
parent 568d0d9106
commit c9c09fb4e5
2 changed files with 179 additions and 10 deletions

View File

@ -2,6 +2,8 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Framework.Internal;
using Microsoft.Framework.WebEncoders;
@ -33,16 +35,6 @@ namespace Microsoft.AspNet.Http
_value = value;
}
/// <summary>
/// Initialize a query string with a single given parameter name and value.
/// </summary>
/// <param name="name">The un-encoded parameter name</param>
/// <param name="value">The un-encoded parameter value</param>
public QueryString(string name, string value)
{
_value = "?" + UrlEncoder.Default.UrlEncode(name) + '=' + UrlEncoder.Default.UrlEncode(value);
}
/// <summary>
/// The escaped query string with the leading '?' character
/// </summary>
@ -114,6 +106,67 @@ namespace Microsoft.AspNet.Http
return new QueryString(queryValue);
}
/// <summary>
/// Create a query string with a single given parameter name and value.
/// </summary>
/// <param name="name">The un-encoded parameter name</param>
/// <param name="value">The un-encoded parameter value</param>
public static QueryString Create(string name, string value)
{
return new QueryString("?" + UrlEncoder.Default.UrlEncode(name) + '=' + UrlEncoder.Default.UrlEncode(value));
}
/// <summary>
/// Creates a query string composed from the given name value pairs.
/// </summary>
/// <param name="parameters"></param>
/// <returns></returns>
public static QueryString Create(IEnumerable<KeyValuePair<string, string>> parameters)
{
var builder = new StringBuilder();
bool first = true;
foreach (var pair in parameters)
{
builder.Append(first ? "?" : "&");
first = false;
builder.Append(UrlEncoder.Default.UrlEncode(pair.Key));
builder.Append("=");
builder.Append(UrlEncoder.Default.UrlEncode(pair.Value));
}
return new QueryString(builder.ToString());
}
public QueryString Add(QueryString other)
{
if (!HasValue || Value.Equals("?", StringComparison.Ordinal))
{
return other;
}
if (!other.HasValue || other.Value.Equals("?", StringComparison.Ordinal))
{
return this;
}
// ?name1=value1 Add ?name2=value2 returns ?name1=value1&name2=value2
return new QueryString(_value + "&" + other.Value.Substring(1));
}
public QueryString Add(string name, string value)
{
if (!HasValue || Value.Equals("?", StringComparison.Ordinal))
{
return Create(name, value);
}
var builder = new StringBuilder(Value);
builder.Append("&");
builder.Append(UrlEncoder.Default.UrlEncode(name));
builder.Append("=");
builder.Append(UrlEncoder.Default.UrlEncode(value));
return new QueryString(builder.ToString());
}
public bool Equals(QueryString other)
{
return string.Equals(_value, other._value);
@ -142,5 +195,10 @@ namespace Microsoft.AspNet.Http
{
return !left.Equals(right);
}
public static QueryString operator +(QueryString left, QueryString right)
{
return left.Add(right);
}
}
}

View File

@ -0,0 +1,111 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNet.Testing;
using Xunit;
namespace Microsoft.AspNet.Http.Abstractions
{
public class QueryStringTests
{
[Fact]
public void CtorThrows_IfQueryDoesNotHaveLeadingQuestionMark()
{
// Act and Assert
ExceptionAssert.ThrowsArgument(() => new QueryString("hello"), "value", "The leading '?' must be included for a non-empty query.");
}
[Fact]
public void CtorNullOrEmpty_Success()
{
var query = new QueryString();
Assert.False(query.HasValue);
Assert.Null(query.Value);
query = new QueryString(null);
Assert.False(query.HasValue);
Assert.Null(query.Value);
query = new QueryString(string.Empty);
Assert.False(query.HasValue);
Assert.Equal(string.Empty, query.Value);
}
[Fact]
public void CtorJustAQuestionMark_Success()
{
var query = new QueryString("?");
Assert.True(query.HasValue);
Assert.Equal("?", query.Value);
}
[Fact]
public void ToString_EncodesHash()
{
var query = new QueryString("?Hello=Wor#ld");
Assert.Equal("?Hello=Wor%23ld", query.ToString());
}
[Theory]
[InlineData("name", "value", "?name=value")]
[InlineData("na me", "val ue", "?na%20me=val%20ue")]
[InlineData("name", "", "?name=")]
[InlineData("", "value", "?=value")]
[InlineData("", "", "?=")]
[InlineData(null, null, "?=")]
public void CreateNameValue_Success(string name, string value, string exepcted)
{
var query = QueryString.Create(name, value);
Assert.Equal(exepcted, query.Value);
}
[Fact]
public void CreateFromList_Success()
{
var query = QueryString.Create(new[]
{
new KeyValuePair<string, string>("key1", "value1"),
new KeyValuePair<string, string>("key2", "value2"),
new KeyValuePair<string, string>("key3", "value3"),
});
Assert.Equal("?key1=value1&key2=value2&key3=value3", query.Value);
}
[Theory]
[InlineData(null, null, null)]
[InlineData("", "", "")]
[InlineData(null, "?name2=value2", "?name2=value2")]
[InlineData("", "?name2=value2", "?name2=value2")]
[InlineData("?", "?name2=value2", "?name2=value2")]
[InlineData("?name1=value1", null, "?name1=value1")]
[InlineData("?name1=value1", "", "?name1=value1")]
[InlineData("?name1=value1", "?", "?name1=value1")]
[InlineData("?name1=value1", "?name2=value2", "?name1=value1&name2=value2")]
public void AddQueryString_Success(string query1, string query2, string expected)
{
var q1 = new QueryString(query1);
var q2 = new QueryString(query2);
Assert.Equal(expected, q1.Add(q2).Value);
Assert.Equal(expected, (q1 + q2).Value);
}
[Theory]
[InlineData(null, null, null, "?=")]
[InlineData("", "", "", "?=")]
[InlineData("?", "", "", "?=")]
[InlineData("?", "name2", "value2", "?name2=value2")]
[InlineData("?name1=value1", "name2", "value2", "?name1=value1&name2=value2")]
[InlineData("?name1=value1", "na me2", "val ue2", "?name1=value1&na%20me2=val%20ue2")]
[InlineData("?name1=value1", "", "", "?name1=value1&=")]
public void AddNameValue_Success(string query1, string name2, string value2, string expected)
{
var q1 = new QueryString(query1);
var q2 = q1.Add(name2, value2);
Assert.Equal(expected, q2.Value);
}
}
}