From 2e9418a997dbaa3d87dd0b729549fc28189db00d Mon Sep 17 00:00:00 2001 From: thisisnabi Date: Mon, 3 Jun 2024 11:47:29 +0330 Subject: [PATCH] Add GetPopularArticlesHandlerTests test --- .../GetPopularArticlesHandler.cs | 7 +- .../GetPopularArticlesQuery.cs | 2 +- .../ArticleAggregate/Article.cs | 11 +++ .../ArticleAggregate/IArticleRepository.cs | 8 +- .../Repositories/ArticleRepository.cs | 22 +++-- .../GetPopularArticlesHandlerTests.cs | 90 +++++++++++++++++++ 6 files changed, 125 insertions(+), 15 deletions(-) create mode 100644 tests/Blogger.IntegrationTests/Articles/GetPopularArticlesHandlerTests.cs diff --git a/src/Blogger.Application/Articles/GetPopularArticles/GetPopularArticlesHandler.cs b/src/Blogger.Application/Articles/GetPopularArticles/GetPopularArticlesHandler.cs index 2f6cb86..a4ecbc9 100644 --- a/src/Blogger.Application/Articles/GetPopularArticles/GetPopularArticlesHandler.cs +++ b/src/Blogger.Application/Articles/GetPopularArticles/GetPopularArticlesHandler.cs @@ -1,15 +1,14 @@ namespace Blogger.Application.Articles.GetPopularArticles; public class GetPopularArticlesHandler(IArticleRepository articleRepository) - : IRequestHandler> + : IRequestHandler> { private readonly IArticleRepository _articleRepository = articleRepository; - public async Task> Handle(GetPopularArticlesQuery request, CancellationToken cancellationToken) + public async Task> Handle(GetPopularArticlesQuery request, CancellationToken cancellationToken) { var articles = await _articleRepository.GetPopularArticlesAsync(request.Size, cancellationToken); - return articles.Select(x => new GetPopularArticlesQueryResponse(x.Id, x.Title)) - .ToImmutableList(); + return [.. articles.Select(x => new GetPopularArticlesQueryResponse(x.Id, x.Title))]; } } diff --git a/src/Blogger.Application/Articles/GetPopularArticles/GetPopularArticlesQuery.cs b/src/Blogger.Application/Articles/GetPopularArticles/GetPopularArticlesQuery.cs index 82c38b5..c1afb71 100644 --- a/src/Blogger.Application/Articles/GetPopularArticles/GetPopularArticlesQuery.cs +++ b/src/Blogger.Application/Articles/GetPopularArticles/GetPopularArticlesQuery.cs @@ -1,3 +1,3 @@ namespace Blogger.Application.Articles.GetPopularArticles; public record GetPopularArticlesQuery(int Size) - : IRequest>; \ No newline at end of file + : IRequest>; \ No newline at end of file diff --git a/src/Blogger.Domain/ArticleAggregate/Article.cs b/src/Blogger.Domain/ArticleAggregate/Article.cs index 746a113..6d46aba 100644 --- a/src/Blogger.Domain/ArticleAggregate/Article.cs +++ b/src/Blogger.Domain/ArticleAggregate/Article.cs @@ -6,6 +6,7 @@ private Article(ArticleId slug) : base(slug) { _tags = []; _commentIds = []; + _likes = []; } private Article() : this(null!) { } @@ -107,5 +108,15 @@ public void Remove() { Status = ArticleStatus.Deleted; } + + public void Like(Like like) + { + var item = _likes.FirstOrDefault(x => x == like); + + if (item is null) + { + _likes.Add(like); + } + } } diff --git a/src/Blogger.Domain/ArticleAggregate/IArticleRepository.cs b/src/Blogger.Domain/ArticleAggregate/IArticleRepository.cs index 51a1f3d..87378d9 100644 --- a/src/Blogger.Domain/ArticleAggregate/IArticleRepository.cs +++ b/src/Blogger.Domain/ArticleAggregate/IArticleRepository.cs @@ -5,11 +5,17 @@ namespace Blogger.Domain.ArticleAggregate; public interface IArticleRepository { Task HasIdAsync(ArticleId articleId, CancellationToken cancellationToken); + void Add(Article article); + Task> GetArchivesAsync(CancellationToken cancellationToken); + Task GetArticleByIdAsync(ArticleId articleId, CancellationToken cancellationToken); + Task> GetLatestArticlesAsync(int pageNumber, int pageSize, CancellationToken cancellationToken); + Task> GetPopularArticlesAsync(int size, CancellationToken cancellationToken); + Task> GetPopularTagsAsync(int size,CancellationToken cancellationToken); Task> GetTagsAsync(CancellationToken cancellationToken); Task SaveChangesAsync(CancellationToken cancellationToken); @@ -17,5 +23,5 @@ public interface IArticleRepository Task GetDraftByIdAsync(ArticleId draftId, CancellationToken cancellationToken); Task> GetLatestArticlesAsync(Tag tag, CancellationToken cancellationToken); - Task> GetPopularArticlesAsync(int size, CancellationToken cancellationToken); + } diff --git a/src/Blogger.Infrastructure/Persistence/Repositories/ArticleRepository.cs b/src/Blogger.Infrastructure/Persistence/Repositories/ArticleRepository.cs index 845d200..fa5d6ee 100644 --- a/src/Blogger.Infrastructure/Persistence/Repositories/ArticleRepository.cs +++ b/src/Blogger.Infrastructure/Persistence/Repositories/ArticleRepository.cs @@ -45,7 +45,19 @@ public async Task> GetLatestArticlesAsync(int pageN return [.. articles]; } - + + public async Task> GetPopularArticlesAsync(int size, CancellationToken cancellationToken) + { + var articles = await bloggerDbContext.Articles.Where(x => x.Status == ArticleStatus.Published) + .OrderByDescending(x => (x.Likes.Count() + x.CommentIds.Count())) + .Take(size) + .ToListAsync(cancellationToken); + + return [.. articles]; + } + + + public async Task> GetPopularTagsAsync(int size, CancellationToken cancellationToken) { var topSizeTags = bloggerDbContext.Articles @@ -87,15 +99,7 @@ public async Task> GetTagsAsync(CancellationToken cancellatio } - public async Task> GetPopularArticlesAsync(int size, CancellationToken cancellationToken) - { - var que = await bloggerDbContext.Articles.Where(x => x.Status == ArticleStatus.Published) - .OrderByDescending(x => x.CommentIds.Count) - .Take(size) - .ToListAsync(cancellationToken); - return que.ToImmutableList(); - } public async Task> GetLatestArticlesAsync(Tag tag, CancellationToken cancellationToken) { diff --git a/tests/Blogger.IntegrationTests/Articles/GetPopularArticlesHandlerTests.cs b/tests/Blogger.IntegrationTests/Articles/GetPopularArticlesHandlerTests.cs new file mode 100644 index 0000000..70f4670 --- /dev/null +++ b/tests/Blogger.IntegrationTests/Articles/GetPopularArticlesHandlerTests.cs @@ -0,0 +1,90 @@ +using Blogger.Application.Articles.GetPopularArticles; +using Blogger.Domain.ArticleAggregate; +using Blogger.Infrastructure.Persistence.Repositories; +using Blogger.IntegrationTests.Fixtures; + +using FluentAssertions; + +namespace Blogger.IntegrationTests.Articles; +public class GetPopularArticlesHandlerTests : IClassFixture +{ + private readonly BloggerDbContextFixture _fixture; + + public GetPopularArticlesHandlerTests(BloggerDbContextFixture fixture) + { + _fixture = fixture; + } + + [Fact] + public async Task Handle_ShouldReturnPopularArticles_WhenArticlesExist() + { + // Arrange + var articleRepository = new ArticleRepository(_fixture.BuildDbContext(Guid.NewGuid().ToString())); + var _sut = new GetPopularArticlesHandler(articleRepository); + + var article_1 = Article.CreateArticle("Title 1", "Test Body", "Test Summary", [Tag.Create("tag1"), Tag.Create("tag2")]); + var article_2 = Article.CreateArticle("Title 2", "Test Body", "Test Summary", [Tag.Create("tag1"), Tag.Create("tag2")]); + var article_3 = Article.CreateArticle("Title 3", "Test Body", "Test Summary", [Tag.Create("tag1"), Tag.Create("tag2")]); + + var like_1 = Like.Create("127.0.0.1", DateTime.UtcNow); + var like_2 = Like.Create("127.0.0.2", DateTime.UtcNow); + var like_3 = Like.Create("127.0.0.3", DateTime.UtcNow); + var like_4 = Like.Create("127.0.0.4", DateTime.UtcNow); + var like_5 = Like.Create("127.0.0.1", DateTime.UtcNow); + var like_6 = Like.Create("127.0.0.2", DateTime.UtcNow); + var like_7 = Like.Create("127.0.0.3", DateTime.UtcNow); + var like_8 = Like.Create("127.0.0.4", DateTime.UtcNow); + var like_9 = Like.Create("127.0.0.1", DateTime.UtcNow); + + article_1.Like(like_1); + article_1.Like(like_2); + articleRepository.Add(article_1); + + article_2.Like(like_3); + article_2.Like(like_4); + article_2.Like(like_5); + articleRepository.Add(article_2); + + article_3.Like(like_6); + article_3.Like(like_7); + article_3.Like(like_8); + article_3.Like(like_9); + articleRepository.Add(article_3); + await articleRepository.SaveChangesAsync(CancellationToken.None); + + var request = new GetPopularArticlesQuery(2); + + // Act + var response = await _sut.Handle(request, CancellationToken.None); + + // Assert + response.Should().NotBeNull(); + response.Should().HaveCount(2); + + var firstArticleResponse = response.First(); + firstArticleResponse.ArticleId.Should().Be(article_3.Id); + + var secondArticleResponse = response.Last(); + secondArticleResponse.ArticleId.Should().Be(article_2.Id); + } + + + [Fact] + public async Task Handle_ShouldReturnEmpty_WhenNoArticlesExist() + { + // Arrange + var articleRepository = new ArticleRepository(_fixture.BuildDbContext(Guid.NewGuid().ToString())); + var _sut = new GetPopularArticlesHandler(articleRepository); + + var request = new GetPopularArticlesQuery(2); + + // Act + var response = await _sut.Handle(request, CancellationToken.None); + + // Assert + response.Should().NotBeNull(); + response.Should().BeEmpty(); + } + + +}