File: Commands\SettingsSchemaBuilderTests.cs
Web Access
Project: src\tests\Aspire.Cli.Tests\Aspire.Cli.Tests.csproj (Aspire.Cli.Tests)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using Aspire.Cli.Commands;
using Aspire.Cli.Configuration;
using Aspire.Cli.Documentation.ApiDocs;
using Aspire.Cli.Documentation.Docs;
 
namespace Aspire.Cli.Tests.Commands;
 
public class SettingsSchemaBuilderTests
{
    [Theory]
    [InlineData(false)]
    [InlineData(true)]
    public void BuildSchema_DescribesSourceNameConstraints(bool global)
    {
        foreach (var schema in new[]
        {
            SettingsSchemaBuilder.BuildSchema(excludeLocalOnly: global),
            SettingsSchemaBuilder.BuildConfigFileSchema(excludeLocalOnly: global)
        })
        {
            foreach (var source in schema.Properties.Where(property =>
                property.Name is "integrationSources" or "skillSources" or "templateSources"))
            {
                Assert.EndsWith(SourceNameValidator.Description, source.Description, StringComparison.Ordinal);
            }
        }
    }
 
    [Theory]
    [InlineData(false)]
    [InlineData(true)]
    public void BuildConfigFileSchema_IncludesOptionalTemplateSourceDisplayName(bool global)
    {
        var schema = SettingsSchemaBuilder.BuildConfigFileSchema(excludeLocalOnly: global);
        var sources = Assert.Single(schema.Properties, property => property.Name == "templateSources");
        var displayName = Assert.Single(sources.SubProperties!, property => property.Name == "displayName");
 
        Assert.Equal("string", displayName.Type);
        Assert.False(displayName.Required);
        Assert.Contains("alias", displayName.Description, StringComparison.Ordinal);
    }
 
    [Fact]
    public void BuildConfigFileSchema_HonorsConditionalJsonIgnore()
    {
        var schema = SettingsSchemaBuilder.BuildConfigFileSchema(excludeLocalOnly: false);
 
        Assert.Equal(
            ["appHost", "certificates", "channel", "configSource", "containerTunnel", "docs", "features",
                "integrationSources", "packages", "portAllocation", "profiles", "sdk", "skillSources", "templateSources"],
            schema.Properties.Select(property => property.Name));
        var configSource = Assert.Single(schema.Properties, property => property.Name == "configSource");
        Assert.NotNull(configSource.SubProperties);
        Assert.Equal(
            ["optOut", "repository", "path", "ref", "appliedVersion"],
            configSource.SubProperties.Select(property => property.Name));
        var optOut = Assert.Single(configSource.SubProperties, property => property.Name == "optOut");
        Assert.Equal("boolean", optOut.Type);
        Assert.False(optOut.Required);
    }
 
    [Theory]
    [InlineData(false)]
    [InlineData(true)]
    public void BuildSchema_IncludesNamedIntegrationSources(bool global)
    {
        foreach (var schema in new[]
        {
            SettingsSchemaBuilder.BuildSchema(excludeLocalOnly: global),
            SettingsSchemaBuilder.BuildConfigFileSchema(excludeLocalOnly: global)
        })
        {
            var sources = Assert.Single(schema.Properties, property => property.Name == "integrationSources");
            Assert.Equal("object", sources.AdditionalPropertiesType);
            Assert.Equal(["enabled", "source", "patterns"], sources.SubProperties!.Select(property => property.Name));
        }
    }
 
    [Theory]
    [InlineData(false)]
    [InlineData(true)]
    public void BuildSchema_IncludesNamedSkillSources(bool global)
    {
        foreach (var schema in new[]
        {
            SettingsSchemaBuilder.BuildSchema(excludeLocalOnly: global),
            SettingsSchemaBuilder.BuildConfigFileSchema(excludeLocalOnly: global)
        })
        {
            var skillSources = Assert.Single(schema.Properties, property => property.Name == "skillSources");
            Assert.Equal("object", skillSources.AdditionalPropertiesType);
            Assert.Equal(
                ["enabled", "repository", "marketplace", "plugins", "ref", "openCodeV1Catalog", "openCodeV2Catalog"],
                skillSources.SubProperties!.Select(property => property.Name));
            Assert.Equal("array", Assert.Single(skillSources.SubProperties!, property => property.Name == "plugins").Type);
        }
    }
 
    [Fact]
    public void BuildSchema_DoesNotIncludeDocsSourceProperties()
    {
        var schema = SettingsSchemaBuilder.BuildSchema(excludeLocalOnly: false);
 
        Assert.DoesNotContain(schema.Properties, static property => property.Name == "docs");
    }
 
    [Fact]
    public void BuildConfigFileSchema_IncludesDocsSourcePropertiesWithDefaults()
    {
        var schema = SettingsSchemaBuilder.BuildConfigFileSchema(excludeLocalOnly: false);
 
        var docsProperty = Assert.Single(schema.Properties, static property => property.Name == "docs");
        Assert.NotNull(docsProperty.SubProperties);
        Assert.Contains("override", docsProperty.Description, StringComparison.OrdinalIgnoreCase);
 
        var llmsProperty = Assert.Single(docsProperty.SubProperties, static property => property.Name == "llmsTxtUrl");
        Assert.Equal("string", llmsProperty.Type);
        Assert.Contains(DocsSourceConfiguration.DefaultLlmsTxtUrl, llmsProperty.Description, StringComparison.Ordinal);
        Assert.Contains("override", llmsProperty.Description, StringComparison.OrdinalIgnoreCase);
 
        var apiProperty = Assert.Single(docsProperty.SubProperties, static property => property.Name == "api");
        Assert.NotNull(apiProperty.SubProperties);
        Assert.Contains("override", apiProperty.Description, StringComparison.OrdinalIgnoreCase);
 
        var sitemapProperty = Assert.Single(apiProperty.SubProperties, static property => property.Name == "sitemapUrl");
        Assert.Equal("string", sitemapProperty.Type);
        Assert.Contains(ApiDocsSourceConfiguration.DefaultSitemapUrl, sitemapProperty.Description, StringComparison.Ordinal);
        Assert.Contains("override", sitemapProperty.Description, StringComparison.OrdinalIgnoreCase);
    }
 
    [Fact]
    public void BuildSchema_DoesNotIncludeLegacyAppHostPath()
    {
        var schema = SettingsSchemaBuilder.BuildSchema(excludeLocalOnly: false);
 
        Assert.DoesNotContain(schema.Properties, static property => property.Name == "appHostPath");
    }
 
    [Fact]
    public void BuildConfigFileSchema_KeepsLocalAppHostPath()
    {
        var schema = SettingsSchemaBuilder.BuildConfigFileSchema(excludeLocalOnly: false);
 
        var appHostProperty = Assert.Single(schema.Properties, static property => property.Name == "appHost");
        Assert.NotNull(appHostProperty.SubProperties);
        Assert.Contains(appHostProperty.SubProperties, static property => property.Name == "path");
    }
}