// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information. using System.Linq; using System.Web.Routing; using Moq; using Xunit; using Assert = Microsoft.TestCommon.AssertEx; namespace System.Web.Mvc.Test { public class RouteCollectionExtensionsTest { private static string[] _nameSpaces = new string[] { "nsA.nsB.nsC", "ns1.ns2.ns3" }; [Fact] public void GetVirtualPathForAreaDoesNotStripAreaTokenIfAreasNotInUse() { // Arrange RouteCollection routes = new RouteCollection(); routes.MapRoute( "Default", "no-area/{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = "" } ); RequestContext requestContext = GetRequestContext(null); RouteValueDictionary values = new RouteValueDictionary() { { "controller", "home" }, { "action", "about" }, { "area", "some-area" } }; // Act VirtualPathData vpd = routes.GetVirtualPathForArea(requestContext, values); // Assert Assert.NotNull(vpd); Assert.Equal(routes["Default"], vpd.Route); // note presence of 'area' query string parameter; RVD should not be modified if areas not in use Assert.Equal("/app/no-area/home/about?area=some-area", vpd.VirtualPath); } [Fact] public void GetVirtualPathForAreaForwardsCallIfRouteNameSpecified() { // Arrange RouteCollection routes = GetRouteCollection(); RequestContext requestContext = GetRequestContext(null); RouteValueDictionary values = new RouteValueDictionary() { { "controller", "home" }, { "action", "index" }, { "area", "some-area" } }; // Act VirtualPathData vpd = routes.GetVirtualPathForArea(requestContext, "admin_default", values); // Assert Assert.NotNull(vpd); Assert.Equal(routes["admin_default"], vpd.Route); // note presence of 'area' query string parameter; RVD should not be modified if route name was provided Assert.Equal("/app/admin-area?area=some-area", vpd.VirtualPath); } [Fact] public void GetVirtualPathForAreaThrowsIfRoutesIsNull() { // Act & assert Assert.ThrowsArgumentNull( delegate { RouteCollectionExtensions.GetVirtualPathForArea(null, null, null); }, "routes"); } [Fact] public void GetVirtualPathForAreaWillJumpBetweenAreasExplicitly() { // Arrange RouteCollection routes = GetRouteCollection(); RequestContext requestContext = GetRequestContext(null); RouteValueDictionary values = new RouteValueDictionary() { { "controller", "home" }, { "action", "tenmostrecent" }, { "tag", "some-tag" }, { "area", "blog" } }; // Act VirtualPathData vpd = routes.GetVirtualPathForArea(requestContext, values); // Assert Assert.NotNull(vpd); Assert.Equal(routes["blog_whatsnew"], vpd.Route); Assert.Equal("/app/whats-new/some-tag", vpd.VirtualPath); } [Fact] public void GetVirtualPathForAreaWillNotJumpBetweenAreasImplicitly() { // Arrange RouteCollection routes = GetRouteCollection(); RequestContext requestContext = GetRequestContext("admin"); RouteValueDictionary values = new RouteValueDictionary() { { "controller", "home" }, { "action", "tenmostrecent" }, { "tag", "some-tag" } }; // Act VirtualPathData vpd = routes.GetVirtualPathForArea(requestContext, values); // Assert Assert.NotNull(vpd); Assert.Equal(routes["admin_default"], vpd.Route); Assert.Equal("/app/admin-area/home/tenmostrecent?tag=some-tag", vpd.VirtualPath); } [Fact] public void MapRoute3() { // Arrange RouteCollection routes = new RouteCollection(); // Act routes.MapRoute("RouteName", "SomeUrl"); // Assert Route route = Assert.Single(routes.Cast()); Assert.NotNull(route); Assert.Same(route, routes["RouteName"]); Assert.Equal("SomeUrl", route.Url); Assert.IsType(route.RouteHandler); Assert.Empty(route.Defaults); Assert.Empty(route.Constraints); Assert.Empty(route.DataTokens); } [Fact] public void MapRoute3WithNameSpaces() { // Arrange RouteCollection routes = new RouteCollection(); //string[] namespaces = new string[] { "nsA.nsB.nsC", "ns1.ns2.ns3" }; // Act routes.MapRoute("RouteName", "SomeUrl", _nameSpaces); // Assert Route route = Assert.Single(routes.Cast()); Assert.NotNull(route); Assert.NotNull(route.DataTokens); Assert.NotNull(route.DataTokens["Namespaces"]); string[] routeNameSpaces = route.DataTokens["Namespaces"] as string[]; Assert.Equal(routeNameSpaces.Length, 2); Assert.Same(route, routes["RouteName"]); Assert.Same(routeNameSpaces, _nameSpaces); Assert.Equal("SomeUrl", route.Url); Assert.IsType(route.RouteHandler); Assert.Empty(route.Defaults); Assert.Empty(route.Constraints); } [Fact] public void MapRoute3WithEmptyNameSpaces() { // Arrange RouteCollection routes = new RouteCollection(); // Act routes.MapRoute("RouteName", "SomeUrl", new string[] { }); // Assert Route route = Assert.Single(routes.Cast()); Assert.NotNull(route); Assert.Same(route, routes["RouteName"]); Assert.Equal("SomeUrl", route.Url); Assert.IsType(route.RouteHandler); Assert.Empty(route.Defaults); Assert.Empty(route.Constraints); Assert.Empty(route.DataTokens); } [Fact] public void MapRoute4() { // Arrange RouteCollection routes = new RouteCollection(); var defaults = new { Foo = "DefaultFoo" }; // Act routes.MapRoute("RouteName", "SomeUrl", defaults); // Assert Route route = Assert.Single(routes.Cast()); Assert.NotNull(route); Assert.Same(route, routes["RouteName"]); Assert.Equal("SomeUrl", route.Url); Assert.IsType(route.RouteHandler); Assert.Equal("DefaultFoo", route.Defaults["Foo"]); Assert.Empty(route.Constraints); Assert.Empty(route.DataTokens); } [Fact] public void MapRoute4WithNameSpaces() { // Arrange RouteCollection routes = new RouteCollection(); var defaults = new { Foo = "DefaultFoo" }; // Act routes.MapRoute("RouteName", "SomeUrl", defaults, _nameSpaces); // Assert Route route = Assert.Single(routes.Cast()); Assert.NotNull(route); Assert.NotNull(route.DataTokens); Assert.NotNull(route.DataTokens["Namespaces"]); string[] routeNameSpaces = route.DataTokens["Namespaces"] as string[]; Assert.Equal(routeNameSpaces.Length, 2); Assert.Same(route, routes["RouteName"]); Assert.Same(routeNameSpaces, _nameSpaces); Assert.Equal("SomeUrl", route.Url); Assert.IsType(route.RouteHandler); Assert.Equal("DefaultFoo", route.Defaults["Foo"]); Assert.Empty(route.Constraints); } [Fact] public void MapRoute5() { // Arrange RouteCollection routes = new RouteCollection(); var defaults = new { Foo = "DefaultFoo" }; var constraints = new { Foo = "ConstraintFoo" }; // Act routes.MapRoute("RouteName", "SomeUrl", defaults, constraints); // Assert Route route = Assert.Single(routes.Cast()); Assert.NotNull(route); Assert.Same(route, routes["RouteName"]); Assert.Equal("SomeUrl", route.Url); Assert.IsType(route.RouteHandler); Assert.Equal("DefaultFoo", route.Defaults["Foo"]); Assert.Equal("ConstraintFoo", route.Constraints["Foo"]); Assert.Empty(route.DataTokens); } [Fact] public void MapRoute5WithNullRouteCollectionThrows() { Assert.ThrowsArgumentNull( delegate { RouteCollectionExtensions.MapRoute(null, null, null, null, null); }, "routes"); } [Fact] public void MapRoute5WithNullUrlThrows() { // Arrange RouteCollection routes = new RouteCollection(); // Act & Assert Assert.ThrowsArgumentNull( delegate { routes.MapRoute(null, null /* url */, null, null); }, "url"); } [Fact] public void IgnoreRoute1WithNullRouteCollectionThrows() { Assert.ThrowsArgumentNull( delegate { RouteCollectionExtensions.IgnoreRoute(null, "foo"); }, "routes"); } [Fact] public void IgnoreRoute1WithNullUrlThrows() { // Arrange RouteCollection routes = new RouteCollection(); // Act & Assert Assert.ThrowsArgumentNull( delegate { routes.IgnoreRoute(null); }, "url"); } [Fact] public void IgnoreRoute3() { // Arrange RouteCollection routes = new RouteCollection(); // Act routes.IgnoreRoute("SomeUrl"); // Assert Route route = Assert.Single(routes.Cast()); Assert.NotNull(route); Assert.Equal("SomeUrl", route.Url); Assert.IsType(route.RouteHandler); Assert.Null(route.Defaults); Assert.Empty(route.Constraints); } [Fact] public void IgnoreRoute4() { // Arrange RouteCollection routes = new RouteCollection(); var constraints = new { Foo = "DefaultFoo" }; // Act routes.IgnoreRoute("SomeUrl", constraints); // Assert Route route = Assert.Single(routes.Cast()); Assert.NotNull(route); Assert.Equal("SomeUrl", route.Url); Assert.IsType(route.RouteHandler); Assert.Null(route.Defaults); Assert.Single(route.Constraints); Assert.Equal("DefaultFoo", route.Constraints["Foo"]); } [Fact] public void IgnoreRouteInternalNeverMatchesUrlGeneration() { // Arrange RouteCollection routes = new RouteCollection(); routes.IgnoreRoute("SomeUrl"); Route route = routes[0] as Route; // Act VirtualPathData vpd = route.GetVirtualPath(new RequestContext(new Mock().Object, new RouteData()), null); // Assert Assert.Null(vpd); } private static RequestContext GetRequestContext(string currentAreaName) { Mock mockHttpContext = new Mock(); mockHttpContext.Setup(c => c.Request.ApplicationPath).Returns("/app"); mockHttpContext.Setup(c => c.Response.ApplyAppPathModifier(It.IsAny())).Returns(virtualPath => virtualPath); RouteData routeData = new RouteData(); routeData.DataTokens["area"] = currentAreaName; return new RequestContext(mockHttpContext.Object, routeData); } private static RouteCollection GetRouteCollection() { RouteCollection routes = new RouteCollection(); routes.MapRoute( "Default", "no-area/{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = "" } ); AreaRegistrationContext blogContext = new AreaRegistrationContext("blog", routes); blogContext.MapRoute( "Blog_WhatsNew", "whats-new/{tag}", new { controller = "Home", action = "TenMostRecent", tag = "" } ); blogContext.MapRoute( "Blog_Default", "blog-area/{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = "" } ); AreaRegistrationContext adminContext = new AreaRegistrationContext("admin", routes); adminContext.MapRoute( "Admin_Default", "admin-area/{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = "" } ); return routes; } } }