From 456cb00a2d0b6b7eafbe2c6844768d38b33d73f4 Mon Sep 17 00:00:00 2001 From: Shannon Date: Tue, 12 Jan 2021 17:06:37 +1100 Subject: [PATCH] Add test for UmbracoRouteValuesFactoryTests --- .../Routing/HijackedRouteEvaluatorTests.cs | 13 ++- .../Routing/UmbracoRouteValuesFactoryTests.cs | 90 +++++++++++++++++++ .../Routing/UmbracoRouteValuesFactory.cs | 8 +- 3 files changed, 108 insertions(+), 3 deletions(-) create mode 100644 src/Umbraco.Tests.UnitTests/Umbraco.Web.Website/Routing/UmbracoRouteValuesFactoryTests.cs diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Web.Website/Routing/HijackedRouteEvaluatorTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Web.Website/Routing/HijackedRouteEvaluatorTests.cs index fecbe76d55..5543a8920a 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Web.Website/Routing/HijackedRouteEvaluatorTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Web.Website/Routing/HijackedRouteEvaluatorTests.cs @@ -1,8 +1,6 @@ -using System; using System.Collections.Generic; using System.Linq; using System.Reflection; -using System.Text; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Abstractions; using Microsoft.AspNetCore.Mvc.Controllers; @@ -21,6 +19,7 @@ using Umbraco.Web.Website.Routing; namespace Umbraco.Tests.UnitTests.Umbraco.Web.Website.Routing { + [TestFixture] public class HijackedRouteEvaluatorTests { @@ -51,6 +50,12 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.Website.Routing ControllerTypeInfo = typeof(Render1Controller).GetTypeInfo() }, new ControllerActionDescriptor + { + ActionName = "Custom", + ControllerName = ControllerExtensions.GetControllerName(), + ControllerTypeInfo = typeof(Render1Controller).GetTypeInfo() + }, + new ControllerActionDescriptor { ActionName = "Index", ControllerName = ControllerExtensions.GetControllerName(), @@ -61,6 +66,8 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.Website.Routing private class Render1Controller : ControllerBase, IRenderController { public IActionResult Index => Content("hello world"); + + public IActionResult Custom => Content("hello world"); } private class Render2Controller : RenderController @@ -71,12 +78,14 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.Website.Routing } } + [TestCase("Index", "RenderNotFound", null, false)] [TestCase("index", "Render", "Index", true)] [TestCase("Index", "Render1", "Index", true)] [TestCase("Index", "render2", "Index", true)] [TestCase("NotFound", "Render", "Index", true)] [TestCase("NotFound", "Render1", "Index", true)] [TestCase("NotFound", "Render2", "Index", true)] + [TestCase("Custom", "Render1", "Custom", true)] public void Matches_Controller(string action, string controller, string resultAction, bool matches) { var evaluator = new HijackedRouteEvaluator( diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Web.Website/Routing/UmbracoRouteValuesFactoryTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Web.Website/Routing/UmbracoRouteValuesFactoryTests.cs new file mode 100644 index 0000000000..ca5329a3f7 --- /dev/null +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Web.Website/Routing/UmbracoRouteValuesFactoryTests.cs @@ -0,0 +1,90 @@ +using System; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc.Infrastructure; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.Logging.Abstractions; +using Moq; +using NUnit.Framework; +using Umbraco.Core; +using Umbraco.Core.Models; +using Umbraco.Core.Models.PublishedContent; +using Umbraco.Core.Services; +using Umbraco.Core.Strings; +using Umbraco.Web.Common.Routing; +using Umbraco.Web.Features; +using Umbraco.Web.Routing; +using Umbraco.Web.Website.Controllers; +using Umbraco.Web.Website.Routing; + +namespace Umbraco.Tests.UnitTests.Umbraco.Web.Website.Routing +{ + [TestFixture] + public class UmbracoRouteValuesFactoryTests + { + private UmbracoRouteValuesFactory GetFactory(IPublishedRouter router, out UmbracoRenderingDefaults renderingDefaults) + { + var builder = new PublishedRequestBuilder(new Uri("https://example.com"), Mock.Of()); + builder.SetPublishedContent(Mock.Of()); + IPublishedRequest request = builder.Build(); + + var publishedRouter = new Mock(); + publishedRouter.Setup(x => x.UpdateRequestToNotFound(It.IsAny())) + .Returns((IPublishedRequest r) => builder) + .Verifiable(); + + renderingDefaults = new UmbracoRenderingDefaults(); + + var factory = new UmbracoRouteValuesFactory( + renderingDefaults, + Mock.Of(), + new UmbracoFeatures(), + new HijackedRouteEvaluator( + new NullLogger(), + Mock.Of()), + publishedRouter.Object); + + return factory; + } + + [Test] + public void Update_Request_To_Not_Found_When_No_Template() + { + var builder = new PublishedRequestBuilder(new Uri("https://example.com"), Mock.Of()); + builder.SetPublishedContent(Mock.Of()); + IPublishedRequest request = builder.Build(); + + var publishedRouter = new Mock(); + publishedRouter.Setup(x => x.UpdateRequestToNotFound(It.IsAny())) + .Returns((IPublishedRequest r) => builder) + .Verifiable(); + + UmbracoRouteValuesFactory factory = GetFactory(publishedRouter.Object, out _); + + UmbracoRouteValues result = factory.Create(new DefaultHttpContext(), new RouteValueDictionary(), request); + + // The request has content, no template, no hijacked route and no disabled template features so UpdateRequestToNotFound will be called + publishedRouter.Verify(m => m.UpdateRequestToNotFound(It.IsAny()), Times.Once); + } + + [Test] + public void Adds_Result_To_Route_Value_Dictionary() + { + var builder = new PublishedRequestBuilder(new Uri("https://example.com"), Mock.Of()); + builder.SetPublishedContent(Mock.Of()); + builder.SetTemplate(Mock.Of()); + IPublishedRequest request = builder.Build(); + + UmbracoRouteValuesFactory factory = GetFactory(Mock.Of(), out UmbracoRenderingDefaults renderingDefaults); + + var routeVals = new RouteValueDictionary(); + UmbracoRouteValues result = factory.Create(new DefaultHttpContext(), routeVals, request); + + Assert.IsNotNull(result); + Assert.IsTrue(routeVals.ContainsKey(Constants.Web.UmbracoRouteDefinitionDataToken)); + Assert.AreEqual(result, routeVals[Constants.Web.UmbracoRouteDefinitionDataToken]); + Assert.AreEqual(renderingDefaults.DefaultControllerType, result.ControllerType); + Assert.AreEqual(UmbracoRouteValues.DefaultActionName, result.ActionName); + Assert.IsNull(result.TemplateName); + } + } +} diff --git a/src/Umbraco.Web.Website/Routing/UmbracoRouteValuesFactory.cs b/src/Umbraco.Web.Website/Routing/UmbracoRouteValuesFactory.cs index fd92f7f11e..d26216204e 100644 --- a/src/Umbraco.Web.Website/Routing/UmbracoRouteValuesFactory.cs +++ b/src/Umbraco.Web.Website/Routing/UmbracoRouteValuesFactory.cs @@ -103,7 +103,7 @@ namespace Umbraco.Web.Website.Routing { IPublishedRequest request = def.PublishedRequest; - var customControllerName = request.PublishedContent?.ContentType.Alias; + var customControllerName = request.PublishedContent?.ContentType?.Alias; if (customControllerName != null) { HijackedRouteResult hijackedResult = _hijackedRouteEvaluator.Evaluate(customControllerName, def.TemplateName); @@ -144,6 +144,12 @@ namespace Umbraco.Web.Website.Routing // We then need to re-run this through the pipeline for the last // chance finders to work. IPublishedRequestBuilder builder = _publishedRouter.UpdateRequestToNotFound(request); + + if (builder == null) + { + throw new InvalidOperationException($"The call to {nameof(IPublishedRouter.UpdateRequestToNotFound)} cannot return null"); + } + request = builder.Build(); def = new UmbracoRouteValues(