Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
252 changes: 252 additions & 0 deletions tests/Aspire.Hosting.Azure.Tests/ProvisioningContextProviderTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -556,4 +556,256 @@ public async Task PublishMode_CreateProvisioningContextAsync_ReturnsValidContext
Assert.NotNull(context.Principal);
Assert.Equal("westus2", context.Location.Name);
}

[Fact]
public async Task CreateProvisioningContextAsync_SubscriptionInputStartsDisabledWhenNotConfigured()
{
// Arrange
var testInteractionService = new TestInteractionService();
var options = ProvisioningTestHelpers.CreateOptions(subscriptionId: null, location: null, resourceGroup: null);
var environment = ProvisioningTestHelpers.CreateEnvironment();
var logger = ProvisioningTestHelpers.CreateLogger();
var armClientProvider = ProvisioningTestHelpers.CreateArmClientProvider();
var userPrincipalProvider = ProvisioningTestHelpers.CreateUserPrincipalProvider();
var tokenCredentialProvider = ProvisioningTestHelpers.CreateTokenCredentialProvider();
var deploymentStateManager = ProvisioningTestHelpers.CreateUserSecretsManager();

var provider = new RunModeProvisioningContextProvider(
testInteractionService,
options,
environment,
logger,
armClientProvider,
userPrincipalProvider,
tokenCredentialProvider,
deploymentStateManager,
new DistributedApplicationExecutionContext(DistributedApplicationOperation.Run));

// Act
_ = provider.CreateProvisioningContextAsync(CancellationToken.None);

// Assert - Wait for the first interaction (message bar)
var messageBarInteraction = await testInteractionService.Interactions.Reader.ReadAsync();
messageBarInteraction.CompletionTcs.SetResult(InteractionResult.Ok(true));

// Wait for the inputs interaction
var inputsInteraction = await testInteractionService.Interactions.Reader.ReadAsync();

// Find the subscription input
var subscriptionInput = inputsInteraction.Inputs[BaseProvisioningContextProvider.SubscriptionIdName];

// Assert that subscription ID input starts disabled when not configured
Assert.True(subscriptionInput.Disabled, "Subscription ID input should be disabled initially when not configured");
Assert.NotNull(subscriptionInput.DynamicLoading);
Assert.Equal(InputType.Choice, subscriptionInput.InputType);

// Assert Resource Group input has no default value initially
var resourceGroupInput = inputsInteraction.Inputs[BaseProvisioningContextProvider.ResourceGroupName];
Assert.Null(resourceGroupInput.Value);
}

[Fact]
public async Task CreateProvisioningContextAsync_SubscriptionInputDependsOnTenantWhenNotConfigured()
{
// Arrange
var testInteractionService = new TestInteractionService();
var options = ProvisioningTestHelpers.CreateOptions(subscriptionId: null, location: null, resourceGroup: null);
var environment = ProvisioningTestHelpers.CreateEnvironment();
var logger = ProvisioningTestHelpers.CreateLogger();
var armClientProvider = ProvisioningTestHelpers.CreateArmClientProvider();
var userPrincipalProvider = ProvisioningTestHelpers.CreateUserPrincipalProvider();
var tokenCredentialProvider = ProvisioningTestHelpers.CreateTokenCredentialProvider();
var deploymentStateManager = ProvisioningTestHelpers.CreateUserSecretsManager();

var provider = new RunModeProvisioningContextProvider(
testInteractionService,
options,
environment,
logger,
armClientProvider,
userPrincipalProvider,
tokenCredentialProvider,
deploymentStateManager,
new DistributedApplicationExecutionContext(DistributedApplicationOperation.Run));

// Act
_ = provider.CreateProvisioningContextAsync(CancellationToken.None);

// Assert - Wait for the first interaction (message bar)
var messageBarInteraction = await testInteractionService.Interactions.Reader.ReadAsync();
messageBarInteraction.CompletionTcs.SetResult(InteractionResult.Ok(true));

// Wait for the inputs interaction
var inputsInteraction = await testInteractionService.Interactions.Reader.ReadAsync();

// Find the subscription input
var subscriptionInput = inputsInteraction.Inputs[BaseProvisioningContextProvider.SubscriptionIdName];

// Assert that subscription ID has dynamic loading that depends on tenant
Assert.NotNull(subscriptionInput.DynamicLoading);
Assert.NotNull(subscriptionInput.DynamicLoading.DependsOnInputs);
var dependsOnInputs = Assert.Single(subscriptionInput.DynamicLoading.DependsOnInputs);
Assert.Equal(BaseProvisioningContextProvider.TenantName, dependsOnInputs);
}

