using Opc.Ua; using Shouldly; using Xunit; using ZB.MOM.WW.OtOpcUa.Client.CLI.Commands; using ZB.MOM.WW.OtOpcUa.Client.CLI.Tests.Fakes; using ZB.MOM.WW.OtOpcUa.Client.Shared.Models; namespace ZB.MOM.WW.OtOpcUa.Client.CLI.Tests; public class HistoryReadCommandTests { [Fact] public async Task Execute_RawRead_PrintsValues() { var time1 = new DateTime(2025, 6, 15, 10, 0, 0, DateTimeKind.Utc); var time2 = new DateTime(2025, 6, 15, 11, 0, 0, DateTimeKind.Utc); var fakeService = new FakeOpcUaClientService { HistoryReadResult = new List { new(new Variant(10.5), StatusCodes.Good, time1, time1), new(new Variant(20.3), StatusCodes.Good, time2, time2) } }; var factory = new FakeOpcUaClientServiceFactory(fakeService); var command = new HistoryReadCommand(factory) { Url = "opc.tcp://localhost:4840", NodeId = "ns=2;s=HistNode", StartTime = "2025-06-15T00:00:00Z", EndTime = "2025-06-15T23:59:59Z" }; using var console = TestConsoleHelper.CreateConsole(); await command.ExecuteAsync(console); var output = TestConsoleHelper.GetOutput(console); output.ShouldContain("History for ns=2;s=HistNode"); output.ShouldContain("Timestamp"); output.ShouldContain("Value"); output.ShouldContain("Status"); output.ShouldContain("2 values returned."); } [Fact] public async Task Execute_RawRead_CallsHistoryReadRaw() { var fakeService = new FakeOpcUaClientService(); var factory = new FakeOpcUaClientServiceFactory(fakeService); var command = new HistoryReadCommand(factory) { Url = "opc.tcp://localhost:4840", NodeId = "ns=2;s=HistNode", MaxValues = 500 }; using var console = TestConsoleHelper.CreateConsole(); await command.ExecuteAsync(console); fakeService.HistoryReadRawCalls.Count.ShouldBe(1); fakeService.HistoryReadRawCalls[0].MaxValues.ShouldBe(500); fakeService.HistoryReadRawCalls[0].NodeId.Identifier.ShouldBe("HistNode"); } [Fact] public async Task Execute_AggregateRead_CallsHistoryReadAggregate() { var fakeService = new FakeOpcUaClientService(); var factory = new FakeOpcUaClientServiceFactory(fakeService); var command = new HistoryReadCommand(factory) { Url = "opc.tcp://localhost:4840", NodeId = "ns=2;s=HistNode", Aggregate = "Average", IntervalMs = 60000 }; using var console = TestConsoleHelper.CreateConsole(); await command.ExecuteAsync(console); fakeService.HistoryReadAggregateCalls.Count.ShouldBe(1); fakeService.HistoryReadAggregateCalls[0].Aggregate.ShouldBe(AggregateType.Average); fakeService.HistoryReadAggregateCalls[0].IntervalMs.ShouldBe(60000); } [Fact] public async Task Execute_AggregateRead_PrintsAggregateInfo() { var fakeService = new FakeOpcUaClientService(); var factory = new FakeOpcUaClientServiceFactory(fakeService); var command = new HistoryReadCommand(factory) { Url = "opc.tcp://localhost:4840", NodeId = "ns=2;s=HistNode", Aggregate = "Maximum", IntervalMs = 7200000 }; using var console = TestConsoleHelper.CreateConsole(); await command.ExecuteAsync(console); var output = TestConsoleHelper.GetOutput(console); output.ShouldContain("Maximum"); output.ShouldContain("7200000"); } [Fact] public async Task Execute_InvalidAggregate_ThrowsArgumentException() { var fakeService = new FakeOpcUaClientService(); var factory = new FakeOpcUaClientServiceFactory(fakeService); var command = new HistoryReadCommand(factory) { Url = "opc.tcp://localhost:4840", NodeId = "ns=2;s=HistNode", Aggregate = "InvalidAgg" }; using var console = TestConsoleHelper.CreateConsole(); await Should.ThrowAsync(async () => await command.ExecuteAsync(console)); } [Fact] public async Task Execute_DisconnectsInFinally() { var fakeService = new FakeOpcUaClientService(); var factory = new FakeOpcUaClientServiceFactory(fakeService); var command = new HistoryReadCommand(factory) { Url = "opc.tcp://localhost:4840", NodeId = "ns=2;s=HistNode" }; using var console = TestConsoleHelper.CreateConsole(); await command.ExecuteAsync(console); fakeService.DisconnectCalled.ShouldBeTrue(); fakeService.DisposeCalled.ShouldBeTrue(); } }