| File: Pages\ResourceOverviewConsoleTests.cs | Web Access |
| Project: src\tests\Aspire.Dashboard.Components.Tests\Aspire.Dashboard.Components.Tests.csproj (Aspire.Dashboard.Components.Tests) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Threading.Channels; using Aspire.Dashboard.Components.Layout; using Aspire.Dashboard.Components.Pages; using Aspire.Dashboard.Components.Resize; using Aspire.Dashboard.Components.Tests.Shared; using Aspire.Dashboard.Model; using Aspire.Dashboard.Tests.Shared; using Aspire.Tests.Shared.DashboardModel; using Bunit; using Microsoft.AspNetCore.Components; using Microsoft.Extensions.DependencyInjection; using Xunit; namespace Aspire.Dashboard.Components.Tests.Pages; [UseCulture("en-US")] public class ResourceOverviewConsoleTests : DashboardTestContext { [Fact] public async Task Selection_DiscardsAlreadyDeliveredBatchFromCanceledResource() { var viewport = new ViewportInformation(IsDesktop: true, IsUltraLowHeight: false, IsUltraLowWidth: false); var resources = Channel.CreateUnbounded<IReadOnlyList<ResourceViewModelChange>>(); var apiLogs = Channel.CreateUnbounded<IReadOnlyList<ResourceLogLine>>(); var cacheLogs = Channel.CreateUnbounded<IReadOnlyList<ResourceLogLine>>(); var delivered = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); var release = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); var disposed = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); var client = new TestDashboardClient(isEnabled: true, initialResources: [ModelTestHelpers.CreateResource("api"), ModelTestHelpers.CreateResource("cache")], resourceChannelProvider: () => resources, consoleLogsChannelProvider: name => name == "api" ? apiLogs : cacheLogs); client.BeforeConsoleLogBatchAsync = async (name, _) => { if (name == "api") { delivered.TrySetResult(); // Model a delivered batch completing after its subscription was canceled. await release.Task; } }; client.OnConsoleSubscriptionDisposed = name => { if (name == "api") { disposed.TrySetResult(); } }; ResourceSetupHelpers.SetupResourceOverview(this, viewport, client); var navigation = Services.GetRequiredService<NavigationManager>(); navigation.NavigateTo("/resources/api"); var cut = Render<ResourcesLayout>(p => p.AddCascadingValue(viewport).Add(p => p.Body, builder => { builder.OpenComponent<ResourceOverview>(0); builder.AddAttribute(1, nameof(ResourceOverview.ResourceName), "api"); builder.CloseComponent(); })); cut.WaitForAssertion(() => Assert.True(cut.Instance.IsLoaded)); await apiLogs.Writer.WriteAsync([new ResourceLogLine(99, "old api output", false)]); await delivered.Task.WaitAsync(DefaultWaitTimeout); try { navigation.NavigateTo("/resources/cache"); cut.Render(); await cacheLogs.Writer.WriteAsync([new ResourceLogLine(1, "current cache output", false)]); cut.WaitForAssertion(() => Assert.Equal(["current cache output"], cut.FindAll(".overview-console-line").Select(line => line.TextContent.Trim()))); release.SetResult(); await disposed.Task.WaitAsync(DefaultWaitTimeout); cut.FindComponent<ResourceOverview>().Render(); Assert.Equal(["current cache output"], cut.FindAll(".overview-console-line").Select(line => line.TextContent.Trim())); Assert.Equal("cache", cut.Find(".resource-overview").GetAttribute("data-resource-subscription")); } finally { release.TrySetResult(); } } }