using System.Net; using System.Text; using System.Text.Json; using Cleanuparr.Domain.Entities.AppStatus; using Cleanuparr.Infrastructure.Hubs; using Cleanuparr.Infrastructure.Services; using Microsoft.AspNetCore.SignalR; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Moq; using Moq.Protected; using Xunit; namespace Cleanuparr.Infrastructure.Tests.Services; public class AppStatusRefreshServiceTests : IDisposable { private readonly Mock> _loggerMock; private readonly Mock> _hubContextMock; private readonly Mock _httpClientFactoryMock; private readonly AppStatusSnapshot _snapshot; private readonly JsonSerializerOptions _jsonOptions; private readonly Mock _httpHandlerMock; private readonly Mock _scopeFactoryMock; private AppStatusRefreshService? _service; public AppStatusRefreshServiceTests() { _loggerMock = new Mock>(); _hubContextMock = new Mock>(); _httpClientFactoryMock = new Mock(); _snapshot = new AppStatusSnapshot(); _jsonOptions = new JsonSerializerOptions { PropertyNameCaseInsensitive = true }; _httpHandlerMock = new Mock(); _scopeFactoryMock = new Mock(); // Setup hub context var clientsMock = new Mock(); var clientProxyMock = new Mock(); clientsMock.Setup(c => c.All).Returns(clientProxyMock.Object); _hubContextMock.Setup(h => h.Clients).Returns(clientsMock.Object); } public void Dispose() { _service?.Dispose(); } private AppStatusRefreshService CreateService() { _service = new AppStatusRefreshService( _loggerMock.Object, _hubContextMock.Object, _httpClientFactoryMock.Object, _snapshot, _jsonOptions, _scopeFactoryMock.Object); return _service; } private void SetupHttpResponse(HttpStatusCode statusCode, string content) { _httpHandlerMock.Protected() .Setup>( "SendAsync", ItExpr.IsAny(), ItExpr.IsAny()) .ReturnsAsync(new HttpResponseMessage { StatusCode = statusCode, Content = new StringContent(content, Encoding.UTF8, "application/json") }); var httpClient = new HttpClient(_httpHandlerMock.Object); _httpClientFactoryMock.Setup(f => f.CreateClient(It.IsAny())).Returns(httpClient); } #region Constructor Tests [Fact] public void Constructor_SetsAllDependencies() { // Act var service = CreateService(); // Assert Assert.NotNull(service); } #endregion #region AppStatusSnapshot Integration Tests [Fact] public void AppStatusSnapshot_UpdateLatestVersion_ChangesStatusReturnsTrue() { // Arrange var snapshot = new AppStatusSnapshot(); // Act var result = snapshot.UpdateLatestVersion("1.0.0", out var status); // Assert Assert.True(result); Assert.Equal("1.0.0", status.LatestVersion); } [Fact] public void AppStatusSnapshot_UpdateLatestVersion_SameVersionReturnsFalse() { // Arrange var snapshot = new AppStatusSnapshot(); snapshot.UpdateLatestVersion("1.0.0", out _); // Act var result = snapshot.UpdateLatestVersion("1.0.0", out var status); // Assert Assert.False(result); Assert.Equal("1.0.0", status.LatestVersion); } [Fact] public void AppStatusSnapshot_UpdateCurrentVersion_ChangesStatusReturnsTrue() { // Arrange var snapshot = new AppStatusSnapshot(); // Act var result = snapshot.UpdateCurrentVersion("2.0.0", out var status); // Assert Assert.True(result); Assert.Equal("2.0.0", status.CurrentVersion); } [Fact] public void AppStatusSnapshot_Current_ReturnsCurrentState() { // Arrange var snapshot = new AppStatusSnapshot(); snapshot.UpdateCurrentVersion("1.0.0", out _); snapshot.UpdateLatestVersion("2.0.0", out _); // Act var current = snapshot.Current; // Assert Assert.Equal("1.0.0", current.CurrentVersion); Assert.Equal("2.0.0", current.LatestVersion); } [Fact] public void AppStatusSnapshot_UpdateWithNull_HandlesCorrectly() { // Arrange var snapshot = new AppStatusSnapshot(); snapshot.UpdateLatestVersion("1.0.0", out _); // Act var result = snapshot.UpdateLatestVersion(null, out var status); // Assert Assert.True(result); Assert.Null(status.LatestVersion); } [Fact] public void AppStatusSnapshot_UpdateWithSameNull_ReturnsFalse() { // Arrange var snapshot = new AppStatusSnapshot(); // Act - Both are null initially var result = snapshot.UpdateLatestVersion(null, out _); // Assert Assert.False(result); } #endregion }