using Aspire.Hosting; using Aspire.Hosting.ApplicationModel; using Aspire.Hosting.Testing; namespace RoslynStone.AppHost.Tests; /// /// Integration tests for the Roslyn-Stone AppHost Aspire configuration. /// These tests verify that the distributed application starts correctly and /// that the MCP server HTTP endpoint is accessible. /// [Trait("Category", "Integration")] [Trait("Component", "Aspire")] public class AppHostTests { [Fact] public async Task AppHost_CreatesSuccessfully() { // Arrange & Act var appHost = await DistributedApplicationTestingBuilder.CreateAsync(); // Assert Assert.NotNull(appHost); } [Fact] public async Task McpServer_HasHttpEndpoint() { // Arrange var appHost = await DistributedApplicationTestingBuilder.CreateAsync(); // Act var mcpServer = appHost .Resources.OfType() .FirstOrDefault(r => r.Name == "roslyn-stone-mcp"); // Assert Assert.NotNull(mcpServer); var endpoints = mcpServer.GetEndpoints(); // The MCP server uses the default 'http' endpoint; ensure it's present. Assert.Contains(endpoints, e => e.EndpointName == "http"); } [Fact] public async Task McpServer_HasCorrectEnvironmentVariables() { // Arrange var appHost = await DistributedApplicationTestingBuilder.CreateAsync(); // Act var mcpServer = appHost .Resources.OfType() .FirstOrDefault(r => r.Name == "roslyn-stone-mcp"); // Assert Assert.NotNull(mcpServer); var env = await mcpServer.GetEnvironmentVariableValuesAsync( DistributedApplicationOperation.Publish ); Assert.True(env.TryGetValue("MCP_TRANSPORT", out var mcpTransport)); Assert.Equal("http", mcpTransport); Assert.True(env.TryGetValue("OTEL_SERVICE_NAME", out var otelServiceName)); Assert.Equal("roslyn-stone-mcp", otelServiceName); } [Fact] public async Task McpServer_IsConfiguredAsProjectResource() { // Arrange var appHost = await DistributedApplicationTestingBuilder.CreateAsync(); // Act var mcpServer = appHost.Resources.FirstOrDefault(r => r.Name == "roslyn-stone-mcp"); // Assert Assert.NotNull(mcpServer); Assert.IsAssignableFrom(mcpServer); } [Fact] public async Task McpServer_DoesNotHaveStdioTransport() { // Arrange var appHost = await DistributedApplicationTestingBuilder.CreateAsync(); // Act - there should only be one resource named "roslyn-stone-mcp" var mcpServers = appHost .Resources.Where(r => r.Name.Contains("roslyn-stone-mcp", StringComparison.OrdinalIgnoreCase) ) .ToList(); // Assert - verify only HTTP transport is configured (no stdio) Assert.Single(mcpServers); Assert.Equal("roslyn-stone-mcp", mcpServers[0].Name); } [Fact] public async Task McpInspector_IsConfiguredInDevelopment() { // Arrange var appHost = await DistributedApplicationTestingBuilder.CreateAsync(); // Act var inspector = appHost.Resources.FirstOrDefault(r => r.Name == "mcp-inspector"); // Assert - inspector should be present in development mode (default for tests) Assert.NotNull(inspector); Assert.IsAssignableFrom(inspector); } [Fact] public async Task McpInspector_HasUiAndProxyEndpoints() { // Arrange var appHost = await DistributedApplicationTestingBuilder.CreateAsync(); // Act var inspector = appHost .Resources.OfType() .FirstOrDefault(r => r.Name == "mcp-inspector"); // Assert Assert.NotNull(inspector); var endpoints = inspector.GetEndpoints().ToList(); Assert.Contains(endpoints, e => e.EndpointName == "client"); Assert.Contains(endpoints, e => e.EndpointName == "server-proxy"); } }