SDT/tests/DevTool.Tests/CommandResolverTests.cs
2026-03-01 20:52:56 -06:00

125 lines
4.6 KiB
C#

using Sdt.Core;
using Sdt.Config;
using Xunit;
namespace DevTool.Tests;
public sealed class CommandResolverTests
{
[Fact]
public void Resolve_Npm_OnWindows_UsesCmdShim()
{
var resolved = CommandResolver.Resolve("npm");
if (OperatingSystem.IsWindows())
Assert.True(
resolved.EndsWith("npm.cmd", StringComparison.OrdinalIgnoreCase) ||
resolved.EndsWith("\\npm", StringComparison.OrdinalIgnoreCase) ||
string.Equals(resolved, "npm.cmd", StringComparison.OrdinalIgnoreCase),
$"Resolved npm path was '{resolved}'");
else
Assert.Equal("npm", resolved);
}
[Fact]
public void Resolve_PathOrExtension_Unchanged()
{
Assert.Equal("C:\\tools\\npm.cmd", CommandResolver.Resolve("C:\\tools\\npm.cmd"));
var resolved = CommandResolver.Resolve("dotnet.exe");
if (OperatingSystem.IsWindows() && Path.IsPathRooted(resolved))
Assert.EndsWith("dotnet.exe", resolved, StringComparison.OrdinalIgnoreCase);
else
Assert.Equal("dotnet.exe", resolved);
}
[Fact]
public void Resolve_Npm_PrefersCmdShim_WhenBothBareAndCmdExist()
{
if (!OperatingSystem.IsWindows())
return;
var temp = Path.Combine(Path.GetTempPath(), "sdt-cmdresolve-" + Guid.NewGuid().ToString("N"));
Directory.CreateDirectory(temp);
File.WriteAllText(Path.Combine(temp, "npm"), "");
File.WriteAllText(Path.Combine(temp, "npm.cmd"), "@echo off");
var originalPath = Environment.GetEnvironmentVariable("PATH");
try
{
Environment.SetEnvironmentVariable("PATH", temp);
var resolved = CommandResolver.Resolve("npm");
Assert.EndsWith("npm.cmd", resolved, StringComparison.OrdinalIgnoreCase);
}
finally
{
Environment.SetEnvironmentVariable("PATH", originalPath);
try { Directory.Delete(temp, recursive: true); } catch { }
}
}
[Fact]
public void ResolveWithTrace_ConfiguredOverride_IsUsed()
{
if (!OperatingSystem.IsWindows())
return;
var temp = Path.Combine(Path.GetTempPath(), "sdt-cmdresolve-" + Guid.NewGuid().ToString("N"));
Directory.CreateDirectory(temp);
var overridePath = Path.Combine(temp, "npm.cmd");
File.WriteAllText(overridePath, "@echo off");
var cfg = new DevToolConfig
{
Tooling = new ToolingConfig
{
Tools =
[
new ToolInstallDefinition
{
Tool = "npm",
Executables = [overridePath]
}
]
}
};
var resolved = CommandResolver.ResolveWithTrace("npm", cfg, "npm");
Assert.Equal(CommandResolutionSource.ConfiguredOverride, resolved.Source);
Assert.EndsWith("npm.cmd", resolved.Resolved, StringComparison.OrdinalIgnoreCase);
}
[Fact]
public void ResolveWithTrace_ExpandsWindowsPathTokens()
{
if (!OperatingSystem.IsWindows())
return;
var nvmHome = Path.Combine(Path.GetTempPath(), "sdt-nvmhome-" + Guid.NewGuid().ToString("N"));
var nvmLink = Path.Combine(Path.GetTempPath(), "sdt-nvmlink-" + Guid.NewGuid().ToString("N"));
Directory.CreateDirectory(nvmHome);
Directory.CreateDirectory(nvmLink);
File.WriteAllText(Path.Combine(nvmLink, "npm.cmd"), "@echo off");
var originalPath = Environment.GetEnvironmentVariable("PATH");
var originalHome = Environment.GetEnvironmentVariable("NVM_HOME");
var originalLink = Environment.GetEnvironmentVariable("NVM_SYMLINK");
try
{
Environment.SetEnvironmentVariable("NVM_HOME", nvmHome);
Environment.SetEnvironmentVariable("NVM_SYMLINK", nvmLink);
Environment.SetEnvironmentVariable("PATH", "%NVM_HOME%;%NVM_SYMLINK%");
var result = CommandResolver.ResolveWithTrace("npm");
Assert.True(result.Source is CommandResolutionSource.Shim or CommandResolutionSource.Path);
Assert.EndsWith("npm.cmd", result.Resolved, StringComparison.OrdinalIgnoreCase);
}
finally
{
Environment.SetEnvironmentVariable("PATH", originalPath);
Environment.SetEnvironmentVariable("NVM_HOME", originalHome);
Environment.SetEnvironmentVariable("NVM_SYMLINK", originalLink);
try { Directory.Delete(nvmHome, recursive: true); } catch { }
try { Directory.Delete(nvmLink, recursive: true); } catch { }
}
}
}