| File: AzureFrontDoorTests.cs | Web Access |
| Project: src\tests\Aspire.Hosting.Azure.Tests\Aspire.Hosting.Azure.Tests.csproj (Aspire.Hosting.Azure.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 ASPIRECOMPUTE002 #pragma warning disable ASPIREPROBES001 using Aspire.Hosting.ApplicationModel; using Aspire.Hosting.Utils; using static Aspire.Hosting.Utils.AzureManifestUtils; namespace Aspire.Hosting.Azure.Tests; public class AzureFrontDoorTests { [Fact] public void AddAzureFrontDoorCreatesResource() { var builder = TestDistributedApplicationBuilder.Create(DistributedApplicationOperation.Publish); var frontDoor = builder.AddAzureFrontDoor("frontdoor"); Assert.NotNull(frontDoor); Assert.Equal("frontdoor", frontDoor.Resource.Name); Assert.IsType<AzureFrontDoorResource>(frontDoor.Resource); } [Fact] public void WithOriginAddsAnnotation() { var builder = TestDistributedApplicationBuilder.Create(DistributedApplicationOperation.Publish); var api = builder.AddProject<Project>("api", launchProfileName: null) .WithHttpsEndpoint(); var frontDoor = builder.AddAzureFrontDoor("frontdoor") .WithOrigin(api); var annotations = frontDoor.Resource.Annotations.OfType<AzureFrontDoorOriginAnnotation>().ToList(); Assert.Single(annotations); } [Fact] public void WithOriginSupportsMultipleOrigins() { var builder = TestDistributedApplicationBuilder.Create(DistributedApplicationOperation.Publish); var api = builder.AddProject<Project>("api", launchProfileName: null) .WithHttpsEndpoint(); var web = builder.AddProject<Project>("web", launchProfileName: null) .WithHttpsEndpoint(); var frontDoor = builder.AddAzureFrontDoor("frontdoor") .WithOrigin(api) .WithOrigin(web); var annotations = frontDoor.Resource.Annotations.OfType<AzureFrontDoorOriginAnnotation>().ToList(); Assert.Equal(2, annotations.Count); } [Fact] public async Task AddAzureFrontDoorWithSingleOriginGeneratesBicep() { var builder = TestDistributedApplicationBuilder.Create(DistributedApplicationOperation.Publish); builder.AddAzureContainerAppEnvironment("env"); var api = builder.AddProject<Project>("my-api", launchProfileName: null) .WithHttpsEndpoint() .WithExternalHttpEndpoints(); var frontDoor = builder.AddAzureFrontDoor("frontdoor") .WithOrigin(api); using var app = builder.Build(); await ExecuteBeforeStartHooksAsync(app, default); var (_, bicep) = await GetManifestWithBicep(frontDoor.Resource); await Verify(bicep, "bicep"); // Verify GetEndpointUrl normalizes the dashed name to match the bicep output var endpointUrl = frontDoor.Resource.GetEndpointUrl("my-api"); Assert.Equal("my_api_endpointUrl", endpointUrl.Name); } [Fact] public async Task AddAzureFrontDoorWithMultipleOriginsGeneratesBicep() { var builder = TestDistributedApplicationBuilder.Create(DistributedApplicationOperation.Publish); builder.AddAzureContainerAppEnvironment("env"); var api = builder.AddProject<Project>("api", launchProfileName: null) .WithHttpsEndpoint() .WithExternalHttpEndpoints(); var web = builder.AddProject<Project>("web", launchProfileName: null) .WithHttpsEndpoint() .WithExternalHttpEndpoints(); var frontDoor = builder.AddAzureFrontDoor("frontdoor") .WithOrigin(api) .WithOrigin(web); using var app = builder.Build(); await ExecuteBeforeStartHooksAsync(app, default); var (_, bicep) = await GetManifestWithBicep(frontDoor.Resource); await Verify(bicep, "bicep"); } [Fact] public async Task AddAzureFrontDoorThrowsWhenOriginHasNoExternalEndpoints() { var builder = TestDistributedApplicationBuilder.Create(DistributedApplicationOperation.Publish); builder.AddAzureContainerAppEnvironment("env"); var api = builder.AddProject<Project>("api", launchProfileName: null); var frontDoor = builder.AddAzureFrontDoor("frontdoor") .WithOrigin(api); using var app = builder.Build(); var exception = await Assert.ThrowsAsync<InvalidOperationException>(() => ExecuteBeforeStartHooksAsync(app, default)); Assert.Contains("does not have an external HTTP or HTTPS endpoint", exception.ToString()); } [Fact] public void EndpointUrlOutputReferenceIsAvailable() { var builder = TestDistributedApplicationBuilder.Create(DistributedApplicationOperation.Publish); var frontDoor = builder.AddAzureFrontDoor("frontdoor"); var endpointUrl = frontDoor.Resource.GetEndpointUrl("api"); Assert.NotNull(endpointUrl); Assert.Equal("api_endpointUrl", endpointUrl.Name); } [Fact] public void AddAzureFrontDoorThrowsOnNullName() { var builder = TestDistributedApplicationBuilder.Create(DistributedApplicationOperation.Publish); Assert.Throws<ArgumentNullException>(() => builder.AddAzureFrontDoor(null!)); } [Fact] public void WithOriginThrowsOnNullResource() { var builder = TestDistributedApplicationBuilder.Create(DistributedApplicationOperation.Publish); var frontDoor = builder.AddAzureFrontDoor("frontdoor"); Assert.Throws<ArgumentNullException>(() => frontDoor.WithOrigin((IResourceBuilder<ProjectResource>)null!)); } [Fact] public async Task HealthProbePathUsesResourceProbeAnnotation() { var builder = TestDistributedApplicationBuilder.Create(DistributedApplicationOperation.Publish); builder.AddAzureContainerAppEnvironment("env"); var api = builder.AddProject<Project>("api", launchProfileName: null) .WithHttpsEndpoint() .WithExternalHttpEndpoints() .WithHttpProbe(ProbeType.Liveness, "/health"); var frontDoor = builder.AddAzureFrontDoor("frontdoor") .WithOrigin(api); using var app = builder.Build(); await ExecuteBeforeStartHooksAsync(app, default); var (_, bicep) = await GetManifestWithBicep(frontDoor.Resource); Assert.Contains("probePath: '/health'", bicep); } [Fact] public async Task HealthProbePathDefaultsToSlashWhenNoProbeAnnotation() { var builder = TestDistributedApplicationBuilder.Create(DistributedApplicationOperation.Publish); builder.AddAzureContainerAppEnvironment("env"); var api = builder.AddProject<Project>("api", launchProfileName: null) .WithHttpsEndpoint() .WithExternalHttpEndpoints(); var frontDoor = builder.AddAzureFrontDoor("frontdoor") .WithOrigin(api); using var app = builder.Build(); await ExecuteBeforeStartHooksAsync(app, default); var (_, bicep) = await GetManifestWithBicep(frontDoor.Resource); Assert.Contains("probePath: '/'", bicep); } [Fact] public async Task WithOriginSkipsNonHttpEndpoints() { var builder = TestDistributedApplicationBuilder.Create(DistributedApplicationOperation.Publish); builder.AddAzureContainerAppEnvironment("env"); // Add a resource with a non-HTTP endpoint and an HTTP endpoint var api = builder.AddProject<Project>("api", launchProfileName: null) .WithEndpoint(scheme: "tcp", name: "grpc") .WithHttpsEndpoint() .WithExternalHttpEndpoints(); var frontDoor = builder.AddAzureFrontDoor("frontdoor") .WithOrigin(api); using var app = builder.Build(); await ExecuteBeforeStartHooksAsync(app, default); var (_, bicep) = await GetManifestWithBicep(frontDoor.Resource); // Should generate valid bicep (picked the HTTPS endpoint, not the TCP one) Assert.Contains("hostName: api_host", bicep); } [Fact] public void WithOriginThrowsOnDuplicateOrigin() { var builder = TestDistributedApplicationBuilder.Create(DistributedApplicationOperation.Publish); var api = builder.AddProject<Project>("api", launchProfileName: null) .WithHttpsEndpoint() .WithExternalHttpEndpoints(); var frontDoor = builder.AddAzureFrontDoor("frontdoor") .WithOrigin(api); var exception = Assert.Throws<InvalidOperationException>(() => frontDoor.WithOrigin(api)); Assert.Contains("has already been added", exception.Message); } private sealed class Project : IProjectMetadata { public string ProjectPath => "project"; } }