fix(m9/T23a): assign distinct SortOrder on folder create (so reorder is visible)
This commit is contained in:
+92
@@ -378,6 +378,98 @@ public class TemplateFolderServiceTests
|
||||
Assert.Contains("not found", result.Error);
|
||||
}
|
||||
|
||||
// ========================================================================
|
||||
// CreateFolderAsync — distinct SortOrder assignment (max+1 among siblings)
|
||||
// ========================================================================
|
||||
|
||||
[Fact]
|
||||
public async Task CreateFolder_FirstSibling_GetsSortOrderZero()
|
||||
{
|
||||
// No existing siblings at root → first folder gets SortOrder 0.
|
||||
_repoMock.Setup(r => r.GetAllFoldersAsync(It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(new List<TemplateFolder>());
|
||||
|
||||
TemplateFolder? captured = null;
|
||||
_repoMock.Setup(r => r.AddFolderAsync(It.IsAny<TemplateFolder>(), It.IsAny<CancellationToken>()))
|
||||
.Callback<TemplateFolder, CancellationToken>((f, _) => captured = f);
|
||||
|
||||
var result = await _sut.CreateFolderAsync("Alpha", null, "admin");
|
||||
|
||||
Assert.True(result.IsSuccess);
|
||||
Assert.NotNull(captured);
|
||||
Assert.Equal(0, captured!.SortOrder);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CreateFolder_SecondSiblingUnderSameParent_GetsSortOrderOne()
|
||||
{
|
||||
// One existing root sibling with SortOrder=0 → new folder gets SortOrder 1.
|
||||
var existing = new TemplateFolder("Alpha") { Id = 1, ParentFolderId = null, SortOrder = 0 };
|
||||
_repoMock.Setup(r => r.GetAllFoldersAsync(It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(new List<TemplateFolder> { existing });
|
||||
|
||||
TemplateFolder? captured = null;
|
||||
_repoMock.Setup(r => r.AddFolderAsync(It.IsAny<TemplateFolder>(), It.IsAny<CancellationToken>()))
|
||||
.Callback<TemplateFolder, CancellationToken>((f, _) => captured = f);
|
||||
|
||||
var result = await _sut.CreateFolderAsync("Beta", null, "admin");
|
||||
|
||||
Assert.True(result.IsSuccess);
|
||||
Assert.NotNull(captured);
|
||||
Assert.Equal(1, captured!.SortOrder);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CreateFolder_SortOrdersDoNotInterferAcrossParents()
|
||||
{
|
||||
// A root folder (SortOrder=5) should NOT influence a subfolder's SortOrder
|
||||
// when the subfolder has no siblings of its own.
|
||||
var root = new TemplateFolder("Root") { Id = 1, ParentFolderId = null, SortOrder = 5 };
|
||||
_repoMock.Setup(r => r.GetFolderByIdAsync(1, It.IsAny<CancellationToken>())).ReturnsAsync(root);
|
||||
_repoMock.Setup(r => r.GetAllFoldersAsync(It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(new List<TemplateFolder> { root });
|
||||
|
||||
TemplateFolder? captured = null;
|
||||
_repoMock.Setup(r => r.AddFolderAsync(It.IsAny<TemplateFolder>(), It.IsAny<CancellationToken>()))
|
||||
.Callback<TemplateFolder, CancellationToken>((f, _) => captured = f);
|
||||
|
||||
// Create a child under root — it has no siblings, so SortOrder should be 0.
|
||||
var result = await _sut.CreateFolderAsync("Child", 1, "admin");
|
||||
|
||||
Assert.True(result.IsSuccess);
|
||||
Assert.NotNull(captured);
|
||||
Assert.Equal(0, captured!.SortOrder);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CreateFolder_TwoSiblingsReorderIsVisiblyEffective()
|
||||
{
|
||||
// Regression: when two newly-created siblings have distinct SortOrders (0, 1),
|
||||
// a Move-up on the second-created folder must visibly change the order.
|
||||
//
|
||||
// Simulate creating two folders sequentially. The first gets SortOrder=0,
|
||||
// the second gets SortOrder=1 (as guaranteed by the max+1 logic under fix).
|
||||
// Then reorder the second folder Up — it should swap to SortOrder=0,
|
||||
// moving it before the first.
|
||||
|
||||
var first = new TemplateFolder("First") { Id = 1, ParentFolderId = null, SortOrder = 0 };
|
||||
var second = new TemplateFolder("Second") { Id = 2, ParentFolderId = null, SortOrder = 1 };
|
||||
var all = new List<TemplateFolder> { first, second };
|
||||
|
||||
_repoMock.Setup(r => r.GetFolderByIdAsync(2, It.IsAny<CancellationToken>())).ReturnsAsync(second);
|
||||
_repoMock.Setup(r => r.GetAllFoldersAsync(It.IsAny<CancellationToken>())).ReturnsAsync(all);
|
||||
|
||||
var result = await _sut.ReorderFolderAsync(2, ReorderDirection.Up, "admin");
|
||||
|
||||
Assert.True(result.IsSuccess);
|
||||
// After a Move-up the second folder should be at SortOrder 0 (before the first).
|
||||
Assert.Equal(0, second.SortOrder);
|
||||
Assert.Equal(1, first.SortOrder);
|
||||
// Verify the swap was actually persisted.
|
||||
_repoMock.Verify(r => r.UpdateFolderAsync(first, It.IsAny<CancellationToken>()), Times.Once);
|
||||
_repoMock.Verify(r => r.UpdateFolderAsync(second, It.IsAny<CancellationToken>()), Times.Once);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ReorderFolder_Persists_And_WritesAudit()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user