using Shouldly;
using Xunit;
namespace ZB.MOM.WW.OtOpcUa.Driver.Calculation.Tests;
///
/// Unit tests for — the Calculation pseudo-driver's Test-Connect
/// probe (parse-only, since there is no backend to reach).
///
public sealed class CalculationDriverProbeTests
{
private static readonly CalculationDriverProbe Sut = new();
[Fact]
public async Task Empty_config_json_fails()
{
var result = await Sut.ProbeAsync("", TimeSpan.FromSeconds(1), TestContext.Current.CancellationToken);
result.Ok.ShouldBeFalse();
result.Message.ShouldNotBeNullOrWhiteSpace();
}
[Fact]
public async Task Malformed_json_fails()
{
var result = await Sut.ProbeAsync("not json", TimeSpan.FromSeconds(1), TestContext.Current.CancellationToken);
result.Ok.ShouldBeFalse();
result.Message.ShouldNotBeNullOrWhiteSpace();
}
[Fact]
public async Task A_config_with_no_rawTags_array_is_still_valid()
{
var result = await Sut.ProbeAsync("{}", TimeSpan.FromSeconds(1), TestContext.Current.CancellationToken);
result.Ok.ShouldBeTrue(result.Message);
}
[Fact]
public async Task A_well_formed_rawTags_config_is_valid()
{
const string json = """{"rawTags":[{"rawPath":"calc/e/x","tagConfig":"{}","writeIdempotent":false}]}""";
var result = await Sut.ProbeAsync(json, TimeSpan.FromSeconds(1), TestContext.Current.CancellationToken);
result.Ok.ShouldBeTrue(result.Message);
}
///
/// The probe must not be STRICTER than the real spawn/reinit path: both
/// CalculationDriverFactoryExtensions.JsonOptions and CalculationDriver.ReinitJsonOptions
/// set AllowTrailingCommas + ReadCommentHandling.Skip. Before this pin the probe's own
/// options omitted both, so a config a real deploy would accept could fail Test-Connect as "invalid".
///
[Fact]
public async Task Tolerates_trailing_commas_like_the_real_spawn_and_reinit_paths()
{
const string json = """{"rawTags":[{"rawPath":"calc/e/x","tagConfig":"{}","writeIdempotent":false},],}""";
var result = await Sut.ProbeAsync(json, TimeSpan.FromSeconds(1), TestContext.Current.CancellationToken);
result.Ok.ShouldBeTrue(result.Message);
}
/// Same parity claim for comments, which the spawn/reinit path also tolerates.
[Fact]
public async Task Tolerates_comments_like_the_real_spawn_and_reinit_paths()
{
const string json = """
{
// a hand-edited config comment
"rawTags": []
}
""";
var result = await Sut.ProbeAsync(json, TimeSpan.FromSeconds(1), TestContext.Current.CancellationToken);
result.Ok.ShouldBeTrue(result.Message);
}
}