using Shouldly;
using Xunit;
using ZB.MOM.WW.OtOpcUa.Client.CLI.Commands;
using ZB.MOM.WW.OtOpcUa.Client.CLI.Tests.Fakes;
namespace ZB.MOM.WW.OtOpcUa.Client.CLI.Tests;
public class SubscribeCommandTests
{
/// Verifies that ExecuteAsync subscribes with the correct parameters.
[Fact]
public async Task Execute_SubscribesWithCorrectParameters()
{
var fakeService = new FakeOpcUaClientService();
var factory = new FakeOpcUaClientServiceFactory(fakeService);
var command = new SubscribeCommand(factory)
{
Url = "opc.tcp://localhost:4840",
NodeId = "ns=2;s=TestVar",
Interval = 500
};
using var console = TestConsoleHelper.CreateConsole();
// The subscribe command waits for cancellation. We need to cancel it.
// Use the console's cancellation to trigger stop.
var task = Task.Run(async () => { await command.ExecuteAsync(console); });
// Give it a moment to subscribe, then cancel
await Task.Delay(100);
console.RequestCancellation();
await task;
fakeService.SubscribeCalls.Count.ShouldBe(1);
fakeService.SubscribeCalls[0].IntervalMs.ShouldBe(500);
fakeService.SubscribeCalls[0].NodeId.Identifier.ShouldBe("TestVar");
}
/// Verifies that ExecuteAsync unsubscribes when cancellation is requested.
[Fact]
public async Task Execute_UnsubscribesOnCancellation()
{
var fakeService = new FakeOpcUaClientService();
var factory = new FakeOpcUaClientServiceFactory(fakeService);
var command = new SubscribeCommand(factory)
{
Url = "opc.tcp://localhost:4840",
NodeId = "ns=2;s=TestVar"
};
using var console = TestConsoleHelper.CreateConsole();
var task = Task.Run(async () => { await command.ExecuteAsync(console); });
await Task.Delay(100);
console.RequestCancellation();
await task;
fakeService.UnsubscribeCalls.Count.ShouldBe(1);
}
/// Verifies that ExecuteAsync disconnects and disposes in a finally block.
[Fact]
public async Task Execute_DisconnectsInFinally()
{
var fakeService = new FakeOpcUaClientService();
var factory = new FakeOpcUaClientServiceFactory(fakeService);
var command = new SubscribeCommand(factory)
{
Url = "opc.tcp://localhost:4840",
NodeId = "ns=2;s=TestVar"
};
using var console = TestConsoleHelper.CreateConsole();
var task = Task.Run(async () => { await command.ExecuteAsync(console); });
await Task.Delay(100);
console.RequestCancellation();
await task;
fakeService.DisconnectCalled.ShouldBeTrue();
fakeService.DisposeCalled.ShouldBeTrue();
}
/// Verifies that ExecuteAsync prints the correct subscription message.
[Fact]
public async Task Execute_PrintsSubscriptionMessage()
{
var fakeService = new FakeOpcUaClientService();
var factory = new FakeOpcUaClientServiceFactory(fakeService);
var command = new SubscribeCommand(factory)
{
Url = "opc.tcp://localhost:4840",
NodeId = "ns=2;s=TestVar",
Interval = 2000
};
using var console = TestConsoleHelper.CreateConsole();
var task = Task.Run(async () => { await command.ExecuteAsync(console); });
await Task.Delay(100);
console.RequestCancellation();
await task;
var output = TestConsoleHelper.GetOutput(console);
// CLI now prints aggregate form "Subscribed to {count}/{total} nodes (interval: ...)" rather than
// the single-node form the original test asserted — the command supports multi-node now.
output.ShouldContain("Subscribed to 1/1 nodes (interval: 2000ms)");
}
}