From 147bdf22bf2ed956329c4b88b66b5a07c24d4bf3 Mon Sep 17 00:00:00 2001 From: Kenn Jacobsen Date: Fri, 31 Jan 2025 11:34:25 +0100 Subject: [PATCH] Use variant context for determining requested culture (#18176) --- .../Querying/QueryOptionBase.cs | 20 +++--- .../Querying/Selectors/AncestorsSelector.cs | 20 +++--- .../Querying/Selectors/ChildrenSelector.cs | 17 ++--- .../Querying/Selectors/DescendantsSelector.cs | 17 ++--- .../DeliveryApi/ApiPublishedContentCache.cs | 24 ++++--- .../DeliveryApi/PublishedContentCacheTests.cs | 62 ++++++++++++++----- .../Selectors/AncestorsSelectorTests.cs | 5 +- .../Selectors/ChildrenSelectorTests.cs | 9 +-- .../Selectors/DescendantsSelectorTests.cs | 9 +-- 9 files changed, 114 insertions(+), 69 deletions(-) diff --git a/src/Umbraco.Cms.Api.Delivery/Querying/QueryOptionBase.cs b/src/Umbraco.Cms.Api.Delivery/Querying/QueryOptionBase.cs index 2b47ea166e..a01f8ee9af 100644 --- a/src/Umbraco.Cms.Api.Delivery/Querying/QueryOptionBase.cs +++ b/src/Umbraco.Cms.Api.Delivery/Querying/QueryOptionBase.cs @@ -1,6 +1,7 @@ using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Core.DeliveryApi; using Umbraco.Cms.Core.DependencyInjection; +using Umbraco.Cms.Core.Models.PublishedContent; using Umbraco.Cms.Core.PublishedCache; using Umbraco.Extensions; @@ -10,8 +11,8 @@ public abstract class QueryOptionBase { private readonly IRequestRoutingService _requestRoutingService; private readonly IRequestPreviewService _requestPreviewService; - private readonly IRequestCultureService _requestCultureService; private readonly IApiDocumentUrlService _apiDocumentUrlService; + private readonly IVariationContextAccessor _variationContextAccessor; [Obsolete("Please use the non-obsolete constructor. Will be removed in V17.")] public QueryOptionBase( @@ -20,8 +21,8 @@ public abstract class QueryOptionBase : this( requestRoutingService, StaticServiceProvider.Instance.GetRequiredService(), - StaticServiceProvider.Instance.GetRequiredService(), - StaticServiceProvider.Instance.GetRequiredService()) + StaticServiceProvider.Instance.GetRequiredService(), + StaticServiceProvider.Instance.GetRequiredService()) { } @@ -31,21 +32,22 @@ public abstract class QueryOptionBase IRequestRoutingService requestRoutingService, IRequestPreviewService requestPreviewService, IRequestCultureService requestCultureService, - IApiDocumentUrlService apiDocumentUrlService) - : this(requestRoutingService, requestPreviewService, requestCultureService, apiDocumentUrlService) + IApiDocumentUrlService apiDocumentUrlService, + IVariationContextAccessor variationContextAccessor) + : this(requestRoutingService, requestPreviewService, apiDocumentUrlService, variationContextAccessor) { } public QueryOptionBase( IRequestRoutingService requestRoutingService, IRequestPreviewService requestPreviewService, - IRequestCultureService requestCultureService, - IApiDocumentUrlService apiDocumentUrlService) + IApiDocumentUrlService apiDocumentUrlService, + IVariationContextAccessor variationContextAccessor) { _requestRoutingService = requestRoutingService; _requestPreviewService = requestPreviewService; - _requestCultureService = requestCultureService; _apiDocumentUrlService = apiDocumentUrlService; + _variationContextAccessor = variationContextAccessor; } protected Guid? GetGuidFromQuery(string queryStringValue) @@ -64,7 +66,7 @@ public abstract class QueryOptionBase var contentRoute = _requestRoutingService.GetContentRoute(queryStringValue); return _apiDocumentUrlService.GetDocumentKeyByRoute( contentRoute, - _requestCultureService.GetRequestedCulture(), + _variationContextAccessor.VariationContext?.Culture, _requestPreviewService.IsPreview()); } } diff --git a/src/Umbraco.Cms.Api.Delivery/Querying/Selectors/AncestorsSelector.cs b/src/Umbraco.Cms.Api.Delivery/Querying/Selectors/AncestorsSelector.cs index 7a3a793118..b3a8dca0d6 100644 --- a/src/Umbraco.Cms.Api.Delivery/Querying/Selectors/AncestorsSelector.cs +++ b/src/Umbraco.Cms.Api.Delivery/Querying/Selectors/AncestorsSelector.cs @@ -2,6 +2,7 @@ using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Api.Delivery.Indexing.Selectors; using Umbraco.Cms.Core.DeliveryApi; using Umbraco.Cms.Core.DependencyInjection; +using Umbraco.Cms.Core.Models.PublishedContent; using Umbraco.Cms.Core.PublishedCache; using Umbraco.Cms.Core.Services.Navigation; @@ -20,10 +21,9 @@ public sealed class AncestorsSelector : QueryOptionBase, ISelectorHandler IRequestPreviewService requestPreviewService) : this( requestRoutingService, - StaticServiceProvider.Instance.GetRequiredService(), - StaticServiceProvider.Instance.GetRequiredService(), - StaticServiceProvider.Instance.GetRequiredService(), + requestPreviewService, StaticServiceProvider.Instance.GetRequiredService(), + StaticServiceProvider.Instance.GetRequiredService(), navigationQueryService) { } @@ -35,10 +35,9 @@ public sealed class AncestorsSelector : QueryOptionBase, ISelectorHandler IDocumentNavigationQueryService navigationQueryService) : this( requestRoutingService, - StaticServiceProvider.Instance.GetRequiredService(), StaticServiceProvider.Instance.GetRequiredService(), - StaticServiceProvider.Instance.GetRequiredService(), StaticServiceProvider.Instance.GetRequiredService(), + StaticServiceProvider.Instance.GetRequiredService(), navigationQueryService) { } @@ -47,10 +46,9 @@ public sealed class AncestorsSelector : QueryOptionBase, ISelectorHandler public AncestorsSelector(IPublishedContentCache publishedContentCache, IRequestRoutingService requestRoutingService) : this( requestRoutingService, - StaticServiceProvider.Instance.GetRequiredService(), StaticServiceProvider.Instance.GetRequiredService(), - StaticServiceProvider.Instance.GetRequiredService(), StaticServiceProvider.Instance.GetRequiredService(), + StaticServiceProvider.Instance.GetRequiredService(), StaticServiceProvider.Instance.GetRequiredService()) { } @@ -58,10 +56,10 @@ public sealed class AncestorsSelector : QueryOptionBase, ISelectorHandler public AncestorsSelector( IRequestRoutingService requestRoutingService, IRequestPreviewService requestPreviewService, - IRequestCultureService requestCultureService, IApiDocumentUrlService apiDocumentUrlService, + IVariationContextAccessor variationContextAccessor, IDocumentNavigationQueryService navigationQueryService) - : base(requestRoutingService, requestPreviewService, requestCultureService, apiDocumentUrlService) + : base(requestRoutingService, requestPreviewService, apiDocumentUrlService, variationContextAccessor) => _navigationQueryService = navigationQueryService; [Obsolete("Use the constructor that takes all parameters. Scheduled for removal in V17.")] @@ -69,10 +67,10 @@ public sealed class AncestorsSelector : QueryOptionBase, ISelectorHandler IRequestRoutingService requestRoutingService, IPublishedContentCache publishedContentCache, IRequestPreviewService requestPreviewService, - IRequestCultureService requestCultureService, IApiDocumentUrlService apiDocumentUrlService, + IVariationContextAccessor variationContextAccessor, IDocumentNavigationQueryService navigationQueryService) - : this(requestRoutingService, requestPreviewService, requestCultureService, apiDocumentUrlService, navigationQueryService) + : this(requestRoutingService, requestPreviewService, apiDocumentUrlService, variationContextAccessor, navigationQueryService) { } diff --git a/src/Umbraco.Cms.Api.Delivery/Querying/Selectors/ChildrenSelector.cs b/src/Umbraco.Cms.Api.Delivery/Querying/Selectors/ChildrenSelector.cs index ba986e0812..4040371f65 100644 --- a/src/Umbraco.Cms.Api.Delivery/Querying/Selectors/ChildrenSelector.cs +++ b/src/Umbraco.Cms.Api.Delivery/Querying/Selectors/ChildrenSelector.cs @@ -2,6 +2,7 @@ using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Api.Delivery.Indexing.Selectors; using Umbraco.Cms.Core.DeliveryApi; using Umbraco.Cms.Core.DependencyInjection; +using Umbraco.Cms.Core.Models.PublishedContent; using Umbraco.Cms.Core.PublishedCache; using Umbraco.Extensions; @@ -16,8 +17,8 @@ public sealed class ChildrenSelector : QueryOptionBase, ISelectorHandler : this( requestRoutingService, StaticServiceProvider.Instance.GetRequiredService(), - StaticServiceProvider.Instance.GetRequiredService(), - StaticServiceProvider.Instance.GetRequiredService()) + StaticServiceProvider.Instance.GetRequiredService(), + StaticServiceProvider.Instance.GetRequiredService()) { } @@ -26,18 +27,18 @@ public sealed class ChildrenSelector : QueryOptionBase, ISelectorHandler IPublishedContentCache publishedContentCache, IRequestRoutingService requestRoutingService, IRequestPreviewService requestPreviewService, - IRequestCultureService requestCultureService, - IApiDocumentUrlService apiDocumentUrlService) - : this(requestRoutingService, requestPreviewService, requestCultureService, apiDocumentUrlService) + IApiDocumentUrlService apiDocumentUrlService, + IVariationContextAccessor variationContextAccessor) + : this(requestRoutingService, requestPreviewService, apiDocumentUrlService, variationContextAccessor) { } public ChildrenSelector( IRequestRoutingService requestRoutingService, IRequestPreviewService requestPreviewService, - IRequestCultureService requestCultureService, - IApiDocumentUrlService apiDocumentUrlService) - : base(requestRoutingService, requestPreviewService, requestCultureService, apiDocumentUrlService) + IApiDocumentUrlService apiDocumentUrlService, + IVariationContextAccessor variationContextAccessor) + : base(requestRoutingService, requestPreviewService, apiDocumentUrlService, variationContextAccessor) { } diff --git a/src/Umbraco.Cms.Api.Delivery/Querying/Selectors/DescendantsSelector.cs b/src/Umbraco.Cms.Api.Delivery/Querying/Selectors/DescendantsSelector.cs index 7ce0c066c4..d46d5499b4 100644 --- a/src/Umbraco.Cms.Api.Delivery/Querying/Selectors/DescendantsSelector.cs +++ b/src/Umbraco.Cms.Api.Delivery/Querying/Selectors/DescendantsSelector.cs @@ -2,6 +2,7 @@ using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Api.Delivery.Indexing.Selectors; using Umbraco.Cms.Core.DeliveryApi; using Umbraco.Cms.Core.DependencyInjection; +using Umbraco.Cms.Core.Models.PublishedContent; using Umbraco.Cms.Core.PublishedCache; using Umbraco.Extensions; @@ -16,8 +17,8 @@ public sealed class DescendantsSelector : QueryOptionBase, ISelectorHandler : this( requestRoutingService, StaticServiceProvider.Instance.GetRequiredService(), - StaticServiceProvider.Instance.GetRequiredService(), - StaticServiceProvider.Instance.GetRequiredService()) + StaticServiceProvider.Instance.GetRequiredService(), + StaticServiceProvider.Instance.GetRequiredService()) { } @@ -26,18 +27,18 @@ public sealed class DescendantsSelector : QueryOptionBase, ISelectorHandler IPublishedContentCache publishedContentCache, IRequestRoutingService requestRoutingService, IRequestPreviewService requestPreviewService, - IRequestCultureService requestCultureService, - IApiDocumentUrlService apiDocumentUrlService) - : this(requestRoutingService, requestPreviewService, requestCultureService, apiDocumentUrlService) + IApiDocumentUrlService apiDocumentUrlService, + IVariationContextAccessor variationContextAccessor) + : this(requestRoutingService, requestPreviewService, apiDocumentUrlService, variationContextAccessor) { } public DescendantsSelector( IRequestRoutingService requestRoutingService, IRequestPreviewService requestPreviewService, - IRequestCultureService requestCultureService, - IApiDocumentUrlService apiDocumentUrlService) - : base(requestRoutingService, requestPreviewService, requestCultureService, apiDocumentUrlService) + IApiDocumentUrlService apiDocumentUrlService, + IVariationContextAccessor variationContextAccessor) + : base(requestRoutingService, requestPreviewService, apiDocumentUrlService, variationContextAccessor) { } diff --git a/src/Umbraco.Core/DeliveryApi/ApiPublishedContentCache.cs b/src/Umbraco.Core/DeliveryApi/ApiPublishedContentCache.cs index e5996595fc..0d6f9ecbf5 100644 --- a/src/Umbraco.Core/DeliveryApi/ApiPublishedContentCache.cs +++ b/src/Umbraco.Core/DeliveryApi/ApiPublishedContentCache.cs @@ -12,9 +12,9 @@ namespace Umbraco.Cms.Core.DeliveryApi; public sealed class ApiPublishedContentCache : IApiPublishedContentCache { private readonly IRequestPreviewService _requestPreviewService; - private readonly IRequestCultureService _requestCultureService; private readonly IApiDocumentUrlService _apiDocumentUrlService; private readonly IPublishedContentCache _publishedContentCache; + private readonly IVariationContextAccessor _variationContextAccessor; private DeliveryApiSettings _deliveryApiSettings; [Obsolete("Use the non-obsolete constructor. Will be removed in V17.")] @@ -24,7 +24,12 @@ public sealed class ApiPublishedContentCache : IApiPublishedContentCache IOptionsMonitor deliveryApiSettings, IDocumentUrlService documentUrlService, IPublishedContentCache publishedContentCache) - : this(requestPreviewService, requestCultureService, deliveryApiSettings, StaticServiceProvider.Instance.GetRequiredService(), publishedContentCache) + : this( + requestPreviewService, + deliveryApiSettings, + StaticServiceProvider.Instance.GetRequiredService(), + publishedContentCache, + StaticServiceProvider.Instance.GetRequiredService()) { } @@ -35,22 +40,23 @@ public sealed class ApiPublishedContentCache : IApiPublishedContentCache IOptionsMonitor deliveryApiSettings, IDocumentUrlService documentUrlService, IApiDocumentUrlService apiDocumentUrlService, - IPublishedContentCache publishedContentCache) - : this(requestPreviewService, requestCultureService, deliveryApiSettings, apiDocumentUrlService, publishedContentCache) + IPublishedContentCache publishedContentCache, + IVariationContextAccessor variationContextAccessor) + : this(requestPreviewService, deliveryApiSettings, apiDocumentUrlService, publishedContentCache, variationContextAccessor) { } public ApiPublishedContentCache( IRequestPreviewService requestPreviewService, - IRequestCultureService requestCultureService, IOptionsMonitor deliveryApiSettings, IApiDocumentUrlService apiDocumentUrlService, - IPublishedContentCache publishedContentCache) + IPublishedContentCache publishedContentCache, + IVariationContextAccessor variationContextAccessor) { _requestPreviewService = requestPreviewService; - _requestCultureService = requestCultureService; _apiDocumentUrlService = apiDocumentUrlService; _publishedContentCache = publishedContentCache; + _variationContextAccessor = variationContextAccessor; _deliveryApiSettings = deliveryApiSettings.CurrentValue; deliveryApiSettings.OnChange(settings => _deliveryApiSettings = settings); } @@ -61,7 +67,7 @@ public sealed class ApiPublishedContentCache : IApiPublishedContentCache Guid? documentKey = _apiDocumentUrlService.GetDocumentKeyByRoute( route, - _requestCultureService.GetRequestedCulture(), + _variationContextAccessor.VariationContext?.Culture, _requestPreviewService.IsPreview()); IPublishedContent? content = documentKey.HasValue @@ -77,7 +83,7 @@ public sealed class ApiPublishedContentCache : IApiPublishedContentCache Guid? documentKey = _apiDocumentUrlService.GetDocumentKeyByRoute( route, - _requestCultureService.GetRequestedCulture(), + _variationContextAccessor.VariationContext?.Culture, _requestPreviewService.IsPreview()); IPublishedContent? content = documentKey.HasValue diff --git a/tests/Umbraco.Tests.UnitTests/Umbraco.Core/DeliveryApi/PublishedContentCacheTests.cs b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/DeliveryApi/PublishedContentCacheTests.cs index f9d4f54659..5075f48a52 100644 --- a/tests/Umbraco.Tests.UnitTests/Umbraco.Core/DeliveryApi/PublishedContentCacheTests.cs +++ b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/DeliveryApi/PublishedContentCacheTests.cs @@ -18,6 +18,8 @@ public class PublishedContentCacheTests : DeliveryApiTests private readonly Guid _contentThreeId = Guid.Parse("013387EE-57AF-4ABD-B03C-F991B0722CCA"); + private readonly Guid _contentFourId = Guid.Parse("76D02780-F7D9-49E9-B5C3-3B992ED98F59"); + private IPublishedContentCache _contentCache; private IDocumentUrlService _documentUrlService; @@ -39,6 +41,11 @@ public class PublishedContentCacheTests : DeliveryApiTests var contentThreeMock = new Mock(); ConfigurePublishedContentMock(contentThreeMock, _contentThreeId, "Content Three", "content-three", contentTypeThreeMock.Object, Array.Empty()); + var contentTypeFourMock = new Mock(); + contentTypeFourMock.SetupGet(m => m.Alias).Returns("theFourthContentType"); + var contentFourMock = new Mock(); + ConfigurePublishedContentMock(contentFourMock, _contentFourId, "Content Four", "content-four", contentTypeFourMock.Object, Array.Empty()); + var documentUrlService = new Mock(); documentUrlService .Setup(x => x.GetDocumentKeyByRoute("/content-one", It.IsAny(), It.IsAny(), It.IsAny())) @@ -49,6 +56,9 @@ public class PublishedContentCacheTests : DeliveryApiTests documentUrlService .Setup(x => x.GetDocumentKeyByRoute("/content-three", It.IsAny(), 1234, It.IsAny())) .Returns(_contentThreeId); + documentUrlService + .Setup(x => x.GetDocumentKeyByRoute("/content-four", It.IsIn("en-US", "da-DK"), It.IsAny(), It.IsAny())) + .Returns(_contentFourId); var contentCacheMock = new Mock(); contentCacheMock @@ -60,6 +70,9 @@ public class PublishedContentCacheTests : DeliveryApiTests contentCacheMock .Setup(m => m.GetById(It.IsAny(), _contentThreeId)) .Returns(contentThreeMock.Object); + contentCacheMock + .Setup(m => m.GetById(It.IsAny(), _contentFourId)) + .Returns(contentFourMock.Object); _contentCache = contentCacheMock.Object; _documentUrlService = documentUrlService.Object; @@ -68,7 +81,7 @@ public class PublishedContentCacheTests : DeliveryApiTests [Test] public void PublishedContentCache_CanGetById() { - var publishedContentCache = new ApiPublishedContentCache(CreateRequestPreviewService(), CreateRequestCultureService(), CreateDeliveryApiSettings(), CreateApiDocumentUrlService(), _contentCache); + var publishedContentCache = new ApiPublishedContentCache(CreateRequestPreviewService(), CreateDeliveryApiSettings(), CreateApiDocumentUrlService(), _contentCache, CreateVariationContextAccessor()); var content = publishedContentCache.GetById(_contentOneId); Assert.IsNotNull(content); Assert.AreEqual(_contentOneId, content.Key); @@ -79,7 +92,7 @@ public class PublishedContentCacheTests : DeliveryApiTests [Test] public void PublishedContentCache_CanGetByRoute() { - var publishedContentCache = new ApiPublishedContentCache(CreateRequestPreviewService(), CreateRequestCultureService(), CreateDeliveryApiSettings(), CreateApiDocumentUrlService(), _contentCache); + var publishedContentCache = new ApiPublishedContentCache(CreateRequestPreviewService(), CreateDeliveryApiSettings(), CreateApiDocumentUrlService(), _contentCache, CreateVariationContextAccessor()); var content = publishedContentCache.GetByRoute("/content-two"); Assert.IsNotNull(content); Assert.AreEqual(_contentTwoId, content.Key); @@ -90,7 +103,7 @@ public class PublishedContentCacheTests : DeliveryApiTests [Test] public void PublishedContentCache_CanGetByRoute_WithStartNodeIdPrefix() { - var publishedContentCache = new ApiPublishedContentCache(CreateRequestPreviewService(), CreateRequestCultureService(), CreateDeliveryApiSettings(), CreateApiDocumentUrlService(), _contentCache); + var publishedContentCache = new ApiPublishedContentCache(CreateRequestPreviewService(), CreateDeliveryApiSettings(), CreateApiDocumentUrlService(), _contentCache, CreateVariationContextAccessor()); var content = publishedContentCache.GetByRoute("1234/content-three"); Assert.IsNotNull(content); Assert.AreEqual(_contentThreeId, content.Key); @@ -101,7 +114,7 @@ public class PublishedContentCacheTests : DeliveryApiTests [Test] public void PublishedContentCache_CanGetByIds() { - var publishedContentCache = new ApiPublishedContentCache(CreateRequestPreviewService(), CreateRequestCultureService(), CreateDeliveryApiSettings(), CreateApiDocumentUrlService(), _contentCache); + var publishedContentCache = new ApiPublishedContentCache(CreateRequestPreviewService(), CreateDeliveryApiSettings(), CreateApiDocumentUrlService(), _contentCache, CreateVariationContextAccessor()); var content = publishedContentCache.GetByIds(new[] { _contentOneId, _contentTwoId }).ToArray(); Assert.AreEqual(2, content.Length); Assert.AreEqual(_contentOneId, content.First().Key); @@ -113,7 +126,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), CreateApiDocumentUrlService(), _contentCache); + var publishedContentCache = new ApiPublishedContentCache(CreateRequestPreviewService(), CreateDeliveryApiSettings(denyList), CreateApiDocumentUrlService(), _contentCache, CreateVariationContextAccessor()); var content = publishedContentCache.GetById(_contentTwoId); if (denied) @@ -131,7 +144,7 @@ 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), CreateApiDocumentUrlService(), _contentCache); + var publishedContentCache = new ApiPublishedContentCache(CreateRequestPreviewService(), CreateDeliveryApiSettings(denyList), CreateApiDocumentUrlService(), _contentCache, CreateVariationContextAccessor()); var content = publishedContentCache.GetByRoute("/content-one"); if (denied) @@ -149,7 +162,7 @@ public class PublishedContentCacheTests : DeliveryApiTests public void PublishedContentCache_GetByIds_SupportsDenyList(string deniedContentType) { var denyList = new[] { deniedContentType }; - var publishedContentCache = new ApiPublishedContentCache(CreateRequestPreviewService(), CreateRequestCultureService(), CreateDeliveryApiSettings(denyList), CreateApiDocumentUrlService(), _contentCache); + var publishedContentCache = new ApiPublishedContentCache(CreateRequestPreviewService(), CreateDeliveryApiSettings(denyList), CreateApiDocumentUrlService(), _contentCache, CreateVariationContextAccessor()); var content = publishedContentCache.GetByIds(new[] { _contentOneId, _contentTwoId }).ToArray(); Assert.AreEqual(1, content.Length); @@ -167,7 +180,7 @@ public class PublishedContentCacheTests : DeliveryApiTests public void PublishedContentCache_GetById_CanRetrieveContentTypesOutsideTheDenyList() { var denyList = new[] { "theContentType" }; - var publishedContentCache = new ApiPublishedContentCache(CreateRequestPreviewService(), CreateRequestCultureService(), CreateDeliveryApiSettings(denyList), CreateApiDocumentUrlService(), _contentCache); + var publishedContentCache = new ApiPublishedContentCache(CreateRequestPreviewService(), CreateDeliveryApiSettings(denyList), CreateApiDocumentUrlService(), _contentCache, CreateVariationContextAccessor()); var content = publishedContentCache.GetById(_contentTwoId); Assert.IsNotNull(content); Assert.AreEqual(_contentTwoId, content.Key); @@ -179,7 +192,7 @@ public class PublishedContentCacheTests : DeliveryApiTests public void PublishedContentCache_GetByRoute_CanRetrieveContentTypesOutsideTheDenyList() { var denyList = new[] { "theOtherContentType" }; - var publishedContentCache = new ApiPublishedContentCache(CreateRequestPreviewService(), CreateRequestCultureService(), CreateDeliveryApiSettings(denyList), CreateApiDocumentUrlService(), _contentCache); + var publishedContentCache = new ApiPublishedContentCache(CreateRequestPreviewService(), CreateDeliveryApiSettings(denyList), CreateApiDocumentUrlService(), _contentCache, CreateVariationContextAccessor()); var content = publishedContentCache.GetByRoute("/content-one"); Assert.IsNotNull(content); Assert.AreEqual(_contentOneId, content.Key); @@ -187,11 +200,32 @@ public class PublishedContentCacheTests : DeliveryApiTests Assert.AreEqual("theContentType", content.ContentType.Alias); } + [TestCase("en-US")] + [TestCase("da-DK")] + public void PublishedContentCache_GetByRoute_CanRetrieveForCulture(string culture) + { + var publishedContentCache = new ApiPublishedContentCache(CreateRequestPreviewService(), CreateDeliveryApiSettings(), CreateApiDocumentUrlService(), _contentCache, CreateVariationContextAccessor(culture)); + var content = publishedContentCache.GetByRoute("/content-four"); + Assert.IsNotNull(content); + Assert.AreEqual(_contentFourId, content.Key); + Assert.AreEqual("content-four", content.UrlSegment); + Assert.AreEqual("theFourthContentType", content.ContentType.Alias); + } + + [TestCase("de-DE")] + [TestCase(null)] + public void PublishedContentCache_GetByRoute_CannotRetrieveForMissingOrUnknownCulture(string? culture) + { + var publishedContentCache = new ApiPublishedContentCache(CreateRequestPreviewService(), CreateDeliveryApiSettings(), CreateApiDocumentUrlService(), _contentCache, CreateVariationContextAccessor(culture)); + var content = publishedContentCache.GetByRoute("/content-four"); + Assert.IsNull(content); + } + [Test] public void PublishedContentCache_GetByIds_CanDenyAllRequestedContent() { var denyList = new[] { "theContentType", "theOtherContentType" }; - var publishedContentCache = new ApiPublishedContentCache(CreateRequestPreviewService(), CreateRequestCultureService(), CreateDeliveryApiSettings(denyList), CreateApiDocumentUrlService(), _contentCache); + var publishedContentCache = new ApiPublishedContentCache(CreateRequestPreviewService(), CreateDeliveryApiSettings(denyList), CreateApiDocumentUrlService(), _contentCache, CreateVariationContextAccessor()); var content = publishedContentCache.GetByIds(new[] { _contentOneId, _contentTwoId }).ToArray(); Assert.IsEmpty(content); } @@ -200,15 +234,15 @@ public class PublishedContentCacheTests : DeliveryApiTests public void PublishedContentCache_DenyListIsCaseInsensitive() { var denyList = new[] { "THEcontentTYPE" }; - var publishedContentCache = new ApiPublishedContentCache(CreateRequestPreviewService(), CreateRequestCultureService(), CreateDeliveryApiSettings(denyList), CreateApiDocumentUrlService(), _contentCache); + var publishedContentCache = new ApiPublishedContentCache(CreateRequestPreviewService(), CreateDeliveryApiSettings(denyList), CreateApiDocumentUrlService(), _contentCache, CreateVariationContextAccessor()); var content = publishedContentCache.GetByRoute("/content-one"); Assert.IsNull(content); } - private IRequestCultureService CreateRequestCultureService() + private IVariationContextAccessor CreateVariationContextAccessor(string? culture = null) { - var mock = new Mock(); - + var mock = new Mock(); + mock.SetupGet(m => m.VariationContext).Returns(new VariationContext(culture)); return mock.Object; } diff --git a/tests/Umbraco.Tests.UnitTests/Umbraco.Core/DeliveryApi/Selectors/AncestorsSelectorTests.cs b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/DeliveryApi/Selectors/AncestorsSelectorTests.cs index 19d1359308..eda96d1d25 100644 --- a/tests/Umbraco.Tests.UnitTests/Umbraco.Core/DeliveryApi/Selectors/AncestorsSelectorTests.cs +++ b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/DeliveryApi/Selectors/AncestorsSelectorTests.cs @@ -2,6 +2,7 @@ using NUnit.Framework; using Umbraco.Cms.Api.Delivery.Querying.Selectors; using Umbraco.Cms.Core.DeliveryApi; +using Umbraco.Cms.Core.Models.PublishedContent; using Umbraco.Cms.Core.Services; using Umbraco.Cms.Core.Services.Navigation; @@ -47,8 +48,8 @@ public class AncestorsSelectorTests var subject = new AncestorsSelector( requestRoutingServiceMock.Object, Mock.Of(), - Mock.Of(), new ApiDocumentUrlService(documentUrlServiceMock.Object), + Mock.Of(), _documentNavigationQueryService); var result = subject.BuildSelectorOption("ancestors:/some/where"); @@ -63,8 +64,8 @@ public class AncestorsSelectorTests var subject = new AncestorsSelector( Mock.Of(), Mock.Of(), - Mock.Of(), Mock.Of(), + Mock.Of(), _documentNavigationQueryService); var result = subject.BuildSelectorOption($"ancestors:{_documentKey:D}"); diff --git a/tests/Umbraco.Tests.UnitTests/Umbraco.Core/DeliveryApi/Selectors/ChildrenSelectorTests.cs b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/DeliveryApi/Selectors/ChildrenSelectorTests.cs index 33a3912de0..3bba1895b8 100644 --- a/tests/Umbraco.Tests.UnitTests/Umbraco.Core/DeliveryApi/Selectors/ChildrenSelectorTests.cs +++ b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/DeliveryApi/Selectors/ChildrenSelectorTests.cs @@ -2,6 +2,7 @@ using NUnit.Framework; using Umbraco.Cms.Api.Delivery.Querying.Selectors; using Umbraco.Cms.Core.DeliveryApi; +using Umbraco.Cms.Core.Models.PublishedContent; using Umbraco.Cms.Core.Services; namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.DeliveryApi.Selectors; @@ -30,8 +31,8 @@ public class ChildrenSelectorTests var subject = new ChildrenSelector( requestRoutingServiceMock.Object, Mock.Of(), - Mock.Of(), - new ApiDocumentUrlService(documentUrlServiceMock.Object)); + new ApiDocumentUrlService(documentUrlServiceMock.Object), + Mock.Of()); var result = subject.BuildSelectorOption("children:/some/where"); Assert.AreEqual(1, result.Values.Length); @@ -46,8 +47,8 @@ public class ChildrenSelectorTests var subject = new ChildrenSelector( Mock.Of(), Mock.Of(), - Mock.Of(), - Mock.Of()); + Mock.Of(), + Mock.Of()); var result = subject.BuildSelectorOption($"children:{documentKey:D}"); Assert.AreEqual(1, result.Values.Length); diff --git a/tests/Umbraco.Tests.UnitTests/Umbraco.Core/DeliveryApi/Selectors/DescendantsSelectorTests.cs b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/DeliveryApi/Selectors/DescendantsSelectorTests.cs index d322dc898a..d85a92b21d 100644 --- a/tests/Umbraco.Tests.UnitTests/Umbraco.Core/DeliveryApi/Selectors/DescendantsSelectorTests.cs +++ b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/DeliveryApi/Selectors/DescendantsSelectorTests.cs @@ -2,6 +2,7 @@ using NUnit.Framework; using Umbraco.Cms.Api.Delivery.Querying.Selectors; using Umbraco.Cms.Core.DeliveryApi; +using Umbraco.Cms.Core.Models.PublishedContent; using Umbraco.Cms.Core.Services; namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.DeliveryApi.Selectors; @@ -30,8 +31,8 @@ public class DescendantsSelectorTests var subject = new DescendantsSelector( requestRoutingServiceMock.Object, Mock.Of(), - Mock.Of(), - new ApiDocumentUrlService(documentUrlServiceMock.Object)); + new ApiDocumentUrlService(documentUrlServiceMock.Object), + Mock.Of()); var result = subject.BuildSelectorOption("descendants:/some/where"); Assert.AreEqual(1, result.Values.Length); @@ -46,8 +47,8 @@ public class DescendantsSelectorTests var subject = new DescendantsSelector( Mock.Of(), Mock.Of(), - Mock.Of(), - Mock.Of()); + Mock.Of(), + Mock.Of()); var result = subject.BuildSelectorOption($"descendants:{documentKey:D}"); Assert.AreEqual(1, result.Values.Length);