File: ComponentsActivitySourceTest.cs
Web Access
Project: src\src\Components\Components\test\Microsoft.AspNetCore.Components.Tests.csproj (Microsoft.AspNetCore.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 System.Diagnostics;
 
namespace Microsoft.AspNetCore.Components;
 
public class ComponentsActivitySourceTest
{
    private readonly ActivityListener _listener;
    private readonly List<Activity> _activities;
 
    public ComponentsActivitySourceTest()
    {
        _activities = new List<Activity>();
        _listener = new ActivityListener
        {
            ShouldListenTo = source => source.Name == ComponentsActivitySource.Name,
            Sample = (ref ActivityCreationOptions<ActivityContext> options) => ActivitySamplingResult.AllData,
            ActivityStarted = activity => _activities.Add(activity),
            ActivityStopped = activity => { }
        };
        ActivitySource.AddActivityListener(_listener);
    }
 
    [Fact]
    public void Constructor_CreatesActivitySourceCorrectly()
    {
        // Arrange & Act
        var componentsActivitySource = new ComponentsActivitySource();
 
        // Assert
        Assert.NotNull(componentsActivitySource);
    }
 
    [Fact]
    public void CaptureHttpContext_ReturnsDefault_WhenNoCurrentActivity()
    {
        // Arrange
        Activity.Current = null;
 
        // Act
        var result = ComponentsActivitySource.CaptureHttpContext();
 
        // Assert
        Assert.Equal(default, result);
    }
 
    [Fact]
    public void CaptureHttpContext_ReturnsDefault_WhenActivityHasWrongName()
    {
        // Arrange
        using var activity = new ActivitySource("Test").StartActivity("WrongName");
        Activity.Current = activity;
 
        // Act
        var result = ComponentsActivitySource.CaptureHttpContext();
 
        // Assert
        Assert.Equal(default, result);
    }
 
    [Fact]
    public void StartCircuitActivity_CreatesAndStartsActivity()
    {
        // Arrange
        var componentsActivitySource = new ComponentsActivitySource();
        var circuitId = "test-circuit-id";
        var httpContext = new ActivityContext(ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom(), ActivityTraceFlags.Recorded);
 
        // Act
        var activity = componentsActivitySource.StartCircuitActivity(circuitId, httpContext);
 
        // Assert
        Assert.NotNull(activity);
        Assert.Equal(ComponentsActivitySource.OnCircuitName, activity.OperationName);
        Assert.Equal($"Circuit {circuitId}", activity.DisplayName);
        Assert.Equal(ActivityKind.Internal, activity.Kind);
        Assert.True(activity.IsAllDataRequested);
        Assert.Equal(circuitId, activity.GetTagItem("aspnetcore.components.circuit.id"));
        Assert.Contains(activity.Links, link => link.Context == httpContext);
        Assert.False(activity.IsStopped);
    }
 
    [Fact]
    public void FailCircuitActivity_SetsErrorStatusAndStopsActivity()
    {
        // Arrange
        var componentsActivitySource = new ComponentsActivitySource();
        var circuitId = "test-circuit-id";
        var httpContext = default(ActivityContext);
        var activity = componentsActivitySource.StartCircuitActivity(circuitId, httpContext);
        var exception = new InvalidOperationException("Test exception");
 
        // Act
        componentsActivitySource.FailCircuitActivity(activity, exception);
 
        // Assert
        Assert.True(activity!.IsStopped);
        Assert.Equal(ActivityStatusCode.Error, activity.Status);
        Assert.Equal(exception.GetType().FullName, activity.GetTagItem("error.type"));
    }
 
    [Fact]
    public void StartRouteActivity_CreatesAndStartsActivity()
    {
        // Arrange
        var componentsActivitySource = new ComponentsActivitySource();
        var componentType = "TestComponent";
        var route = "/test-route";
 
        // First set up a circuit context
        componentsActivitySource.StartCircuitActivity("test-circuit-id", default);
 
        // Act
        var activity = componentsActivitySource.StartRouteActivity(componentType, route);
 
        // Assert
        Assert.NotNull(activity);
        Assert.Equal(ComponentsActivitySource.OnRouteName, activity.OperationName);
        Assert.Equal($"Route {route} -> {componentType}", activity.DisplayName);
        Assert.Equal(ActivityKind.Internal, activity.Kind);
        Assert.True(activity.IsAllDataRequested);
        Assert.Equal(componentType, activity.GetTagItem("aspnetcore.components.type"));
        Assert.Equal(route, activity.GetTagItem("aspnetcore.components.route"));
        Assert.Equal("test-circuit-id", activity.GetTagItem("aspnetcore.components.circuit.id"));
        Assert.False(activity.IsStopped);
    }
 
    [Fact]
    public void StartEventActivity_CreatesAndStartsActivity()
    {
        // Arrange
        var componentsActivitySource = new ComponentsActivitySource();
        var componentType = "TestComponent";
        var methodName = "OnClick";
        var attributeName = "onclick";
 
        // First set up a circuit and route context
        componentsActivitySource.StartCircuitActivity("test-circuit-id", default);
        componentsActivitySource.StartRouteActivity("ParentComponent", "/parent");
 
        // Act
        var activity = componentsActivitySource.StartEventActivity(componentType, methodName, attributeName);
 
        // Assert
        Assert.NotNull(activity);
        Assert.Equal(ComponentsActivitySource.OnEventName, activity.OperationName);
        Assert.Equal($"Event {attributeName} -> {componentType}.{methodName}", activity.DisplayName);
        Assert.Equal(ActivityKind.Internal, activity.Kind);
        Assert.True(activity.IsAllDataRequested);
        Assert.Equal(componentType, activity.GetTagItem("aspnetcore.components.type"));
        Assert.Equal(methodName, activity.GetTagItem("aspnetcore.components.method"));
        Assert.Equal(attributeName, activity.GetTagItem("aspnetcore.components.attribute.name"));
        Assert.Equal("test-circuit-id", activity.GetTagItem("aspnetcore.components.circuit.id"));
        Assert.False(activity.IsStopped);
    }
 
    [Fact]
    public void FailEventActivity_SetsErrorStatusAndStopsActivity()
    {
        // Arrange
        var componentsActivitySource = new ComponentsActivitySource();
        var activity = componentsActivitySource.StartEventActivity("TestComponent", "OnClick", "onclick");
        var exception = new InvalidOperationException("Test exception");
 
        // Act
        ComponentsActivitySource.FailEventActivity(activity, exception);
 
        // Assert
        Assert.True(activity!.IsStopped);
        Assert.Equal(ActivityStatusCode.Error, activity.Status);
        Assert.Equal(exception.GetType().FullName, activity.GetTagItem("error.type"));
    }
 
    [Fact]
    public async Task CaptureEventStopAsync_StopsActivityOnSuccessfulTask()
    {
        // Arrange
        var componentsActivitySource = new ComponentsActivitySource();
        var activity = componentsActivitySource.StartEventActivity("TestComponent", "OnClick", "onclick");
        var task = Task.CompletedTask;
 
        // Act
        await ComponentsActivitySource.CaptureEventStopAsync(task, activity);
 
        // Assert
        Assert.True(activity!.IsStopped);
        Assert.Equal(ActivityStatusCode.Unset, activity.Status);
    }
 
    [Fact]
    public async Task CaptureEventStopAsync_FailsActivityOnException()
    {
        // Arrange
        var componentsActivitySource = new ComponentsActivitySource();
        var activity = componentsActivitySource.StartEventActivity("TestComponent", "OnClick", "onclick");
        var exception = new InvalidOperationException("Test exception");
        var task = Task.FromException(exception);
 
        // Act
        await ComponentsActivitySource.CaptureEventStopAsync(task, activity);
 
        // Assert
        Assert.True(activity!.IsStopped);
        Assert.Equal(ActivityStatusCode.Error, activity.Status);
        Assert.Equal(exception.GetType().FullName, activity.GetTagItem("error.type"));
    }
 
    [Fact]
    public void StartCircuitActivity_HandlesNullValues()
    {
        // Arrange
        var componentsActivitySource = new ComponentsActivitySource();
 
        // Act
        var activity = componentsActivitySource.StartCircuitActivity(null, default);
 
        // Assert
        Assert.NotNull(activity);
        Assert.Equal("Circuit ", activity.DisplayName);
    }
 
    [Fact]
    public void StartRouteActivity_HandlesNullValues()
    {
        // Arrange
        var componentsActivitySource = new ComponentsActivitySource();
 
        // Act
        var activity = componentsActivitySource.StartRouteActivity(null, null);
 
        // Assert
        Assert.NotNull(activity);
        Assert.Equal("Route [unknown path] -> [unknown component]", activity.DisplayName);
    }
 
    [Fact]
    public void StartEventActivity_HandlesNullValues()
    {
        // Arrange
        var componentsActivitySource = new ComponentsActivitySource();
 
        // Act
        var activity = componentsActivitySource.StartEventActivity(null, null, null);
 
        // Assert
        Assert.NotNull(activity);
        Assert.Equal("Event [unknown attribute] -> [unknown component].[unknown method]", activity.DisplayName);
    }
}