File: DotnetProjectOptionsTests.cs
Web Access
Project: src\tests\Aspire.Hosting.Dotnet.Tests\Aspire.Hosting.Dotnet.Tests.csproj (Aspire.Hosting.Dotnet.Tests)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
#pragma warning disable ASPIREDOTNETPROJECT001
#pragma warning disable ASPIREEXTENSION001
 
using Aspire.Hosting.ApplicationModel;
using Aspire.Hosting.Tests.Utils;
using Aspire.Hosting.Utils;
 
namespace Aspire.Hosting.Dotnet.Tests;
 
public class DotnetProjectOptionsTests(ITestOutputHelper outputHelper)
{
    [Theory]
    [InlineData(null, false, "first", 5111)]
    [InlineData("second", false, "second", 5222)]
    [InlineData(null, true, "", null)]
    [InlineData("second", true, "", null)]
    public async Task PolyglotOptionsPreserveLaunchProfileSelection(
        string? requestedProfile,
        bool excludeLaunchProfile,
        string expectedProfile,
        int? expectedPort)
    {
        using var workspace = TemporaryWorkspace.Create(outputHelper);
        var projectPath = await CreateProjectAsync(workspace.Path, includeKestrel: false);
        using var builder = TestDistributedApplicationBuilder.Create(DistributedApplicationOperation.Run);
        var resource = builder.AddDotnetProjectForPolyglot("svc", projectPath, new DotnetProjectOptions
        {
            LaunchProfileName = requestedProfile,
            ExcludeLaunchProfile = excludeLaunchProfile
        });
 
        var callbackContext = LaunchConfigurationTestHelpers.CreateCallbackContext(resource.Resource, ExecutableLaunchMode.Debug);
        var launchConfig = Assert.IsType<ProjectLaunchConfiguration>(
            await resource.Resource.CreateLaunchConfigurationAsync(callbackContext));
 
        Assert.Equal(excludeLaunchProfile, launchConfig.DisableLaunchProfile);
        Assert.Equal(expectedProfile, launchConfig.LaunchProfile);
        AssertEndpointPort(resource.Resource, expectedPort);
    }
 
    [Theory]
    [InlineData(true)]
    [InlineData(false)]
    public async Task OmittedAndEmptyPolyglotOptionsUseDefaultProfile(bool omitOptions)
    {
        using var workspace = TemporaryWorkspace.Create(outputHelper);
        var projectPath = await CreateProjectAsync(workspace.Path, includeKestrel: false);
        using var builder = TestDistributedApplicationBuilder.Create(DistributedApplicationOperation.Run);
        var resource = omitOptions
            ? builder.AddDotnetProjectForPolyglot("svc", projectPath)
            : builder.AddDotnetProjectForPolyglot("svc", projectPath, new DotnetProjectOptions());
 
        var endpoint = Assert.Single(resource.Resource.Annotations.OfType<EndpointAnnotation>());
        Assert.Equal("http", endpoint.Name);
        Assert.Equal(5111, endpoint.Port);
    }
 
    [Theory]
    [InlineData(false, false, 5333)]
    [InlineData(true, false, 5111)]
    [InlineData(false, true, 5333)]
    [InlineData(true, true, null)]
    public async Task PolyglotOptionsControlKestrelAndLaunchProfileEndpointsIndependently(
        bool excludeKestrelEndpoints,
        bool excludeLaunchProfile,
        int? expectedPort)
    {
        using var workspace = TemporaryWorkspace.Create(outputHelper);
        var projectPath = await CreateProjectAsync(workspace.Path, includeKestrel: true);
        using var builder = TestDistributedApplicationBuilder.Create(DistributedApplicationOperation.Run);
        var resource = builder.AddDotnetProjectForPolyglot("svc", projectPath, new DotnetProjectOptions
        {
            ExcludeKestrelEndpoints = excludeKestrelEndpoints,
            ExcludeLaunchProfile = excludeLaunchProfile
        });
 
        AssertEndpointPort(resource.Resource, expectedPort);
    }
 
    private static void AssertEndpointPort(IResource resource, int? expectedPort)
    {
        var endpoints = resource.Annotations.OfType<EndpointAnnotation>();
        if (expectedPort is { } port)
        {
            Assert.Equal(port, Assert.Single(endpoints).Port);
        }
        else
        {
            Assert.Empty(endpoints);
        }
    }
 
    private static async Task<string> CreateProjectAsync(string workspacePath, bool includeKestrel)
    {
        var projectDirectory = Directory.CreateDirectory(Path.Combine(workspacePath, "Service"));
        var projectPath = Path.Combine(projectDirectory.FullName, "Service.csproj");
        await File.WriteAllTextAsync(projectPath, "<Project Sdk=\"Microsoft.NET.Sdk.Web\" />");
        var propertiesDirectory = Directory.CreateDirectory(Path.Combine(projectDirectory.FullName, "Properties"));
        await File.WriteAllTextAsync(Path.Combine(propertiesDirectory.FullName, "launchSettings.json"), """
            {
              "profiles": {
                "first": {
                  "commandName": "Project",
                  "applicationUrl": "http://localhost:5111"
                },
                "second": {
                  "commandName": "Project",
                  "applicationUrl": "http://localhost:5222"
                }
              }
            }
            """);
        if (includeKestrel)
        {
            await File.WriteAllTextAsync(Path.Combine(projectDirectory.FullName, "appsettings.json"), """
                {
                  "Kestrel": {
                    "Endpoints": {
                      "Http": {
                        "Url": "http://localhost:5333"
                      }
                    }
                  }
                }
                """);
        }
 
        return projectPath;
    }
}