// Copyright (c) Umbraco. // See LICENSE for more details. using Microsoft.Extensions.Options; using Moq; using NUnit.Framework; using Umbraco.Cms.Core; using Umbraco.Cms.Core.Configuration.Models; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Models.PublishedContent; using Umbraco.Cms.Core.Routing; using Umbraco.Cms.Core.Services.Navigation; using Umbraco.Cms.Core.Templates; using Umbraco.Cms.Tests.Common; using Umbraco.Cms.Tests.UnitTests.TestHelpers.Objects; namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Templates; [TestFixture] public class HtmlLocalLinkParserTests { [Test] public void Returns_Udis_From_LocalLinks() { var input = @"

other page

media

"; var parser = new HtmlLocalLinkParser(Mock.Of()); var result = parser.FindUdisFromLocalLinks(input).ToList(); Assert.Multiple(() => { Assert.AreEqual(2, result.Count); Assert.Contains(UdiParser.Parse("umb://document/eed5fc6b-96fd-45a5-a0f1-b1adfb483c2f"), result); Assert.Contains(UdiParser.Parse("umb://media/7e21a725-b905-4c5f-86dc-8c41ec116e39"), result); }); } // todo remove at some point and the implementation. [Test] public void Returns_Udis_From_Legacy_LocalLinks() { var input = @"

hello

hello

"; var parser = new HtmlLocalLinkParser(Mock.Of()); var result = parser.FindUdisFromLocalLinks(input).ToList(); Assert.Multiple(() => { Assert.AreEqual(2, result.Count); Assert.Contains(UdiParser.Parse("umb://document/C093961595094900AAF9170DDE6AD442"), result); Assert.Contains(UdiParser.Parse("umb://document-type/2D692FCB070B4CDA92FB6883FDBFD6E2"), result); }); } // todo remove at some point and the implementation. [Test] public void Returns_Udis_From_Legacy_And_Current_LocalLinks() { var input = @"

hello

hello

other page

media

"; var parser = new HtmlLocalLinkParser(Mock.Of()); var result = parser.FindUdisFromLocalLinks(input).ToList(); Assert.Multiple(() => { Assert.AreEqual(4, result.Count); Assert.Contains(UdiParser.Parse("umb://document/eed5fc6b-96fd-45a5-a0f1-b1adfb483c2f"), result); Assert.Contains(UdiParser.Parse("umb://media/7e21a725-b905-4c5f-86dc-8c41ec116e39"), result); Assert.Contains(UdiParser.Parse("umb://document/C093961595094900AAF9170DDE6AD442"), result); Assert.Contains(UdiParser.Parse("umb://document-type/2D692FCB070B4CDA92FB6883FDBFD6E2"), result); }); } [TestCase("", "")] // current [TestCase( "world", "world")] [TestCase( "world", "world")] [TestCase( "world", "world")] [TestCase( "world", "world")] [TestCase( "

world

world

", "

world

world

")] // attributes order should not matter [TestCase( "world", "world")] [TestCase( "world", "world")] [TestCase( "world", "world")] // anchors and query strings [TestCase( "world", "world")] [TestCase( "world", "world")] // custom type ignored [TestCase( "world", "world")] // legacy [TestCase( "hello href=\"{localLink:1234}\" world ", "hello href=\"/my-test-url\" world ")] [TestCase( "hello href=\"{localLink:umb://document/9931BDE0-AAC3-4BAB-B838-909A7B47570E}\" world ", "hello href=\"/my-test-url\" world ")] [TestCase( "hello href=\"{localLink:umb://document/9931BDE0AAC34BABB838909A7B47570E}\" world ", "hello href=\"/my-test-url\" world ")] [TestCase( "hello href=\"{localLink:umb://document/9931BDE0AAC34BABB838909A7B47570E}#anchor\" world ", "hello href=\"/my-test-url#anchor\" world ")] [TestCase( "hello href=\"{localLink:umb://media/9931BDE0AAC34BABB838909A7B47570E}\" world ", "hello href=\"/media/1001/my-image.jpg\" world ")] [TestCase( "hello href='{localLink:umb://media/9931BDE0AAC34BABB838909A7B47570E}' world ", "hello href='/media/1001/my-image.jpg' world ")] // This one has an invalid char so won't match. [TestCase( "hello href=\"{localLink:umb^://document/9931BDE0-AAC3-4BAB-B838-909A7B47570E}\" world ", "hello href=\"{localLink:umb^://document/9931BDE0-AAC3-4BAB-B838-909A7B47570E}\" world ")] [TestCase( "hello href=\"{localLink:umb://document-type/9931BDE0-AAC3-4BAB-B838-909A7B47570E}\" world ", "hello href=\"\" world ")] public void ParseLocalLinks(string input, string result) { // setup a mock URL provider which we'll use for testing var contentUrlProvider = new Mock(); contentUrlProvider .Setup(x => x.GetUrl( It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) .Returns(UrlInfo.Url("/my-test-url")); var contentType = new PublishedContentType( Guid.NewGuid(), 666, "alias", PublishedItemType.Content, Enumerable.Empty(), Enumerable.Empty(), ContentVariation.Nothing); var publishedContent = new Mock(); publishedContent.Setup(x => x.Id).Returns(1234); publishedContent.Setup(x => x.ContentType).Returns(contentType); var mediaType = new PublishedContentType( Guid.NewGuid(), 777, "image", PublishedItemType.Media, Enumerable.Empty(), Enumerable.Empty(), ContentVariation.Nothing); var media = new Mock(); media.Setup(x => x.ContentType).Returns(mediaType); var mediaUrlProvider = new Mock(); mediaUrlProvider.Setup(x => x.GetMediaUrl( It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) .Returns(UrlInfo.Url("/media/1001/my-image.jpg")); var umbracoContextAccessor = new TestUmbracoContextAccessor(); var umbracoContextFactory = TestUmbracoContextFactory.Create( umbracoContextAccessor: umbracoContextAccessor); var webRoutingSettings = new WebRoutingSettings(); var navigationQueryService = new Mock(); Guid? parentKey = null; navigationQueryService.Setup(x => x.TryGetParentKey(It.IsAny(), out parentKey)).Returns(true); using (var reference = umbracoContextFactory.EnsureUmbracoContext()) { var contentCache = Mock.Get(reference.UmbracoContext.Content); contentCache.Setup(x => x.GetById(It.IsAny())).Returns(publishedContent.Object); contentCache.Setup(x => x.GetById(It.IsAny())).Returns(publishedContent.Object); var mediaCache = Mock.Get(reference.UmbracoContext.Media); mediaCache.Setup(x => x.GetById(It.IsAny())).Returns(media.Object); mediaCache.Setup(x => x.GetById(It.IsAny())).Returns(media.Object); var publishStatusQueryService = new Mock(); publishStatusQueryService .Setup(x => x.IsDocumentPublished(It.IsAny(), It.IsAny())) .Returns(true); var publishedUrlProvider = new UrlProvider( umbracoContextAccessor, Options.Create(webRoutingSettings), new UrlProviderCollection(() => new[] { contentUrlProvider.Object }), new MediaUrlProviderCollection(() => new[] { mediaUrlProvider.Object }), Mock.Of(), contentCache.Object, navigationQueryService.Object, publishStatusQueryService.Object); var linkParser = new HtmlLocalLinkParser(publishedUrlProvider); var output = linkParser.EnsureInternalLinks(input); Assert.AreEqual(result, output); } } }