using System.Text.Json; using ZB.MOM.WW.ScadaBridge.CLI.Commands; using ZB.MOM.WW.ScadaBridge.Commons.Messages.Management; using ZB.MOM.WW.ScadaBridge.Commons.Types.Deployment; using ZB.MOM.WW.ScadaBridge.Commons.Types.Enums; namespace ZB.MOM.WW.ScadaBridge.CLI.Tests; /// /// Tests for the deploy status table projection (deferred-work register rows /// 37/87). The handler now returns a OBJECT where /// it used to return a bare row array; without a projector the generic renderer takes /// its Property/Value branch and prints the whole deployments array as raw JSON /// inside one cell. The projection unwraps the envelope and keeps the total visible as /// a trailing note — which matters more here than for the audit query, because the /// page size is bounded server-side and a full page is no longer proof there is /// nothing more. /// public class DeploymentStatusTableProjectionTests { /// /// The real server shape, serialised from the REAL /// / types rather than hand-written JSON, so renaming /// one of their properties fails this test instead of silently blanking a column. /// private static string RealPayload(int rowCount, int totalCount) => JsonSerializer.Serialize( new DeploymentQueryResult( Enumerable.Range(1, rowCount).Select(i => new DeploymentListRow( i, $"dep-{i:D3}", i, $"Line3.Pump{i}", 2, DeploymentStatus.Success, $"rev-{i}", "alice", new DateTimeOffset(2026, 8, 15, 12, 0, 0, TimeSpan.Zero), null, null)).ToList(), totalCount, Page: 1, PageSize: rowCount), new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }); [Fact] public void Projection_UnwrapsTheEnvelopeToARowArray() { var projected = DeploymentStatusTableProjection.ProjectRows(RealPayload(2, 2)); using var doc = JsonDocument.Parse(projected); Assert.Equal(JsonValueKind.Array, doc.RootElement.ValueKind); Assert.Equal(2, doc.RootElement.GetArrayLength()); Assert.Equal("dep-001", doc.RootElement[0].GetProperty("deploymentId").GetString()); Assert.Equal("Line3.Pump1", doc.RootElement[0].GetProperty("instanceUniqueName").GetString()); } [Fact] public void Projection_WhenPageIsAStrictSubset_AppendsATotalNote() { var projected = DeploymentStatusTableProjection.ProjectRows(RealPayload(2, 57)); using var doc = JsonDocument.Parse(projected); Assert.Equal(3, doc.RootElement.GetArrayLength()); var note = doc.RootElement[2].GetProperty("note").GetString(); Assert.Contains("showing 2 of 57", note); Assert.Contains("--page-size", note); } [Fact] public void Projection_WhenPageIsTheWholeResult_EmitsNoNoteColumn() { var projected = DeploymentStatusTableProjection.ProjectRows(RealPayload(2, 2)); using var doc = JsonDocument.Parse(projected); Assert.All(doc.RootElement.EnumerateArray(), e => Assert.False(e.TryGetProperty("note", out _))); } [Fact] public void Projection_AcceptsABareRowArray_FromAPreEnvelopeServer() { var projected = DeploymentStatusTableProjection.ProjectRows("""[{"deploymentId":"dep-001"}]"""); using var doc = JsonDocument.Parse(projected); Assert.Equal("dep-001", Assert.Single(doc.RootElement.EnumerateArray()) .GetProperty("deploymentId").GetString()); } [Theory] [InlineData("not json at all")] [InlineData("""{"error":"boom"}""")] public void Projection_LeavesUnrecognisedBodiesUntouched(string body) { Assert.Equal(body, DeploymentStatusTableProjection.ProjectRows(body)); } }