using JdeScoping.Api.Hubs; using JdeScoping.Core.Models; using JdeScoping.Core.Models.Enums; using JdeScoping.Core.Models.Infrastructure; using JdeScoping.Core.Models.Search; using Microsoft.AspNetCore.SignalR; using Microsoft.Extensions.Logging; using NSubstitute; using Shouldly; namespace JdeScoping.Api.Tests.Hubs; public class StatusHubTests { private readonly ILogger _logger; private readonly StatusHub _hub; public StatusHubTests() { _logger = Substitute.For>(); _hub = new StatusHub(_logger); } [Fact] public async Task SetStatus_CachesAndBroadcasts() { // Arrange var clientProxy = Substitute.For(); var hubClients = Substitute.For(); hubClients.All.Returns(clientProxy); var hubContext = Substitute.For(); hubContext.ConnectionId.Returns("test-connection-id"); // Use reflection to set the Clients property since Hub properties are typically set by the framework var clientsProperty = typeof(Hub).GetProperty("Clients"); clientsProperty?.SetValue(_hub, hubClients); var statusUpdate = new StatusUpdate { Message = "Processing", Timestamp = DateTime.UtcNow }; // Act await _hub.SetStatus(statusUpdate); // Assert - verify broadcast was called await clientProxy.Received(1).SendCoreAsync( "statusUpdate", Arg.Is(args => args.Length == 1 && args[0] == statusUpdate), Arg.Any()); } [Fact] public void GetCachedStatus_ReturnsLastSetStatus() { // The hub uses a static cached status, so this test checks the initial state // Note: Due to static state, tests may affect each other if run in parallel // Act var status = _hub.GetCachedStatus(); // Assert status.ShouldNotBeNull(); // Initial message is "Unknown" status.Message.ShouldNotBeNullOrEmpty(); } [Fact] public void GetCachedStatus_InitialStatusIsUnknown() { // This test verifies the default initial state // Note: This test assumes no other test has modified the static state // Act var status = _hub.GetCachedStatus(); // Assert status.ShouldNotBeNull(); // The timestamp should be set status.Timestamp.ShouldNotBe(default); } [Fact] public async Task PublishSearchUpdate_BroadcastsToAll() { // Arrange var clientProxy = Substitute.For(); var hubClients = Substitute.For(); hubClients.All.Returns(clientProxy); var clientsProperty = typeof(Hub).GetProperty("Clients"); clientsProperty?.SetValue(_hub, hubClients); var searchUpdate = new SearchUpdate { Id = 42, UserName = "testuser", Name = "Test Search", Status = SearchStatus.Running, Timestamp = DateTime.UtcNow }; // Act await _hub.PublishSearchUpdate(searchUpdate); // Assert await clientProxy.Received(1).SendCoreAsync( "searchUpdate", Arg.Is(args => args.Length == 1 && args[0] == searchUpdate), Arg.Any()); } }