using FluentAssertions; using StorageService.Domain.AggregatesModel.FolderAggregate; using Xunit; namespace StorageService.UnitTests.Domain; /// /// EN: Tests for Folder aggregate root. /// VI: Kiểm thử cho aggregate root Folder. /// 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() .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() .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() .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 }