< Summary

Information
Class: Chronicis.Client.Services.PublicBreadcrumbBuilder
Assembly: Chronicis.Client
File(s): /home/runner/work/chronicis/chronicis/src/Chronicis.Client/Services/PublicBreadcrumbBuilder.cs
Line coverage
100%
Covered lines: 38
Uncovered lines: 0
Coverable lines: 38
Total lines: 94
Line coverage: 100%
Branch coverage
100%
Covered branches: 36
Total branches: 36
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.cctor()100%11100%
Build(...)100%66100%
ClassifyCrumb(...)100%88100%
IsVirtualGroup(...)100%22100%
IsVirtualEntity(...)100%66100%
BuildPathTo(...)100%22100%
IsRealArticle(...)100%1212100%

File(s)

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

#LineLine coverage
 1using System.Collections.Frozen;
 2using Chronicis.Shared.DTOs;
 3using MudBlazor;
 4
 5namespace Chronicis.Client.Services;
 6
 7/// <summary>
 8/// Builds MudBlazor BreadcrumbItems for public world pages from BreadcrumbDto data.
 9/// Pure data transformation — no API calls or UI state.
 10/// </summary>
 11public static class PublicBreadcrumbBuilder
 12{
 113    private static readonly FrozenSet<string> VirtualGroupSlugs =
 114        new HashSet<string>(StringComparer.OrdinalIgnoreCase)
 115        {
 116            "characters", "wiki", "campaigns", "uncategorized"
 117        }.ToFrozenSet(StringComparer.OrdinalIgnoreCase);
 18
 19    /// <summary>
 20    /// Converts article breadcrumb DTOs into MudBlazor BreadcrumbItems for public pages.
 21    /// </summary>
 22    public static List<BreadcrumbItem> Build(
 23        string publicSlug,
 24        ArticleDto article)
 25    {
 826        if (article.Breadcrumbs == null || !article.Breadcrumbs.Any())
 327            return new List<BreadcrumbItem>();
 28
 529        var items = new List<BreadcrumbItem>();
 30
 4231        foreach (var crumb in article.Breadcrumbs)
 32        {
 1633            items.Add(ClassifyCrumb(crumb, publicSlug, article));
 34        }
 35
 536        return items;
 37    }
 38
 39    internal static BreadcrumbItem ClassifyCrumb(
 40        BreadcrumbDto crumb,
 41        string publicSlug,
 42        ArticleDto article)
 43    {
 1644        if (crumb.IsWorld)
 545            return new BreadcrumbItem(crumb.Title, $"/w/{publicSlug}");
 46
 1147        if (IsVirtualGroup(crumb))
 148            return new BreadcrumbItem(crumb.Title, null, disabled: true);
 49
 1050        if (IsVirtualEntity(crumb, article))
 251            return new BreadcrumbItem(crumb.Title, null, disabled: true);
 52
 853        if (crumb.Id == article.Id)
 554            return new BreadcrumbItem(crumb.Title, null, disabled: true);
 55
 356        var path = BuildPathTo(crumb, article);
 357        return new BreadcrumbItem(crumb.Title, $"/w/{publicSlug}/{path}");
 58    }
 59
 60    internal static bool IsVirtualGroup(BreadcrumbDto crumb)
 61    {
 1862        return crumb.Id == Guid.Empty || VirtualGroupSlugs.Contains(crumb.Slug);
 63    }
 64
 65    internal static bool IsVirtualEntity(BreadcrumbDto crumb, ArticleDto article)
 66    {
 1367        return (article.CampaignId.HasValue && crumb.Id == article.CampaignId.Value)
 1368            || (article.ArcId.HasValue && crumb.Id == article.ArcId.Value);
 69    }
 70
 71    internal static string BuildPathTo(BreadcrumbDto target, ArticleDto article)
 72    {
 473        if (article.Breadcrumbs == null)
 174            return target.Slug;
 75
 376        var slugs = article.Breadcrumbs
 377            .Where(b => IsRealArticle(b, article))
 378            .TakeWhile(b => b.Id != target.Id)
 379            .Select(b => b.Slug)
 380            .ToList();
 81
 382        slugs.Add(target.Slug);
 383        return string.Join("/", slugs);
 84    }
 85
 86    private static bool IsRealArticle(BreadcrumbDto crumb, ArticleDto article)
 87    {
 988        return !crumb.IsWorld
 989            && crumb.Id != Guid.Empty
 990            && !VirtualGroupSlugs.Contains(crumb.Slug)
 991            && !(article.CampaignId.HasValue && crumb.Id == article.CampaignId.Value)
 992            && !(article.ArcId.HasValue && crumb.Id == article.ArcId.Value);
 93    }
 94}