Merge branch 'main' into v17/dev
# Conflicts: # src/Umbraco.Web.UI.Client/package-lock.json # src/Umbraco.Web.UI.Client/package.json # version.json
This commit is contained in:
3
tests/Umbraco.Tests.AcceptanceTest/console-errors.json
Normal file
3
tests/Umbraco.Tests.AcceptanceTest/console-errors.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"consoleErrors": []
|
||||
}
|
||||
@@ -8,7 +8,7 @@
|
||||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
"@umbraco/json-models-builders": "^2.0.37",
|
||||
"@umbraco/playwright-testhelpers": "^16.0.34",
|
||||
"@umbraco/playwright-testhelpers": "^16.0.36",
|
||||
"camelize": "^1.0.0",
|
||||
"dotenv": "^16.3.1",
|
||||
"node-fetch": "^2.6.7"
|
||||
@@ -67,9 +67,10 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@umbraco/playwright-testhelpers": {
|
||||
"version": "16.0.34",
|
||||
"resolved": "https://registry.npmjs.org/@umbraco/playwright-testhelpers/-/playwright-testhelpers-16.0.34.tgz",
|
||||
"integrity": "sha512-hCOqSUrTVZPNxD3DP+olYz/QFc8HwyZ1QZR6gTv87nIkAlvEjk44+7KblPartfBXQDd93uvasptr7dO3XCapZA==",
|
||||
"version": "16.0.36",
|
||||
"resolved": "https://registry.npmjs.org/@umbraco/playwright-testhelpers/-/playwright-testhelpers-16.0.36.tgz",
|
||||
"integrity": "sha512-SjPrVgWI18ErfyCUEuIwt1V7HjCGXFLae0S8u3NO74QBbOO9z79+JM0/U4Xwqwq9KdV2XMiVPkzDm/5xThSvMg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@umbraco/json-models-builders": "2.0.37",
|
||||
"node-fetch": "^2.6.7"
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@umbraco/json-models-builders": "^2.0.37",
|
||||
"@umbraco/playwright-testhelpers": "^16.0.34",
|
||||
"@umbraco/playwright-testhelpers": "^16.0.36",
|
||||
"camelize": "^1.0.0",
|
||||
"dotenv": "^16.3.1",
|
||||
"node-fetch": "^2.6.7"
|
||||
|
||||
@@ -71,16 +71,17 @@ internal sealed class BackOfficeExamineSearcherTests : ExamineBaseTest
|
||||
builder.Services.AddHostedService<QueuedHostedService>();
|
||||
}
|
||||
|
||||
private IEnumerable<ISearchResult> BackOfficeExamineSearch(string query, int pageSize = 20, int pageIndex = 0) =>
|
||||
private IEnumerable<ISearchResult> BackOfficeExamineSearch(string query, int pageSize = 20, int pageIndex = 0, bool ignoreUserStartNodes = false) =>
|
||||
BackOfficeExamineSearcher.Search(
|
||||
query,
|
||||
UmbracoEntityTypes.Document,
|
||||
pageSize,
|
||||
pageIndex,
|
||||
out _,
|
||||
null,
|
||||
null,
|
||||
ignoreUserStartNodes: true);
|
||||
totalFound: out _,
|
||||
contentTypeAliases: null,
|
||||
trashed: null,
|
||||
searchFrom: null,
|
||||
ignoreUserStartNodes: ignoreUserStartNodes);
|
||||
|
||||
private async Task SetupUserIdentity(string userId)
|
||||
{
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
@@ -26,8 +27,8 @@ namespace Umbraco.Cms.Tests.Integration.Umbraco.PublishedCache.HybridCache;
|
||||
internal sealed class DocumentHybridCacheMockTests : UmbracoIntegrationTestWithContent
|
||||
{
|
||||
private IPublishedContentCache _mockedCache;
|
||||
private Mock<IDatabaseCacheRepository> _mockedNucacheRepository;
|
||||
private IDocumentCacheService _mockDocumentCacheService;
|
||||
private Mock<IDatabaseCacheRepository> _mockDatabaseCacheRepository;
|
||||
private IDocumentCacheService _documentCacheService;
|
||||
|
||||
protected override void CustomTestSetup(IUmbracoBuilder builder) => builder.AddUmbracoHybridCache();
|
||||
|
||||
@@ -38,7 +39,7 @@ internal sealed class DocumentHybridCacheMockTests : UmbracoIntegrationTestWithC
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
_mockedNucacheRepository = new Mock<IDatabaseCacheRepository>();
|
||||
_mockDatabaseCacheRepository = new Mock<IDatabaseCacheRepository>();
|
||||
|
||||
var contentData = new ContentData(
|
||||
Textpage.Name,
|
||||
@@ -76,25 +77,29 @@ internal sealed class DocumentHybridCacheMockTests : UmbracoIntegrationTestWithC
|
||||
IsDraft = false,
|
||||
};
|
||||
|
||||
_mockedNucacheRepository.Setup(r => r.GetContentSourceAsync(It.IsAny<Guid>(), true))
|
||||
_mockDatabaseCacheRepository.Setup(r => r.GetContentSourceAsync(It.IsAny<Guid>(), true))
|
||||
.ReturnsAsync(draftTestCacheNode);
|
||||
_mockDatabaseCacheRepository.Setup(r => r.GetContentSourcesAsync(It.IsAny<IEnumerable<Guid>>(), true))
|
||||
.ReturnsAsync([draftTestCacheNode]);
|
||||
|
||||
_mockedNucacheRepository.Setup(r => r.GetContentSourceAsync(It.IsAny<Guid>(), false))
|
||||
_mockDatabaseCacheRepository.Setup(r => r.GetContentSourceAsync(It.IsAny<Guid>(), false))
|
||||
.ReturnsAsync(publishedTestCacheNode);
|
||||
_mockDatabaseCacheRepository.Setup(r => r.GetContentSourcesAsync(It.IsAny<IEnumerable<Guid>>(), false))
|
||||
.ReturnsAsync([publishedTestCacheNode]);
|
||||
|
||||
_mockedNucacheRepository.Setup(r => r.GetContentByContentTypeKey(It.IsAny<IReadOnlyCollection<Guid>>(), ContentCacheDataSerializerEntityType.Document)).Returns(
|
||||
_mockDatabaseCacheRepository.Setup(r => r.GetContentByContentTypeKey(It.IsAny<IReadOnlyCollection<Guid>>(), ContentCacheDataSerializerEntityType.Document)).Returns(
|
||||
new List<ContentCacheNode>()
|
||||
{
|
||||
draftTestCacheNode,
|
||||
});
|
||||
|
||||
_mockedNucacheRepository.Setup(r => r.DeleteContentItemAsync(It.IsAny<int>()));
|
||||
_mockDatabaseCacheRepository.Setup(r => r.DeleteContentItemAsync(It.IsAny<int>()));
|
||||
|
||||
var mockedPublishedStatusService = new Mock<IPublishStatusQueryService>();
|
||||
mockedPublishedStatusService.Setup(x => x.IsDocumentPublishedInAnyCulture(It.IsAny<Guid>())).Returns(true);
|
||||
|
||||
_mockDocumentCacheService = new DocumentCacheService(
|
||||
_mockedNucacheRepository.Object,
|
||||
_documentCacheService = new DocumentCacheService(
|
||||
_mockDatabaseCacheRepository.Object,
|
||||
GetRequiredService<IIdKeyMap>(),
|
||||
GetRequiredService<ICoreScopeProvider>(),
|
||||
GetRequiredService<Microsoft.Extensions.Caching.Hybrid.HybridCache>(),
|
||||
@@ -105,9 +110,10 @@ internal sealed class DocumentHybridCacheMockTests : UmbracoIntegrationTestWithC
|
||||
GetRequiredService<IPublishedModelFactory>(),
|
||||
GetRequiredService<IPreviewService>(),
|
||||
mockedPublishedStatusService.Object,
|
||||
GetRequiredService<IDocumentNavigationQueryService>());
|
||||
new NullLogger<DocumentCacheService>());
|
||||
|
||||
_mockedCache = new DocumentCache(_mockDocumentCacheService,
|
||||
_mockedCache = new DocumentCache(
|
||||
_documentCacheService,
|
||||
GetRequiredService<IPublishedContentTypeCache>(),
|
||||
GetRequiredService<IDocumentNavigationQueryService>(),
|
||||
GetRequiredService<IDocumentUrlService>(),
|
||||
@@ -118,8 +124,10 @@ internal sealed class DocumentHybridCacheMockTests : UmbracoIntegrationTestWithC
|
||||
// So we'll manually create them with a magic options mock.
|
||||
private IEnumerable<IDocumentSeedKeyProvider> GetSeedProviders(IPublishStatusQueryService publishStatusQueryService)
|
||||
{
|
||||
_cacheSettings = new CacheSettings();
|
||||
_cacheSettings.DocumentBreadthFirstSeedCount = 0;
|
||||
_cacheSettings = new CacheSettings
|
||||
{
|
||||
DocumentBreadthFirstSeedCount = 0
|
||||
};
|
||||
|
||||
var mock = new Mock<IOptions<CacheSettings>>();
|
||||
mock.Setup(m => m.Value).Returns(() => _cacheSettings);
|
||||
@@ -140,7 +148,7 @@ internal sealed class DocumentHybridCacheMockTests : UmbracoIntegrationTestWithC
|
||||
var textPage2 = await _mockedCache.GetByIdAsync(Textpage.Key, true);
|
||||
AssertTextPage(textPage);
|
||||
AssertTextPage(textPage2);
|
||||
_mockedNucacheRepository.Verify(x => x.GetContentSourceAsync(It.IsAny<Guid>(), It.IsAny<bool>()), Times.Exactly(1));
|
||||
_mockDatabaseCacheRepository.Verify(x => x.GetContentSourceAsync(It.IsAny<Guid>(), It.IsAny<bool>()), Times.Exactly(1));
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -152,79 +160,79 @@ internal sealed class DocumentHybridCacheMockTests : UmbracoIntegrationTestWithC
|
||||
var textPage2 = await _mockedCache.GetByIdAsync(Textpage.Id, true);
|
||||
AssertTextPage(textPage);
|
||||
AssertTextPage(textPage2);
|
||||
_mockedNucacheRepository.Verify(x => x.GetContentSourceAsync(It.IsAny<Guid>(), It.IsAny<bool>()), Times.Exactly(1));
|
||||
_mockDatabaseCacheRepository.Verify(x => x.GetContentSourceAsync(It.IsAny<Guid>(), It.IsAny<bool>()), Times.Exactly(1));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Content_Is_Seeded_By_Id()
|
||||
{
|
||||
var schedule = new CultureAndScheduleModel
|
||||
var schedule = new CulturePublishScheduleModel
|
||||
{
|
||||
CulturesToPublishImmediately = new HashSet<string> { "*" }, Schedules = new ContentScheduleCollection(),
|
||||
Culture = Constants.System.InvariantCulture,
|
||||
};
|
||||
|
||||
var publishResult = await ContentPublishingService.PublishAsync(Textpage.Key, schedule, Constants.Security.SuperUserKey);
|
||||
var publishResult = await ContentPublishingService.PublishAsync(Textpage.Key, [schedule], Constants.Security.SuperUserKey);
|
||||
Assert.IsTrue(publishResult.Success);
|
||||
Textpage.Published = true;
|
||||
await _mockDocumentCacheService.DeleteItemAsync(Textpage);
|
||||
await _documentCacheService.DeleteItemAsync(Textpage);
|
||||
|
||||
_cacheSettings.ContentTypeKeys = [ Textpage.ContentType.Key ];
|
||||
await _mockDocumentCacheService.SeedAsync(CancellationToken.None);
|
||||
_mockedNucacheRepository.Verify(x => x.GetContentSourceAsync(It.IsAny<Guid>(), It.IsAny<bool>()), Times.Exactly(1));
|
||||
await _documentCacheService.SeedAsync(CancellationToken.None);
|
||||
_mockDatabaseCacheRepository.Verify(x => x.GetContentSourcesAsync(It.IsAny<IEnumerable<Guid>>(), It.IsAny<bool>()), Times.Exactly(1));
|
||||
|
||||
var textPage = await _mockedCache.GetByIdAsync(Textpage.Id);
|
||||
AssertTextPage(textPage);
|
||||
|
||||
_mockedNucacheRepository.Verify(x => x.GetContentSourceAsync(It.IsAny<Guid>(), It.IsAny<bool>()), Times.Exactly(1));
|
||||
_mockDatabaseCacheRepository.Verify(x => x.GetContentSourcesAsync(It.IsAny<IEnumerable<Guid>>(), It.IsAny<bool>()), Times.Exactly(1));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Content_Is_Seeded_By_Key()
|
||||
{
|
||||
var schedule = new CultureAndScheduleModel
|
||||
var schedule = new CulturePublishScheduleModel
|
||||
{
|
||||
CulturesToPublishImmediately = new HashSet<string> { "*" }, Schedules = new ContentScheduleCollection(),
|
||||
Culture = Constants.System.InvariantCulture,
|
||||
};
|
||||
|
||||
var publishResult = await ContentPublishingService.PublishAsync(Textpage.Key, schedule, Constants.Security.SuperUserKey);
|
||||
var publishResult = await ContentPublishingService.PublishAsync(Textpage.Key, [schedule], Constants.Security.SuperUserKey);
|
||||
Assert.IsTrue(publishResult.Success);
|
||||
Textpage.Published = true;
|
||||
await _mockDocumentCacheService.DeleteItemAsync(Textpage);
|
||||
await _documentCacheService.DeleteItemAsync(Textpage);
|
||||
|
||||
_cacheSettings.ContentTypeKeys = [ Textpage.ContentType.Key ];
|
||||
await _mockDocumentCacheService.SeedAsync(CancellationToken.None);
|
||||
_mockedNucacheRepository.Verify(x => x.GetContentSourceAsync(It.IsAny<Guid>(), It.IsAny<bool>()), Times.Exactly(1));
|
||||
await _documentCacheService.SeedAsync(CancellationToken.None);
|
||||
_mockDatabaseCacheRepository.Verify(x => x.GetContentSourcesAsync(It.IsAny<IEnumerable<Guid>>(), It.IsAny<bool>()), Times.Exactly(1));
|
||||
var textPage = await _mockedCache.GetByIdAsync(Textpage.Key);
|
||||
AssertTextPage(textPage);
|
||||
|
||||
_mockedNucacheRepository.Verify(x => x.GetContentSourceAsync(It.IsAny<Guid>(), It.IsAny<bool>()), Times.Exactly(1));
|
||||
_mockDatabaseCacheRepository.Verify(x => x.GetContentSourcesAsync(It.IsAny<IEnumerable<Guid>>(), It.IsAny<bool>()), Times.Exactly(1));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Content_Is_Not_Seeded_If_Unpblished_By_Id()
|
||||
{
|
||||
|
||||
await _mockDocumentCacheService.DeleteItemAsync(Textpage);
|
||||
await _documentCacheService.DeleteItemAsync(Textpage);
|
||||
|
||||
_cacheSettings.ContentTypeKeys = [ Textpage.ContentType.Key ];
|
||||
await _mockDocumentCacheService.SeedAsync(CancellationToken.None);
|
||||
await _documentCacheService.SeedAsync(CancellationToken.None);
|
||||
var textPage = await _mockedCache.GetByIdAsync(Textpage.Id, true);
|
||||
AssertTextPage(textPage);
|
||||
|
||||
_mockedNucacheRepository.Verify(x => x.GetContentSourceAsync(It.IsAny<Guid>(), It.IsAny<bool>()), Times.Exactly(1));
|
||||
_mockDatabaseCacheRepository.Verify(x => x.GetContentSourceAsync(It.IsAny<Guid>(), It.IsAny<bool>()), Times.Exactly(1));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Content_Is_Not_Seeded_If_Unpublished_By_Key()
|
||||
{
|
||||
_cacheSettings.ContentTypeKeys = [ Textpage.ContentType.Key ];
|
||||
await _mockDocumentCacheService.DeleteItemAsync(Textpage);
|
||||
await _documentCacheService.DeleteItemAsync(Textpage);
|
||||
|
||||
await _mockDocumentCacheService.SeedAsync(CancellationToken.None);
|
||||
await _documentCacheService.SeedAsync(CancellationToken.None);
|
||||
var textPage = await _mockedCache.GetByIdAsync(Textpage.Key, true);
|
||||
AssertTextPage(textPage);
|
||||
|
||||
_mockedNucacheRepository.Verify(x => x.GetContentSourceAsync(It.IsAny<Guid>(), It.IsAny<bool>()), Times.Exactly(1));
|
||||
_mockDatabaseCacheRepository.Verify(x => x.GetContentSourceAsync(It.IsAny<Guid>(), It.IsAny<bool>()), Times.Exactly(1));
|
||||
}
|
||||
|
||||
private void AssertTextPage(IPublishedContent textPage)
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
// Copyright (c) Umbraco.
|
||||
// See LICENSE for more details.
|
||||
|
||||
using System.Threading;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Cms.Core.Cache;
|
||||
using Umbraco.Extensions;
|
||||
@@ -13,18 +12,21 @@ public abstract class RuntimeAppCacheTests : AppCacheTests
|
||||
internal abstract IAppPolicyCache AppPolicyCache { get; }
|
||||
|
||||
[Test]
|
||||
[Explicit("Testing for timeouts cannot work on VSTS.")]
|
||||
public void Can_Add_And_Expire_Struct_Strongly_Typed_With_Null()
|
||||
{
|
||||
var now = DateTime.Now;
|
||||
AppPolicyCache.Insert("DateTimeTest", () => now, new TimeSpan(0, 0, 0, 0, 200));
|
||||
Assert.AreEqual(now, AppCache.GetCacheItem<DateTime>("DateTimeTest"));
|
||||
Assert.AreEqual(now, AppCache.GetCacheItem<DateTime?>("DateTimeTest"));
|
||||
AppPolicyCache.Insert("DateTimeTest", () => now, new TimeSpan(0, 0, 0, 0, 20));
|
||||
var cachedDateTime = AppCache.GetCacheItem<DateTime>("DateTimeTest");
|
||||
var cachedDateTimeNullable = AppCache.GetCacheItem<DateTime?>("DateTimeTest");
|
||||
Assert.AreEqual(now, cachedDateTime);
|
||||
Assert.AreEqual(now, cachedDateTimeNullable);
|
||||
|
||||
Thread.Sleep(300); // sleep longer than the cache expiration
|
||||
Thread.Sleep(30); // sleep longer than the cache expiration
|
||||
|
||||
Assert.AreEqual(default(DateTime), AppCache.GetCacheItem<DateTime>("DateTimeTest"));
|
||||
Assert.AreEqual(null, AppCache.GetCacheItem<DateTime?>("DateTimeTest"));
|
||||
cachedDateTime = AppCache.GetCacheItem<DateTime>("DateTimeTest");
|
||||
cachedDateTimeNullable = AppCache.GetCacheItem<DateTime?>("DateTimeTest");
|
||||
Assert.AreEqual(default(DateTime), cachedDateTime);
|
||||
Assert.AreEqual(null, cachedDateTimeNullable);
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
||||
@@ -28,8 +28,6 @@ public class SliderPropertyValueEditorTests
|
||||
true,
|
||||
new object(),
|
||||
new List<string> { "some", "values" },
|
||||
Guid.NewGuid(),
|
||||
new GuidUdi(Constants.UdiEntityType.Document, Guid.NewGuid())
|
||||
};
|
||||
|
||||
[TestCaseSource(nameof(InvalidCaseData))]
|
||||
@@ -39,6 +37,20 @@ public class SliderPropertyValueEditorTests
|
||||
Assert.IsNull(fromEditor);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Can_Handle_Invalid_Values_From_Editor_Guid()
|
||||
{
|
||||
var fromEditor = FromEditor(Guid.NewGuid());
|
||||
Assert.IsNull(fromEditor);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Can_Handle_Invalid_Values_From_Editor_Udi()
|
||||
{
|
||||
var fromEditor = FromEditor(new GuidUdi(Constants.UdiEntityType.Document, Guid.NewGuid()));
|
||||
Assert.IsNull(fromEditor);
|
||||
}
|
||||
|
||||
[TestCase("1", 1)]
|
||||
[TestCase("0", 0)]
|
||||
[TestCase("-1", -1)]
|
||||
|
||||
@@ -0,0 +1,153 @@
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Cms.Core.Configuration.Models;
|
||||
using Umbraco.Cms.Core.Models.PublishedContent;
|
||||
using Umbraco.Cms.Core.PublishedCache;
|
||||
using Umbraco.Cms.Core.Routing;
|
||||
using Umbraco.Cms.Core.Services;
|
||||
using Umbraco.Cms.Core.Web;
|
||||
|
||||
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Routing;
|
||||
|
||||
[TestFixture]
|
||||
public class ContentFinderByUrlNewTests
|
||||
{
|
||||
private const int DomainContentId = 1233;
|
||||
private const int ContentId = 1234;
|
||||
private static readonly Guid _contentKey = Guid.NewGuid();
|
||||
private const string ContentPath = "/test-page";
|
||||
private const string DomainHost = "example.com";
|
||||
|
||||
[TestCase(ContentPath, true)]
|
||||
[TestCase("/missing-page", false)]
|
||||
public async Task Can_Find_Invariant_Content(string path, bool expectSuccess)
|
||||
{
|
||||
var mockContent = CreateMockPublishedContent();
|
||||
|
||||
var mockUmbracoContextAccessor = CreateMockUmbracoContextAccessor();
|
||||
|
||||
var mockDocumentUrlService = CreateMockDocumentUrlService();
|
||||
|
||||
var mockPublishedContentCache = CreateMockPublishedContentCache(mockContent);
|
||||
|
||||
var sut = CreateContentFinder(mockUmbracoContextAccessor, mockDocumentUrlService, mockPublishedContentCache);
|
||||
|
||||
var publishedRequestBuilder = CreatePublishedRequestBuilder(path);
|
||||
|
||||
var result = await sut.TryFindContent(publishedRequestBuilder);
|
||||
|
||||
Assert.AreEqual(expectSuccess, result);
|
||||
if (expectSuccess)
|
||||
{
|
||||
Assert.IsNotNull(publishedRequestBuilder.PublishedContent);
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.IsNull(publishedRequestBuilder.PublishedContent);
|
||||
}
|
||||
}
|
||||
|
||||
[TestCase(ContentPath, true, false, true)]
|
||||
[TestCase("/missing-page", true, false, false)]
|
||||
[TestCase(ContentPath, true, true, true)]
|
||||
[TestCase(ContentPath, false, true, false)]
|
||||
public async Task Can_Find_Invariant_Content_With_Domain(string path, bool setDomain, bool useStrictDomainMatching, bool expectSuccess)
|
||||
{
|
||||
var mockContent = CreateMockPublishedContent();
|
||||
|
||||
var mockUmbracoContextAccessor = CreateMockUmbracoContextAccessor();
|
||||
|
||||
var mockDocumentUrlService = CreateMockDocumentUrlService();
|
||||
|
||||
var mockPublishedContentCache = CreateMockPublishedContentCache(mockContent);
|
||||
|
||||
var sut = CreateContentFinder(
|
||||
mockUmbracoContextAccessor,
|
||||
mockDocumentUrlService,
|
||||
mockPublishedContentCache,
|
||||
new WebRoutingSettings
|
||||
{
|
||||
UseStrictDomainMatching = useStrictDomainMatching
|
||||
});
|
||||
|
||||
var publishedRequestBuilder = CreatePublishedRequestBuilder(path, withDomain: setDomain);
|
||||
|
||||
var result = await sut.TryFindContent(publishedRequestBuilder);
|
||||
|
||||
Assert.AreEqual(expectSuccess, result);
|
||||
if (expectSuccess)
|
||||
{
|
||||
Assert.IsNotNull(publishedRequestBuilder.PublishedContent);
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.IsNull(publishedRequestBuilder.PublishedContent);
|
||||
}
|
||||
}
|
||||
|
||||
private static Mock<IPublishedContent> CreateMockPublishedContent()
|
||||
{
|
||||
var mockContent = new Mock<IPublishedContent>();
|
||||
mockContent
|
||||
.SetupGet(x => x.Id)
|
||||
.Returns(ContentId);
|
||||
mockContent
|
||||
.SetupGet(x => x.ContentType.ItemType)
|
||||
.Returns(PublishedItemType.Content);
|
||||
return mockContent;
|
||||
}
|
||||
|
||||
private static Mock<IUmbracoContextAccessor> CreateMockUmbracoContextAccessor()
|
||||
{
|
||||
var mockUmbracoContext = new Mock<IUmbracoContext>();
|
||||
var mockUmbracoContextAccessor = new Mock<IUmbracoContextAccessor>();
|
||||
var umbracoContext = mockUmbracoContext.Object;
|
||||
mockUmbracoContextAccessor
|
||||
.Setup(x => x.TryGetUmbracoContext(out umbracoContext))
|
||||
.Returns(true);
|
||||
return mockUmbracoContextAccessor;
|
||||
}
|
||||
|
||||
private static Mock<IDocumentUrlService> CreateMockDocumentUrlService()
|
||||
{
|
||||
var mockDocumentUrlService = new Mock<IDocumentUrlService>();
|
||||
mockDocumentUrlService
|
||||
.Setup(x => x.GetDocumentKeyByRoute(It.Is<string>(y => y == ContentPath), It.IsAny<string?>(), It.IsAny<int?>(), It.IsAny<bool>()))
|
||||
.Returns(_contentKey);
|
||||
return mockDocumentUrlService;
|
||||
}
|
||||
|
||||
private static Mock<IPublishedContentCache> CreateMockPublishedContentCache(Mock<IPublishedContent> mockContent)
|
||||
{
|
||||
var mockPublishedContentCache = new Mock<IPublishedContentCache>();
|
||||
mockPublishedContentCache
|
||||
.Setup(x => x.GetById(It.IsAny<bool>(), It.Is<Guid>(y => y == _contentKey)))
|
||||
.Returns(mockContent.Object);
|
||||
return mockPublishedContentCache;
|
||||
}
|
||||
|
||||
private static ContentFinderByUrlNew CreateContentFinder(
|
||||
Mock<IUmbracoContextAccessor> mockUmbracoContextAccessor,
|
||||
Mock<IDocumentUrlService> mockDocumentUrlService,
|
||||
Mock<IPublishedContentCache> mockPublishedContentCache,
|
||||
WebRoutingSettings? webRoutingSettings = null)
|
||||
=> new(
|
||||
new NullLogger<ContentFinderByUrlNew>(),
|
||||
mockUmbracoContextAccessor.Object,
|
||||
mockDocumentUrlService.Object,
|
||||
mockPublishedContentCache.Object,
|
||||
Mock.Of<IOptionsMonitor<WebRoutingSettings>>(x => x.CurrentValue == (webRoutingSettings ?? new WebRoutingSettings())));
|
||||
|
||||
private static PublishedRequestBuilder CreatePublishedRequestBuilder(string path, bool withDomain = false)
|
||||
{
|
||||
var publishedRequestBuilder = new PublishedRequestBuilder(new Uri($"https://example.com{path}"), Mock.Of<IFileService>());
|
||||
if (withDomain)
|
||||
{
|
||||
publishedRequestBuilder.SetDomain(new DomainAndUri(new Domain(1, $"https://{DomainHost}/", DomainContentId, "en-US", false, 0), new Uri($"https://{DomainHost}{path}")));
|
||||
}
|
||||
|
||||
return publishedRequestBuilder;
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement;
|
||||
|
||||
namespace Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Persistence.Repositories;
|
||||
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Infrastructure.Persistence.Repositories;
|
||||
|
||||
[TestFixture]
|
||||
internal sealed class SimilarNodeNameTests
|
||||
@@ -156,45 +156,19 @@ internal sealed class SimilarNodeNameTests
|
||||
Assert.AreEqual(expected, res);
|
||||
}
|
||||
|
||||
/* Original Tests - Can be deleted, as new tests cover all cases */
|
||||
|
||||
[TestCase(0, "Charlie", "Charlie")]
|
||||
[TestCase(0, "Zulu", "Zulu (1)")]
|
||||
[TestCase(0, "Golf", "Golf (1)")]
|
||||
[TestCase(0, "Kilo", "Kilo (2)")]
|
||||
[TestCase(0, "Alpha", "Alpha (3)")]
|
||||
//// [TestCase(0, "Kilo (1)", "Kilo (1) (1)")] // though... we might consider "Kilo (2)"
|
||||
[TestCase(0, "Kilo (1)", "Kilo (2)")] // names[] contains "Kilo" AND "Kilo (1)", which implies that result should be "Kilo (2)"
|
||||
[TestCase(6, "Kilo (1)", "Kilo (1)")] // because of the id
|
||||
[TestCase(0, "alpha", "alpha (3)")]
|
||||
[TestCase(0, "", " (1)")]
|
||||
[TestCase(0, null, " (1)")]
|
||||
public void Test(int nodeId, string nodeName, string expected)
|
||||
{
|
||||
SimilarNodeName[] names =
|
||||
{
|
||||
new SimilarNodeName {Id = 1, Name = "Alpha (2)"}, new SimilarNodeName {Id = 2, Name = "Alpha"},
|
||||
new SimilarNodeName {Id = 3, Name = "Golf"}, new SimilarNodeName {Id = 4, Name = "Zulu"},
|
||||
new SimilarNodeName {Id = 5, Name = "Mike"}, new SimilarNodeName {Id = 6, Name = "Kilo (1)"},
|
||||
new SimilarNodeName {Id = 7, Name = "Yankee"}, new SimilarNodeName {Id = 8, Name = "Kilo"},
|
||||
new SimilarNodeName {Id = 9, Name = "Golf (2)"}, new SimilarNodeName {Id = 10, Name = "Alpha (1)"}
|
||||
};
|
||||
|
||||
Assert.AreEqual(expected, SimilarNodeName.GetUniqueName(names, nodeId, nodeName));
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Explicit("This test fails! We need to fix up the logic")]
|
||||
public void TestMany()
|
||||
public void Handles_Many_Similar_Names()
|
||||
{
|
||||
SimilarNodeName[] names =
|
||||
{
|
||||
new SimilarNodeName {Id = 1, Name = "Alpha (2)"}, new SimilarNodeName {Id = 2, Name = "Test"},
|
||||
new SimilarNodeName {Id = 3, Name = "Test (1)"}, new SimilarNodeName {Id = 4, Name = "Test (2)"},
|
||||
new SimilarNodeName {Id = 1, Name = "Alpha (2)"},
|
||||
new SimilarNodeName {Id = 2, Name = "Test"},
|
||||
new SimilarNodeName {Id = 3, Name = "Test (1)"},
|
||||
new SimilarNodeName {Id = 4, Name = "Test (2)"},
|
||||
new SimilarNodeName {Id = 22, Name = "Test (1) (1)"}
|
||||
};
|
||||
|
||||
// TODO: this will yield "Test (2)" which is already in use
|
||||
Assert.AreEqual("Test (3)", SimilarNodeName.GetUniqueName(names, 0, "Test"));
|
||||
var uniqueName = SimilarNodeName.GetUniqueName(names, 0, "Test");
|
||||
Assert.AreEqual("Test (3)", uniqueName);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
using Microsoft.Extensions.Options;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Cms.Core.Models;
|
||||
@@ -6,6 +6,7 @@ using Umbraco.Cms.Core.Services.Navigation;
|
||||
using Umbraco.Cms.Infrastructure.HybridCache.SeedKeyProviders.Document;
|
||||
|
||||
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.PublishedCache.HybridCache;
|
||||
|
||||
[TestFixture]
|
||||
public class DocumentBreadthFirstKeyProviderTests
|
||||
{
|
||||
|
||||
@@ -0,0 +1,186 @@
|
||||
using Microsoft.Extensions.Caching.Hybrid;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Cms.Infrastructure.HybridCache.Extensions;
|
||||
|
||||
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.PublishedCache.HybridCache.Extensions;
|
||||
|
||||
/// <summary>
|
||||
/// Provides tests to cover the <see cref="HybridCacheExtensions"/> class.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Hat-tip: https://github.com/dotnet/aspnetcore/discussions/57191
|
||||
/// </remarks>
|
||||
[TestFixture]
|
||||
public class HybridCacheExtensionsTests
|
||||
{
|
||||
private Mock<Microsoft.Extensions.Caching.Hybrid.HybridCache> _cacheMock;
|
||||
|
||||
[SetUp]
|
||||
public void TestInitialize()
|
||||
{
|
||||
_cacheMock = new Mock<Microsoft.Extensions.Caching.Hybrid.HybridCache>();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task ExistsAsync_WhenKeyExists_ShouldReturnTrue()
|
||||
{
|
||||
// Arrange
|
||||
string key = "test-key";
|
||||
var expectedValue = "test-value";
|
||||
|
||||
_cacheMock
|
||||
.Setup(cache => cache.GetOrCreateAsync(
|
||||
key,
|
||||
null!,
|
||||
It.IsAny<Func<object, CancellationToken, ValueTask<object>>>(),
|
||||
It.IsAny<HybridCacheEntryOptions>(),
|
||||
null,
|
||||
CancellationToken.None))
|
||||
.ReturnsAsync(expectedValue);
|
||||
|
||||
// Act
|
||||
var exists = await HybridCacheExtensions.ExistsAsync(_cacheMock.Object, key);
|
||||
|
||||
// Assert
|
||||
Assert.IsTrue(exists);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task ExistsAsync_WhenKeyDoesNotExist_ShouldReturnFalse()
|
||||
{
|
||||
// Arrange
|
||||
string key = "test-key";
|
||||
|
||||
_cacheMock
|
||||
.Setup(cache => cache.GetOrCreateAsync(
|
||||
key,
|
||||
null!,
|
||||
It.IsAny<Func<object, CancellationToken, ValueTask<object>>>(),
|
||||
It.IsAny<HybridCacheEntryOptions>(),
|
||||
null,
|
||||
CancellationToken.None))
|
||||
.Returns((
|
||||
string key,
|
||||
object? state,
|
||||
Func<object, CancellationToken, ValueTask<object>> factory,
|
||||
HybridCacheEntryOptions? options,
|
||||
IEnumerable<string>? tags,
|
||||
CancellationToken token) =>
|
||||
{
|
||||
return factory(state!, token);
|
||||
});
|
||||
|
||||
// Act
|
||||
var exists = await HybridCacheExtensions.ExistsAsync(_cacheMock.Object, key);
|
||||
|
||||
// Assert
|
||||
Assert.IsFalse(exists);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TryGetValueAsync_WhenKeyExists_ShouldReturnTrueAndValueAsString()
|
||||
{
|
||||
// Arrange
|
||||
string key = "test-key";
|
||||
var expectedValue = "test-value";
|
||||
|
||||
_cacheMock
|
||||
.Setup(cache => cache.GetOrCreateAsync(
|
||||
key,
|
||||
null!,
|
||||
It.IsAny<Func<object, CancellationToken, ValueTask<string>>>(),
|
||||
It.IsAny<HybridCacheEntryOptions>(),
|
||||
null,
|
||||
CancellationToken.None))
|
||||
.ReturnsAsync(expectedValue);
|
||||
|
||||
// Act
|
||||
var (exists, value) = await HybridCacheExtensions.TryGetValueAsync<string>(_cacheMock.Object, key);
|
||||
|
||||
// Assert
|
||||
Assert.IsTrue(exists);
|
||||
Assert.AreEqual(expectedValue, value);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TryGetValueAsync_WhenKeyExists_ShouldReturnTrueAndValueAsInteger()
|
||||
{
|
||||
// Arrange
|
||||
string key = "test-key";
|
||||
var expectedValue = 5;
|
||||
|
||||
_cacheMock
|
||||
.Setup(cache => cache.GetOrCreateAsync(
|
||||
key,
|
||||
null!,
|
||||
It.IsAny<Func<object, CancellationToken, ValueTask<int>>>(),
|
||||
It.IsAny<HybridCacheEntryOptions>(),
|
||||
null,
|
||||
CancellationToken.None))
|
||||
.ReturnsAsync(expectedValue);
|
||||
|
||||
// Act
|
||||
var (exists, value) = await HybridCacheExtensions.TryGetValueAsync<int>(_cacheMock.Object, key);
|
||||
|
||||
// Assert
|
||||
Assert.IsTrue(exists);
|
||||
Assert.AreEqual(expectedValue, value);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TryGetValueAsync_WhenKeyExistsButValueIsNull_ShouldReturnTrueAndNullValue()
|
||||
{
|
||||
// Arrange
|
||||
string key = "test-key";
|
||||
|
||||
_cacheMock
|
||||
.Setup(cache => cache.GetOrCreateAsync(
|
||||
key,
|
||||
null!,
|
||||
It.IsAny<Func<object, CancellationToken, ValueTask<object>>>(),
|
||||
It.IsAny<HybridCacheEntryOptions>(),
|
||||
null,
|
||||
CancellationToken.None))
|
||||
.ReturnsAsync(null!);
|
||||
|
||||
// Act
|
||||
var (exists, value) = await HybridCacheExtensions.TryGetValueAsync<int?>(_cacheMock.Object, key);
|
||||
|
||||
// Assert
|
||||
Assert.IsTrue(exists);
|
||||
Assert.IsNull(value);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TryGetValueAsync_WhenKeyDoesNotExist_ShouldReturnFalseAndNull()
|
||||
{
|
||||
// Arrange
|
||||
string key = "test-key";
|
||||
|
||||
_cacheMock.Setup(cache => cache.GetOrCreateAsync(
|
||||
key,
|
||||
null,
|
||||
It.IsAny<Func<object?, CancellationToken, ValueTask<string>>>(),
|
||||
It.IsAny<HybridCacheEntryOptions>(),
|
||||
null,
|
||||
CancellationToken.None))
|
||||
.Returns((
|
||||
string key,
|
||||
object? state,
|
||||
Func<object?, CancellationToken, ValueTask<string>> factory,
|
||||
HybridCacheEntryOptions? options,
|
||||
IEnumerable<string>? tags,
|
||||
CancellationToken token) =>
|
||||
{
|
||||
return factory(state, token);
|
||||
});
|
||||
|
||||
// Act
|
||||
var (exists, value) = await HybridCacheExtensions.TryGetValueAsync<string>(_cacheMock.Object, key);
|
||||
|
||||
// Assert
|
||||
Assert.IsFalse(exists);
|
||||
Assert.IsNull(value);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user