[Fact]
public async Task CreateProvisioningContextAsync_SubscriptionInputBecomesEnabledAfterTenantSelection()
{
// Arrange
var testInteractionService = new TestInteractionService();
var options = ProvisioningTestHelpers.CreateOptions(subscriptionId: null, location: null, resourceGroup: null);
var environment = ProvisioningTestHelpers.CreateEnvironment();
var logger = ProvisioningTestHelpers.CreateLogger();
var armClientProvider = ProvisioningTestHelpers.CreateArmClientProvider();
var userPrincipalProvider = ProvisioningTestHelpers.CreateUserPrincipalProvider();
var tokenCredentialProvider = ProvisioningTestHelpers.CreateTokenCredentialProvider();
var deploymentStateManager = ProvisioningTestHelpers.CreateUserSecretsManager();

var provider = new RunModeProvisioningContextProvider(
testInteractionService,
options,
environment,
logger,
armClientProvider,
userPrincipalProvider,
tokenCredentialProvider,
deploymentStateManager,
new DistributedApplicationExecutionContext(DistributedApplicationOperation.Run));

// Act
var createTask = provider.CreateProvisioningContextAsync(CancellationToken.None);

// Assert - Wait for the first interaction (message bar)
var messageBarInteraction = await testInteractionService.Interactions.Reader.ReadAsync();
messageBarInteraction.CompletionTcs.SetResult(InteractionResult.Ok(true));

// Wait for the inputs interaction
var inputsInteraction = await testInteractionService.Interactions.Reader.ReadAsync();

// Set tenant ID
inputsInteraction.Inputs[BaseProvisioningContextProvider.TenantName].Value = "87654321-4321-4321-4321-210987654321";

// Find the subscription input
var subscriptionInput = inputsInteraction.Inputs[BaseProvisioningContextProvider.SubscriptionIdName];

// Assert subscription is initially disabled
Assert.True(subscriptionInput.Disabled);

// Trigger dynamic loading callback for subscription based on tenant selection
await subscriptionInput.DynamicLoading!.LoadCallback(new LoadInputContext
{
AllInputs = inputsInteraction.Inputs,
CancellationToken = CancellationToken.None,
Input = subscriptionInput,
Services = new ServiceCollection().BuildServiceProvider()
});

// Assert that subscription input is now enabled after tenant selection
Assert.False(subscriptionInput.Disabled, "Subscription ID input should be enabled after tenant selection");
Assert.NotNull(subscriptionInput.Options);
Assert.NotEmpty(subscriptionInput.Options);
}

