diff --git a/src/Umbraco.Core/Services/Navigation/ContentNavigationServiceBase.cs b/src/Umbraco.Core/Services/Navigation/ContentNavigationServiceBase.cs index 531b3952a7..d7562a76b9 100644 --- a/src/Umbraco.Core/Services/Navigation/ContentNavigationServiceBase.cs +++ b/src/Umbraco.Core/Services/Navigation/ContentNavigationServiceBase.cs @@ -293,12 +293,12 @@ internal abstract class ContentNavigationServiceBaseThe read lock value, should be -333 or -334 for content and media trees. /// The key of the object type to rebuild. /// Indicates whether the items are in the recycle bin. - protected async Task HandleRebuildAsync(int readLock, Guid objectTypeKey, bool trashed) + protected Task HandleRebuildAsync(int readLock, Guid objectTypeKey, bool trashed) { // This is only relevant for items in the content and media trees if (readLock != Constants.Locks.ContentTree && readLock != Constants.Locks.MediaTree) { - return; + return Task.CompletedTask; } using ICoreScope scope = _coreScopeProvider.CreateCoreScope(autoComplete: true); @@ -307,14 +307,18 @@ internal abstract class ContentNavigationServiceBase navigationModels = _navigationRepository.GetTrashedContentNodesByObjectType(objectTypeKey); BuildNavigationDictionary(_recycleBinNavigationStructure, _recycleBinRoots, navigationModels); } else { + _roots.Clear(); IEnumerable navigationModels = _navigationRepository.GetContentNodesByObjectType(objectTypeKey); BuildNavigationDictionary(_navigationStructure, _roots, navigationModels); } + + return Task.CompletedTask; } private bool TryGetParentKeyFromStructure(ConcurrentDictionary structure, Guid childKey, out Guid? parentKey) diff --git a/tests/Umbraco.Tests.Integration/CompatibilitySuppressions.xml b/tests/Umbraco.Tests.Integration/CompatibilitySuppressions.xml index 880504a1d4..3b12394aaa 100644 --- a/tests/Umbraco.Tests.Integration/CompatibilitySuppressions.xml +++ b/tests/Umbraco.Tests.Integration/CompatibilitySuppressions.xml @@ -78,6 +78,20 @@ lib/net9.0/Umbraco.Tests.Integration.dll true + + CP0002 + M:Umbraco.Cms.Tests.Integration.Umbraco.Core.Services.DocumentNavigationServiceTests.Bin_Structure_Can_Rebuild + lib/net9.0/Umbraco.Tests.Integration.dll + lib/net9.0/Umbraco.Tests.Integration.dll + true + + + CP0002 + M:Umbraco.Cms.Tests.Integration.Umbraco.Core.Services.DocumentNavigationServiceTests.Structure_Can_Rebuild + lib/net9.0/Umbraco.Tests.Integration.dll + lib/net9.0/Umbraco.Tests.Integration.dll + true + CP0002 M:Umbraco.Cms.Tests.Integration.Umbraco.Core.Services.UserServiceCrudTests.Cannot_Request_Disabled_If_Hidden(Umbraco.Cms.Core.Models.Membership.UserState) @@ -92,6 +106,13 @@ lib/net9.0/Umbraco.Tests.Integration.dll true + + CP0002 + M:Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Services.EntityServiceTests.CreateTestData + lib/net9.0/Umbraco.Tests.Integration.dll + lib/net9.0/Umbraco.Tests.Integration.dll + true + CP0002 M:Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Services.MemberEditingServiceTests.Cannot_Change_IsApproved_Without_Access @@ -106,13 +127,6 @@ lib/net9.0/Umbraco.Tests.Integration.dll true - - CP0002 - M:Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Services.EntityServiceTests.CreateTestData - lib/net9.0/Umbraco.Tests.Integration.dll - lib/net9.0/Umbraco.Tests.Integration.dll - true - CP0002 M:Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Services.TemplateServiceTests.Deleting_Master_Template_Also_Deletes_Children diff --git a/tests/Umbraco.Tests.Integration/Umbraco.Core/Services/DocumentNavigationServiceTests.Rebuild.cs b/tests/Umbraco.Tests.Integration/Umbraco.Core/Services/DocumentNavigationServiceTests.Rebuild.cs index 52f9bb77bd..0389152074 100644 --- a/tests/Umbraco.Tests.Integration/Umbraco.Core/Services/DocumentNavigationServiceTests.Rebuild.cs +++ b/tests/Umbraco.Tests.Integration/Umbraco.Core/Services/DocumentNavigationServiceTests.Rebuild.cs @@ -9,8 +9,9 @@ namespace Umbraco.Cms.Tests.Integration.Umbraco.Core.Services; public partial class DocumentNavigationServiceTests { - [Test] - public async Task Structure_Can_Rebuild() + [TestCase(1, TestName = "Structure_Can_Rebuild")] + [TestCase(2, TestName = "Structure_Can_Rebuild_MultipleTimes")] + public async Task Structure_Can_Rebuild(int numberOfRebuilds) { // Arrange Guid nodeKey = Root.Key; @@ -21,6 +22,7 @@ public partial class DocumentNavigationServiceTests DocumentNavigationQueryService.TryGetDescendantsKeys(nodeKey, out IEnumerable originalDescendantsKeys); DocumentNavigationQueryService.TryGetAncestorsKeys(nodeKey, out IEnumerable originalAncestorsKeys); DocumentNavigationQueryService.TryGetSiblingsKeys(nodeKey, out IEnumerable originalSiblingsKeys); + DocumentNavigationQueryService.TryGetRootKeys(out IEnumerable originalRouteKeys); // In-memory navigation structure is empty here var newDocumentNavigationService = new DocumentNavigationService( @@ -30,7 +32,10 @@ public partial class DocumentNavigationServiceTests var initialNodeExists = newDocumentNavigationService.TryGetParentKey(nodeKey, out _); // Act - await newDocumentNavigationService.RebuildAsync(); + for (int i = 0; i < numberOfRebuilds; i++) + { + await newDocumentNavigationService.RebuildAsync(); + } // Capture rebuilt state var nodeExists = newDocumentNavigationService.TryGetParentKey(nodeKey, out Guid? parentKeyFromRebuild); @@ -38,6 +43,7 @@ public partial class DocumentNavigationServiceTests newDocumentNavigationService.TryGetDescendantsKeys(nodeKey, out IEnumerable descendantsKeysFromRebuild); newDocumentNavigationService.TryGetAncestorsKeys(nodeKey, out IEnumerable ancestorsKeysFromRebuild); newDocumentNavigationService.TryGetSiblingsKeys(nodeKey, out IEnumerable siblingsKeysFromRebuild); + newDocumentNavigationService.TryGetRootKeys(out IEnumerable routeKeysFromRebuild); // Assert Assert.Multiple(() => @@ -53,11 +59,13 @@ public partial class DocumentNavigationServiceTests CollectionAssert.AreEquivalent(originalDescendantsKeys, descendantsKeysFromRebuild); CollectionAssert.AreEquivalent(originalAncestorsKeys, ancestorsKeysFromRebuild); CollectionAssert.AreEquivalent(originalSiblingsKeys, siblingsKeysFromRebuild); + CollectionAssert.AreEquivalent(originalRouteKeys, routeKeysFromRebuild); }); } - [Test] - public async Task Bin_Structure_Can_Rebuild() + [TestCase(1, TestName = "Bin_Structure_Can_Rebuild")] + [TestCase(2, TestName = "Bin_Structure_Can_Rebuild_MultipleTimes")] + public async Task Bin_Structure_Can_Rebuild(int numberOfRebuilds) { // Arrange Guid nodeKey = Root.Key; @@ -69,6 +77,7 @@ public partial class DocumentNavigationServiceTests DocumentNavigationQueryService.TryGetDescendantsKeysInBin(nodeKey, out IEnumerable originalDescendantsKeys); DocumentNavigationQueryService.TryGetAncestorsKeysInBin(nodeKey, out IEnumerable originalAncestorsKeys); DocumentNavigationQueryService.TryGetSiblingsKeysInBin(nodeKey, out IEnumerable originalSiblingsKeys); + DocumentNavigationQueryService.TryGetRootKeys(out IEnumerable originalRouteKeys); // In-memory navigation structure is empty here var newDocumentNavigationService = new DocumentNavigationService( @@ -78,7 +87,10 @@ public partial class DocumentNavigationServiceTests var initialNodeExists = newDocumentNavigationService.TryGetParentKeyInBin(nodeKey, out _); // Act - await newDocumentNavigationService.RebuildBinAsync(); + for (int i = 0; i < numberOfRebuilds; i++) + { + await newDocumentNavigationService.RebuildBinAsync(); + } // Capture rebuilt state var nodeExists = newDocumentNavigationService.TryGetParentKeyInBin(nodeKey, out Guid? parentKeyFromRebuild); @@ -86,6 +98,7 @@ public partial class DocumentNavigationServiceTests newDocumentNavigationService.TryGetDescendantsKeysInBin(nodeKey, out IEnumerable descendantsKeysFromRebuild); newDocumentNavigationService.TryGetAncestorsKeysInBin(nodeKey, out IEnumerable ancestorsKeysFromRebuild); newDocumentNavigationService.TryGetSiblingsKeysInBin(nodeKey, out IEnumerable siblingsKeysFromRebuild); + newDocumentNavigationService.TryGetRootKeys(out IEnumerable routeKeysFromRebuild); // Assert Assert.Multiple(() => @@ -101,6 +114,7 @@ public partial class DocumentNavigationServiceTests CollectionAssert.AreEquivalent(originalDescendantsKeys, descendantsKeysFromRebuild); CollectionAssert.AreEquivalent(originalAncestorsKeys, ancestorsKeysFromRebuild); CollectionAssert.AreEquivalent(originalSiblingsKeys, siblingsKeysFromRebuild); + CollectionAssert.AreEquivalent(originalRouteKeys, routeKeysFromRebuild); }); } }