diff --git a/backend/src/PostService/PostService.Application/Commands/AddPost/AddPostCommandHandler.cs b/backend/src/PostService/PostService.Application/Commands/AddPost/AddPostCommandHandler.cs index 54e6084..adaee54 100644 --- a/backend/src/PostService/PostService.Application/Commands/AddPost/AddPostCommandHandler.cs +++ b/backend/src/PostService/PostService.Application/Commands/AddPost/AddPostCommandHandler.cs @@ -1,6 +1,7 @@ using FluentValidation; using PostService.Application.DTOs; using PostService.Domain.Entities; +using PostService.Domain.Enums; using PostService.Persistence; using Shared.Application.Abstractions; using Shared.Application.Common; @@ -28,12 +29,7 @@ public async Task> HandleAsync(AddPostCommand command) return Result.Failure(new Error(errorMessage)); } - var post = new Post( - command.UserId, - command.CreatePost.Title, - command.CreatePost.Description, - command.CreatePost.ContentUrl, - command.CreatePost.ContentType); + var post = CreatePostForSpecifiedType(command); _context.Posts.Add(post); await _context.SaveChangesAsync(); @@ -49,4 +45,18 @@ public async Task> HandleAsync(AddPostCommand command) return Result.Success(postDto); } + + private static Post CreatePostForSpecifiedType(AddPostCommand command) + { + return command.CreatePost.ContentType switch + { + ContentType.Text => Post.CreateTextPost(command.UserId, command.CreatePost.Title, command.CreatePost.Description), + + ContentType.Image => Post.CreateImagePost(command.UserId, command.CreatePost.ContentUrl, command.CreatePost.Title, command.CreatePost.Description), + + ContentType.Video => Post.CreateVideoPost(command.UserId, command.CreatePost.ContentUrl, command.CreatePost.Title, command.CreatePost.Description), + + _ => throw new InvalidOperationException("Unsupported content type.") + }; + } } \ No newline at end of file diff --git a/backend/src/PostService/PostService.Domain/Entities/Post.cs b/backend/src/PostService/PostService.Domain/Entities/Post.cs index 0df0a0e..b4624c8 100644 --- a/backend/src/PostService/PostService.Domain/Entities/Post.cs +++ b/backend/src/PostService/PostService.Domain/Entities/Post.cs @@ -14,7 +14,7 @@ public class Post public uint CommentCount { get; private set; } public DateTime CreatedAt { get; private set; } - public Post(Guid userId, string title, string description, string contentUrl, ContentType contentType) + private Post(Guid userId, string title, string description, string contentUrl, ContentType contentType) { if (userId == Guid.Empty) { @@ -34,6 +34,21 @@ public Post(Guid userId, string title, string description, string contentUrl, Co CreatedAt = DateTime.UtcNow; } + public static Post CreateTextPost(Guid userId, string title, string description) + { + return new Post(userId, title, description, string.Empty, ContentType.Text); + } + + public static Post CreateImagePost(Guid userId, string contentUrl, string title = "", string description = "") + { + return new Post(userId, title, description, contentUrl, ContentType.Image); + } + + public static Post CreateVideoPost(Guid userId, string contentUrl, string title = "", string description = "") + { + return new Post(userId, title, description, contentUrl, ContentType.Video); + } + public void Update(string title, string description) { ValidateContent(ContentType, title, description, ContentUrl); @@ -63,7 +78,7 @@ private static void ValidateContent(ContentType contentType, string title, strin } } - if ((contentType == ContentType.Image || contentType == ContentType.Video) && string.IsNullOrWhiteSpace(contentUrl)) + else if ((contentType == ContentType.Image || contentType == ContentType.Video) && string.IsNullOrWhiteSpace(contentUrl)) { throw new ArgumentException("ContentUrl is required for image or video content.", nameof(contentUrl)); } diff --git a/backend/tests/PostService/PostService.Domain.Tests/PostTests.cs b/backend/tests/PostService/PostService.Domain.Tests/PostTests.cs index d817ad4..617a111 100644 --- a/backend/tests/PostService/PostService.Domain.Tests/PostTests.cs +++ b/backend/tests/PostService/PostService.Domain.Tests/PostTests.cs @@ -8,24 +8,68 @@ namespace PostService.Domain.Tests; public class PostTests { [Fact] - public void Constructor_ShouldInitializeFieldsCorrectly() + public void CreateTextPost_ShouldInitializeFieldsCorrectly() { // Arrange var userId = Guid.NewGuid(); var title = "Sample Title"; var description = "Sample Description"; - var contentUrl = "https://example.com/content"; - var contentType = ContentType.Text; // Act - var post = new Post(userId, title, description, contentUrl, contentType); + var post = Post.CreateTextPost(userId, title, description); + + // Assert + post.UserId.Should().Be(userId); + post.Title.Should().Be(title); + post.Description.Should().Be(description); + post.ContentUrl.Should().Be(string.Empty); + post.ContentType.Should().Be(ContentType.Text); + post.LikeCount.Should().Be(0); + post.CommentCount.Should().Be(0); + post.CreatedAt.Date.Should().Be(DateTime.UtcNow.Date); + } + + [Fact] + public void CreateImagePost_ShouldInitializeFieldsCorrectly() + { + // Arrange + var userId = Guid.NewGuid(); + var title = "Sample Title"; + var description = "Sample Description"; + var contentUrl = "https://example.com/image.jpg"; + + // Act + var post = Post.CreateImagePost(userId, contentUrl, title, description); // Assert post.UserId.Should().Be(userId); post.Title.Should().Be(title); post.Description.Should().Be(description); post.ContentUrl.Should().Be(contentUrl); - post.ContentType.Should().Be(contentType); + post.ContentType.Should().Be(ContentType.Image); + post.LikeCount.Should().Be(0); + post.CommentCount.Should().Be(0); + post.CreatedAt.Date.Should().Be(DateTime.UtcNow.Date); + } + + [Fact] + public void CreateVideoPost_ShouldInitializeFieldsCorrectly() + { + // Arrange + var userId = Guid.NewGuid(); + var title = "Sample Title"; + var description = "Sample Description"; + var contentUrl = "https://example.com/video.mp4"; + + // Act + var post = Post.CreateVideoPost(userId, contentUrl, title, description); + + // Assert + post.UserId.Should().Be(userId); + post.Title.Should().Be(title); + post.Description.Should().Be(description); + post.ContentUrl.Should().Be(contentUrl); + post.ContentType.Should().Be(ContentType.Video); post.LikeCount.Should().Be(0); post.CommentCount.Should().Be(0); post.CreatedAt.Date.Should().Be(DateTime.UtcNow.Date); @@ -35,13 +79,11 @@ public void Constructor_ShouldInitializeFieldsCorrectly() public void Update_ShouldModifyTitleAndDescription() { // Arrange - var post = new Post( + var post = Post.CreateTextPost( Guid.NewGuid(), "Old Title", - "Old Description", - "https://example.com", - ContentType.Text); - + "Old Description"); + var newTitle = "New Title"; var newDescription = "New Description"; @@ -57,12 +99,10 @@ public void Update_ShouldModifyTitleAndDescription() public void IncrementLikeCount_ShouldIncreaseLikeCountByOne() { // Arrange - var post = new Post( + var post = Post.CreateTextPost( Guid.NewGuid(), "Title", - "Description", - "https://example.com", - ContentType.Text); + "Description"); // Act post.IncrementLikeCount(); @@ -75,12 +115,10 @@ public void IncrementLikeCount_ShouldIncreaseLikeCountByOne() public void DecrementLikeCount_ShouldDecreaseLikeCountByOne() { // Arrange - var post = new Post( + var post = Post.CreateTextPost( Guid.NewGuid(), "Title", - "Description", - "https://example.com", - ContentType.Text); + "Description"); post.IncrementLikeCount(); // Initial increment to avoid negative count @@ -95,12 +133,10 @@ public void DecrementLikeCount_ShouldDecreaseLikeCountByOne() public void IncrementCommentCount_ShouldIncreaseCommentCountByOne() { // Arrange - var post = new Post( + var post = Post.CreateTextPost( Guid.NewGuid(), "Title", - "Description", - "https://example.com", - ContentType.Text); + "Description"); // Act post.IncrementCommentCount(); @@ -113,12 +149,10 @@ public void IncrementCommentCount_ShouldIncreaseCommentCountByOne() public void DecrementCommentCount_ShouldDecreaseCommentCountByOne() { // Arrange - var post = new Post( + var post = Post.CreateTextPost( Guid.NewGuid(), "Title", - "Description", - "https://example.com", - ContentType.Text); + "Description"); post.IncrementCommentCount(); // Initial increment to avoid negative count @@ -130,17 +164,15 @@ public void DecrementCommentCount_ShouldDecreaseCommentCountByOne() } [Fact] - public void Constructor_ShouldThrowArgumentException_WhenUserIdIsEmpty() + public void CreateTextPost_ShouldThrowArgumentException_WhenUserIdIsEmpty() { // Arrange var userId = Guid.Empty; var title = "Title"; var description = "Description"; - var contentUrl = "https://example.com"; - var contentType = ContentType.Text; // Act - var act = () => new Post(userId, title, description, contentUrl, contentType); + var act = () => Post.CreateTextPost(userId, title, description); // Assert act.Should().ThrowExactly() @@ -149,17 +181,15 @@ public void Constructor_ShouldThrowArgumentException_WhenUserIdIsEmpty() } [Fact] - public void Constructor_ShouldThrowArgumentException_WhenTitleIsEmpty_ForTextContent() + public void CreateTextPost_ShouldThrowArgumentException_WhenTitleIsEmpty_ForTextContent() { // Arrange var userId = Guid.NewGuid(); var title = ""; var description = "Description"; - var contentUrl = "https://example.com"; - var contentType = ContentType.Text; // Act - var act = () => new Post(userId, title, description, contentUrl, contentType); + var act = () => Post.CreateTextPost(userId, title, description); // Assert act.Should().ThrowExactly() @@ -168,17 +198,15 @@ public void Constructor_ShouldThrowArgumentException_WhenTitleIsEmpty_ForTextCon } [Fact] - public void Constructor_ShouldThrowArgumentException_WhenDescriptionIsEmpty_ForTextContent() + public void CreateTextPost_ShouldThrowArgumentException_WhenDescriptionIsEmpty_ForTextContent() { // Arrange var userId = Guid.NewGuid(); var title = "Title"; var description = ""; - var contentUrl = "https://example.com"; - var contentType = ContentType.Text; // Act - var act = () => new Post(userId, title, description, contentUrl, contentType); + var act = () => Post.CreateTextPost(userId, title, description); // Assert act.Should().ThrowExactly() @@ -187,17 +215,34 @@ public void Constructor_ShouldThrowArgumentException_WhenDescriptionIsEmpty_ForT } [Fact] - public void Constructor_ShouldThrowArgumentException_WhenContentUrlIsEmpty_ForImageOrVideoContent() + public void CreateImagePost_ShouldThrowArgumentException_WhenContentUrlIsEmpty_ForImageContent() + { + // Arrange + var userId = Guid.NewGuid(); + var title = "Title"; + var description = "Description"; + var contentUrl = ""; + + // Act + var act = () => Post.CreateImagePost(userId, contentUrl, title, description); + + // Assert + act.Should().ThrowExactly() + .WithMessage($"ContentUrl is required for image or video content. (Parameter '{nameof(contentUrl)}')") + .And.ParamName.Should().Be("contentUrl"); + } + + [Fact] + public void CreateVideoPost_ShouldThrowArgumentException_WhenContentUrlIsEmpty_ForVideoContent() { // Arrange var userId = Guid.NewGuid(); var title = "Title"; var description = "Description"; var contentUrl = ""; - var contentType = ContentType.Image; // Act - var act = () => new Post(userId, title, description, contentUrl, contentType); + var act = () => Post.CreateVideoPost(userId, contentUrl, title, description); // Assert act.Should().ThrowExactly()