< Summary

Information
Class: Chronicis.Api.Services.ValidationResult
Assembly: Chronicis.Api
File(s): /home/runner/work/chronicis/chronicis/src/Chronicis.Api/Services/ArticleValidationService.cs
Line coverage
100%
Covered lines: 8
Uncovered lines: 0
Coverable lines: 8
Total lines: 100
Line coverage: 100%
Branch coverage
100%
Covered branches: 6
Total branches: 6
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor()100%11100%
get_IsValid()100%11100%
get_Errors()100%11100%
AddError(...)100%22100%
GetFirstError()100%44100%

File(s)

/home/runner/work/chronicis/chronicis/src/Chronicis.Api/Services/ArticleValidationService.cs

#LineLine coverage
 1using Chronicis.Api.Data;
 2using Chronicis.Shared.DTOs;
 3using Microsoft.EntityFrameworkCore;
 4
 5namespace Chronicis.Api.Services;
 6
 7public class ArticleValidationService : IArticleValidationService
 8{
 9    private readonly ChronicisDbContext _context;
 10
 11    public ArticleValidationService(ChronicisDbContext context)
 12    {
 13        _context = context;
 14    }
 15
 16    public async Task<ValidationResult> ValidateCreateAsync(ArticleCreateDto dto)
 17    {
 18        var result = new ValidationResult();
 19
 20        // Parent must exist if specified
 21        if (dto.ParentId.HasValue)
 22        {
 23            var parentExists = await _context.Articles
 24                .AnyAsync(a => a.Id == dto.ParentId.Value);
 25
 26            if (!parentExists)
 27            {
 28                result.AddError("ParentId", "Parent article does not exist");
 29            }
 30        }
 31
 32        return result;
 33    }
 34
 35    public async Task<ValidationResult> ValidateUpdateAsync(Guid articleId, ArticleUpdateDto dto)
 36    {
 37        var result = new ValidationResult();
 38
 39        // Article must exist
 40        var articleExists = await _context.Articles
 41            .AnyAsync(a => a.Id == articleId);
 42
 43        if (!articleExists)
 44        {
 45            result.AddError("Id", "Article not found");
 46        }
 47
 48        // Title is required
 49        if (string.IsNullOrWhiteSpace(dto.Title))
 50        {
 51            result.AddError("Title", "Title is required");
 52        }
 53
 54        return result;
 55    }
 56
 57    public async Task<ValidationResult> ValidateDeleteAsync(Guid articleId)
 58    {
 59        var result = new ValidationResult();
 60
 61        // Article must exist
 62        var article = await _context.Articles
 63            .Include(a => a.Children)
 64            .FirstOrDefaultAsync(a => a.Id == articleId);
 65
 66        if (article == null)
 67        {
 68            result.AddError("Id", "Article not found");
 69            return result;
 70        }
 71
 72        return result;
 73    }
 74}
 75
 76/// <summary>
 77/// Represents the result of a validation operation.
 78/// </summary>
 79public class ValidationResult
 80{
 1681    private readonly Dictionary<string, List<string>> _errors = new();
 82
 1483    public bool IsValid => _errors.Count == 0;
 84
 1685    public IReadOnlyDictionary<string, List<string>> Errors => _errors;
 86
 87    public void AddError(string field, string message)
 88    {
 1289        if (!_errors.ContainsKey(field))
 90        {
 1191            _errors[field] = new List<string>();
 92        }
 1293        _errors[field].Add(message);
 1294    }
 95
 96    public string GetFirstError()
 97    {
 298        return _errors.Values.FirstOrDefault()?.FirstOrDefault() ?? "Validation failed";
 99    }
 100}