[Fact]
public async Task CreateProvisioningContextAsync_SubscriptionInputHasNoDynamicLoadingWhenConfigured()
{
// Arrange
var testInteractionService = new TestInteractionService();
var subscriptionId = "12345678-1234-1234-1234-123456789012";
var options = ProvisioningTestHelpers.CreateOptions(subscriptionId, location: null, resourceGroup: null);
var environment = ProvisioningTestHelpers.CreateEnvironment();
var logger = ProvisioningTestHelpers.CreateLogger();
var armClientProvider = ProvisioningTestHelpers.CreateArmClientProvider();
var userPrincipalProvider = ProvisioningTestHelpers.CreateUserPrincipalProvider();
var tokenCredentialProvider = ProvisioningTestHelpers.CreateTokenCredentialProvider();
var deploymentStateManager = ProvisioningTestHelpers.CreateUserSecretsManager();

var provider = new RunModeProvisioningContextProvider(
testInteractionService,
options,
environment,
logger,
armClientProvider,
userPrincipalProvider,
tokenCredentialProvider,
deploymentStateManager,
new DistributedApplicationExecutionContext(DistributedApplicationOperation.Run));

// Act
_ = provider.CreateProvisioningContextAsync(CancellationToken.None);

// Assert - Wait for the first interaction (message bar)
var messageBarInteraction = await testInteractionService.Interactions.Reader.ReadAsync();
messageBarInteraction.CompletionTcs.SetResult(InteractionResult.Ok(true));

// Wait for the inputs interaction
var inputsInteraction = await testInteractionService.Interactions.Reader.ReadAsync();

// Find the subscription input
var subscriptionInput = inputsInteraction.Inputs[BaseProvisioningContextProvider.SubscriptionIdName];

// Assert that subscription ID has no dynamic loading when pre-configured
Assert.Null(subscriptionInput.DynamicLoading);
Assert.True(subscriptionInput.Disabled, "Subscription ID input should remain disabled when pre-configured");
Assert.Equal(InputType.Text, subscriptionInput.InputType);
Assert.Equal(subscriptionId, subscriptionInput.Value);
}

[Fact]
public async Task CreateProvisioningContextAsync_ResourceGroupHasNoDefaultValueInitially()
{
// Arrange
var testInteractionService = new TestInteractionService();
var options = ProvisioningTestHelpers.CreateOptions(subscriptionId: null, location: null, resourceGroup: null);
var environment = ProvisioningTestHelpers.CreateEnvironment();
var logger = ProvisioningTestHelpers.CreateLogger();
var armClientProvider = ProvisioningTestHelpers.CreateArmClientProvider();
var userPrincipalProvider = ProvisioningTestHelpers.CreateUserPrincipalProvider();
var tokenCredentialProvider = ProvisioningTestHelpers.CreateTokenCredentialProvider();
var deploymentStateManager = ProvisioningTestHelpers.CreateUserSecretsManager();

var provider = new RunModeProvisioningContextProvider(
testInteractionService,
options,
environment,
logger,
armClientProvider,
userPrincipalProvider,
tokenCredentialProvider,
deploymentStateManager,
new DistributedApplicationExecutionContext(DistributedApplicationOperation.Run));

// Act
_ = provider.CreateProvisioningContextAsync(CancellationToken.None);

// Assert - Wait for the first interaction (message bar)
var messageBarInteraction = await testInteractionService.Interactions.Reader.ReadAsync();
messageBarInteraction.CompletionTcs.SetResult(InteractionResult.Ok(true));

// Wait for the inputs interaction
var inputsInteraction = await testInteractionService.Interactions.Reader.ReadAsync();

// Find the resource group input
var resourceGroupInput = inputsInteraction.Inputs[BaseProvisioningContextProvider.ResourceGroupName];

// Resource group should have no default value initially (PR #13065 change)
Assert.Null(resourceGroupInput.Value);

// Set subscription ID to trigger resource group loading
inputsInteraction.Inputs[BaseProvisioningContextProvider.SubscriptionIdName].Value = "12345678-1234-1234-1234-123456789012";

// Trigger dynamic loading callback for resource group
await resourceGroupInput.DynamicLoading!.LoadCallback(new LoadInputContext
{
AllInputs = inputsInteraction.Inputs,
CancellationToken = CancellationToken.None,
Input = resourceGroupInput,
Services = new ServiceCollection().BuildServiceProvider()
});

// After dynamic loading with existing resource groups found, value should still be null
// Default value is only set when NO existing resource groups are found
Assert.Null(resourceGroupInput.Value);
Assert.NotEmpty(resourceGroupInput.Options!);
}
}
Loading