mirror of
https://github.com/Kareadita/Kavita.git
synced 2025-05-31 04:04:19 -04:00
455 lines
14 KiB
C#
455 lines
14 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Net.Http;
|
|
using System.Reflection;
|
|
using System.Threading.Tasks;
|
|
using API.DTOs.Update;
|
|
using API.Extensions;
|
|
using API.Services;
|
|
using API.Services.Tasks;
|
|
using API.SignalR;
|
|
using Flurl.Http;
|
|
using Flurl.Http.Testing;
|
|
using Kavita.Common.EnvironmentInfo;
|
|
using Microsoft.Extensions.Logging;
|
|
using NSubstitute;
|
|
using Xunit;
|
|
|
|
namespace API.Tests.Services;
|
|
|
|
public class VersionUpdaterServiceTests : IDisposable
|
|
{
|
|
private readonly ILogger<VersionUpdaterService> _logger;
|
|
private readonly IEventHub _eventHub;
|
|
private readonly IDirectoryService _directoryService;
|
|
private readonly VersionUpdaterService _service;
|
|
private readonly string _tempPath;
|
|
private readonly HttpTest _httpTest;
|
|
|
|
public VersionUpdaterServiceTests()
|
|
{
|
|
_logger = Substitute.For<ILogger<VersionUpdaterService>>();
|
|
_eventHub = Substitute.For<IEventHub>();
|
|
_directoryService = Substitute.For<IDirectoryService>();
|
|
|
|
// Create temp directory for cache
|
|
_tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
|
Directory.CreateDirectory(_tempPath);
|
|
_directoryService.LongTermCacheDirectory.Returns(_tempPath);
|
|
|
|
_service = new VersionUpdaterService(_logger, _eventHub, _directoryService);
|
|
|
|
// Setup HTTP testing
|
|
_httpTest = new HttpTest();
|
|
|
|
// Mock BuildInfo.Version for consistent testing
|
|
typeof(BuildInfo).GetProperty(nameof(BuildInfo.Version))?.SetValue(null, new Version("0.5.0.0"));
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
_httpTest.Dispose();
|
|
|
|
// Cleanup temp directory
|
|
if (Directory.Exists(_tempPath))
|
|
{
|
|
Directory.Delete(_tempPath, true);
|
|
}
|
|
|
|
// Reset BuildInfo.Version
|
|
typeof(BuildInfo).GetProperty(nameof(BuildInfo.Version))?.SetValue(null, null);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task CheckForUpdate_ShouldReturnNull_WhenGithubApiReturnsNull()
|
|
{
|
|
|
|
_httpTest.RespondWith("null");
|
|
|
|
|
|
var result = await _service.CheckForUpdate();
|
|
|
|
|
|
Assert.Null(result);
|
|
}
|
|
|
|
// Depends on BuildInfo.CurrentVersion
|
|
//[Fact]
|
|
public async Task CheckForUpdate_ShouldReturnUpdateNotification_WhenNewVersionIsAvailable()
|
|
{
|
|
|
|
var githubResponse = new
|
|
{
|
|
tag_name = "v0.6.0",
|
|
name = "Release 0.6.0",
|
|
body = "# Added\n- Feature 1\n- Feature 2\n# Fixed\n- Bug 1\n- Bug 2",
|
|
html_url = "https://github.com/Kareadita/Kavita/releases/tag/v0.6.0",
|
|
published_at = DateTime.UtcNow.ToString("o")
|
|
};
|
|
|
|
_httpTest.RespondWithJson(githubResponse);
|
|
|
|
|
|
var result = await _service.CheckForUpdate();
|
|
|
|
|
|
Assert.NotNull(result);
|
|
Assert.Equal("0.6.0", result.UpdateVersion);
|
|
Assert.Equal("0.5.0.0", result.CurrentVersion);
|
|
Assert.True(result.IsReleaseNewer);
|
|
Assert.Equal(2, result.Added.Count);
|
|
Assert.Equal(2, result.Fixed.Count);
|
|
}
|
|
|
|
//[Fact]
|
|
public async Task CheckForUpdate_ShouldDetectEqualVersion()
|
|
{
|
|
// I can't figure this out
|
|
typeof(BuildInfo).GetProperty(nameof(BuildInfo.Version))?.SetValue(null, new Version("0.5.0.0"));
|
|
|
|
|
|
var githubResponse = new
|
|
{
|
|
tag_name = "v0.5.0",
|
|
name = "Release 0.5.0",
|
|
body = "# Added\n- Feature 1",
|
|
html_url = "https://github.com/Kareadita/Kavita/releases/tag/v0.5.0",
|
|
published_at = DateTime.UtcNow.ToString("o")
|
|
};
|
|
|
|
_httpTest.RespondWithJson(githubResponse);
|
|
|
|
|
|
var result = await _service.CheckForUpdate();
|
|
|
|
|
|
Assert.NotNull(result);
|
|
Assert.True(result.IsReleaseEqual);
|
|
Assert.False(result.IsReleaseNewer);
|
|
}
|
|
|
|
|
|
//[Fact]
|
|
public async Task PushUpdate_ShouldSendUpdateEvent_WhenNewerVersionAvailable()
|
|
{
|
|
|
|
var update = new UpdateNotificationDto
|
|
{
|
|
UpdateVersion = "0.6.0",
|
|
CurrentVersion = "0.5.0.0",
|
|
UpdateBody = "",
|
|
UpdateTitle = null,
|
|
UpdateUrl = null,
|
|
PublishDate = null
|
|
};
|
|
|
|
|
|
await _service.PushUpdate(update);
|
|
|
|
|
|
await _eventHub.Received(1).SendMessageAsync(
|
|
Arg.Is(MessageFactory.UpdateAvailable),
|
|
Arg.Any<SignalRMessage>(),
|
|
Arg.Is(true)
|
|
);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task PushUpdate_ShouldNotSendUpdateEvent_WhenVersionIsEqual()
|
|
{
|
|
|
|
var update = new UpdateNotificationDto
|
|
{
|
|
UpdateVersion = "0.5.0.0",
|
|
CurrentVersion = "0.5.0.0",
|
|
UpdateBody = "",
|
|
UpdateTitle = null,
|
|
UpdateUrl = null,
|
|
PublishDate = null
|
|
};
|
|
|
|
|
|
await _service.PushUpdate(update);
|
|
|
|
|
|
await _eventHub.DidNotReceive().SendMessageAsync(
|
|
Arg.Any<string>(),
|
|
Arg.Any<SignalRMessage>(),
|
|
Arg.Any<bool>()
|
|
);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task GetAllReleases_ShouldReturnReleases_LimitedByCount()
|
|
{
|
|
|
|
var releases = new List<object>
|
|
{
|
|
new
|
|
{
|
|
tag_name = "v0.7.0",
|
|
name = "Release 0.7.0",
|
|
body = "# Added\n- Feature A",
|
|
html_url = "https://github.com/Kareadita/Kavita/releases/tag/v0.7.0",
|
|
published_at = DateTime.UtcNow.AddDays(-1).ToString("o")
|
|
},
|
|
new
|
|
{
|
|
tag_name = "v0.6.0",
|
|
name = "Release 0.6.0",
|
|
body = "# Added\n- Feature B",
|
|
html_url = "https://github.com/Kareadita/Kavita/releases/tag/v0.6.0",
|
|
published_at = DateTime.UtcNow.AddDays(-10).ToString("o")
|
|
},
|
|
new
|
|
{
|
|
tag_name = "v0.5.0",
|
|
name = "Release 0.5.0",
|
|
body = "# Added\n- Feature C",
|
|
html_url = "https://github.com/Kareadita/Kavita/releases/tag/v0.5.0",
|
|
published_at = DateTime.UtcNow.AddDays(-20).ToString("o")
|
|
}
|
|
};
|
|
|
|
_httpTest.RespondWithJson(releases);
|
|
|
|
|
|
var result = await _service.GetAllReleases(2);
|
|
|
|
|
|
Assert.Equal(2, result.Count);
|
|
Assert.Equal("0.7.0.0", result[0].UpdateVersion);
|
|
Assert.Equal("0.6.0", result[1].UpdateVersion);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task GetAllReleases_ShouldUseCachedData_WhenCacheIsValid()
|
|
{
|
|
|
|
var releases = new List<UpdateNotificationDto>
|
|
{
|
|
new()
|
|
{
|
|
UpdateVersion = "0.6.0",
|
|
CurrentVersion = "0.5.0.0",
|
|
PublishDate = DateTime.UtcNow.AddDays(-10)
|
|
.ToString("o"),
|
|
UpdateBody = "",
|
|
UpdateTitle = null,
|
|
UpdateUrl = null
|
|
}
|
|
};
|
|
releases.Add(new()
|
|
{
|
|
UpdateVersion = "0.7.0",
|
|
CurrentVersion = "0.5.0.0",
|
|
PublishDate = DateTime.UtcNow.AddDays(-1)
|
|
.ToString("o"),
|
|
UpdateBody = "",
|
|
UpdateTitle = null,
|
|
UpdateUrl = null
|
|
});
|
|
|
|
// Create cache file
|
|
var cacheFilePath = Path.Combine(_tempPath, "github_releases_cache.json");
|
|
await File.WriteAllTextAsync(cacheFilePath, System.Text.Json.JsonSerializer.Serialize(releases));
|
|
File.SetLastWriteTimeUtc(cacheFilePath, DateTime.UtcNow); // Ensure it's fresh
|
|
|
|
|
|
var result = await _service.GetAllReleases();
|
|
|
|
|
|
Assert.Equal(2, result.Count);
|
|
Assert.Empty(_httpTest.CallLog); // No HTTP calls made
|
|
}
|
|
|
|
[Fact]
|
|
public async Task GetAllReleases_ShouldFetchNewData_WhenCacheIsExpired()
|
|
{
|
|
|
|
var releases = new List<UpdateNotificationDto>
|
|
{
|
|
new()
|
|
{
|
|
UpdateVersion = "0.6.0",
|
|
CurrentVersion = "0.5.0.0",
|
|
PublishDate = DateTime.UtcNow.AddDays(-10)
|
|
.ToString("o"),
|
|
UpdateBody = null,
|
|
UpdateTitle = null,
|
|
UpdateUrl = null
|
|
}
|
|
};
|
|
|
|
// Create expired cache file
|
|
var cacheFilePath = Path.Combine(_tempPath, "github_releases_cache.json");
|
|
await File.WriteAllTextAsync(cacheFilePath, System.Text.Json.JsonSerializer.Serialize(releases));
|
|
File.SetLastWriteTimeUtc(cacheFilePath, DateTime.UtcNow.AddHours(-2)); // Expired (older than 1 hour)
|
|
|
|
// Setup HTTP response for new fetch
|
|
var newReleases = new List<object>
|
|
{
|
|
new
|
|
{
|
|
tag_name = "v0.7.0",
|
|
name = "Release 0.7.0",
|
|
body = "# Added\n- Feature A",
|
|
html_url = "https://github.com/Kareadita/Kavita/releases/tag/v0.7.0",
|
|
published_at = DateTime.UtcNow.ToString("o")
|
|
}
|
|
};
|
|
|
|
_httpTest.RespondWithJson(newReleases);
|
|
|
|
|
|
var result = await _service.GetAllReleases();
|
|
|
|
|
|
Assert.Equal(1, result.Count);
|
|
Assert.Equal("0.7.0.0", result[0].UpdateVersion);
|
|
Assert.NotEmpty(_httpTest.CallLog); // HTTP call was made
|
|
}
|
|
|
|
public async Task GetNumberOfReleasesBehind_ShouldReturnCorrectCount()
|
|
{
|
|
|
|
var releases = new List<object>
|
|
{
|
|
new
|
|
{
|
|
tag_name = "v0.7.0",
|
|
name = "Release 0.7.0",
|
|
body = "# Added\n- Feature A",
|
|
html_url = "https://github.com/Kareadita/Kavita/releases/tag/v0.7.0",
|
|
published_at = DateTime.UtcNow.AddDays(-1).ToString("o")
|
|
},
|
|
new
|
|
{
|
|
tag_name = "v0.6.0",
|
|
name = "Release 0.6.0",
|
|
body = "# Added\n- Feature B",
|
|
html_url = "https://github.com/Kareadita/Kavita/releases/tag/v0.6.0",
|
|
published_at = DateTime.UtcNow.AddDays(-10).ToString("o")
|
|
},
|
|
new
|
|
{
|
|
tag_name = "v0.5.0",
|
|
name = "Release 0.5.0",
|
|
body = "# Added\n- Feature C",
|
|
html_url = "https://github.com/Kareadita/Kavita/releases/tag/v0.5.0",
|
|
published_at = DateTime.UtcNow.AddDays(-20).ToString("o")
|
|
}
|
|
};
|
|
|
|
_httpTest.RespondWithJson(releases);
|
|
|
|
|
|
var result = await _service.GetNumberOfReleasesBehind();
|
|
|
|
|
|
Assert.Equal(2 + 1, result); // Behind 0.7.0 and 0.6.0 - We have to add 1 because the current release is > 0.7.0
|
|
}
|
|
|
|
public async Task GetNumberOfReleasesBehind_ShouldReturnCorrectCount_WithNightlies()
|
|
{
|
|
|
|
var releases = new List<object>
|
|
{
|
|
new
|
|
{
|
|
tag_name = "v0.7.1",
|
|
name = "Release 0.7.1",
|
|
body = "# Added\n- Feature A",
|
|
html_url = "https://github.com/Kareadita/Kavita/releases/tag/v0.7.1",
|
|
published_at = DateTime.UtcNow.AddDays(-1).ToString("o")
|
|
},
|
|
new
|
|
{
|
|
tag_name = "v0.7.0",
|
|
name = "Release 0.7.0",
|
|
body = "# Added\n- Feature A",
|
|
html_url = "https://github.com/Kareadita/Kavita/releases/tag/v0.7.0",
|
|
published_at = DateTime.UtcNow.AddDays(-10).ToString("o")
|
|
},
|
|
};
|
|
|
|
_httpTest.RespondWithJson(releases);
|
|
|
|
|
|
var result = await _service.GetNumberOfReleasesBehind();
|
|
|
|
|
|
Assert.Equal(2, result); // We have to add 1 because the current release is > 0.7.0
|
|
}
|
|
|
|
[Fact]
|
|
public async Task ParseReleaseBody_ShouldExtractSections()
|
|
{
|
|
|
|
var githubResponse = new
|
|
{
|
|
tag_name = "v0.6.0",
|
|
name = "Release 0.6.0",
|
|
body = "This is a great release with many improvements!\n\n# Added\n- Feature 1\n- Feature 2\n# Fixed\n- Bug 1\n- Bug 2\n# Changed\n- Change 1\n# Developer\n- Dev note 1",
|
|
html_url = "https://github.com/Kareadita/Kavita/releases/tag/v0.6.0",
|
|
published_at = DateTime.UtcNow.ToString("o")
|
|
};
|
|
|
|
_httpTest.RespondWithJson(githubResponse);
|
|
|
|
|
|
var result = await _service.CheckForUpdate();
|
|
|
|
|
|
Assert.NotNull(result);
|
|
Assert.Equal(2, result.Added.Count);
|
|
Assert.Equal(2, result.Fixed.Count);
|
|
Assert.Equal(1, result.Changed.Count);
|
|
Assert.Equal(1, result.Developer.Count);
|
|
Assert.Contains("This is a great release", result.BlogPart);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task GetAllReleases_ShouldHandleNightlyBuilds()
|
|
{
|
|
|
|
// Set BuildInfo.Version to a nightly build version
|
|
typeof(BuildInfo).GetProperty(nameof(BuildInfo.Version))?.SetValue(null, new Version("0.7.1.0"));
|
|
|
|
// Mock regular releases
|
|
var releases = new List<object>
|
|
{
|
|
new
|
|
{
|
|
tag_name = "v0.7.0",
|
|
name = "Release 0.7.0",
|
|
body = "# Added\n- Feature A",
|
|
html_url = "https://github.com/Kareadita/Kavita/releases/tag/v0.7.0",
|
|
published_at = DateTime.UtcNow.AddDays(-1).ToString("o")
|
|
},
|
|
new
|
|
{
|
|
tag_name = "v0.6.0",
|
|
name = "Release 0.6.0",
|
|
body = "# Added\n- Feature B",
|
|
html_url = "https://github.com/Kareadita/Kavita/releases/tag/v0.6.0",
|
|
published_at = DateTime.UtcNow.AddDays(-10).ToString("o")
|
|
}
|
|
};
|
|
|
|
_httpTest.RespondWithJson(releases);
|
|
|
|
// Mock commit info for develop branch
|
|
_httpTest.RespondWithJson(new List<object>());
|
|
|
|
|
|
var result = await _service.GetAllReleases();
|
|
|
|
|
|
Assert.NotNull(result);
|
|
Assert.True(result[0].IsOnNightlyInRelease);
|
|
}
|
|
}
|