Fix various routing and preview issues for the Delivery API in V15 (#18036)

* Fix various routing and preview issues for the Delivery API in V15

* Fix breaking change in ctor

* Fix ambigious constructors

---------

Co-authored-by: Nikolaj Geisle <70372949+Zeegaan@users.noreply.github.com>
This commit is contained in:
Kenn Jacobsen
2025-01-20 22:27:10 +01:00
committed by GitHub
parent 31fbd29879
commit c00e86e0ea
15 changed files with 491 additions and 112 deletions

View File

@@ -0,0 +1,46 @@
using Moq;
using NUnit.Framework;
using Umbraco.Cms.Core.DeliveryApi;
using Umbraco.Cms.Core.Services;
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.DeliveryApi;
[TestFixture]
public class ApiDocumentUrlServiceTests
{
[Test]
public void Can_Resolve_Document_Key_With_Start_Node()
{
var documentKey = Guid.NewGuid();
var documentUrlServiceMock = new Mock<IDocumentUrlService>();
documentUrlServiceMock
.Setup(m => m.GetDocumentKeyByRoute(
"/some/where",
It.IsAny<string?>(),
1234,
false))
.Returns(documentKey);
var apiDocumentUrlService = new ApiDocumentUrlService(documentUrlServiceMock.Object);
var result = apiDocumentUrlService.GetDocumentKeyByRoute("1234/some/where", null, false);
Assert.AreEqual(documentKey, result);
}
[Test]
public void Can_Resolve_Document_Key_Without_Start_Node()
{
var documentKey = Guid.NewGuid();
var documentUrlServiceMock = new Mock<IDocumentUrlService>();
documentUrlServiceMock
.Setup(m => m.GetDocumentKeyByRoute(
"/some/where",
It.IsAny<string?>(),
null,
false))
.Returns(documentKey);
var apiDocumentUrlService = new ApiDocumentUrlService(documentUrlServiceMock.Object);
var result = apiDocumentUrlService.GetDocumentKeyByRoute("/some/where", null, false);
Assert.AreEqual(documentKey, result);
}
}

View File

@@ -6,7 +6,6 @@ using Umbraco.Cms.Core.DeliveryApi;
using Umbraco.Cms.Core.Models.PublishedContent;
using Umbraco.Cms.Core.PublishedCache;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Infrastructure.HybridCache;
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.DeliveryApi;
@@ -17,8 +16,9 @@ public class PublishedContentCacheTests : DeliveryApiTests
private readonly Guid _contentTwoId = Guid.Parse("4EF11E1E-FB50-4627-8A86-E10ED6F4DCE4");
private readonly Guid _contentThreeId = Guid.Parse("013387EE-57AF-4ABD-B03C-F991B0722CCA");
private IPublishedContentCache _contentCache;
private IPublishedContentCache _contentCacheMock;
private IDocumentUrlService _documentUrlService;
[SetUp]
@@ -34,37 +34,41 @@ public class PublishedContentCacheTests : DeliveryApiTests
var contentTwoMock = new Mock<IPublishedContent>();
ConfigurePublishedContentMock(contentTwoMock, _contentTwoId, "Content Two", "content-two", contentTypeTwoMock.Object, Array.Empty<IPublishedProperty>());
var contentTypeThreeMock = new Mock<IPublishedContentType>();
contentTypeThreeMock.SetupGet(m => m.Alias).Returns("theThirdContentType");
var contentThreeMock = new Mock<IPublishedContent>();
ConfigurePublishedContentMock(contentThreeMock, _contentThreeId, "Content Three", "content-three", contentTypeThreeMock.Object, Array.Empty<IPublishedProperty>());
var documentUrlService = new Mock<IDocumentUrlService>();
documentUrlService
.Setup(x => x.GetDocumentKeyByRoute("content-one", It.IsAny<string?>(), It.IsAny<int?>(), It.IsAny<bool>()))
.Setup(x => x.GetDocumentKeyByRoute("/content-one", It.IsAny<string?>(), It.IsAny<int?>(), It.IsAny<bool>()))
.Returns(_contentOneId);
documentUrlService
.Setup(x => x.GetDocumentKeyByRoute("content-two", It.IsAny<string?>(), It.IsAny<int?>(), It.IsAny<bool>()))
.Setup(x => x.GetDocumentKeyByRoute("/content-two", It.IsAny<string?>(), It.IsAny<int?>(), It.IsAny<bool>()))
.Returns(_contentTwoId);
documentUrlService
.Setup(x => x.GetDocumentKeyByRoute("/content-three", It.IsAny<string?>(), 1234, It.IsAny<bool>()))
.Returns(_contentThreeId);
var contentCacheMock = new Mock<IPublishedContentCache>();
contentCacheMock
.Setup(m => m.GetByRoute(It.IsAny<bool>(), "content-one", null, null))
.Returns(contentOneMock.Object);
contentCacheMock
.Setup(m => m.GetById(It.IsAny<bool>(), _contentOneId))
.Returns(contentOneMock.Object);
contentCacheMock
.Setup(m => m.GetByRoute(It.IsAny<bool>(), "content-two", null, null))
.Returns(contentTwoMock.Object);
contentCacheMock
.Setup(m => m.GetById(It.IsAny<bool>(), _contentTwoId))
.Returns(contentTwoMock.Object);
contentCacheMock
.Setup(m => m.GetById(It.IsAny<bool>(), _contentThreeId))
.Returns(contentThreeMock.Object);
_contentCache = contentCacheMock.Object;
_contentCacheMock = contentCacheMock.Object;
_documentUrlService = documentUrlService.Object;
}
[Test]
public void PublishedContentCache_CanGetById()
{
var publishedContentCache = new ApiPublishedContentCache(CreateRequestPreviewService(), CreateRequestCultureService(), CreateDeliveryApiSettings(), _documentUrlService, _contentCacheMock);
var publishedContentCache = new ApiPublishedContentCache(CreateRequestPreviewService(), CreateRequestCultureService(), CreateDeliveryApiSettings(), CreateApiDocumentUrlService(), _contentCache);
var content = publishedContentCache.GetById(_contentOneId);
Assert.IsNotNull(content);
Assert.AreEqual(_contentOneId, content.Key);
@@ -75,18 +79,29 @@ public class PublishedContentCacheTests : DeliveryApiTests
[Test]
public void PublishedContentCache_CanGetByRoute()
{
var publishedContentCache = new ApiPublishedContentCache(CreateRequestPreviewService(), CreateRequestCultureService(), CreateDeliveryApiSettings(), _documentUrlService, _contentCacheMock);
var content = publishedContentCache.GetByRoute("content-two");
var publishedContentCache = new ApiPublishedContentCache(CreateRequestPreviewService(), CreateRequestCultureService(), CreateDeliveryApiSettings(), CreateApiDocumentUrlService(), _contentCache);
var content = publishedContentCache.GetByRoute("/content-two");
Assert.IsNotNull(content);
Assert.AreEqual(_contentTwoId, content.Key);
Assert.AreEqual("content-two", content.UrlSegment);
Assert.AreEqual("theOtherContentType", content.ContentType.Alias);
}
[Test]
public void PublishedContentCache_CanGetByRoute_WithStartNodeIdPrefix()
{
var publishedContentCache = new ApiPublishedContentCache(CreateRequestPreviewService(), CreateRequestCultureService(), CreateDeliveryApiSettings(), CreateApiDocumentUrlService(), _contentCache);
var content = publishedContentCache.GetByRoute("1234/content-three");
Assert.IsNotNull(content);
Assert.AreEqual(_contentThreeId, content.Key);
Assert.AreEqual("content-three", content.UrlSegment);
Assert.AreEqual("theThirdContentType", content.ContentType.Alias);
}
[Test]
public void PublishedContentCache_CanGetByIds()
{
var publishedContentCache = new ApiPublishedContentCache(CreateRequestPreviewService(), CreateRequestCultureService(), CreateDeliveryApiSettings(), _documentUrlService, _contentCacheMock);
var publishedContentCache = new ApiPublishedContentCache(CreateRequestPreviewService(), CreateRequestCultureService(), CreateDeliveryApiSettings(), CreateApiDocumentUrlService(), _contentCache);
var content = publishedContentCache.GetByIds(new[] { _contentOneId, _contentTwoId }).ToArray();
Assert.AreEqual(2, content.Length);
Assert.AreEqual(_contentOneId, content.First().Key);
@@ -98,7 +113,7 @@ public class PublishedContentCacheTests : DeliveryApiTests
public void PublishedContentCache_GetById_SupportsDenyList(bool denied)
{
var denyList = denied ? new[] { "theOtherContentType" } : null;
var publishedContentCache = new ApiPublishedContentCache(CreateRequestPreviewService(), CreateRequestCultureService(), CreateDeliveryApiSettings(denyList), _documentUrlService, _contentCacheMock);
var publishedContentCache = new ApiPublishedContentCache(CreateRequestPreviewService(), CreateRequestCultureService(), CreateDeliveryApiSettings(denyList), CreateApiDocumentUrlService(), _contentCache);
var content = publishedContentCache.GetById(_contentTwoId);
if (denied)
@@ -116,8 +131,8 @@ public class PublishedContentCacheTests : DeliveryApiTests
public void PublishedContentCache_GetByRoute_SupportsDenyList(bool denied)
{
var denyList = denied ? new[] { "theContentType" } : null;
var publishedContentCache = new ApiPublishedContentCache(CreateRequestPreviewService(), CreateRequestCultureService(), CreateDeliveryApiSettings(denyList), _documentUrlService, _contentCacheMock);
var content = publishedContentCache.GetByRoute("content-one");
var publishedContentCache = new ApiPublishedContentCache(CreateRequestPreviewService(), CreateRequestCultureService(), CreateDeliveryApiSettings(denyList), CreateApiDocumentUrlService(), _contentCache);
var content = publishedContentCache.GetByRoute("/content-one");
if (denied)
{
@@ -134,7 +149,7 @@ public class PublishedContentCacheTests : DeliveryApiTests
public void PublishedContentCache_GetByIds_SupportsDenyList(string deniedContentType)
{
var denyList = new[] { deniedContentType };
var publishedContentCache = new ApiPublishedContentCache(CreateRequestPreviewService(), CreateRequestCultureService(), CreateDeliveryApiSettings(denyList), _documentUrlService, _contentCacheMock);
var publishedContentCache = new ApiPublishedContentCache(CreateRequestPreviewService(), CreateRequestCultureService(), CreateDeliveryApiSettings(denyList), CreateApiDocumentUrlService(), _contentCache);
var content = publishedContentCache.GetByIds(new[] { _contentOneId, _contentTwoId }).ToArray();
Assert.AreEqual(1, content.Length);
@@ -152,7 +167,7 @@ public class PublishedContentCacheTests : DeliveryApiTests
public void PublishedContentCache_GetById_CanRetrieveContentTypesOutsideTheDenyList()
{
var denyList = new[] { "theContentType" };
var publishedContentCache = new ApiPublishedContentCache(CreateRequestPreviewService(), CreateRequestCultureService(), CreateDeliveryApiSettings(denyList), _documentUrlService, _contentCacheMock);
var publishedContentCache = new ApiPublishedContentCache(CreateRequestPreviewService(), CreateRequestCultureService(), CreateDeliveryApiSettings(denyList), CreateApiDocumentUrlService(), _contentCache);
var content = publishedContentCache.GetById(_contentTwoId);
Assert.IsNotNull(content);
Assert.AreEqual(_contentTwoId, content.Key);
@@ -164,8 +179,8 @@ public class PublishedContentCacheTests : DeliveryApiTests
public void PublishedContentCache_GetByRoute_CanRetrieveContentTypesOutsideTheDenyList()
{
var denyList = new[] { "theOtherContentType" };
var publishedContentCache = new ApiPublishedContentCache(CreateRequestPreviewService(), CreateRequestCultureService(), CreateDeliveryApiSettings(denyList), _documentUrlService, _contentCacheMock);
var content = publishedContentCache.GetByRoute("content-one");
var publishedContentCache = new ApiPublishedContentCache(CreateRequestPreviewService(), CreateRequestCultureService(), CreateDeliveryApiSettings(denyList), CreateApiDocumentUrlService(), _contentCache);
var content = publishedContentCache.GetByRoute("/content-one");
Assert.IsNotNull(content);
Assert.AreEqual(_contentOneId, content.Key);
Assert.AreEqual("content-one", content.UrlSegment);
@@ -176,7 +191,7 @@ public class PublishedContentCacheTests : DeliveryApiTests
public void PublishedContentCache_GetByIds_CanDenyAllRequestedContent()
{
var denyList = new[] { "theContentType", "theOtherContentType" };
var publishedContentCache = new ApiPublishedContentCache(CreateRequestPreviewService(), CreateRequestCultureService(), CreateDeliveryApiSettings(denyList), _documentUrlService, _contentCacheMock);
var publishedContentCache = new ApiPublishedContentCache(CreateRequestPreviewService(), CreateRequestCultureService(), CreateDeliveryApiSettings(denyList), CreateApiDocumentUrlService(), _contentCache);
var content = publishedContentCache.GetByIds(new[] { _contentOneId, _contentTwoId }).ToArray();
Assert.IsEmpty(content);
}
@@ -185,8 +200,8 @@ public class PublishedContentCacheTests : DeliveryApiTests
public void PublishedContentCache_DenyListIsCaseInsensitive()
{
var denyList = new[] { "THEcontentTYPE" };
var publishedContentCache = new ApiPublishedContentCache(CreateRequestPreviewService(), CreateRequestCultureService(), CreateDeliveryApiSettings(denyList), _documentUrlService, _contentCacheMock);
var content = publishedContentCache.GetByRoute("content-one");
var publishedContentCache = new ApiPublishedContentCache(CreateRequestPreviewService(), CreateRequestCultureService(), CreateDeliveryApiSettings(denyList), CreateApiDocumentUrlService(), _contentCache);
var content = publishedContentCache.GetByRoute("/content-one");
Assert.IsNull(content);
}
@@ -211,4 +226,6 @@ public class PublishedContentCacheTests : DeliveryApiTests
deliveryApiOptionsMonitorMock.SetupGet(s => s.CurrentValue).Returns(deliveryApiSettings);
return deliveryApiOptionsMonitorMock.Object;
}
private IApiDocumentUrlService CreateApiDocumentUrlService() => new ApiDocumentUrlService(_documentUrlService);
}

View File

@@ -0,0 +1,75 @@
using Moq;
using NUnit.Framework;
using Umbraco.Cms.Api.Delivery.Querying.Selectors;
using Umbraco.Cms.Core.DeliveryApi;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Core.Services.Navigation;
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.DeliveryApi.Selectors;
[TestFixture]
public class AncestorsSelectorTests
{
private readonly Guid _documentKey = Guid.NewGuid();
private IDocumentNavigationQueryService _documentNavigationQueryService;
[SetUp]
public void SetUp()
{
IEnumerable<Guid> ancestorKeys =
[
new("863e10d5-b0f8-421d-902d-5e4d1bd8e780"),
new("11fc9bdc-8366-4a6b-a9c2-6b8b2717c4b8")
];
var documentNavigationQueryServiceMock = new Mock<IDocumentNavigationQueryService>();
documentNavigationQueryServiceMock
.Setup(m => m.TryGetAncestorsKeys(_documentKey, out ancestorKeys))
.Returns(true);
_documentNavigationQueryService = documentNavigationQueryServiceMock.Object;
}
[TestCase(null)]
[TestCase(1234)]
public void Can_Build_Selector_Option_For_Path(int? documentStartNodeId)
{
var documentUrlServiceMock = new Mock<IDocumentUrlService>();
documentUrlServiceMock
.Setup(m => m.GetDocumentKeyByRoute(
"/some/where",
It.IsAny<string?>(),
documentStartNodeId,
false))
.Returns(_documentKey);
var requestRoutingServiceMock = new Mock<IRequestRoutingService>();
requestRoutingServiceMock.Setup(m => m.GetContentRoute("/some/where")).Returns($"{documentStartNodeId}/some/where");
var subject = new AncestorsSelector(
requestRoutingServiceMock.Object,
Mock.Of<IRequestPreviewService>(),
Mock.Of<IRequestCultureService>(),
new ApiDocumentUrlService(documentUrlServiceMock.Object),
_documentNavigationQueryService);
var result = subject.BuildSelectorOption("ancestors:/some/where");
Assert.AreEqual(2, result.Values.Length);
Assert.AreEqual("863e10d5-b0f8-421d-902d-5e4d1bd8e780", result.Values[0]);
Assert.AreEqual("11fc9bdc-8366-4a6b-a9c2-6b8b2717c4b8", result.Values[1]);
}
[Test]
public void Can_Build_Selector_Option_For_Id()
{
var subject = new AncestorsSelector(
Mock.Of<IRequestRoutingService>(),
Mock.Of<IRequestPreviewService>(),
Mock.Of<IRequestCultureService>(),
Mock.Of<IApiDocumentUrlService>(),
_documentNavigationQueryService);
var result = subject.BuildSelectorOption($"ancestors:{_documentKey:D}");
Assert.AreEqual(2, result.Values.Length);
Assert.AreEqual("863e10d5-b0f8-421d-902d-5e4d1bd8e780", result.Values[0]);
Assert.AreEqual("11fc9bdc-8366-4a6b-a9c2-6b8b2717c4b8", result.Values[1]);
}
}

View File

@@ -0,0 +1,56 @@
using Moq;
using NUnit.Framework;
using Umbraco.Cms.Api.Delivery.Querying.Selectors;
using Umbraco.Cms.Core.DeliveryApi;
using Umbraco.Cms.Core.Services;
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.DeliveryApi.Selectors;
[TestFixture]
public class ChildrenSelectorTests
{
[TestCase(null)]
[TestCase(1234)]
public void Can_Build_Selector_Option_For_Path(int? documentStartNodeId)
{
var documentKey = Guid.NewGuid();
var documentUrlServiceMock = new Mock<IDocumentUrlService>();
documentUrlServiceMock
.Setup(m => m.GetDocumentKeyByRoute(
"/some/where",
It.IsAny<string?>(),
documentStartNodeId,
false))
.Returns(documentKey);
var requestRoutingServiceMock = new Mock<IRequestRoutingService>();
requestRoutingServiceMock.Setup(m => m.GetContentRoute("/some/where")).Returns($"{documentStartNodeId}/some/where");
var subject = new ChildrenSelector(
requestRoutingServiceMock.Object,
Mock.Of<IRequestPreviewService>(),
Mock.Of<IRequestCultureService>(),
new ApiDocumentUrlService(documentUrlServiceMock.Object));
var result = subject.BuildSelectorOption("children:/some/where");
Assert.AreEqual(1, result.Values.Length);
Assert.AreEqual(documentKey.ToString("D"), result.Values[0]);
}
[Test]
public void Can_Build_Selector_Option_For_Id()
{
var documentKey = Guid.NewGuid();
var subject = new ChildrenSelector(
Mock.Of<IRequestRoutingService>(),
Mock.Of<IRequestPreviewService>(),
Mock.Of<IRequestCultureService>(),
Mock.Of<IApiDocumentUrlService>());
var result = subject.BuildSelectorOption($"children:{documentKey:D}");
Assert.AreEqual(1, result.Values.Length);
Assert.AreEqual(documentKey.ToString("D"), result.Values[0]);
}
}

View File

@@ -0,0 +1,56 @@
using Moq;
using NUnit.Framework;
using Umbraco.Cms.Api.Delivery.Querying.Selectors;
using Umbraco.Cms.Core.DeliveryApi;
using Umbraco.Cms.Core.Services;
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.DeliveryApi.Selectors;
[TestFixture]
public class DescendantsSelectorTests
{
[TestCase(null)]
[TestCase(1234)]
public void Can_Build_Selector_Option_For_Path(int? documentStartNodeId)
{
var documentKey = Guid.NewGuid();
var documentUrlServiceMock = new Mock<IDocumentUrlService>();
documentUrlServiceMock
.Setup(m => m.GetDocumentKeyByRoute(
"/some/where",
It.IsAny<string?>(),
documentStartNodeId,
false))
.Returns(documentKey);
var requestRoutingServiceMock = new Mock<IRequestRoutingService>();
requestRoutingServiceMock.Setup(m => m.GetContentRoute("/some/where")).Returns($"{documentStartNodeId}/some/where");
var subject = new DescendantsSelector(
requestRoutingServiceMock.Object,
Mock.Of<IRequestPreviewService>(),
Mock.Of<IRequestCultureService>(),
new ApiDocumentUrlService(documentUrlServiceMock.Object));
var result = subject.BuildSelectorOption("descendants:/some/where");
Assert.AreEqual(1, result.Values.Length);
Assert.AreEqual(documentKey.ToString("D"), result.Values[0]);
}
[Test]
public void Can_Build_Selector_Option_For_Id()
{
var documentKey = Guid.NewGuid();
var subject = new DescendantsSelector(
Mock.Of<IRequestRoutingService>(),
Mock.Of<IRequestPreviewService>(),
Mock.Of<IRequestCultureService>(),
Mock.Of<IApiDocumentUrlService>());
var result = subject.BuildSelectorOption($"descendants:{documentKey:D}");
Assert.AreEqual(1, result.Values.Length);
Assert.AreEqual(documentKey.ToString("D"), result.Values[0]);
}
}