using ClaudeDo.Installer.Core; namespace ClaudeDo.Installer.Tests; public sealed class InstallModeDetectorTests : IDisposable { private readonly string _tempDir; public InstallModeDetectorTests() { _tempDir = Path.Combine(Path.GetTempPath(), "ClaudeDoDetector-" + Guid.NewGuid().ToString("N")); Directory.CreateDirectory(_tempDir); } public void Dispose() { try { Directory.Delete(_tempDir, recursive: true); } catch { } } private sealed class FakeReleaseClient : IReleaseClient { public GiteaRelease? Release { get; set; } public Task GetLatestReleaseAsync(CancellationToken ct) => Task.FromResult(Release); public Task DownloadAsync(string url, string destPath, IProgress progress, CancellationToken ct) => throw new NotSupportedException(); } [Fact] public async Task Detect_FreshInstall_WhenManifestMissing() { var detector = new InstallModeDetector(new FakeReleaseClient()); var state = await detector.DetectAsync(_tempDir, CancellationToken.None); Assert.Equal(InstallerMode.FreshInstall, state.Mode); Assert.Null(state.Existing); } [Fact] public async Task Detect_Config_WhenManifestPresent_And_Api_Unreachable() { InstallManifestStore.Write(_tempDir, new InstallManifest("0.1.0", _tempDir, _tempDir, DateTimeOffset.UtcNow)); var detector = new InstallModeDetector(new FakeReleaseClient { Release = null }); var state = await detector.DetectAsync(_tempDir, CancellationToken.None); Assert.Equal(InstallerMode.Config, state.Mode); Assert.Equal("0.1.0", state.Existing!.Version); } [Fact] public async Task Detect_Update_WhenLatest_GreaterThan_Installed() { InstallManifestStore.Write(_tempDir, new InstallManifest("0.1.0", _tempDir, _tempDir, DateTimeOffset.UtcNow)); var fake = new FakeReleaseClient { Release = new GiteaRelease("v0.2.0", "v0.2.0", Array.Empty()) }; var detector = new InstallModeDetector(fake); var state = await detector.DetectAsync(_tempDir, CancellationToken.None); Assert.Equal(InstallerMode.Update, state.Mode); Assert.Equal("0.1.0", state.Existing!.Version); Assert.Equal("0.2.0", state.LatestVersion); } [Fact] public async Task Detect_Config_WhenLatest_EqualsOrOlderThan_Installed() { InstallManifestStore.Write(_tempDir, new InstallManifest("0.2.0", _tempDir, _tempDir, DateTimeOffset.UtcNow)); var fake = new FakeReleaseClient { Release = new GiteaRelease("v0.2.0", "v0.2.0", Array.Empty()) }; var detector = new InstallModeDetector(fake); var state = await detector.DetectAsync(_tempDir, CancellationToken.None); Assert.Equal(InstallerMode.Config, state.Mode); } [Fact] public async Task Detect_Config_WhenInstalledIs_Newer_Than_Latest() { InstallManifestStore.Write(_tempDir, new InstallManifest("0.3.0", _tempDir, _tempDir, DateTimeOffset.UtcNow)); var fake = new FakeReleaseClient { Release = new GiteaRelease("v0.2.0", "v0.2.0", Array.Empty()) }; var detector = new InstallModeDetector(fake); var state = await detector.DetectAsync(_tempDir, CancellationToken.None); Assert.Equal(InstallerMode.Config, state.Mode); } }