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

117 lines
3.7 KiB
C#

using System.Diagnostics;
using System.Text.Json;
using System.Runtime.CompilerServices;
using Xunit;
namespace DevTool.Tests;
public sealed class DevShellScriptTests
{
[Theory]
[InlineData("pwsh")]
[InlineData("bash")]
[InlineData("zsh")]
[InlineData("cmd")]
public async Task DevShellExport_ReturnsSuccess_ForSupportedShells(string shell)
{
var python = ResolvePython();
var result = await RunAsync(
python,
["scripts/dev_shell.py", "export", "--shell", shell, "--json"]);
Assert.Equal(0, result.ExitCode);
using var doc = JsonDocument.Parse(result.StdOut);
Assert.True(doc.RootElement.TryGetProperty("projectRoot", out _));
Assert.True(doc.RootElement.TryGetProperty("env", out _));
}
[Fact]
public async Task DevShellExport_InvalidShell_ReturnsExitCode3()
{
var python = ResolvePython();
var result = await RunAsync(
python,
["scripts/dev_shell.py", "export", "--shell", "fish"]);
Assert.Equal(3, result.ExitCode);
}
[Fact]
public async Task DevShellDoctor_ReturnsJson()
{
var python = ResolvePython();
var result = await RunAsync(
python,
["scripts/dev_shell.py", "doctor"]);
Assert.Equal(0, result.ExitCode);
using var doc = JsonDocument.Parse(result.StdOut);
Assert.True(doc.RootElement.TryGetProperty("repo_root", out _));
}
private static string ResolvePython()
{
var candidates = OperatingSystem.IsWindows()
? new[] { "python", "py" }
: new[] { "python3", "python" };
foreach (var candidate in candidates)
{
try
{
using var process = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = candidate,
RedirectStandardOutput = true,
RedirectStandardError = true,
UseShellExecute = false,
CreateNoWindow = true,
}
};
process.StartInfo.ArgumentList.Add("--version");
process.Start();
process.WaitForExit(2000);
if (process.ExitCode == 0)
return candidate;
}
catch
{
}
}
throw new InvalidOperationException("Python executable not found.");
}
private static async Task<(int ExitCode, string StdOut, string StdErr)> RunAsync(string command, IReadOnlyList<string> args)
{
var psi = new ProcessStartInfo
{
FileName = command,
RedirectStandardOutput = true,
RedirectStandardError = true,
UseShellExecute = false,
CreateNoWindow = true,
WorkingDirectory = RepoRoot(),
};
foreach (var arg in args)
psi.ArgumentList.Add(arg);
using var process = new Process { StartInfo = psi };
process.Start();
var stdout = await process.StandardOutput.ReadToEndAsync();
var stderr = await process.StandardError.ReadToEndAsync();
await process.WaitForExitAsync();
return (process.ExitCode, stdout, stderr);
}
private static string RepoRoot([CallerFilePath] string file = "")
{
var repoRoot = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(file)!, "..", ".."));
if (!File.Exists(Path.Combine(repoRoot, "scripts", "dev_shell.py")))
throw new InvalidOperationException("Could not locate repo root.");
return repoRoot;
}
}