using System.Net.Http; using ClaudeDo.Releases; using ClaudeDo.Ui.Services; namespace ClaudeDo.Ui.Tests.Services; public class UpdateCheckServiceTests { private sealed class FakeReleaseClient : IReleaseClient { public GiteaRelease? Release { get; set; } public bool Throw { get; set; } public Task GetLatestReleaseAsync(CancellationToken ct) { if (Throw) throw new HttpRequestException(); return Task.FromResult(Release); } public Task DownloadAsync(string url, string destPath, IProgress progress, CancellationToken ct) => throw new NotSupportedException(); } [Fact] public async Task Check_NewerRelease_SetsUpdateAvailable() { var svc = new UpdateCheckService(new FakeReleaseClient { Release = new GiteaRelease("v0.3.0", "r", new[] { new ReleaseAsset("ClaudeDo-0.3.0-win-x64.zip", "u", 1) }), }, currentVersion: "0.1.0"); await svc.CheckNowAsync(CancellationToken.None); Assert.Equal(UpdateCheckStatus.UpdateAvailable, svc.LastCheckStatus); Assert.True(svc.IsUpdateAvailable); Assert.Equal("0.3.0", svc.LatestVersion); } [Fact] public async Task Check_SameRelease_SetsUpToDate() { var svc = new UpdateCheckService(new FakeReleaseClient { Release = new GiteaRelease("v0.1.0", "r", new[] { new ReleaseAsset("ClaudeDo-0.1.0-win-x64.zip", "u", 1) }), }, currentVersion: "0.1.0"); await svc.CheckNowAsync(CancellationToken.None); Assert.Equal(UpdateCheckStatus.UpToDate, svc.LastCheckStatus); Assert.False(svc.IsUpdateAvailable); } [Fact] public async Task Check_NetworkError_SetsCheckFailedButDoesNotThrow() { var svc = new UpdateCheckService(new FakeReleaseClient { Throw = true }, "0.1.0"); await svc.CheckNowAsync(CancellationToken.None); Assert.Equal(UpdateCheckStatus.CheckFailed, svc.LastCheckStatus); } }