< Summary

Information
Class: Chronicis.Client.Services.ArticleApiService
Assembly: Chronicis.Client
File(s): /home/runner/work/chronicis/chronicis/src/Chronicis.Client/Services/ArticleApiService.cs
Line coverage
0%
Covered lines: 0
Uncovered lines: 84
Coverable lines: 84
Total lines: 147
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 16
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%210%
GetRootArticlesAsync()0%620%
GetAllArticlesAsync()0%620%
GetChildrenAsync()100%210%
GetArticleDetailAsync()100%210%
GetArticleAsync()100%210%
GetArticleByPathAsync()100%210%
CreateArticleAsync()100%210%
UpdateArticleAsync()100%210%
DeleteArticleAsync()100%210%
MoveArticleAsync()100%210%
SearchArticlesAsync()0%2040%
SearchArticlesByTitleAsync()0%4260%
UpdateAliasesAsync()0%620%

File(s)

/home/runner/work/chronicis/chronicis/src/Chronicis.Client/Services/ArticleApiService.cs

#LineLine coverage
 1using Chronicis.Shared.DTOs;
 2
 3namespace Chronicis.Client.Services;
 4
 5/// <summary>
 6/// Service for communicating with the Article API.
 7/// Uses HttpClientExtensions for consistent error handling and logging.
 8/// </summary>
 9public class ArticleApiService : IArticleApiService
 10{
 11    private readonly HttpClient _http;
 12    private readonly ILogger<ArticleApiService> _logger;
 13
 014    public ArticleApiService(HttpClient http, ILogger<ArticleApiService> logger)
 15    {
 016        _http = http;
 017        _logger = logger;
 018    }
 19
 20    public async Task<List<ArticleTreeDto>> GetRootArticlesAsync(Guid? worldId = null)
 21    {
 022        var url = worldId.HasValue
 023            ? $"articles?worldId={worldId.Value}"
 024            : "articles";
 25
 026        return await _http.GetListAsync<ArticleTreeDto>(url, _logger, "root articles");
 027    }
 28
 29    public async Task<List<ArticleTreeDto>> GetAllArticlesAsync(Guid? worldId = null)
 30    {
 031        var url = worldId.HasValue
 032            ? $"articles/all?worldId={worldId.Value}"
 033            : "articles/all";
 34
 035        return await _http.GetListAsync<ArticleTreeDto>(url, _logger, "all articles");
 036    }
 37
 38    public async Task<List<ArticleTreeDto>> GetChildrenAsync(Guid parentId)
 39    {
 040        return await _http.GetListAsync<ArticleTreeDto>(
 041            $"articles/{parentId}/children",
 042            _logger,
 043            $"children for article {parentId}");
 044    }
 45
 46    public async Task<ArticleDto?> GetArticleDetailAsync(Guid id)
 47    {
 048        return await _http.GetEntityAsync<ArticleDto>(
 049            $"articles/{id}",
 050            _logger,
 051            $"article {id}");
 052    }
 53
 054    public async Task<ArticleDto?> GetArticleAsync(Guid id) => await GetArticleDetailAsync(id);
 55
 56    public async Task<ArticleDto?> GetArticleByPathAsync(string path)
 57    {
 058        var encodedPath = string.Join("/", path.Split('/').Select(Uri.EscapeDataString));
 59
 060        return await _http.GetEntityAsync<ArticleDto>(
 061            $"articles/by-path/{encodedPath}",
 062            _logger,
 063            $"article at path '{path}'");
 064    }
 65
 66    public async Task<ArticleDto?> CreateArticleAsync(ArticleCreateDto dto)
 67    {
 068        return await _http.PostEntityAsync<ArticleDto>(
 069            "articles",
 070            dto,
 071            _logger,
 072            "article");
 073    }
 74
 75    public async Task<ArticleDto?> UpdateArticleAsync(Guid id, ArticleUpdateDto dto)
 76    {
 077        return await _http.PutEntityAsync<ArticleDto>(
 078            $"articles/{id}",
 079            dto,
 080            _logger,
 081            $"article {id}");
 082    }
 83
 84    public async Task<bool> DeleteArticleAsync(Guid id)
 85    {
 086        return await _http.DeleteEntityAsync(
 087            $"articles/{id}",
 088            _logger,
 089            $"article {id}");
 090    }
 91
 92    public async Task<bool> MoveArticleAsync(Guid articleId, Guid? newParentId)
 93    {
 094        var moveDto = new ArticleMoveDto { NewParentId = newParentId };
 95
 096        return await _http.PutBoolAsync(
 097            $"articles/{articleId}/move",
 098            moveDto,
 099            _logger,
 0100            $"move article {articleId}");
 0101    }
 102
 103    public async Task<List<ArticleSearchResultDto>> SearchArticlesAsync(string query)
 104    {
 0105        if (string.IsNullOrWhiteSpace(query))
 0106            return new List<ArticleSearchResultDto>();
 107
 0108        var results = await _http.GetEntityAsync<GlobalSearchResultsDto>(
 0109            $"articles/search?query={Uri.EscapeDataString(query)}",
 0110            _logger,
 0111            $"search results for '{query}'");
 112
 0113        if (results == null)
 0114            return new List<ArticleSearchResultDto>();
 115
 116        // Combine all match types into a single list
 0117        var allResults = new List<ArticleSearchResultDto>();
 0118        allResults.AddRange(results.TitleMatches);
 0119        allResults.AddRange(results.BodyMatches);
 0120        allResults.AddRange(results.HashtagMatches);
 0121        return allResults;
 0122    }
 123
 124    public async Task<List<ArticleSearchResultDto>> SearchArticlesByTitleAsync(string query)
 125    {
 0126        if (string.IsNullOrWhiteSpace(query))
 0127            return new List<ArticleSearchResultDto>();
 128
 0129        var results = await _http.GetEntityAsync<GlobalSearchResultsDto>(
 0130            $"articles/search?query={Uri.EscapeDataString(query)}",
 0131            _logger,
 0132            $"title search results for '{query}'");
 133
 0134        return results?.TitleMatches ?? new List<ArticleSearchResultDto>();
 0135    }
 136
 137    public async Task<ArticleDto?> UpdateAliasesAsync(Guid articleId, string aliases)
 138    {
 0139        var dto = new ArticleAliasesUpdateDto { Aliases = aliases ?? string.Empty };
 140
 0141        return await _http.PutEntityAsync<ArticleDto>(
 0142            $"articles/{articleId}/aliases",
 0143            dto,
 0144            _logger,
 0145            $"aliases for article {articleId}");
 0146    }
 147}