using Opc.Ua;
using ZB.MOM.WW.LmxOpcUa.Client.Shared;
using ZB.MOM.WW.LmxOpcUa.Client.Shared.Models;
using BrowseResult = ZB.MOM.WW.LmxOpcUa.Client.Shared.Models.BrowseResult;
namespace ZB.MOM.WW.LmxOpcUa.Client.UI.Tests.Fakes;
///
/// Fake IOpcUaClientService for unit testing.
///
public sealed class FakeOpcUaClientService : IOpcUaClientService
{
// Configurable responses
public ConnectionInfo? ConnectResult { get; set; }
public Exception? ConnectException { get; set; }
public IReadOnlyList BrowseResults { get; set; } = [];
public Dictionary> BrowseResultsByParent { get; set; } = new();
public Exception? BrowseException { get; set; }
public DataValue ReadResult { get; set; } =
new(new Variant(42), StatusCodes.Good, DateTime.UtcNow, DateTime.UtcNow);
public Exception? ReadException { get; set; }
public StatusCode WriteResult { get; set; } = StatusCodes.Good;
public Exception? WriteException { get; set; }
public RedundancyInfo? RedundancyResult { get; set; }
public Exception? RedundancyException { get; set; }
public IReadOnlyList HistoryRawResult { get; set; } = [];
public IReadOnlyList HistoryAggregateResult { get; set; } = [];
public Exception? HistoryException { get; set; }
// Call tracking
public int ConnectCallCount { get; private set; }
public int DisconnectCallCount { get; private set; }
public int ReadCallCount { get; private set; }
public int WriteCallCount { get; private set; }
public int BrowseCallCount { get; private set; }
public int SubscribeCallCount { get; private set; }
public int UnsubscribeCallCount { get; private set; }
public int SubscribeAlarmsCallCount { get; private set; }
public int UnsubscribeAlarmsCallCount { get; private set; }
public int RequestConditionRefreshCallCount { get; private set; }
public int HistoryReadRawCallCount { get; private set; }
public int HistoryReadAggregateCallCount { get; private set; }
public int GetRedundancyInfoCallCount { get; private set; }
public ConnectionSettings? LastConnectionSettings { get; private set; }
public NodeId? LastReadNodeId { get; private set; }
public NodeId? LastWriteNodeId { get; private set; }
public object? LastWriteValue { get; private set; }
public NodeId? LastBrowseParentNodeId { get; private set; }
public NodeId? LastSubscribeNodeId { get; private set; }
public int LastSubscribeIntervalMs { get; private set; }
public NodeId? LastUnsubscribeNodeId { get; private set; }
public AggregateType? LastAggregateType { get; private set; }
public bool IsConnected { get; set; }
public ConnectionInfo? CurrentConnectionInfo { get; set; }
public event EventHandler? DataChanged;
public event EventHandler? AlarmEvent;
public event EventHandler? ConnectionStateChanged;
public Task ConnectAsync(ConnectionSettings settings, CancellationToken ct = default)
{
ConnectCallCount++;
LastConnectionSettings = settings;
if (ConnectException != null) throw ConnectException;
IsConnected = true;
CurrentConnectionInfo = ConnectResult;
return Task.FromResult(ConnectResult!);
}
public Task DisconnectAsync(CancellationToken ct = default)
{
DisconnectCallCount++;
IsConnected = false;
CurrentConnectionInfo = null;
return Task.CompletedTask;
}
public Task ReadValueAsync(NodeId nodeId, CancellationToken ct = default)
{
ReadCallCount++;
LastReadNodeId = nodeId;
if (ReadException != null) throw ReadException;
return Task.FromResult(ReadResult);
}
public Task WriteValueAsync(NodeId nodeId, object value, CancellationToken ct = default)
{
WriteCallCount++;
LastWriteNodeId = nodeId;
LastWriteValue = value;
if (WriteException != null) throw WriteException;
return Task.FromResult(WriteResult);
}
public Task> BrowseAsync(NodeId? parentNodeId = null, CancellationToken ct = default)
{
BrowseCallCount++;
LastBrowseParentNodeId = parentNodeId;
if (BrowseException != null) throw BrowseException;
if (parentNodeId != null && BrowseResultsByParent.TryGetValue(parentNodeId.ToString(), out var perParent))
return Task.FromResult(perParent);
return Task.FromResult(BrowseResults);
}
public Task SubscribeAsync(NodeId nodeId, int intervalMs = 1000, CancellationToken ct = default)
{
SubscribeCallCount++;
LastSubscribeNodeId = nodeId;
LastSubscribeIntervalMs = intervalMs;
return Task.CompletedTask;
}
public Task UnsubscribeAsync(NodeId nodeId, CancellationToken ct = default)
{
UnsubscribeCallCount++;
LastUnsubscribeNodeId = nodeId;
return Task.CompletedTask;
}
public Task SubscribeAlarmsAsync(NodeId? sourceNodeId = null, int intervalMs = 1000, CancellationToken ct = default)
{
SubscribeAlarmsCallCount++;
return Task.CompletedTask;
}
public Task UnsubscribeAlarmsAsync(CancellationToken ct = default)
{
UnsubscribeAlarmsCallCount++;
return Task.CompletedTask;
}
public Task RequestConditionRefreshAsync(CancellationToken ct = default)
{
RequestConditionRefreshCallCount++;
return Task.CompletedTask;
}
public StatusCode AcknowledgeResult { get; set; } = StatusCodes.Good;
public Exception? AcknowledgeException { get; set; }
public int AcknowledgeCallCount { get; private set; }
public Task AcknowledgeAlarmAsync(string conditionNodeId, byte[] eventId, string comment,
CancellationToken ct = default)
{
AcknowledgeCallCount++;
if (AcknowledgeException != null) throw AcknowledgeException;
return Task.FromResult(AcknowledgeResult);
}
public Task> HistoryReadRawAsync(NodeId nodeId, DateTime startTime, DateTime endTime,
int maxValues = 1000, CancellationToken ct = default)
{
HistoryReadRawCallCount++;
if (HistoryException != null) throw HistoryException;
return Task.FromResult(HistoryRawResult);
}
public Task> HistoryReadAggregateAsync(NodeId nodeId, DateTime startTime, DateTime endTime,
AggregateType aggregate, double intervalMs = 3600000, CancellationToken ct = default)
{
HistoryReadAggregateCallCount++;
LastAggregateType = aggregate;
if (HistoryException != null) throw HistoryException;
return Task.FromResult(HistoryAggregateResult);
}
public Task GetRedundancyInfoAsync(CancellationToken ct = default)
{
GetRedundancyInfoCallCount++;
if (RedundancyException != null) throw RedundancyException;
return Task.FromResult(RedundancyResult!);
}
public void Dispose()
{
// No-op for testing
}
// Methods to raise events from tests
public void RaiseDataChanged(DataChangedEventArgs args)
{
DataChanged?.Invoke(this, args);
}
public void RaiseAlarmEvent(AlarmEventArgs args)
{
AlarmEvent?.Invoke(this, args);
}
public void RaiseConnectionStateChanged(ConnectionStateChangedEventArgs args)
{
ConnectionStateChanged?.Invoke(this, args);
}
}