Files
ClaudeDo/tests/ClaudeDo.Installer.Tests/Checks/ClaudeCliLookupTests.cs
T
mika kuns 05be07b28c feat(installer): pull in preflight check implementations as prerequisite for SystemCheckPage
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.
2026-08-05 19:56:07 +02:00

85 lines
3.0 KiB
C#

using ClaudeDo.Installer.Checks;
using ClaudeDo.Installer.Core;
namespace ClaudeDo.Installer.Tests.Checks;
public sealed class ClaudeCliLookupTests : IDisposable
{
private readonly string _dir;
public ClaudeCliLookupTests()
{
_dir = Path.Combine(Path.GetTempPath(), $"cdclaudelookup_{Guid.NewGuid():N}");
Directory.CreateDirectory(_dir);
File.WriteAllText(Path.Combine(_dir, "claude.exe"), "");
}
public void Dispose()
{
try { Directory.Delete(_dir, recursive: true); } catch { }
}
[Fact]
public async Task Version_is_executed_only_once_across_repeated_calls()
{
var runner = new FakeProcessRunner((0, "2.1.230 (Claude Code)"));
var lookup = new ClaudeCliLookup(runner, pathOverride: _dir, pathExtOverride: ".exe");
await lookup.ResolveAsync(new InstallContext(), CancellationToken.None);
await lookup.ResolveAsync(new InstallContext(), CancellationToken.None);
await lookup.ResolveAsync(new InstallContext(), CancellationToken.None);
Assert.Single(runner.Calls);
}
[Fact]
public async Task Concurrent_calls_still_run_version_only_once()
{
var runner = new FakeProcessRunner((0, "2.1.230 (Claude Code)"));
var lookup = new ClaudeCliLookup(runner, pathOverride: _dir, pathExtOverride: ".exe");
await Task.WhenAll(Enumerable.Range(0, 8)
.Select(_ => lookup.ResolveAsync(new InstallContext(), CancellationToken.None)));
Assert.Single(runner.Calls);
}
[Fact]
public async Task Version_is_executed_only_once_when_shared_across_all_four_checks()
{
var runner = new FakeProcessRunner((0, "2.1.230 (Claude Code)"));
var lookup = new ClaudeCliLookup(runner, pathOverride: _dir, pathExtOverride: ".exe");
var ctx = new InstallContext();
await new ClaudeCliCheck(lookup).RunAsync(ctx, CancellationToken.None);
await new ClaudeVersionCheck(lookup).RunAsync(ctx, CancellationToken.None);
await new ClaudeAuthCheck(lookup).RunAsync(ctx, CancellationToken.None);
await new PermissionModeAutoCheck(lookup).RunAsync(ctx, CancellationToken.None);
var versionCalls = runner.Calls.Count(c => c.Arguments.Contains("--version"));
Assert.Equal(1, versionCalls);
}
[Fact]
public async Task Cli_not_found_returns_null_resolved_without_running_a_process()
{
var emptyDir = Path.Combine(Path.GetTempPath(), $"cdclaudelookup_empty_{Guid.NewGuid():N}");
Directory.CreateDirectory(emptyDir);
try
{
var runner = new FakeProcessRunner();
var lookup = new ClaudeCliLookup(runner, pathOverride: emptyDir, pathExtOverride: ".exe");
var ctx = new InstallContext { ClaudeBin = "claudedo_totally_missing_cmd_9f3a1" };
var result = await lookup.ResolveAsync(ctx, CancellationToken.None);
Assert.Null(result.Resolved);
Assert.Empty(runner.Calls);
}
finally
{
Directory.Delete(emptyDir, recursive: true);
}
}
}