summaryrefslogtreecommitdiffstats
path: root/src/DotNetOpenAuth.AspNet.Test
diff options
context:
space:
mode:
Diffstat (limited to 'src/DotNetOpenAuth.AspNet.Test')
-rw-r--r--src/DotNetOpenAuth.AspNet.Test/DotNetOpenAuth.Web.Test.csproj79
-rw-r--r--src/DotNetOpenAuth.AspNet.Test/OAuth2ClientTest.cs140
-rw-r--r--src/DotNetOpenAuth.AspNet.Test/OAuthAuthenticationTickerHelperTest.cs152
-rw-r--r--src/DotNetOpenAuth.AspNet.Test/OAuthClientTest.cs143
-rw-r--r--src/DotNetOpenAuth.AspNet.Test/Properties/AssemblyInfo.cs35
-rw-r--r--src/DotNetOpenAuth.AspNet.Test/UriHelperTest.cs41
6 files changed, 590 insertions, 0 deletions
diff --git a/src/DotNetOpenAuth.AspNet.Test/DotNetOpenAuth.Web.Test.csproj b/src/DotNetOpenAuth.AspNet.Test/DotNetOpenAuth.Web.Test.csproj
new file mode 100644
index 0000000..0d2c7af
--- /dev/null
+++ b/src/DotNetOpenAuth.AspNet.Test/DotNetOpenAuth.Web.Test.csproj
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildProjectDirectory), EnlistmentInfo.props))\EnlistmentInfo.props" Condition=" '$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildProjectDirectory), EnlistmentInfo.props))' != '' " />
+ <PropertyGroup>
+ <StyleCopEnabled>False</StyleCopEnabled>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>8.0.30703</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{C23B217B-4D35-4A72-A1F7-FAEB4F39CB91}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>DotNetOpenAuth.Web.Test</RootNamespace>
+ <AssemblyName>DotNetOpenAuth.Web.Test</AssemblyName>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <Import Project="$(ProjectRoot)tools\DotNetOpenAuth.props" />
+ <PropertyGroup>
+ <DelaySign>true</DelaySign>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="Moq">
+ <HintPath>..\..\lib\Moq.dll</HintPath>
+ </Reference>
+ <Reference Include="nunit.framework">
+ <HintPath>..\..\lib\nunit.framework.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Web" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="OAuth2ClientTest.cs" />
+ <Compile Include="OAuthAuthenticationTickerHelperTest.cs" />
+ <Compile Include="OAuthClientTest.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="UriHelperTest.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\DotNetOpenAuth.Messaging\DotNetOpenAuth.Messaging.csproj">
+ <Project>{60426312-6AE5-4835-8667-37EDEA670222}</Project>
+ <Name>DotNetOpenAuth.Messaging</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\DotNetOpenAuth.OAuth\DotNetOpenAuth.OAuth.csproj">
+ <Project>{A288FCC8-6FCF-46DA-A45E-5F9281556361}</Project>
+ <Name>DotNetOpenAuth.OAuth</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\DotNetOpenAuth.AspNet\DotNetOpenAuth.AspNet.csproj">
+ <Project>{51835086-9611-4C53-819B-F2D5C9320873}</Project>
+ <Name>DotNetOpenAuth.AspNet</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <Import Project="$(ProjectRoot)tools\DotNetOpenAuth.targets" />
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildProjectDirectory), EnlistmentInfo.targets))\EnlistmentInfo.targets" Condition=" '$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildProjectDirectory), EnlistmentInfo.targets))' != '' " />
+</Project> \ No newline at end of file
diff --git a/src/DotNetOpenAuth.AspNet.Test/OAuth2ClientTest.cs b/src/DotNetOpenAuth.AspNet.Test/OAuth2ClientTest.cs
new file mode 100644
index 0000000..bc28f63
--- /dev/null
+++ b/src/DotNetOpenAuth.AspNet.Test/OAuth2ClientTest.cs
@@ -0,0 +1,140 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.Web;
+using DotNetOpenAuth.AspNet.Clients;
+using Moq;
+using NUnit.Framework;
+
+namespace DotNetOpenAuth.AspNet.Test
+{
+ [TestFixture]
+ public class OAuth2ClientTest
+ {
+ [TestCase]
+ public void TestProviderName()
+ {
+ // Arrange
+ var client = new MockOAuth2Client();
+
+ // Act
+ string providerName = client.ProviderName;
+
+ // Assert
+ Assert.AreEqual("mockprovider", providerName);
+ }
+
+ [TestCase]
+ public void RequestAuthenticationIssueCorrectRedirect()
+ {
+ // Arrange
+ var client = new MockOAuth2Client();
+ var context = new Mock<HttpContextBase>(MockBehavior.Strict);
+ context.Setup(c => c.Response.Redirect("http://live.com/?q=http://return.to.me/", true)).Verifiable();
+
+ // Act
+ client.RequestAuthentication(context.Object, new Uri("http://return.to.me"));
+
+ // Assert
+ context.Verify();
+ }
+
+ [TestCase]
+ public void VerifyAuthenticationThrowsIfContextIsNull()
+ {
+ // Arrange
+ var client = new MockOAuth2Client();
+
+ // Act && Assert
+ Assert.Throws<ArgumentNullException>(() => client.VerifyAuthentication(null));
+ }
+
+ [TestCase]
+ public void VerifyAuthenticationFailsIfCodeIsNotPresent()
+ {
+ // Arrange
+ var client = new MockOAuth2Client();
+ var context = new Mock<HttpContextBase>(MockBehavior.Strict);
+ var queryStrings = new NameValueCollection();
+ context.Setup(c => c.Request.QueryString).Returns(queryStrings);
+
+ // Act
+ AuthenticationResult result = client.VerifyAuthentication(context.Object);
+
+ // Assert
+ Assert.IsFalse(result.IsSuccessful);
+ }
+
+ [TestCase]
+ public void VerifyAuthenticationFailsIfAccessTokenIsNull()
+ {
+ // Arrange
+ var client = new MockOAuth2Client();
+ var context = new Mock<HttpContextBase>(MockBehavior.Strict);
+ var queryStrings = new NameValueCollection();
+ queryStrings.Add("code", "random");
+ context.Setup(c => c.Request.QueryString).Returns(queryStrings);
+
+ // Act
+ AuthenticationResult result = client.VerifyAuthentication(context.Object);
+
+ // Assert
+ Assert.IsFalse(result.IsSuccessful);
+ }
+
+ [TestCase]
+ public void VerifyAuthenticationSucceeds()
+ {
+ // Arrange
+ var client = new MockOAuth2Client();
+ var context = new Mock<HttpContextBase>(MockBehavior.Strict);
+ var queryStrings = new NameValueCollection();
+ queryStrings.Add("code", "secret");
+ context.Setup(c => c.Request.QueryString).Returns(queryStrings);
+
+ // Act
+ AuthenticationResult result = client.VerifyAuthentication(context.Object);
+
+ // Assert
+ Assert.True(result.IsSuccessful);
+ Assert.AreEqual("mockprovider", result.Provider);
+ Assert.AreEqual("12345", result.ProviderUserId);
+ Assert.AreEqual("John Doe", result.UserName);
+ Assert.NotNull(result.ExtraData);
+ Assert.AreEqual("abcde", result.ExtraData["token"]);
+ }
+
+ private class MockOAuth2Client : OAuth2Client
+ {
+ public MockOAuth2Client() : base("mockprovider")
+ {
+ }
+
+ protected override Uri GetServiceLoginUrl(Uri returnUrl)
+ {
+ string url = "http://live.com/?q=" + returnUrl.ToString();
+ return new Uri(url);
+ }
+
+ protected override string QueryAccessToken(Uri returnUrl, string authorizationCode)
+ {
+ return (authorizationCode == "secret") ? "abcde" : null;
+ }
+
+ protected override IDictionary<string, string> GetUserData(string accessToken)
+ {
+ if (accessToken == "abcde")
+ {
+ return new Dictionary<string, string>
+ {
+ {"id", "12345"},
+ {"token", accessToken},
+ {"name", "John Doe"}
+ };
+ }
+
+ return null;
+ }
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth.AspNet.Test/OAuthAuthenticationTickerHelperTest.cs b/src/DotNetOpenAuth.AspNet.Test/OAuthAuthenticationTickerHelperTest.cs
new file mode 100644
index 0000000..f3fea5c
--- /dev/null
+++ b/src/DotNetOpenAuth.AspNet.Test/OAuthAuthenticationTickerHelperTest.cs
@@ -0,0 +1,152 @@
+using System;
+using System.Web;
+using System.Web.Security;
+using DotNetOpenAuth.AspNet;
+using Moq;
+using NUnit.Framework;
+
+namespace DotNetOpenAuth.Test.Web
+{
+ [TestFixture]
+ public class OAuthAuthenticationTickerHelperTest
+ {
+ [TestCase]
+ public void SetAuthenticationTicketSetCookieOnHttpResponseWithPersistentSet()
+ {
+ SetAuthenticationTicketSetCookieOnHttpResponse(isPersistent: true);
+ }
+
+ [TestCase]
+ public void SetAuthenticationTicketSetCookieOnHttpResponseWithPersistentNotSet()
+ {
+ SetAuthenticationTicketSetCookieOnHttpResponse(isPersistent: false);
+ }
+
+ [TestCase]
+ public void IsOAuthAuthenticationTicketReturnsTrueIfCookieIsPresent()
+ {
+ // Arrange
+ var ticket = new FormsAuthenticationTicket(
+ 2,
+ "username",
+ DateTime.Now,
+ DateTime.Now.Add(FormsAuthentication.Timeout),
+ false,
+ "OAuth",
+ FormsAuthentication.FormsCookiePath);
+
+ var cookie = new HttpCookie(name: FormsAuthentication.FormsCookieName,
+ value: FormsAuthentication.Encrypt(ticket));
+ var cookies = new HttpCookieCollection {cookie};
+
+ var context = new Mock<HttpContextBase>();
+ context.Setup(c => c.Request.Cookies).Returns(cookies);
+
+ // Act
+ bool result = OpenAuthAuthenticationTicketHelper.IsValidAuthenticationTicket(context.Object);
+
+ // Assert
+ Assert.IsTrue(result);
+ }
+
+ [TestCase]
+ public void IsOAuthAuthenticationTicketReturnsFalseIfCookieIsNotPresent()
+ {
+ // Arrange
+ var context = new Mock<HttpContextBase>();
+ context.Setup(c => c.Request.Cookies).Returns(new HttpCookieCollection());
+
+ // Act
+ bool result = OpenAuthAuthenticationTicketHelper.IsValidAuthenticationTicket(context.Object);
+
+ // Assert
+ Assert.IsFalse(result);
+ }
+
+ [TestCase]
+ public void IsOAuthAuthenticationTicketReturnsFalseIfCookieIsPresentButDoesNotHaveOAuthData()
+ {
+ // Arrange
+ var ticket = new FormsAuthenticationTicket(
+ 2,
+ "username",
+ DateTime.Now,
+ DateTime.Now.Add(FormsAuthentication.Timeout),
+ false,
+ null,
+ FormsAuthentication.FormsCookiePath);
+
+ var cookie = new HttpCookie(name: FormsAuthentication.FormsCookieName,
+ value: FormsAuthentication.Encrypt(ticket));
+ var cookies = new HttpCookieCollection { cookie };
+
+ var context = new Mock<HttpContextBase>();
+ context.Setup(c => c.Request.Cookies).Returns(cookies);
+
+ // Act
+ bool result = OpenAuthAuthenticationTicketHelper.IsValidAuthenticationTicket(context.Object);
+
+ // Assert
+ Assert.IsFalse(result);
+ }
+
+ [TestCase]
+ public void IsOAuthAuthenticationTicketReturnsFalseIfCookieIsPresentButDoesNotHaveCorrectName()
+ {
+ // Arrange
+ var response = new Mock<HttpResponseBase>();
+
+ var ticket = new FormsAuthenticationTicket(
+ 2,
+ "username",
+ DateTime.Now,
+ DateTime.Now.Add(FormsAuthentication.Timeout),
+ false,
+ "OAuth",
+ FormsAuthentication.FormsCookiePath);
+
+ var cookie = new HttpCookie(name: "random cookie name",
+ value: FormsAuthentication.Encrypt(ticket));
+ var cookies = new HttpCookieCollection { cookie };
+
+ var context = new Mock<HttpContextBase>();
+ context.Setup(c => c.Request.Cookies).Returns(cookies);
+
+ // Act
+ bool result = OpenAuthAuthenticationTicketHelper.IsValidAuthenticationTicket(context.Object);
+
+ // Assert
+ Assert.IsFalse(result);
+ }
+
+ private void SetAuthenticationTicketSetCookieOnHttpResponse(bool isPersistent)
+ {
+ // Arrange
+ var cookies = new HttpCookieCollection();
+
+ var context = new Mock<HttpContextBase>();
+ context.Setup(c => c.Request.IsSecureConnection).Returns(true);
+ context.Setup(c => c.Response.Cookies).Returns(cookies);
+
+ // Act
+ OpenAuthAuthenticationTicketHelper.SetAuthenticationTicket(context.Object, "user", isPersistent);
+
+ // Assert
+ Assert.AreEqual(1, cookies.Count);
+ HttpCookie addedCookie = cookies[0];
+
+ Assert.AreEqual(FormsAuthentication.FormsCookieName, addedCookie.Name);
+ Assert.IsTrue(addedCookie.HttpOnly);
+ Assert.AreEqual("/", addedCookie.Path);
+ Assert.IsFalse(addedCookie.Secure);
+ Assert.IsNotNullOrEmpty(addedCookie.Value);
+
+ FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(addedCookie.Value);
+ Assert.NotNull(ticket);
+ Assert.AreEqual(2, ticket.Version);
+ Assert.AreEqual("user", ticket.Name);
+ Assert.AreEqual("OAuth", ticket.UserData);
+ Assert.AreEqual(isPersistent, ticket.IsPersistent);
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth.AspNet.Test/OAuthClientTest.cs b/src/DotNetOpenAuth.AspNet.Test/OAuthClientTest.cs
new file mode 100644
index 0000000..6c14927
--- /dev/null
+++ b/src/DotNetOpenAuth.AspNet.Test/OAuthClientTest.cs
@@ -0,0 +1,143 @@
+using System;
+using System.Web;
+using DotNetOpenAuth.Messaging;
+using DotNetOpenAuth.OAuth.Messages;
+using DotNetOpenAuth.AspNet.Clients;
+using Moq;
+using NUnit.Framework;
+using DotNetOpenAuth.AspNet;
+
+namespace DotNetOpenAuth.AspNet.Test
+{
+ [TestFixture]
+ public class OAuthClientTest
+ {
+ [TestCase]
+ public void TestProviderNamePropertyIsCorrect()
+ {
+ // Arrange
+ var client = new MockOAuthClient();
+
+ // Act
+ var provider = client.ProviderName;
+
+ // Assert
+ Assert.AreEqual("mockoauth", provider);
+ }
+
+ [TestCase]
+ public void RequestAuthenticationInvokeMethodOnWebWorker()
+ {
+ // Arrange
+ var webWorker = new Mock<IOAuthWebWorker>(MockBehavior.Strict);
+ webWorker.Setup(
+ w => w.RequestAuthentication(
+ It.Is<Uri>(u => u.ToString().Equals("http://live.com/my/path.cshtml?q=one"))))
+ .Verifiable();
+
+ var client = new MockOAuthClient(webWorker.Object);
+ var returnUri = new Uri("http://live.com/my/path.cshtml?q=one");
+ var context = new Mock<HttpContextBase>();
+
+ // Act
+ client.RequestAuthentication(context.Object, returnUri);
+
+ // Assert
+ webWorker.Verify();
+ }
+
+ [TestCase]
+ public void VerifyAuthenticationFailsIfResponseTokenIsNull()
+ {
+ // Arrange
+ var webWorker = new Mock<IOAuthWebWorker>(MockBehavior.Strict);
+ webWorker.Setup(w => w.ProcessUserAuthorization()).Returns((AuthorizedTokenResponse)null);
+
+ var client = new MockOAuthClient(webWorker.Object);
+ var context = new Mock<HttpContextBase>();
+
+ // Act
+ client.VerifyAuthentication(context.Object);
+
+ // Assert
+ webWorker.Verify();
+ }
+
+ [TestCase]
+ public void VerifyAuthenticationFailsIfAccessTokenIsInvalid()
+ {
+ // Arrange
+ var endpoint = new MessageReceivingEndpoint("http://live.com/path/?a=b", HttpDeliveryMethods.GetRequest);
+ var request = new AuthorizedTokenRequest(endpoint, new Version("1.0"));
+ var response = new AuthorizedTokenResponse(request)
+ {
+ AccessToken = "invalid token"
+ };
+
+ var webWorker = new Mock<IOAuthWebWorker>(MockBehavior.Strict);
+ webWorker.Setup(w => w.ProcessUserAuthorization()).Returns(response).Verifiable();
+
+ var client = new MockOAuthClient(webWorker.Object);
+ var context = new Mock<HttpContextBase>();
+
+ // Act
+ AuthenticationResult result = client.VerifyAuthentication(context.Object);
+
+ // Assert
+ webWorker.Verify();
+
+ Assert.False(result.IsSuccessful);
+ }
+
+ [TestCase]
+ public void VerifyAuthenticationSucceeds()
+ {
+ // Arrange
+ var endpoint = new MessageReceivingEndpoint("http://live.com/path/?a=b", HttpDeliveryMethods.GetRequest);
+ var request = new AuthorizedTokenRequest(endpoint, new Version("1.0"));
+ var response = new AuthorizedTokenResponse(request)
+ {
+ AccessToken = "ok"
+ };
+
+ var webWorker = new Mock<IOAuthWebWorker>(MockBehavior.Strict);
+ webWorker.Setup(w => w.ProcessUserAuthorization()).Returns(response).Verifiable();
+
+ var client = new MockOAuthClient(webWorker.Object);
+ var context = new Mock<HttpContextBase>();
+
+ // Act
+ AuthenticationResult result = client.VerifyAuthentication(context.Object);
+
+ // Assert
+ webWorker.Verify();
+
+ Assert.True(result.IsSuccessful);
+ Assert.AreEqual("mockoauth", result.Provider);
+ Assert.AreEqual("12345", result.ProviderUserId);
+ Assert.AreEqual("super", result.UserName);
+ }
+
+ private class MockOAuthClient : OAuthClient
+ {
+ public MockOAuthClient()
+ : this(new Mock<IOAuthWebWorker>().Object)
+ {
+ }
+
+ public MockOAuthClient(IOAuthWebWorker worker) : base("mockoauth", worker)
+ {
+ }
+
+ protected override AuthenticationResult VerifyAuthenticationCore(AuthorizedTokenResponse response)
+ {
+ if (response.AccessToken == "ok")
+ {
+ return new AuthenticationResult(true, "mockoauth", "12345", "super", response.ExtraData);
+ }
+
+ return AuthenticationResult.Failed;
+ }
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth.AspNet.Test/Properties/AssemblyInfo.cs b/src/DotNetOpenAuth.AspNet.Test/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..3c9f4f6
--- /dev/null
+++ b/src/DotNetOpenAuth.AspNet.Test/Properties/AssemblyInfo.cs
@@ -0,0 +1,35 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("DotNetOpenAuth.AspNet.Test")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Microsoft IT")]
+[assembly: AssemblyProduct("DotNetOpenAuth.AspNet.Test")]
+[assembly: AssemblyCopyright("Copyright © Microsoft IT 2011")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("6c32d8f7-1394-40ef-9ec0-b8953adc0a4f")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/src/DotNetOpenAuth.AspNet.Test/UriHelperTest.cs b/src/DotNetOpenAuth.AspNet.Test/UriHelperTest.cs
new file mode 100644
index 0000000..53a2b52
--- /dev/null
+++ b/src/DotNetOpenAuth.AspNet.Test/UriHelperTest.cs
@@ -0,0 +1,41 @@
+using System;
+using DotNetOpenAuth.AspNet.Clients;
+using NUnit.Framework;
+
+namespace DotNetOpenAuth.AspNet.Test
+{
+ [TestFixture]
+ public class UriHelperTest
+ {
+ [TestCase]
+ public void TestAttachQueryStringParameterMethod()
+ {
+ // Arrange
+ string[] input = new string[]
+ {
+ "http://x.com",
+ "https://xxx.com/one?s=123",
+ "https://yyy.com/?s=6&u=a",
+ "https://zzz.com/default.aspx?name=sd"
+ };
+
+ string[] expectedOutput = new string[]
+ {
+ "http://x.com/?s=awesome",
+ "https://xxx.com/one?s=awesome",
+ "https://yyy.com/?s=awesome&u=a",
+ "https://zzz.com/default.aspx?name=sd&s=awesome"
+ };
+
+ for (int i = 0; i < input.Length; i++)
+ {
+ // Act
+ var inputUrl = new Uri(input[i]);
+ var outputUri = UriHelper.AttachQueryStringParameter(inputUrl, "s", "awesome");
+
+ // Assert
+ Assert.AreEqual(expectedOutput[i], outputUri.ToString());
+ }
+ }
+ }
+}