File: ResourceTraitBuilderTests.cs
Web Access
Project: src\tests\Aspire.Hosting.Tests\Aspire.Hosting.Tests.csproj (Aspire.Hosting.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.Dashboard.Model;
using Aspire.Hosting.Utils;
 
namespace Aspire.Hosting.Tests;
 
[Trait("Partition", "2")]
public class ResourceTraitBuilderTests
{
    [Fact]
    public void RepeatedTraitsAndTagsPreserveAllValues()
    {
        using var builder = TestDistributedApplicationBuilder.Create();
        var resource = builder.AddContainer("api", "image")
            .WithTags("Backend", "API")
            .WithTrait("Owner", "Finance").WithTrait("Owner", "Platform")
            .WithDashboardPosition(20).WithDashboardPosition(-10);
 
        Assert.Equal(
            [
                (KnownResourceTraits.DashboardTag, "Backend"),
                (KnownResourceTraits.DashboardTag, "API"),
                ("Owner", "Finance"),
                ("Owner", "Platform"),
                (KnownResourceTraits.DashboardPosition, "-10")
            ],
            resource.Resource.Annotations.OfType<TraitAnnotation>().Select(t => (t.Name, t.Value)));
    }
 
    [Theory]
    [InlineData("", "value")]
    [InlineData("Owner", " ")]
    [InlineData("Aspire_Dashboard_Tag", "  Backend")]
    [InlineData("Aspire_Dashboard_Tag", "Back  end")]
    [InlineData("Aspire_Dashboard_Position", "invalid")]
    [InlineData("Aspire_Dashboard_Position", "2147483648")]
    public void InvalidTraitsAreRejected(string name, string value)
    {
        Assert.ThrowsAny<ArgumentException>(() => new TraitAnnotation(name, value));
    }
 
    [Fact]
    public void TraitsProduceListValuedSnapshotProperties()
    {
        using var builder = TestDistributedApplicationBuilder.Create();
        var resource = builder.AddContainer("api", "image")
            .WithTags("Backend", "API")
            .WithTrait("Owner", "Finance, Inc.").WithTrait("Owner", "Platform")
            .WithTrait("Owner", "Finance, Inc.");
        var source = new ResourcePropertySnapshot("existing", "value");
        var properties = ResourceTraitSnapshotProperties.AddTraitProperties(resource.Resource, [source]);
 
        Assert.Same(source, properties[0]);
        Assert.Equal(["existing", "resource.trait.Aspire_Dashboard_Tag", "resource.trait.Owner"], properties.Select(p => p.Name));
        Assert.Equal(["Backend", "API"], Assert.IsType<string[]>(properties[1].Value));
        Assert.Equal(["Finance, Inc.", "Platform"], Assert.IsType<string[]>(properties[2].Value));
        Assert.Equal("Owner", properties[2].DisplayName);
    }
 
    [Fact]
    public void PositionTraitReplacesOnlyPositionAndValidatesBeforeReplacing()
    {
        using var builder = TestDistributedApplicationBuilder.Create();
        var resource = builder.AddContainer("api", "image").WithTags("Backend").WithDashboardPosition(10);
        Assert.Throws<ArgumentException>(() => resource.WithTrait(KnownResourceTraits.DashboardPosition, "invalid"));
        resource.WithTrait(KnownResourceTraits.DashboardPosition, "20");
 
        Assert.Equal([(KnownResourceTraits.DashboardTag, "Backend"), (KnownResourceTraits.DashboardPosition, "20")],
            resource.Resource.Annotations.OfType<TraitAnnotation>().Select(t => (t.Name, t.Value)));
    }
 
    [Fact]
    public void WithTagsAcceptsSingleMultipleAndSpanArguments()
    {
        using var builder = TestDistributedApplicationBuilder.Create();
        var resource = builder.AddContainer("api", "image");
        ReadOnlySpan<string> tags = ["Finance", "Platform"];
 
        Assert.Same(resource, resource.WithTags("Backend"));
        Assert.Same(resource, resource.WithTags("API", "Service"));
        Assert.Same(resource, resource.WithTags(tags));
        Assert.Same(resource, resource.WithTags());
        Assert.Equal(["Backend", "API", "Service", "Finance", "Platform"],
            resource.Resource.Annotations.OfType<TraitAnnotation>().Select(t => t.Value));
    }
}