File: Controls\StableSectionContentTests.cs
Web Access
Project: src\tests\Aspire.Dashboard.Components.Tests\Aspire.Dashboard.Components.Tests.csproj (Aspire.Dashboard.Components.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.Components.Controls;
using Aspire.Dashboard.Components.Tests.Shared;
using Bunit;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Rendering;
using Microsoft.AspNetCore.Components.Sections;
using Xunit;
 
namespace Aspire.Dashboard.Components.Tests.Controls;
 
public class StableSectionContentTests : DashboardTestContext
{
    [Fact]
    public void Render_OwnerRerenders_KeepsContentInstancesAndShowsLatestContent()
    {
        var instances = new List<Probe>();
 
        var cut = Render<Owner>(builder => builder
            .Add(p => p.Instances, instances)
            .Add(p => p.Label, "first"));
 
        Assert.Single(instances);
        Assert.Equal("first", cut.Find(".probe").TextContent);
 
        cut.Render(parameters => parameters.Add(p => p.Label, "second"));
        cut.Render(parameters => parameters.Add(p => p.Label, "third"));
 
        // A plain SectionContent would have created a new probe for each render of the owner.
        Assert.Single(instances);
        Assert.Equal("third", cut.Find(".probe").TextContent);
    }
 
    private sealed class Owner : ComponentBase
    {
        [Parameter]
        public required List<Probe> Instances { get; set; }
 
        [Parameter]
        public string Label { get; set; } = string.Empty;
 
        protected override void BuildRenderTree(RenderTreeBuilder builder)
        {
            builder.OpenComponent<SectionOutlet>(0);
            builder.AddComponentParameter(1, nameof(SectionOutlet.SectionName), "test-section");
            builder.CloseComponent();
 
            builder.OpenComponent<StableSectionContent>(2);
            builder.AddComponentParameter(3, nameof(StableSectionContent.SectionName), "test-section");
            builder.AddComponentParameter(4, nameof(StableSectionContent.ChildContent), (RenderFragment)(content =>
            {
                content.OpenComponent<Probe>(0);
                content.AddComponentParameter(1, nameof(Probe.Instances), Instances);
                content.AddComponentParameter(2, nameof(Probe.Label), Label);
                content.CloseComponent();
            }));
            builder.CloseComponent();
        }
    }
 
    private sealed class Probe : ComponentBase
    {
        [Parameter]
        public required List<Probe> Instances { get; set; }
 
        [Parameter]
        public string Label { get; set; } = string.Empty;
 
        protected override void OnInitialized() => Instances.Add(this);
 
        protected override void BuildRenderTree(RenderTreeBuilder builder)
        {
            builder.OpenElement(0, "span");
            builder.AddAttribute(1, "class", "probe");
            builder.AddContent(2, Label);
            builder.CloseElement();
        }
    }
}