Skip to content

Commit 5f3ce28

Browse files
authored
Clear roots before rebuilding navigation dictionary (#18766)
* Clear roots before rebuilding navigation dictionary. * Added tests to verify fix. * Correct test implementation. * Convert integration tests with method overloads into test cases. * Integration test compatibility supressions.
1 parent ad7053a commit 5f3ce28

File tree

3 files changed

+43
-11
lines changed

3 files changed

+43
-11
lines changed

src/Umbraco.Core/Services/Navigation/ContentNavigationServiceBase.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -293,12 +293,12 @@ public bool RestoreFromBin(Guid key, Guid? targetParentKey = null)
293293
/// <param name="readLock">The read lock value, should be -333 or -334 for content and media trees.</param>
294294
/// <param name="objectTypeKey">The key of the object type to rebuild.</param>
295295
/// <param name="trashed">Indicates whether the items are in the recycle bin.</param>
296-
protected async Task HandleRebuildAsync(int readLock, Guid objectTypeKey, bool trashed)
296+
protected Task HandleRebuildAsync(int readLock, Guid objectTypeKey, bool trashed)
297297
{
298298
// This is only relevant for items in the content and media trees
299299
if (readLock != Constants.Locks.ContentTree && readLock != Constants.Locks.MediaTree)
300300
{
301-
return;
301+
return Task.CompletedTask;
302302
}
303303

304304
using ICoreScope scope = _coreScopeProvider.CreateCoreScope(autoComplete: true);
@@ -307,14 +307,18 @@ protected async Task HandleRebuildAsync(int readLock, Guid objectTypeKey, bool t
307307
// Build the corresponding navigation structure
308308
if (trashed)
309309
{
310+
_recycleBinRoots.Clear();
310311
IEnumerable<INavigationModel> navigationModels = _navigationRepository.GetTrashedContentNodesByObjectType(objectTypeKey);
311312
BuildNavigationDictionary(_recycleBinNavigationStructure, _recycleBinRoots, navigationModels);
312313
}
313314
else
314315
{
316+
_roots.Clear();
315317
IEnumerable<INavigationModel> navigationModels = _navigationRepository.GetContentNodesByObjectType(objectTypeKey);
316318
BuildNavigationDictionary(_navigationStructure, _roots, navigationModels);
317319
}
320+
321+
return Task.CompletedTask;
318322
}
319323

320324
private bool TryGetParentKeyFromStructure(ConcurrentDictionary<Guid, NavigationNode> structure, Guid childKey, out Guid? parentKey)

tests/Umbraco.Tests.Integration/CompatibilitySuppressions.xml

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,20 @@
7878
<Right>lib/net9.0/Umbraco.Tests.Integration.dll</Right>
7979
<IsBaselineSuppression>true</IsBaselineSuppression>
8080
</Suppression>
81+
<Suppression>
82+
<DiagnosticId>CP0002</DiagnosticId>
83+
<Target>M:Umbraco.Cms.Tests.Integration.Umbraco.Core.Services.DocumentNavigationServiceTests.Bin_Structure_Can_Rebuild</Target>
84+
<Left>lib/net9.0/Umbraco.Tests.Integration.dll</Left>
85+
<Right>lib/net9.0/Umbraco.Tests.Integration.dll</Right>
86+
<IsBaselineSuppression>true</IsBaselineSuppression>
87+
</Suppression>
88+
<Suppression>
89+
<DiagnosticId>CP0002</DiagnosticId>
90+
<Target>M:Umbraco.Cms.Tests.Integration.Umbraco.Core.Services.DocumentNavigationServiceTests.Structure_Can_Rebuild</Target>
91+
<Left>lib/net9.0/Umbraco.Tests.Integration.dll</Left>
92+
<Right>lib/net9.0/Umbraco.Tests.Integration.dll</Right>
93+
<IsBaselineSuppression>true</IsBaselineSuppression>
94+
</Suppression>
8195
<Suppression>
8296
<DiagnosticId>CP0002</DiagnosticId>
8397
<Target>M:Umbraco.Cms.Tests.Integration.Umbraco.Core.Services.UserServiceCrudTests.Cannot_Request_Disabled_If_Hidden(Umbraco.Cms.Core.Models.Membership.UserState)</Target>
@@ -94,21 +108,21 @@
94108
</Suppression>
95109
<Suppression>
96110
<DiagnosticId>CP0002</DiagnosticId>
97-
<Target>M:Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Services.MemberEditingServiceTests.Cannot_Change_IsApproved_Without_Access</Target>
111+
<Target>M:Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Services.EntityServiceTests.CreateTestData</Target>
98112
<Left>lib/net9.0/Umbraco.Tests.Integration.dll</Left>
99113
<Right>lib/net9.0/Umbraco.Tests.Integration.dll</Right>
100114
<IsBaselineSuppression>true</IsBaselineSuppression>
101115
</Suppression>
102116
<Suppression>
103117
<DiagnosticId>CP0002</DiagnosticId>
104-
<Target>M:Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Services.MemberEditingServiceTests.Cannot_Change_IsLockedOut_Without_Access</Target>
118+
<Target>M:Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Services.MemberEditingServiceTests.Cannot_Change_IsApproved_Without_Access</Target>
105119
<Left>lib/net9.0/Umbraco.Tests.Integration.dll</Left>
106120
<Right>lib/net9.0/Umbraco.Tests.Integration.dll</Right>
107121
<IsBaselineSuppression>true</IsBaselineSuppression>
108122
</Suppression>
109123
<Suppression>
110124
<DiagnosticId>CP0002</DiagnosticId>
111-
<Target>M:Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Services.EntityServiceTests.CreateTestData</Target>
125+
<Target>M:Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Services.MemberEditingServiceTests.Cannot_Change_IsLockedOut_Without_Access</Target>
112126
<Left>lib/net9.0/Umbraco.Tests.Integration.dll</Left>
113127
<Right>lib/net9.0/Umbraco.Tests.Integration.dll</Right>
114128
<IsBaselineSuppression>true</IsBaselineSuppression>

tests/Umbraco.Tests.Integration/Umbraco.Core/Services/DocumentNavigationServiceTests.Rebuild.cs

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,9 @@ namespace Umbraco.Cms.Tests.Integration.Umbraco.Core.Services;
99

1010
public partial class DocumentNavigationServiceTests
1111
{
12-
[Test]
13-
public async Task Structure_Can_Rebuild()
12+
[TestCase(1, TestName = "Structure_Can_Rebuild")]
13+
[TestCase(2, TestName = "Structure_Can_Rebuild_MultipleTimes")]
14+
public async Task Structure_Can_Rebuild(int numberOfRebuilds)
1415
{
1516
// Arrange
1617
Guid nodeKey = Root.Key;
@@ -21,6 +22,7 @@ public async Task Structure_Can_Rebuild()
2122
DocumentNavigationQueryService.TryGetDescendantsKeys(nodeKey, out IEnumerable<Guid> originalDescendantsKeys);
2223
DocumentNavigationQueryService.TryGetAncestorsKeys(nodeKey, out IEnumerable<Guid> originalAncestorsKeys);
2324
DocumentNavigationQueryService.TryGetSiblingsKeys(nodeKey, out IEnumerable<Guid> originalSiblingsKeys);
25+
DocumentNavigationQueryService.TryGetRootKeys(out IEnumerable<Guid> originalRouteKeys);
2426

2527
// In-memory navigation structure is empty here
2628
var newDocumentNavigationService = new DocumentNavigationService(
@@ -30,14 +32,18 @@ public async Task Structure_Can_Rebuild()
3032
var initialNodeExists = newDocumentNavigationService.TryGetParentKey(nodeKey, out _);
3133

3234
// Act
33-
await newDocumentNavigationService.RebuildAsync();
35+
for (int i = 0; i < numberOfRebuilds; i++)
36+
{
37+
await newDocumentNavigationService.RebuildAsync();
38+
}
3439

3540
// Capture rebuilt state
3641
var nodeExists = newDocumentNavigationService.TryGetParentKey(nodeKey, out Guid? parentKeyFromRebuild);
3742
newDocumentNavigationService.TryGetChildrenKeys(nodeKey, out IEnumerable<Guid> childrenKeysFromRebuild);
3843
newDocumentNavigationService.TryGetDescendantsKeys(nodeKey, out IEnumerable<Guid> descendantsKeysFromRebuild);
3944
newDocumentNavigationService.TryGetAncestorsKeys(nodeKey, out IEnumerable<Guid> ancestorsKeysFromRebuild);
4045
newDocumentNavigationService.TryGetSiblingsKeys(nodeKey, out IEnumerable<Guid> siblingsKeysFromRebuild);
46+
newDocumentNavigationService.TryGetRootKeys(out IEnumerable<Guid> routeKeysFromRebuild);
4147

4248
// Assert
4349
Assert.Multiple(() =>
@@ -53,11 +59,13 @@ public async Task Structure_Can_Rebuild()
5359
CollectionAssert.AreEquivalent(originalDescendantsKeys, descendantsKeysFromRebuild);
5460
CollectionAssert.AreEquivalent(originalAncestorsKeys, ancestorsKeysFromRebuild);
5561
CollectionAssert.AreEquivalent(originalSiblingsKeys, siblingsKeysFromRebuild);
62+
CollectionAssert.AreEquivalent(originalRouteKeys, routeKeysFromRebuild);
5663
});
5764
}
5865

59-
[Test]
60-
public async Task Bin_Structure_Can_Rebuild()
66+
[TestCase(1, TestName = "Bin_Structure_Can_Rebuild")]
67+
[TestCase(2, TestName = "Bin_Structure_Can_Rebuild_MultipleTimes")]
68+
public async Task Bin_Structure_Can_Rebuild(int numberOfRebuilds)
6169
{
6270
// Arrange
6371
Guid nodeKey = Root.Key;
@@ -69,6 +77,7 @@ public async Task Bin_Structure_Can_Rebuild()
6977
DocumentNavigationQueryService.TryGetDescendantsKeysInBin(nodeKey, out IEnumerable<Guid> originalDescendantsKeys);
7078
DocumentNavigationQueryService.TryGetAncestorsKeysInBin(nodeKey, out IEnumerable<Guid> originalAncestorsKeys);
7179
DocumentNavigationQueryService.TryGetSiblingsKeysInBin(nodeKey, out IEnumerable<Guid> originalSiblingsKeys);
80+
DocumentNavigationQueryService.TryGetRootKeys(out IEnumerable<Guid> originalRouteKeys);
7281

7382
// In-memory navigation structure is empty here
7483
var newDocumentNavigationService = new DocumentNavigationService(
@@ -78,14 +87,18 @@ public async Task Bin_Structure_Can_Rebuild()
7887
var initialNodeExists = newDocumentNavigationService.TryGetParentKeyInBin(nodeKey, out _);
7988

8089
// Act
81-
await newDocumentNavigationService.RebuildBinAsync();
90+
for (int i = 0; i < numberOfRebuilds; i++)
91+
{
92+
await newDocumentNavigationService.RebuildBinAsync();
93+
}
8294

8395
// Capture rebuilt state
8496
var nodeExists = newDocumentNavigationService.TryGetParentKeyInBin(nodeKey, out Guid? parentKeyFromRebuild);
8597
newDocumentNavigationService.TryGetChildrenKeysInBin(nodeKey, out IEnumerable<Guid> childrenKeysFromRebuild);
8698
newDocumentNavigationService.TryGetDescendantsKeysInBin(nodeKey, out IEnumerable<Guid> descendantsKeysFromRebuild);
8799
newDocumentNavigationService.TryGetAncestorsKeysInBin(nodeKey, out IEnumerable<Guid> ancestorsKeysFromRebuild);
88100
newDocumentNavigationService.TryGetSiblingsKeysInBin(nodeKey, out IEnumerable<Guid> siblingsKeysFromRebuild);
101+
newDocumentNavigationService.TryGetRootKeys(out IEnumerable<Guid> routeKeysFromRebuild);
89102

90103
// Assert
91104
Assert.Multiple(() =>
@@ -101,6 +114,7 @@ public async Task Bin_Structure_Can_Rebuild()
101114
CollectionAssert.AreEquivalent(originalDescendantsKeys, descendantsKeysFromRebuild);
102115
CollectionAssert.AreEquivalent(originalAncestorsKeys, ancestorsKeysFromRebuild);
103116
CollectionAssert.AreEquivalent(originalSiblingsKeys, siblingsKeysFromRebuild);
117+
CollectionAssert.AreEquivalent(originalRouteKeys, routeKeysFromRebuild);
104118
});
105119
}
106120
}

0 commit comments

Comments
 (0)