mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2026-11-13 15:28:40 +00:00
115 lines
4.3 KiB
C#
115 lines
4.3 KiB
C#
using AIStudio.Tests.Models.Generation;
|
|
|
|
using Microsoft.CodeAnalysis;
|
|
|
|
using SourceCodeRules.UsageAnalyzers;
|
|
|
|
namespace AIStudio.Tests.Analyzers;
|
|
|
|
/// <summary>
|
|
/// Checks that the app takes its icons only from the catalog AppIcons.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// AppIcons names every icon after its meaning and decides there which Lucide icon stands for it. MWAIS0017 refuses
|
|
/// an icon of LucideIcons or of MudBlazor anywhere else while compiling, so no component picks an icon on its own.
|
|
/// </remarks>
|
|
[TestFixture]
|
|
public sealed class IconCatalogAnalyzerTests
|
|
{
|
|
[TestCase("public string Icon => LucideIcons.HOUSE;", "AIStudio.Tools.LucideIcons.HOUSE", TestName = "A Lucide icon")]
|
|
[TestCase("public string Icon => MudBlazor.Icons.Material.Filled.Home;", "MudBlazor.Icons.Material.Filled.Home", TestName = "A Material icon of MudBlazor")]
|
|
[TestCase("public string Icon => Icons.Material.Outlined.Home;", "MudBlazor.Icons.Material.Outlined.Home", TestName = "A Material icon of MudBlazor through its using")]
|
|
[TestCase("public string Icon => Icons.Custom.Brands.GitHub;", "MudBlazor.Icons.Custom.Brands.GitHub", TestName = "A brand logo of MudBlazor")]
|
|
[TestCase("public int Rank(string icon) => icon switch { LucideIcons.HOUSE => 1, _ => 0 };", "AIStudio.Tools.LucideIcons.HOUSE", TestName = "A Lucide icon in a pattern")]
|
|
[TestCase("private const string ICON = LucideIcons.HOUSE;", "AIStudio.Tools.LucideIcons.HOUSE", TestName = "A Lucide icon in a constant of another class")]
|
|
public async Task AnIconOutsideTheCatalogIsRefused(string member, string icon)
|
|
{
|
|
var reported = await AnalyzeAsync(member);
|
|
|
|
using (Assert.EnterMultipleScope())
|
|
{
|
|
Assert.That(reported, Has.Count.EqualTo(1));
|
|
Assert.That(reported.FirstOrDefault()?.Id, Is.EqualTo("MWAIS0017"));
|
|
Assert.That(reported.FirstOrDefault()?.GetMessage(), Does.Contain($"'{icon}'"));
|
|
}
|
|
}
|
|
|
|
[TestCase("public string Icon => AppIcons.DELETE;", TestName = "A constant of the catalog")]
|
|
[TestCase("public bool Find(out string icon) => LucideIconRegistry.TryGet(\"house\", out icon);", TestName = "The registry plugins name their icons with")]
|
|
[TestCase("public string Icon => \"lucide/x\";", TestName = "A plain string")]
|
|
public async Task EverythingElseIsAllowed(string member)
|
|
{
|
|
var reported = await AnalyzeAsync(member);
|
|
|
|
Assert.That(reported, Is.Empty);
|
|
}
|
|
|
|
[Test]
|
|
public async Task TheCatalogMayUseBothIconSets()
|
|
{
|
|
//
|
|
// The snippet declares its own AppIcons where the analyzer looks for it. It takes the place of the one
|
|
// of the app, which the compilation references as well:
|
|
//
|
|
const string SOURCE =
|
|
"""
|
|
namespace AIStudio.Tools;
|
|
|
|
public static class AppIcons
|
|
{
|
|
public const string HOME = LucideIcons.HOUSE;
|
|
|
|
public const string GITHUB = MudBlazor.Icons.Custom.Brands.GitHub;
|
|
|
|
public static class Steps
|
|
{
|
|
public const string FIRST = MudBlazor.Icons.Material.Filled.LooksOne;
|
|
}
|
|
}
|
|
""";
|
|
|
|
var reported = await CompilationHarness.AnalyzeAsync(SOURCE, new IconCatalogAnalyzer());
|
|
|
|
Assert.That(reported, Is.Empty);
|
|
}
|
|
|
|
[Test]
|
|
public async Task GeneratedCodeIsCheckedAsWell()
|
|
{
|
|
//
|
|
// The Razor compiler turns the markup of a component into generated code, where most icons are set:
|
|
//
|
|
const string SOURCE =
|
|
"""
|
|
// <auto-generated/>
|
|
namespace Sample;
|
|
|
|
public sealed class Component
|
|
{
|
|
public string Icon => AIStudio.Tools.LucideIcons.HOUSE;
|
|
}
|
|
""";
|
|
|
|
var reported = await CompilationHarness.AnalyzeAsync(SOURCE, new IconCatalogAnalyzer());
|
|
|
|
Assert.That(reported, Has.Count.EqualTo(1));
|
|
}
|
|
|
|
private static async Task<IReadOnlyList<Diagnostic>> AnalyzeAsync(string member)
|
|
{
|
|
var source =
|
|
$$"""
|
|
using AIStudio.Tools;
|
|
using MudBlazor;
|
|
|
|
namespace Sample;
|
|
|
|
public sealed class Component
|
|
{
|
|
{{member}}
|
|
}
|
|
""";
|
|
|
|
return await CompilationHarness.AnalyzeAsync(source, new IconCatalogAnalyzer());
|
|
}
|
|
} |