diff --git a/src/Aspire.Dashboard/Components/Pages/ConsoleLogs.razor.cs b/src/Aspire.Dashboard/Components/Pages/ConsoleLogs.razor.cs index 2391d64f1c7..1090db849d9 100644 --- a/src/Aspire.Dashboard/Components/Pages/ConsoleLogs.razor.cs +++ b/src/Aspire.Dashboard/Components/Pages/ConsoleLogs.razor.cs @@ -427,7 +427,7 @@ private async Task SubscribeAsync(bool isAllSelected, string? selectedResourceNa private bool IsAllSelected() { - return PageViewModel.SelectedResource == _allResource; + return PageViewModel?.SelectedResource is not null && PageViewModel.SelectedResource == _allResource; } private void UpdateMenuButtons() @@ -451,27 +451,27 @@ private void UpdateMenuButtons() var selectedResource = GetSelectedResource(); - CommonMenuItems.AddToggleHiddenResourcesMenuItem( - _logsMenuItems, - ControlsStringsLoc, - _showHiddenResources, - _resourceByName.Values, - SessionStorage, - EventCallback.Factory.Create(this, async - value => - { - _showHiddenResources = value; - UpdateResourcesList(); - UpdateMenuButtons(); - - if (!_showHiddenResources && selectedResource?.IsResourceHidden(showHiddenResources: false) is true) + // Only show the "Hide hidden resources" menu item when viewing all resources + // Use IsAllSelected() instead of _isSubscribedToAll because UpdateMenuButtons() + // can be called before the subscription is established + if (IsAllSelected()) + { + CommonMenuItems.AddToggleHiddenResourcesMenuItem( + _logsMenuItems, + ControlsStringsLoc, + _showHiddenResources, + _resourceByName.Values, + SessionStorage, + EventCallback.Factory.Create(this, async + value => { - PageViewModel.SelectedResource = _allResource; - await this.AfterViewModelChangedAsync(_contentLayout, false); - } + _showHiddenResources = value; + UpdateResourcesList(); + UpdateMenuButtons(); - await this.RefreshIfMobileAsync(_contentLayout); - })); + await this.RefreshIfMobileAsync(_contentLayout); + })); + } _logsMenuItems.Add(new() { diff --git a/tests/Aspire.Dashboard.Components.Tests/Pages/ConsoleLogsTests.cs b/tests/Aspire.Dashboard.Components.Tests/Pages/ConsoleLogsTests.cs index a843ef20aea..7654c343d14 100644 --- a/tests/Aspire.Dashboard.Components.Tests/Pages/ConsoleLogsTests.cs +++ b/tests/Aspire.Dashboard.Components.Tests/Pages/ConsoleLogsTests.cs @@ -171,7 +171,8 @@ public async Task ResourceName_SubscribeOnLoadAndChange_SubscribeConsoleLogsOnce public void ToggleHiddenResources_HiddenResourceVisibilityAndSelection_WorksCorrectly() { // Arrange - var regularResource = ModelTestHelpers.CreateResource(resourceName: "regular-resource", state: KnownResourceState.Running); + var regularResource1 = ModelTestHelpers.CreateResource(resourceName: "regular-resource1", state: KnownResourceState.Running); + var regularResource2 = ModelTestHelpers.CreateResource(resourceName: "regular-resource2", state: KnownResourceState.Running); var hiddenResource = ModelTestHelpers.CreateResource(resourceName: "hidden-resource", state: KnownResourceState.Running, hidden: true); var consoleLogsChannel = Channel.CreateUnbounded>(); @@ -180,7 +181,7 @@ public void ToggleHiddenResources_HiddenResourceVisibilityAndSelection_WorksCorr isEnabled: true, consoleLogsChannelProvider: name => consoleLogsChannel, resourceChannelProvider: () => resourceChannel, - initialResources: [regularResource, hiddenResource]); + initialResources: [regularResource1, regularResource2, hiddenResource]); SetupConsoleLogsServices(dashboardClient); @@ -203,8 +204,8 @@ public void ToggleHiddenResources_HiddenResourceVisibilityAndSelection_WorksCorr var selectElement = resourceSelect.Find("fluent-select"); var selectOptions = selectElement.QuerySelectorAll("fluent-option"); - // Should have at least 1 option (regular resource) when resources are loaded - Assert.True(selectOptions.Length >= 1); + // Should have "All" + 2 regular resources when resources are loaded + Assert.Equal(3, selectOptions.Length); }); // Initially, hidden resources should not be shown @@ -212,10 +213,11 @@ public void ToggleHiddenResources_HiddenResourceVisibilityAndSelection_WorksCorr var selectElement = resourceSelect.Find("fluent-select"); var selectOptions = selectElement.QuerySelectorAll("fluent-option"); - // Should only have regular resource (hidden resource filtered out) - Assert.Equal(1, selectOptions.Length); // regular-resource + // Should have "All" + 2 regular resources (hidden resource filtered out) + Assert.Equal(3, selectOptions.Length); var optionValues = selectOptions.Select(opt => opt.GetAttribute("value")).ToList(); - Assert.Contains("regular-resource", optionValues); + Assert.Contains("regular-resource1", optionValues); + Assert.Contains("regular-resource2", optionValues); Assert.DoesNotContain("hidden-resource", optionValues); // Act & Assert 2: Click the settings menu button to show the menu, then click "Show hidden resources" @@ -235,21 +237,16 @@ public void ToggleHiddenResources_HiddenResourceVisibilityAndSelection_WorksCorr cut.WaitForAssertion(() => { var updatedOptions = selectElement.QuerySelectorAll("fluent-option"); - // Should now have both resources - Assert.Equal(3, updatedOptions.Length); // "None" + regular-resource + hidden-resource + // Should now have "All" + all three resources + Assert.Equal(4, updatedOptions.Length); var updatedOptionValues = updatedOptions.Select(opt => opt.GetAttribute("value")).ToList(); - Assert.Contains("regular-resource", updatedOptionValues); + Assert.Contains("regular-resource1", updatedOptionValues); + Assert.Contains("regular-resource2", updatedOptionValues); Assert.Contains("hidden-resource", updatedOptionValues); }); - // Act & Assert 3: Select the hidden resource - var hiddenResourceOption = selectElement.QuerySelector("fluent-option[value='hidden-resource']"); - Assert.NotNull(hiddenResourceOption); - selectElement.Change("hidden-resource"); - - cut.WaitForState(() => instance.PageViewModel.SelectedResource?.Name == "hidden-resource"); - - // Act & Assert 4: Click the settings menu button again and click "Hide hidden resources" to hide them again + // Act & Assert 3: Click the settings menu button again and click "Hide hidden resources" to hide them again + // Note: We stay on "All" view to test the hide functionality settingsMenuButton.Click(); cut.WaitForAssertion(() => @@ -259,19 +256,70 @@ public void ToggleHiddenResources_HiddenResourceVisibilityAndSelection_WorksCorr hideHiddenMenuItem.Click(); }); - // Wait for UI to update - hidden resource should be filtered out and selection should be cleared + // Wait for UI to update - hidden resource should be filtered out cut.WaitForAssertion(() => { var finalOptions = selectElement.QuerySelectorAll("fluent-option"); - // Should be back to regular resource only - Assert.Equal(1, finalOptions.Length); // regular-resource + // Should be back to "All" + 2 regular resources only + Assert.Equal(3, finalOptions.Length); var finalOptionValues = finalOptions.Select(opt => opt.GetAttribute("value")).ToList(); - Assert.Contains("regular-resource", finalOptionValues); + Assert.Contains("regular-resource1", finalOptionValues); + Assert.Contains("regular-resource2", finalOptionValues); Assert.DoesNotContain("hidden-resource", finalOptionValues); }); + } + + [Fact] + public void ToggleHiddenResourcesMenuItem_WhenSingleResourceSelected_NotShown() + { + // Arrange + var testResource = ModelTestHelpers.CreateResource(resourceName: "test-resource", state: KnownResourceState.Running); + var hiddenResource = ModelTestHelpers.CreateResource(resourceName: "hidden-resource", state: KnownResourceState.Running, hidden: true); + + var consoleLogsChannel = Channel.CreateUnbounded>(); + var resourceChannel = Channel.CreateUnbounded>(); + var dashboardClient = new TestDashboardClient( + isEnabled: true, + consoleLogsChannelProvider: name => consoleLogsChannel, + resourceChannelProvider: () => resourceChannel, + initialResources: [testResource, hiddenResource]); + + SetupConsoleLogsServices(dashboardClient); + + var dimensionManager = Services.GetRequiredService(); + var viewport = new ViewportInformation(IsDesktop: true, IsUltraLowHeight: false, IsUltraLowWidth: false); + dimensionManager.InvokeOnViewportInformationChanged(viewport); + + // Act: Render component with a specific resource selected + var cut = RenderComponent(builder => + { + builder.Add(p => p.ViewportInformation, viewport); + builder.Add(p => p.ResourceName, "test-resource"); + }); + + var instance = cut.Instance; - // Selection should be cleared since selected resource is now hidden - cut.WaitForState(() => instance.PageViewModel.SelectedResource.Id?.InstanceId == regularResource.Name); + // Wait for resources to load and specific resource to be selected + cut.WaitForState(() => instance.PageViewModel.SelectedResource?.Id?.InstanceId == "test-resource"); + + // Act: Click the settings menu button + var settingsMenuButton = cut.Find("fluent-button[title='" + Resources.ConsoleLogs.ConsoleLogsSettings + "']"); + Assert.NotNull(settingsMenuButton); + settingsMenuButton.Click(); + + // Assert: The "Show hidden resources" / "Hide hidden resources" menu item should NOT be present + cut.WaitForAssertion(() => + { + var menuItems = cut.FindAll("fluent-menu-item"); + var hiddenResourcesMenuItems = menuItems.Where(item => + { + var text = item.TextContent; + return text.Contains(Resources.ControlsStrings.ShowHiddenResources) || + text.Contains(Resources.ControlsStrings.HideHiddenResources); + }).ToList(); + + Assert.Empty(hiddenResourcesMenuItems); + }); } [Fact]