Git/GitIdentity/Port/WriteAccess and Claude CLI/Version/Auth/PermissionModeAuto checks plus the ExecutableResolver they depend on were built in two sibling task branches that hadn't landed on main yet. Vendored the finished files in from those branches (same content, verified building + tests green) so the SystemCheckPage task has something to consume.
80 lines
3.0 KiB
C#
80 lines
3.0 KiB
C#
using ClaudeDo.Installer.Checks;
|
|
using ClaudeDo.Installer.Core;
|
|
|
|
namespace ClaudeDo.Installer.Tests.Checks;
|
|
|
|
public sealed class ClaudeCliCheckTests : IDisposable
|
|
{
|
|
private readonly string _dir;
|
|
|
|
public ClaudeCliCheckTests()
|
|
{
|
|
_dir = Path.Combine(Path.GetTempPath(), $"cdclaudecli_{Guid.NewGuid():N}");
|
|
Directory.CreateDirectory(_dir);
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
try { Directory.Delete(_dir, recursive: true); } catch { }
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Found_as_exe_reports_ok_with_path_and_version_and_no_shim_detail()
|
|
{
|
|
File.WriteAllText(Path.Combine(_dir, "claude.exe"), "");
|
|
var runner = new FakeProcessRunner((0, "2.1.230 (Claude Code)"));
|
|
var check = new ClaudeCliCheck(new ClaudeCliLookup(runner, pathOverride: _dir, pathExtOverride: ".exe"));
|
|
|
|
var result = await check.RunAsync(new InstallContext(), CancellationToken.None);
|
|
|
|
Assert.Equal(CheckStatus.Ok, result.Status);
|
|
Assert.Contains(_dir, result.Message);
|
|
Assert.Contains("2.1.230", result.Message);
|
|
Assert.Null(result.Detail);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Found_as_shim_flags_it_in_detail()
|
|
{
|
|
File.WriteAllText(Path.Combine(_dir, "claude.cmd"), "");
|
|
var runner = new FakeProcessRunner((0, "2.1.230 (Claude Code)"));
|
|
var check = new ClaudeCliCheck(new ClaudeCliLookup(runner, pathOverride: _dir, pathExtOverride: ".cmd"));
|
|
|
|
var result = await check.RunAsync(new InstallContext(), CancellationToken.None);
|
|
|
|
Assert.Equal(CheckStatus.Ok, result.Status);
|
|
Assert.NotNull(result.Detail);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Not_found_reports_failed_naming_searched_locations()
|
|
{
|
|
var runner = new FakeProcessRunner();
|
|
var check = new ClaudeCliCheck(new ClaudeCliLookup(runner, pathOverride: _dir, pathExtOverride: ".exe"));
|
|
// A distinctive, definitely-missing name — a plain "claude" would still resolve via
|
|
// ExecutableResolver's fixed fallback dirs (e.g. %USERPROFILE%\.local\bin) on a machine
|
|
// that has the real CLI installed, regardless of pathOverride.
|
|
var ctx = new InstallContext { ClaudeBin = "claudedo_totally_missing_cmd_9f3a1" };
|
|
|
|
var result = await check.RunAsync(ctx, CancellationToken.None);
|
|
|
|
Assert.Equal(CheckStatus.Failed, result.Status);
|
|
Assert.Equal(CheckSeverity.Error, result.Severity);
|
|
Assert.Contains(_dir, result.Message);
|
|
Assert.NotNull(result.HintKey);
|
|
Assert.Empty(runner.Calls);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Nonzero_exit_reports_failed()
|
|
{
|
|
File.WriteAllText(Path.Combine(_dir, "claude.exe"), "");
|
|
var runner = new FakeProcessRunner((1, "some error"));
|
|
var check = new ClaudeCliCheck(new ClaudeCliLookup(runner, pathOverride: _dir, pathExtOverride: ".exe"));
|
|
|
|
var result = await check.RunAsync(new InstallContext(), CancellationToken.None);
|
|
|
|
Assert.Equal(CheckStatus.Failed, result.Status);
|
|
}
|
|
}
|