| File: Mcp\ApiDocs\ApiDocsCacheTests.cs | Web Access |
| Project: src\tests\Aspire.Cli.Tests\Aspire.Cli.Tests.csproj (Aspire.Cli.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.Net; using Aspire.Cli.Documentation.ApiDocs; using Aspire.Cli.Tests.Utils; using Microsoft.AspNetCore.InternalTesting; using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging.Abstractions; namespace Aspire.Cli.Tests.Documentation.ApiDocs; public class ApiDocsCacheTests(ITestOutputHelper outputHelper) { private const string DefaultSitemapUrl = "https://aspire.dev/sitemap-0.xml"; private const string DefaultPageUrl = "https://aspire.dev/reference/api/csharp/aspire.test.package/testtype/methods"; [Fact] public async Task FetchSitemapAsync_PersistsFriendlySitemapCacheFileNames() { using var workspace = TemporaryWorkspace.CreateForCli(outputHelper); using var memoryCache = new MemoryCache(new MemoryCacheOptions()); var configuration = new ConfigurationBuilder().Build(); var cache = CreateCache(workspace, memoryCache, configuration); using var response = new HttpResponseMessage(HttpStatusCode.OK) { Content = new StringContent("<urlset></urlset>") }; response.Headers.ETag = new System.Net.Http.Headers.EntityTagHeaderValue("\"etag\""); using var handler = new MockHttpMessageHandler(response); using var httpClient = new HttpClient(handler); var fetcher = new ApiDocsFetcher(httpClient, cache, configuration, NullLogger<ApiDocsFetcher>.Instance); _ = await fetcher.FetchSitemapAsync().DefaultTimeout(); var cacheFiles = GetCacheFiles(workspace, "api-docs"); Assert.Contains("sitemap-0.txt", cacheFiles); Assert.Contains("sitemap-0.etag.txt", cacheFiles); Assert.DoesNotContain(cacheFiles, static file => file.StartsWith("https___aspire.dev_", StringComparison.Ordinal)); } [Fact] public async Task FetchPageAsync_PersistsFriendlyPageCacheFileNames() { using var workspace = TemporaryWorkspace.CreateForCli(outputHelper); using var memoryCache = new MemoryCache(new MemoryCacheOptions()); var configuration = new ConfigurationBuilder().Build(); var cache = CreateCache(workspace, memoryCache, configuration); using var response = new HttpResponseMessage(HttpStatusCode.OK) { Content = new StringContent("# Methods") }; response.Headers.ETag = new System.Net.Http.Headers.EntityTagHeaderValue("\"etag\""); using var handler = new MockHttpMessageHandler(response); using var httpClient = new HttpClient(handler); var fetcher = new ApiDocsFetcher(httpClient, cache, configuration, NullLogger<ApiDocsFetcher>.Instance); _ = await fetcher.FetchPageAsync(DefaultPageUrl).DefaultTimeout(); var cacheFiles = GetCacheFiles(workspace, "api-docs"); Assert.Contains($"{ApiDocsSourceConfiguration.GetPageContentCacheKey(DefaultPageUrl, DefaultSitemapUrl)}.txt", cacheFiles); Assert.Contains($"{ApiDocsSourceConfiguration.GetPageContentCacheKey(DefaultPageUrl, DefaultSitemapUrl)}.etag.txt", cacheFiles); Assert.DoesNotContain(cacheFiles, static file => file.StartsWith("https___aspire.dev_", StringComparison.Ordinal)); } [Fact] public async Task SetIndexAsync_PersistsFriendlyIndexFiles() { using var workspace = TemporaryWorkspace.CreateForCli(outputHelper); using var memoryCache = new MemoryCache(new MemoryCacheOptions()); var configuration = new ConfigurationBuilder().Build(); var cache = CreateCache(workspace, memoryCache, configuration); ApiReferenceItem[] items = [ new ApiReferenceItem { Id = "csharp/aspire.test.package", Name = "Aspire.Test.Package", Language = ApiReferenceLanguages.CSharp, Kind = ApiReferenceKinds.Package, PageUrl = "https://aspire.dev/reference/api/csharp/aspire.test.package/" } ]; await cache.SetIndexAsync(items).DefaultTimeout(); await cache.SetIndexSourceFingerprintAsync("fingerprint").DefaultTimeout(); var cachedItems = await cache.GetIndexAsync().DefaultTimeout(); var fingerprint = await cache.GetIndexSourceFingerprintAsync().DefaultTimeout(); var item = Assert.Single(cachedItems!); Assert.Equal("csharp/aspire.test.package", item.Id); Assert.Equal("fingerprint", fingerprint); var cacheFiles = GetCacheFiles(workspace, "api-docs"); Assert.Contains("index_sitemap-0.json", cacheFiles); Assert.Contains("index_sitemap-0_fingerprint.txt", cacheFiles); } private static ApiDocsCache CreateCache(TemporaryWorkspace workspace, IMemoryCache memoryCache, IConfiguration configuration) => new(memoryCache, CreateExecutionContext(workspace), configuration, NullLogger<ApiDocsCache>.Instance); private static CliExecutionContext CreateExecutionContext(TemporaryWorkspace workspace) => new( workspace.WorkspaceRoot, new DirectoryInfo(Path.Combine(workspace.WorkspaceRoot.FullName, ".aspire", "hives")), new DirectoryInfo(Path.Combine(workspace.WorkspaceRoot.FullName, ".aspire", "cache")), new DirectoryInfo(Path.Combine(Path.GetTempPath(), "aspire-test-runtimes")), new DirectoryInfo(Path.Combine(Path.GetTempPath(), "aspire-test-logs")), "test.log", identityChannel: "local"); private static string[] GetCacheFiles(TemporaryWorkspace workspace, string subdirectory) => Directory.GetFiles(Path.Combine(workspace.WorkspaceRoot.FullName, ".aspire", "cache", subdirectory)) .Select(Path.GetFileName) .ToArray()!; }