| File: Templating\TemplatePackageLockTests.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.Text.Json; namespace Aspire.Cli.Tests.Templating; public class TemplatePackageLockTests { [Theory] [InlineData("ts-starter")] [InlineData("py-starter")] [InlineData("java-starter")] public void StarterFrontendPackageJson_UsesNpm10CompatibleBraceExpansionOverride(string templateName) { var filePath = Path.Combine( GetRepoRoot(), "src", "Aspire.Cli", "Templating", "Templates", templateName, "frontend", "package.json"); using var packageJson = JsonDocument.Parse(File.ReadAllText(filePath)); var overrides = packageJson.RootElement.GetProperty("overrides"); Assert.True(overrides.TryGetProperty("minimatch@3.1.5", out var minimatchOverride)); Assert.Equal( "2.1.3", minimatchOverride.GetProperty("brace-expansion").GetString()); Assert.False(overrides.TryGetProperty("brace-expansion@1", out _)); } [Theory] [InlineData("ts-starter")] [InlineData("py-starter")] [InlineData("java-starter")] public void StarterFrontendPackageLock_UsesPublicNpmRegistry(string templateName) { var filePath = Path.Combine( GetRepoRoot(), "src", "Aspire.Cli", "Templating", "Templates", templateName, "frontend", "package-lock.json"); using var packageLock = JsonDocument.Parse(File.ReadAllText(filePath)); var registryHosts = packageLock.RootElement .GetProperty("packages") .EnumerateObject() .Where(package => package.Value.TryGetProperty("resolved", out _)) .Select(package => new Uri(package.Value.GetProperty("resolved").GetString()!).Host) .Distinct(StringComparer.Ordinal) .Order(StringComparer.Ordinal) .ToArray(); Assert.Equal(["registry.npmjs.org"], registryHosts); } [Theory] [InlineData("ts-starter")] [InlineData("py-starter")] public void StarterAppHostPackageLock_UsesPublicNpmRegistry(string templateName) { // Guards the top-level (AppHost) lockfile in addition to the frontend one covered above. // A shipped lockfile pins the `resolved` registry for every dependency npm restores in a // generated starter, so these must resolve from the public npm registry — otherwise restore // fails for customers who cannot reach a private feed. See https://github.com/microsoft/aspire/issues/19370. var filePath = Path.Combine( GetRepoRoot(), "src", "Aspire.Cli", "Templating", "Templates", templateName, "package-lock.json"); AssertPackageLockResolvesToPublicNpmRegistry(filePath); } [Fact] public void ProjectTemplateFrontendPackageLock_UsesPublicNpmRegistry() { var filePath = Path.Combine( GetRepoRoot(), "src", "Aspire.ProjectTemplates", "templates", "aspire-ts-cs-starter", "frontend", "package-lock.json"); AssertPackageLockResolvesToPublicNpmRegistry(filePath); } [Theory] [InlineData("ts-starter")] [InlineData("py-starter")] [InlineData("java-starter")] public void StarterFrontendPackageLock_DoesNotIncludeLegacyEslintYamlLoader(string templateName) { var filePath = Path.Combine( GetRepoRoot(), "src", "Aspire.Cli", "Templating", "Templates", templateName, "frontend", "package-lock.json"); using var packageLock = JsonDocument.Parse(File.ReadAllText(filePath)); var packages = packageLock.RootElement.GetProperty("packages"); Assert.False(packages.TryGetProperty("node_modules/@eslint/eslintrc", out _)); Assert.False(packages.TryGetProperty("node_modules/js-yaml", out _)); } private static void AssertPackageLockResolvesToPublicNpmRegistry(string filePath) { using var packageLock = JsonDocument.Parse(File.ReadAllText(filePath)); var registryHosts = packageLock.RootElement .GetProperty("packages") .EnumerateObject() .Where(package => package.Value.TryGetProperty("resolved", out _)) .Select(package => new Uri(package.Value.GetProperty("resolved").GetString()!).Host) .Distinct(StringComparer.Ordinal) .Order(StringComparer.Ordinal) .ToArray(); Assert.Equal(["registry.npmjs.org"], registryHosts); } private static string GetRepoRoot() => Path.GetFullPath(Path.Combine(AppContext.BaseDirectory, "..", "..", "..", "..", "..")); }