// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information. using System.Collections.Generic; using System.Net.Http; using System.Web.Http.Controllers; using Microsoft.TestCommon; using Xunit; using Xunit.Extensions; using Assert = Microsoft.TestCommon.AssertEx; namespace System.Web.Http.Routing { public class UrlHelperTest { [Fact] public void UrlHelper_CtorThrows_WithNullContext() { Assert.ThrowsArgumentNull( () => new UrlHelper(null), "controllerContext"); } [Fact] public void ControllerContext_HasUrlHelperWithValidContext() { HttpControllerContext cc = new HttpControllerContext(); Assert.NotNull(cc.Url); Assert.IsType(cc.Url); Assert.Same(cc, cc.Url.ControllerContext); } [Theory] [PropertyData("UrlGeneratorTestData")] public void UrlHelper_UsesCurrentRouteDataToPopulateValues_WithObjectValues(string controller, int? id, string expectedUrl) { var url = GetUrlHelperForApi(); object routeValues = GetRouteValuesAsObject(controller, id); string generatedUrl = url.Route("route1", routeValues); Assert.Equal(expectedUrl, generatedUrl); } [Theory] [PropertyData("UrlGeneratorTestData")] public void UrlHelper_UsesCurrentRouteDataToPopulateValues_WithDictionaryValues(string controller, int? id, string expectedUrl) { var url = GetUrlHelperForApi(); Dictionary routeValues = GetRouteValuesAsDictionary(controller, id); string generatedUrl = url.Route("route1", routeValues); Assert.Equal(expectedUrl, generatedUrl); } [Fact] public void UrlHelper_Throws_WhenWrongNameUsed_WithObjectValues() { var url = GetUrlHelperForApi(); Assert.ThrowsArgument( () => url.Route("route-doesn't-exist", null), "name", "A route named 'route-doesn't-exist' could not be found in the route collection."); } [Fact] public void UrlHelper_Throws_WhenWrongNameUsed_WithDictionaryValues() { var url = GetUrlHelperForApi(); Assert.ThrowsArgument( () => url.Route("route-doesn't-exist", (IDictionary)null), "name", "A route named 'route-doesn't-exist' could not be found in the route collection."); } [Theory] [TestDataSet( typeof(UrlHelperTest), "UrlGeneratorTestData", typeof(UrlHelperTest), "RequestUrlTestData")] public void UrlHelper_LinkGeneration_GeneratesRightLinksWithDictionary(string controller, int? id, string expectedUrl, string requestUrl) { var urlHelper = GetUrlHelperForApi(); urlHelper.ControllerContext.Request = new HttpRequestMessage(HttpMethod.Get, requestUrl); Dictionary routeValues = GetRouteValuesAsDictionary(controller, id); string baseUrl = new Uri(requestUrl).GetLeftPart(UriPartial.Authority); string generatedlink = urlHelper.Link("route1", routeValues); Assert.Equal(expectedUrl != null ? baseUrl + expectedUrl : null, generatedlink); } [Theory] [TestDataSet( typeof(UrlHelperTest), "UrlGeneratorTestData", typeof(UrlHelperTest), "RequestUrlTestData")] public void UrlHelper_LinkGeneration_GeneratesRightLinksWithObject(string controller, int? id, string expectedUrl, string requestUrl) { var urlHelper = GetUrlHelperForApi(); urlHelper.ControllerContext.Request = new HttpRequestMessage(HttpMethod.Get, requestUrl); object routeValues = GetRouteValuesAsObject(controller, id); string baseUrl = new Uri(requestUrl).GetLeftPart(UriPartial.Authority); string generatedlink = urlHelper.Link("route1", routeValues); Assert.Equal(expectedUrl != null ? baseUrl + expectedUrl : null, generatedlink); } private static UrlHelper GetUrlHelperForApi() { HttpControllerContext cc = new HttpControllerContext(); // Set up routes var routes = new HttpRouteCollection("/somerootpath"); IHttpRoute route = routes.MapHttpRoute("route1", "{controller}/{id}"); cc.Configuration = new HttpConfiguration(routes); cc.RouteData = new HttpRouteData(route, new HttpRouteValueDictionary(new { controller = "people", id = "123" })); return cc.Url; } private static object GetRouteValuesAsObject(string controller, int? id) { object routeValues = null; if (controller == null) { if (id == null) { routeValues = null; } else { routeValues = new { id }; } } else { if (id == null) { routeValues = new { controller }; } else { routeValues = new { controller, id }; } } return routeValues; } private static Dictionary GetRouteValuesAsDictionary(string controller, int? id) { Dictionary routeValues = new Dictionary(); if (controller == null) { if (id == null) { routeValues = null; } else { routeValues.Add("id", id); } } else { if (id == null) { routeValues.Add("controller", controller); } else { routeValues.Add("controller", controller); routeValues.Add("id", id); } } return routeValues; } public static IEnumerable UrlGeneratorTestData { get { return new TheoryDataSet() { { null, 456, "/somerootpath/people/456"}, // Just override ID, so ID is replaced { "people", 456, "/somerootpath/people/456"}, // Just override ID, so ID is replaced { null, null, "/somerootpath/people/123"}, // Override nothing, so everything the same { "people", null, "/somerootpath/people/123"}, // Override nothing, so everything the same { "customers", 456, "/somerootpath/customers/456"}, // Override everything, so everything changed { "customers", null, null}, // Override controller, which clears out the ID, so it doesn't match (i.e. null) }; } } public static IEnumerable RequestUrlTestData { get { return new[] { "http://localhost", "http://localhost/123", "http://localhost/123?q=odata&$filter=123#123" }; } } } }