104 lines
4.5 KiB
C#
104 lines
4.5 KiB
C#
using System.Reflection;
|
|
using System.Security.Claims;
|
|
using Bunit;
|
|
using Microsoft.AspNetCore.Components.Authorization;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
using Microsoft.Extensions.Logging.Abstractions;
|
|
using Microsoft.Extensions.Options;
|
|
using NSubstitute;
|
|
using ZB.MOM.WW.ScadaBridge.CentralUI.Auth;
|
|
using ZB.MOM.WW.ScadaBridge.Commons.Entities.Sites;
|
|
using ZB.MOM.WW.ScadaBridge.Commons.Interfaces.Repositories;
|
|
using ZB.MOM.WW.ScadaBridge.Commons.Messages.DebugView;
|
|
using ZB.MOM.WW.ScadaBridge.Commons.Messages.Streaming;
|
|
using ZB.MOM.WW.ScadaBridge.Commons.Types.Alarms;
|
|
using ZB.MOM.WW.ScadaBridge.Commons.Types.Enums;
|
|
using ZB.MOM.WW.ScadaBridge.Communication;
|
|
using ZB.MOM.WW.ScadaBridge.Communication.Grpc;
|
|
using DebugViewPage = ZB.MOM.WW.ScadaBridge.CentralUI.Components.Pages.Deployment.DebugView;
|
|
|
|
namespace ZB.MOM.WW.ScadaBridge.CentralUI.Tests.Deployment;
|
|
|
|
/// <summary>
|
|
/// Task 23: the DebugView alarm table surfaces enriched native alarm state —
|
|
/// kind, severity, source reference, and a composite condition badge set
|
|
/// (Unacked / Shelved / Suppressed).
|
|
/// </summary>
|
|
public class DebugViewAlarmTableTests : BunitContext
|
|
{
|
|
private IRenderedComponent<DebugViewPage> RenderPage()
|
|
{
|
|
JSInterop.Mode = JSRuntimeMode.Loose;
|
|
|
|
var repo = Substitute.For<ITemplateEngineRepository>();
|
|
var siteRepo = Substitute.For<ISiteRepository>();
|
|
siteRepo.GetAllSitesAsync().Returns(new List<Site>());
|
|
Services.AddSingleton(repo);
|
|
Services.AddSingleton(siteRepo);
|
|
|
|
var comms = new CommunicationService(
|
|
Options.Create(new CommunicationOptions()),
|
|
NullLogger<CommunicationService>.Instance);
|
|
Services.AddSingleton(comms);
|
|
|
|
var grpcFactory = new SiteStreamGrpcClientFactory(NullLoggerFactory.Instance);
|
|
var debugStream = new DebugStreamService(
|
|
comms, new ServiceCollection().BuildServiceProvider(), grpcFactory,
|
|
NullLogger<DebugStreamService>.Instance);
|
|
Services.AddSingleton(debugStream);
|
|
|
|
var identity = new ClaimsIdentity(new[] { new Claim(ClaimTypes.Name, "deployer") }, "TestCookie");
|
|
var stubAuth = new StubAuthStateProvider(new AuthenticationState(new ClaimsPrincipal(identity)));
|
|
Services.AddSingleton<AuthenticationStateProvider>(stubAuth);
|
|
Services.AddScoped(_ => new SiteScopeService(stubAuth));
|
|
|
|
return Render<DebugViewPage>();
|
|
}
|
|
|
|
private sealed class StubAuthStateProvider : AuthenticationStateProvider
|
|
{
|
|
private readonly AuthenticationState _state;
|
|
public StubAuthStateProvider(AuthenticationState state) => _state = state;
|
|
public override Task<AuthenticationState> GetAuthenticationStateAsync() => Task.FromResult(_state);
|
|
}
|
|
|
|
private static void SetField(DebugViewPage c, string name, object? value) =>
|
|
typeof(DebugViewPage).GetField(name, BindingFlags.Instance | BindingFlags.NonPublic)!.SetValue(c, value);
|
|
|
|
private static Dictionary<string, AlarmStateChanged> AlarmStates(DebugViewPage c) =>
|
|
(Dictionary<string, AlarmStateChanged>)typeof(DebugViewPage)
|
|
.GetField("_alarmStates", BindingFlags.Instance | BindingFlags.NonPublic)!.GetValue(c)!;
|
|
|
|
[Fact]
|
|
public void AlarmTable_RendersNativeAlarm_WithSeverityKindAndShelvedBadge()
|
|
{
|
|
var cut = RenderPage();
|
|
|
|
var native = new AlarmStateChanged("inst", "T01.Hi", AlarmState.Active, 800, DateTimeOffset.UtcNow)
|
|
{
|
|
Kind = AlarmKind.NativeOpcUa,
|
|
SourceReference = "ns=2;s=Tank01.Level.HiHi",
|
|
Condition = new AlarmConditionState(
|
|
Active: true, Acknowledged: false, Confirmed: null,
|
|
Shelve: AlarmShelveState.OneShotShelved, Suppressed: false, Severity: 800)
|
|
};
|
|
|
|
cut.InvokeAsync(() =>
|
|
{
|
|
SetField(cut.Instance, "_connected", true);
|
|
SetField(cut.Instance, "_snapshot",
|
|
new DebugViewSnapshot("inst", new List<AttributeValueChanged>(),
|
|
new List<AlarmStateChanged> { native }, DateTimeOffset.UtcNow));
|
|
AlarmStates(cut.Instance)["T01.Hi"] = native;
|
|
});
|
|
cut.Render();
|
|
|
|
var markup = cut.Markup;
|
|
Assert.Contains("800", markup); // severity surfaced
|
|
Assert.Contains("Shelved", markup); // composite condition badge
|
|
Assert.Contains("OPC UA", markup); // native kind badge
|
|
Assert.Contains("ns=2;s=Tank01.Level.HiHi", markup); // source reference
|
|
Assert.Contains("Unacked", markup); // active + unacknowledged
|
|
}
|
|
}
|