diff --git a/src/Aspire.Dashboard/Components/Pages/ConsoleLogs.razor.cs b/src/Aspire.Dashboard/Components/Pages/ConsoleLogs.razor.cs index 312e95ec8e..e6f738b965 100644 --- a/src/Aspire.Dashboard/Components/Pages/ConsoleLogs.razor.cs +++ b/src/Aspire.Dashboard/Components/Pages/ConsoleLogs.razor.cs @@ -271,17 +271,19 @@ private async ValueTask LoadLogsAsync() } else { - Logger.LogDebug("Subscribing to console logs for resource {ResourceName}.", PageViewModel.SelectedResource.Name); + var resourceSubscriptionName = PageViewModel.SelectedResource.Name; + + Logger.LogDebug("Subscribing to console logs for resource {ResourceName}.", resourceSubscriptionName); var cancellationToken = await _logSubscriptionCancellationSeries.NextAsync(); - var subscription = DashboardClient.SubscribeConsoleLogs(PageViewModel.SelectedResource.Name, cancellationToken); + var subscription = DashboardClient.SubscribeConsoleLogs(resourceSubscriptionName, cancellationToken); if (subscription is not null) { - var task = _logViewer.SetLogSourceAsync(PageViewModel.SelectedResource.Name, subscription); + var task = _logViewer.SetLogSourceAsync(resourceSubscriptionName, subscription); - _subscriptionResourceName = PageViewModel.SelectedResource.Name; + _subscriptionResourceName = resourceSubscriptionName; PageViewModel.Status = Loc[nameof(Dashboard.Resources.ConsoleLogs.ConsoleLogsWatchingLogs)]; _ = Task.Run(async () => @@ -292,6 +294,8 @@ private async ValueTask LoadLogsAsync() } finally { + Logger.LogDebug("Finished watching logs for resource {ResourceName}.", resourceSubscriptionName); + _subscriptionResourceName = null; PageViewModel.Status = Loc[nameof(Dashboard.Resources.ConsoleLogs.ConsoleLogsFinishedWatchingLogs)]; } diff --git a/tests/Aspire.Dashboard.Components.Tests/Aspire.Dashboard.Components.Tests.csproj b/tests/Aspire.Dashboard.Components.Tests/Aspire.Dashboard.Components.Tests.csproj index cb7824b084..7774f04878 100644 --- a/tests/Aspire.Dashboard.Components.Tests/Aspire.Dashboard.Components.Tests.csproj +++ b/tests/Aspire.Dashboard.Components.Tests/Aspire.Dashboard.Components.Tests.csproj @@ -16,6 +16,7 @@ + diff --git a/tests/Aspire.Dashboard.Components.Tests/Pages/ConsoleLogsTests.cs b/tests/Aspire.Dashboard.Components.Tests/Pages/ConsoleLogsTests.cs index 3a77ca1ad5..b7b617b394 100644 --- a/tests/Aspire.Dashboard.Components.Tests/Pages/ConsoleLogsTests.cs +++ b/tests/Aspire.Dashboard.Components.Tests/Pages/ConsoleLogsTests.cs @@ -12,15 +12,24 @@ using Google.Protobuf.WellKnownTypes; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Microsoft.FluentUI.AspNetCore.Components; using Xunit; +using Xunit.Abstractions; namespace Aspire.Dashboard.Components.Tests.Pages; [UseCulture("en-US")] public partial class ConsoleLogsTests : TestContext { + private readonly ITestOutputHelper _testOutputHelper; + + public ConsoleLogsTests(ITestOutputHelper testOutputHelper) + { + _testOutputHelper = testOutputHelper; + } + [Fact] public void ResourceName_MultiRender_SubscribeConsoleLogsOnce() { @@ -51,6 +60,7 @@ public void ResourceName_MultiRender_SubscribeConsoleLogsOnce() }); var instance = cut.Instance; + var logger = Services.GetRequiredService>(); var testResource = CreateResourceViewModel("test-resource", KnownResourceState.Running); resourceChannel.Writer.TryWrite([ @@ -58,17 +68,16 @@ public void ResourceName_MultiRender_SubscribeConsoleLogsOnce() ]); // Assert + logger.LogInformation("Waiting for selected resource."); cut.WaitForState(() => instance.PageViewModel.SelectedResource == testResource); - viewport = new ViewportInformation(IsDesktop: false, IsUltraLowHeight: false, IsUltraLowWidth: false); - dimensionManager.InvokeOnViewportInformationChanged(viewport); - - // Re-invoke + // Ensure component is rendered again. cut.SetParametersAndRender(builder => { }); consoleLogsChannel.Writer.TryWrite([new ResourceLogLine(1, "Test content", IsErrorMessage: false)]); consoleLogsChannel.Writer.Complete(); + logger.LogInformation("Waiting for finish message."); var loc = Services.GetRequiredService>(); cut.WaitForState(() => instance.PageViewModel.Status == loc[nameof(Resources.ConsoleLogs.ConsoleLogsFinishedWatchingLogs)]); @@ -96,7 +105,10 @@ private void SetupConsoleLogsServices(TestDashboardClient? dashboardClient = nul JSInterop.SetupVoid("initializeContinuousScroll"); JSInterop.SetupVoid("resetContinuousScrollPosition"); + var loggerFactory = IntegrationTestHelpers.CreateLoggerFactory(_testOutputHelper); + Services.AddLocalization(); + Services.AddSingleton(loggerFactory); Services.AddSingleton(); Services.AddSingleton(); Services.AddSingleton>(Options.Create(new DashboardOptions())); diff --git a/tests/Aspire.Dashboard.Components.Tests/Shared/IntegrationTestHelpers.cs b/tests/Aspire.Dashboard.Components.Tests/Shared/IntegrationTestHelpers.cs new file mode 100644 index 0000000000..f4e318bdef --- /dev/null +++ b/tests/Aspire.Dashboard.Components.Tests/Shared/IntegrationTestHelpers.cs @@ -0,0 +1,24 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Testing; +using Xunit.Abstractions; + +namespace Aspire.Dashboard.Components.Tests.Shared; + +public static class IntegrationTestHelpers +{ + public static ILoggerFactory CreateLoggerFactory(ITestOutputHelper testOutputHelper, ITestSink? testSink = null) + { + return LoggerFactory.Create(builder => + { + builder.AddXunit(testOutputHelper, LogLevel.Trace, DateTimeOffset.UtcNow); + builder.SetMinimumLevel(LogLevel.Trace); + if (testSink != null) + { + builder.AddProvider(new TestLoggerProvider(testSink)); + } + }); + } +}