feat(admin): stabilize blog and admin patterns
TaxBaik CI/CD / build-and-deploy (push) Has been cancelled

This commit is contained in:
2026-07-02 10:46:27 +09:00
parent b3cab87539
commit cb47349a25
67 changed files with 1354 additions and 486 deletions
+30 -3
View File
@@ -44,15 +44,34 @@ public class BlogServiceTests
Assert.Equal("같은-제목-2", post.Slug);
}
[Fact]
public async Task DeleteAsync_SoftDeletesPost_AndExcludesFromSlugLookup()
{
var repository = new FakeBlogPostRepository
{
Posts =
[
new BlogPost { Id = 1, Title = "삭제 대상", Content = "본문", Slug = "delete-me", IsPublished = true }
]
};
var service = new BlogService(repository, new MemoryCache(new MemoryCacheOptions()));
await service.DeleteAsync(1);
Assert.NotNull(repository.Posts.Single().DeletedAt);
Assert.Null(await service.GetBySlugAsync("delete-me"));
Assert.Null(await service.GetByIdAsync(1));
}
private sealed class FakeBlogPostRepository : IBlogPostRepository
{
public List<BlogPost> Posts { get; init; } = [];
public Task<BlogPost?> GetByIdAsync(int id, CancellationToken cancellationToken = default) =>
Task.FromResult(Posts.FirstOrDefault(x => x.Id == id));
Task.FromResult(Posts.FirstOrDefault(x => x.Id == id && x.DeletedAt == null));
public Task<BlogPost?> GetBySlugAsync(string slug, CancellationToken cancellationToken = default) =>
Task.FromResult(Posts.FirstOrDefault(x => x.Slug == slug && x.IsPublished));
Task.FromResult(Posts.FirstOrDefault(x => x.Slug == slug && x.IsPublished && x.DeletedAt == null));
public Task<(IEnumerable<BlogPost> Items, int Total)> GetPublishedPagedAsync(
int page, int pageSize, int? categoryId = null, CancellationToken cancellationToken = default)
@@ -83,7 +102,15 @@ public class BlogServiceTests
public Task UpdateAsync(BlogPost post, CancellationToken cancellationToken = default) => Task.CompletedTask;
public Task DeleteAsync(int id, CancellationToken cancellationToken = default) => Task.CompletedTask;
public Task DeleteAsync(int id, CancellationToken cancellationToken = default)
{
var post = Posts.FirstOrDefault(x => x.Id == id);
if (post != null)
post.DeletedAt = DateTime.UtcNow;
return Task.CompletedTask;
}
public Task ArchiveAsync(int id, CancellationToken cancellationToken = default) => DeleteAsync(id, cancellationToken);
public Task IncrementViewCountAsync(int id, CancellationToken cancellationToken = default) => Task.CompletedTask;
}