Files
Ho Ngoc Hai 76d75c753b Migrate
2026-05-23 18:37:02 +07:00

353 lines
8.9 KiB
C#

using FluentAssertions;
using StorageService.Domain.AggregatesModel.FolderAggregate;
using Xunit;
namespace StorageService.UnitTests.Domain;
/// <summary>
/// EN: Tests for Folder aggregate root.
/// VI: Kiểm thử cho aggregate root Folder.
/// </summary>
public class FolderTests
{
private const string ValidUserId = "user-123";
private const string ValidFolderName = "Documents";
#region CreateRoot Tests
[Fact]
public void CreateRoot_ValidParams_CreatesRootFolder()
{
// Arrange & Act
var folder = Folder.CreateRoot(ValidUserId, ValidFolderName);
// Assert
folder.Should().NotBeNull();
folder.Id.Should().NotBeEmpty();
folder.UserId.Should().Be(ValidUserId);
folder.Name.Should().Be(ValidFolderName);
folder.IsDeleted.Should().BeFalse();
}
[Fact]
public void CreateRoot_SetsLevelToZero()
{
// Arrange & Act
var folder = Folder.CreateRoot(ValidUserId, ValidFolderName);
// Assert
folder.Level.Should().Be(0);
}
[Fact]
public void CreateRoot_SetsPathCorrectly()
{
// Arrange & Act
var folder = Folder.CreateRoot(ValidUserId, ValidFolderName);
// Assert
folder.Path.Should().Be($"/{ValidFolderName}/");
}
[Fact]
public void CreateRoot_SetsParentIdToNull()
{
// Arrange & Act
var folder = Folder.CreateRoot(ValidUserId, ValidFolderName);
// Assert
folder.ParentId.Should().BeNull();
}
[Fact]
public void CreateRoot_SetsCreatedAtAndUpdatedAt()
{
// Arrange & Act
var beforeCreate = DateTime.UtcNow;
var folder = Folder.CreateRoot(ValidUserId, ValidFolderName);
// Assert
folder.CreatedAt.Should().BeOnOrAfter(beforeCreate);
folder.UpdatedAt.Should().BeOnOrAfter(beforeCreate);
folder.CreatedAt.Should().BeCloseTo(DateTime.UtcNow, TimeSpan.FromSeconds(1));
}
#endregion
#region CreateChild Tests
[Fact]
public void CreateChild_InheritsUserId()
{
// Arrange
var parentFolder = Folder.CreateRoot(ValidUserId, "Parent");
// Act
var childFolder = parentFolder.CreateChild("Child");
// Assert
childFolder.UserId.Should().Be(ValidUserId);
}
[Fact]
public void CreateChild_SetsParentId()
{
// Arrange
var parentFolder = Folder.CreateRoot(ValidUserId, "Parent");
// Act
var childFolder = parentFolder.CreateChild("Child");
// Assert
childFolder.ParentId.Should().Be(parentFolder.Id);
}
[Fact]
public void CreateChild_IncrementsLevel()
{
// Arrange
var rootFolder = Folder.CreateRoot(ValidUserId, "Root");
// Act
var level1 = rootFolder.CreateChild("Level1");
var level2 = level1.CreateChild("Level2");
var level3 = level2.CreateChild("Level3");
// Assert
rootFolder.Level.Should().Be(0);
level1.Level.Should().Be(1);
level2.Level.Should().Be(2);
level3.Level.Should().Be(3);
}
[Fact]
public void CreateChild_AppendsToPath()
{
// Arrange
var rootFolder = Folder.CreateRoot(ValidUserId, "Root");
// Act
var childFolder = rootFolder.CreateChild("Child");
var grandchildFolder = childFolder.CreateChild("Grandchild");
// Assert
rootFolder.Path.Should().Be("/Root/");
childFolder.Path.Should().Be("/Root/Child/");
grandchildFolder.Path.Should().Be("/Root/Child/Grandchild/");
}
[Fact]
public void CreateChild_GeneratesUniqueId()
{
// Arrange
var parentFolder = Folder.CreateRoot(ValidUserId, "Parent");
// Act
var child1 = parentFolder.CreateChild("Child1");
var child2 = parentFolder.CreateChild("Child2");
// Assert
child1.Id.Should().NotBe(child2.Id);
child1.Id.Should().NotBe(parentFolder.Id);
}
#endregion
#region Rename Tests
[Fact]
public void Rename_ValidName_UpdatesNameAndPath()
{
// Arrange
var folder = Folder.CreateRoot(ValidUserId, "OldName");
var beforeRename = folder.UpdatedAt;
// Act
Thread.Sleep(10); // Ensure time difference
folder.Rename("NewName");
// Assert
folder.Name.Should().Be("NewName");
folder.Path.Should().Be("/NewName/");
folder.UpdatedAt.Should().BeAfter(beforeRename);
}
[Fact]
public void Rename_ChildFolder_UpdatesPathCorrectly()
{
// Arrange
var rootFolder = Folder.CreateRoot(ValidUserId, "Root");
var childFolder = rootFolder.CreateChild("OldChild");
// Act
childFolder.Rename("NewChild");
// Assert
childFolder.Name.Should().Be("NewChild");
childFolder.Path.Should().Be("/Root/NewChild/");
}
[Fact]
public void Rename_DeletedFolder_ThrowsException()
{
// Arrange
var folder = Folder.CreateRoot(ValidUserId, "Folder");
folder.Delete();
// Act
var act = () => folder.Rename("NewName");
// Assert
act.Should().Throw<InvalidOperationException>()
.WithMessage("*deleted*");
}
#endregion
#region MoveTo Tests
[Fact]
public void MoveTo_NullParent_BecomesRoot()
{
// Arrange
var rootFolder = Folder.CreateRoot(ValidUserId, "Root");
var childFolder = rootFolder.CreateChild("Child");
// Act
childFolder.MoveTo(null);
// Assert
childFolder.ParentId.Should().BeNull();
childFolder.Level.Should().Be(0);
childFolder.Path.Should().Be("/Child/");
}
[Fact]
public void MoveTo_ValidParent_UpdatesHierarchy()
{
// Arrange
var folder1 = Folder.CreateRoot(ValidUserId, "Folder1");
var folder2 = Folder.CreateRoot(ValidUserId, "Folder2");
var childFolder = folder1.CreateChild("Child");
// Act
childFolder.MoveTo(folder2);
// Assert
childFolder.ParentId.Should().Be(folder2.Id);
childFolder.Level.Should().Be(1);
childFolder.Path.Should().Be("/Folder2/Child/");
}
[Fact]
public void MoveTo_DifferentUser_ThrowsException()
{
// Arrange
var folder1 = Folder.CreateRoot("user-1", "Folder1");
var folder2 = Folder.CreateRoot("user-2", "Folder2");
// Act
var act = () => folder1.MoveTo(folder2);
// Assert
act.Should().Throw<InvalidOperationException>()
.WithMessage("*different user*");
}
[Fact]
public void MoveTo_DeletedFolder_ThrowsException()
{
// Arrange
var folder = Folder.CreateRoot(ValidUserId, "Folder");
var targetFolder = Folder.CreateRoot(ValidUserId, "Target");
folder.Delete();
// Act
var act = () => folder.MoveTo(targetFolder);
// Assert
act.Should().Throw<InvalidOperationException>()
.WithMessage("*deleted*");
}
[Fact]
public void MoveTo_UpdatesUpdatedAt()
{
// Arrange
var folder1 = Folder.CreateRoot(ValidUserId, "Folder1");
var folder2 = Folder.CreateRoot(ValidUserId, "Folder2");
var beforeMove = folder1.UpdatedAt;
// Act
Thread.Sleep(10);
folder1.MoveTo(folder2);
// Assert
folder1.UpdatedAt.Should().BeAfter(beforeMove);
}
#endregion
#region Delete Tests
[Fact]
public void Delete_SetsIsDeletedAndDeletedAt()
{
// Arrange
var folder = Folder.CreateRoot(ValidUserId, ValidFolderName);
// Act
folder.Delete();
// Assert
folder.IsDeleted.Should().BeTrue();
folder.DeletedAt.Should().NotBeNull();
folder.DeletedAt.Should().BeCloseTo(DateTime.UtcNow, TimeSpan.FromSeconds(1));
}
[Fact]
public void Delete_AlreadyDeleted_DoesNotUpdateDeletedAt()
{
// Arrange
var folder = Folder.CreateRoot(ValidUserId, ValidFolderName);
folder.Delete();
var firstDeletedAt = folder.DeletedAt;
// Act
Thread.Sleep(10);
folder.Delete();
// Assert
folder.DeletedAt.Should().Be(firstDeletedAt);
}
[Fact]
public void Delete_RootFolder_SetsDeleted()
{
// Arrange
var folder = Folder.CreateRoot(ValidUserId, "Root");
// Act
folder.Delete();
// Assert
folder.IsDeleted.Should().BeTrue();
}
[Fact]
public void Delete_ChildFolder_SetsDeleted()
{
// Arrange
var rootFolder = Folder.CreateRoot(ValidUserId, "Root");
var childFolder = rootFolder.CreateChild("Child");
// Act
childFolder.Delete();
// Assert
childFolder.IsDeleted.Should().BeTrue();
rootFolder.IsDeleted.Should().BeFalse(); // Parent should not be affected
}
#endregion
}