Files
Tommaso Stocchi 60af59ba8b .NET: Features/3768-devui-aspire-integration (#3771)
* adds devui integration and samples

* adds unit tests for devui integration

* fix: correct formatting of copyright notice in unit test files

* fixes formatting issues

* fixes build for net8 target

* fixes formatting errors on test apphost

* adds copyright notice to multiple files and removes unnecessary using directives

* Update dotnet/aspire-integration/Aspire.Hosting.AgentFramework.DevUI/DevUIAggregatorHostedService.cs

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update dotnet/aspire-integration/Aspire.Hosting.AgentFramework.DevUI/DevUIAggregatorHostedService.cs

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update dotnet/tests/Aspire.Hosting.AgentFramework.DevUI.UnitTests/Aspire.Hosting.AgentFramework.DevUI.UnitTests.csproj

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update dotnet/samples/DevUIIntegration/DevUIIntegration.AppHost/DevUIIntegration.AppHost.csproj

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update dotnet/aspire-integration/Aspire.Hosting.AgentFramework.DevUI/DevUIAggregatorHostedService.cs

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Refactor project files to use TargetFrameworks instead of TargetFramework for multi-targeting support; add optional port property to DevUIResource class.

* Add unit tests for DevUIAggregatorHostedService; refactor project files for TargetFrameworks support

* Refactor project files to use TargetFrameworks for multi-targeting support in DevUIIntegration samples

* Remove unnecessary using directive for Aspire.Hosting in DevUIAggregatorHostedServiceTests

* merge

* fixes Conversation routing for non-first backends

* add documentation for devui integration sample

* update project references in solution file for improved integration

* fixes package versions post merge

* move Aspire.Hosting.AgentFramework.DevUI to dotnet/src

Move the project from aspire-integration/ to src/ to be consistent
with the location of all other projects in the repo.

* move DevUI sample to samples/05-end-to-end/DevUIAspireIntegration

Move the sample from samples/DevUIIntegration/ to
samples/05-end-to-end/DevUIAspireIntegration/ to match the location
of other end-to-end samples.

* remove unnecessary net472 framework condition from sample csproj files

These projects only target net10.0, so the
Condition="'$(TargetFramework)' != 'net472'" on ItemGroup is unnecessary.

* update sample model name from gpt-4.1 to gpt-5.4

Use a more up-to-date model name in the DevUI integration samples.

* Revert "remove unnecessary net472 framework condition from sample csproj files"

This reverts commit 08cf41253b.

* fix: use TargetFrameworks to override multi-targeting from Directory.Build.props

The parent Directory.Build.props sets TargetFrameworks to net10.0;net472,
which overrides the singular TargetFramework in each csproj. Use the plural
TargetFrameworks property set to net10.0 only to properly override it, and
remove the now-unnecessary net472 condition on ItemGroup.

* fixes aspire config

* fix: update Microsoft.Extensions packages to version 10.0.1

* Address Copilot review feedback on DevUI Aspire integration

- Fix request body dropping in ProxyConversationsAsync: always read the
  body when ContentLength > 0 before routing, then pass it through to
  all proxy calls (previously null was passed when backend was resolved
  from query param or conversation map)
- Fix resource leak: dispose aggregator on startup failure in catch block
- Fix XML docs: accurately describe embedded resource serving behavior
- Remove reflection from DevUIResourceTests (InternalsVisibleTo already set)
- Make sensitive telemetry conditional on Development environment in samples

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: update chat client version to gpt41 in both EditorAgent and WriterAgent

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Roger Barreto <19890735+rogerbarreto@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-20 11:12:54 +00:00

196 lines
5.0 KiB
C#

// Copyright (c) Microsoft. All rights reserved.
using System.Linq;
using System.Net.Sockets;
using Aspire.Hosting.ApplicationModel;
namespace Aspire.Hosting.AgentFramework.DevUI.UnitTests;
/// <summary>
/// Unit tests for the <see cref="DevUIResource"/> class.
/// </summary>
public class DevUIResourceTests
{
#region Constructor Tests
/// <summary>
/// Verifies that the resource name is correctly set.
/// </summary>
[Fact]
public void Constructor_WithName_SetsName()
{
// Arrange & Act
var resource = new DevUIResource("test-devui");
// Assert
Assert.Equal("test-devui", resource.Name);
}
/// <summary>
/// Verifies that the resource implements IResourceWithEndpoints.
/// </summary>
[Fact]
public void Resource_ImplementsIResourceWithEndpoints()
{
// Arrange & Act
var resource = new DevUIResource("test-devui");
// Assert
Assert.IsAssignableFrom<IResourceWithEndpoints>(resource);
}
/// <summary>
/// Verifies that the resource implements IResourceWithWaitSupport.
/// </summary>
[Fact]
public void Resource_ImplementsIResourceWithWaitSupport()
{
// Arrange & Act
var resource = new DevUIResource("test-devui");
// Assert
Assert.IsAssignableFrom<IResourceWithWaitSupport>(resource);
}
#endregion
#region Endpoint Annotation Tests
/// <summary>
/// Verifies that the resource has an HTTP endpoint annotation when port is specified.
/// </summary>
[Fact]
public void Constructor_WithPort_AddsEndpointAnnotation()
{
// Arrange & Act
var resource = CreateResourceWithPort(8090);
// Assert
var endpoint = resource.Annotations.OfType<EndpointAnnotation>().FirstOrDefault();
Assert.NotNull(endpoint);
Assert.Equal("http", endpoint.Name);
Assert.Equal(8090, endpoint.Port);
}
/// <summary>
/// Verifies that the endpoint annotation has correct protocol type.
/// </summary>
[Fact]
public void EndpointAnnotation_HasTcpProtocol()
{
// Arrange
var resource = CreateResourceWithPort(8080);
// Act
var endpoint = resource.Annotations.OfType<EndpointAnnotation>().First();
// Assert
Assert.Equal(ProtocolType.Tcp, endpoint.Protocol);
}
/// <summary>
/// Verifies that the endpoint annotation has HTTP URI scheme.
/// </summary>
[Fact]
public void EndpointAnnotation_HasHttpUriScheme()
{
// Arrange
var resource = CreateResourceWithPort(8080);
// Act
var endpoint = resource.Annotations.OfType<EndpointAnnotation>().First();
// Assert
Assert.Equal("http", endpoint.UriScheme);
}
/// <summary>
/// Verifies that the endpoint is not proxied.
/// </summary>
[Fact]
public void EndpointAnnotation_IsNotProxied()
{
// Arrange
var resource = CreateResourceWithPort(8080);
// Act
var endpoint = resource.Annotations.OfType<EndpointAnnotation>().First();
// Assert
Assert.False(endpoint.IsProxied);
}
/// <summary>
/// Verifies that the endpoint target host is localhost.
/// </summary>
[Fact]
public void EndpointAnnotation_TargetHostIsLocalhost()
{
// Arrange
var resource = CreateResourceWithPort(8080);
// Act
var endpoint = resource.Annotations.OfType<EndpointAnnotation>().First();
// Assert
Assert.Equal("localhost", endpoint.TargetHost);
}
/// <summary>
/// Verifies that the endpoint has no fixed port when null is passed.
/// </summary>
[Fact]
public void Constructor_WithNullPort_EndpointHasNullPort()
{
// Arrange & Act
var resource = CreateResourceWithPort(null);
// Assert
var endpoint = resource.Annotations.OfType<EndpointAnnotation>().FirstOrDefault();
Assert.NotNull(endpoint);
Assert.Null(endpoint.Port);
}
#endregion
#region PrimaryEndpoint Tests
/// <summary>
/// Verifies that PrimaryEndpoint returns an endpoint reference.
/// </summary>
[Fact]
public void PrimaryEndpoint_ReturnsEndpointReference()
{
// Arrange
var resource = CreateResourceWithPort(8080);
// Act
var endpoint = resource.PrimaryEndpoint;
// Assert
Assert.NotNull(endpoint);
Assert.Same(resource, endpoint.Resource);
}
/// <summary>
/// Verifies that PrimaryEndpoint returns the same instance on multiple calls.
/// </summary>
[Fact]
public void PrimaryEndpoint_MultipleCalls_ReturnsSameInstance()
{
// Arrange
var resource = CreateResourceWithPort(8080);
// Act
var endpoint1 = resource.PrimaryEndpoint;
var endpoint2 = resource.PrimaryEndpoint;
// Assert
Assert.Same(endpoint1, endpoint2);
}
#endregion
private static DevUIResource CreateResourceWithPort(int? port) => new("test-devui", port);
}