File: Integration\Playwright\AspireMenuButtonFocusTests.cs
Web Access
Project: src\tests\Aspire.Dashboard.Tests\Aspire.Dashboard.Tests.csproj (Aspire.Dashboard.Tests)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using Aspire.Dashboard.Resources;
using Aspire.Dashboard.Tests.Integration.Playwright.Infrastructure;
using Aspire.TestUtilities;
using Microsoft.AspNetCore.InternalTesting;
using Microsoft.Playwright;
using Xunit;
 
namespace Aspire.Dashboard.Tests.Integration.Playwright;
 
[RequiresFeature(TestFeature.Playwright)]
public class AspireMenuButtonFocusTests : PlaywrightTestsBase<DashboardServerFixture>
{
    public AspireMenuButtonFocusTests(DashboardServerFixture dashboardServerFixture)
        : base(dashboardServerFixture)
    {
    }
 
    [Fact]
    [OuterloopTest("Resource-intensive Playwright browser test")]
    public async Task MenuButton_ItemSelected_RestoresFocusToMenuButton()
    {
        await RunTestAsync(async page =>
        {
            await page.GotoAsync("/structuredlogs").DefaultTimeout();
 
            // The structured logs "Remove data" menu relies on the AspireMenuButton default for focus
            // restoration rather than opting in explicitly, so it covers the menus that regressed in
            // https://github.com/microsoft/aspire/issues/17656. Its items only clear the telemetry
            // repository, so nothing else legitimately claims focus and the assertion stays meaningful.
            // Focus after a menu closes is a browser-only behavior that bUnit can't observe.
            //
            // Keep the host for focus restoration. Expanded-state behavior is covered by
            // ResourcesTests.ViewOptionsMenu_ReportsExpandedState.
            var clearButton = page.Locator($"fluent-button[title='{ControlsStrings.ClearSignalsButtonTitle}'][aria-haspopup='menu']").First;
            var clearButtonId = await clearButton.GetAttributeAsync("id");
            Assert.False(string.IsNullOrEmpty(clearButtonId));
 
            await clearButton.ClickAsync();
            var clearAllItem = page.Locator("fluent-menu-item#clear-menu-all");
            await Assertions.Expect(clearAllItem).ToBeVisibleAsync();
            await clearAllItem.ClickAsync();
 
            await AsyncTestHelpers.AssertIsTrueRetryAsync(
                async () => string.Equals(await page.EvaluateAsync<string?>("() => document.activeElement?.id"), clearButtonId, StringComparison.Ordinal),
                "Focus should return to the menu button after a menu item is selected.");
        });
    }
}