Files
jdescopingtool/NEW/tests/JdeScoping.Api.Tests/Hubs/StatusHubTests.cs
T
Joseph Doherty 26ff8d9b4f Initial commit: JDE Scoping Tool migration project
Set up repository with legacy .NET Framework 4.8 source (OLD/),
new .NET 10 Blazor solution (NEW/), OpenSpec specifications,
documentation, and project configuration.
2026-01-02 07:43:29 -05:00

115 lines
3.5 KiB
C#

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<StatusHub> _logger;
private readonly StatusHub _hub;
public StatusHubTests()
{
_logger = Substitute.For<ILogger<StatusHub>>();
_hub = new StatusHub(_logger);
}
[Fact]
public async Task SetStatus_CachesAndBroadcasts()
{
// Arrange
var clientProxy = Substitute.For<IClientProxy>();
var hubClients = Substitute.For<IHubCallerClients>();
hubClients.All.Returns(clientProxy);
var hubContext = Substitute.For<HubCallerContext>();
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<object?[]>(args => args.Length == 1 && args[0] == statusUpdate),
Arg.Any<CancellationToken>());
}
[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<IClientProxy>();
var hubClients = Substitute.For<IHubCallerClients>();
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<object?[]>(args => args.Length == 1 && args[0] == searchUpdate),
Arg.Any<CancellationToken>());
}
}