using MxGateway.Contracts.Proto; using MxGateway.Contracts.Proto.Galaxy; using MxGateway.Server.Dashboard; namespace MxGateway.Tests.Gateway.Dashboard; /// /// Unit tests for the pure projection/formatting helpers behind the /// dashboard Browse and Alarms tabs. /// public sealed class DashboardBrowseAndAlarmModelTests { [Fact] public void BuildTree_LinksChildrenToParents_AndPromotesOrphansToRoots() { GalaxyObject area = new() { GobjectId = 1, BrowseName = "AreaA", IsArea = true, ParentGobjectId = 0 }; GalaxyObject child = new() { GobjectId = 2, BrowseName = "Pump01", ParentGobjectId = 1 }; GalaxyObject orphan = new() { GobjectId = 3, BrowseName = "Lost", ParentGobjectId = 99 }; IReadOnlyList roots = DashboardBrowseTreeBuilder.Build([area, child, orphan]); // The area and the orphan (its parent id is absent) are both roots. Assert.Equal(2, roots.Count); DashboardBrowseNode areaNode = Assert.Single(roots, node => node.Object.GobjectId == 1); Assert.Single(areaNode.Children); Assert.Equal(2, areaNode.Children[0].Object.GobjectId); Assert.Contains(roots, node => node.Object.GobjectId == 3); } [Fact] public void BuildTree_SortsAreasBeforeObjects() { GalaxyObject instance = new() { GobjectId = 1, BrowseName = "Zeta", IsArea = false }; GalaxyObject areaB = new() { GobjectId = 2, BrowseName = "Beta", IsArea = true }; IReadOnlyList roots = DashboardBrowseTreeBuilder.Build([instance, areaB]); Assert.Equal(2, roots.Count); Assert.True(roots[0].IsArea); Assert.Equal("Beta", roots[0].DisplayName); Assert.False(roots[1].IsArea); } [Theory] [InlineData(true, "true")] [InlineData(false, "false")] public void FormatValue_FormatsBooleans(bool input, string expected) { MxValue value = new() { DataType = MxDataType.Boolean, BoolValue = input }; Assert.Equal(expected, DashboardMxValueFormatter.FormatValue(value)); } [Fact] public void FormatValue_FormatsNumbersAndStrings() { Assert.Equal("42", DashboardMxValueFormatter.FormatValue(new MxValue { Int32Value = 42 })); Assert.Equal("hello", DashboardMxValueFormatter.FormatValue(new MxValue { StringValue = "hello" })); } [Fact] public void FormatValue_HandlesNullPayloadAndNullReference() { Assert.Equal("-", DashboardMxValueFormatter.FormatValue(null)); Assert.Equal("(null)", DashboardMxValueFormatter.FormatValue(new MxValue { IsNull = true })); } [Fact] public void TagValue_FromSuccessfulReadResult_MarksGoodQuality() { BulkReadResult result = new() { TagAddress = "Galaxy!Area.Tag", WasSuccessful = true, Quality = 192, Value = new MxValue { DataType = MxDataType.Double, DoubleValue = 1.5 }, }; DashboardTagValue value = DashboardTagValue.FromBulkReadResult(result); Assert.True(value.Ok); Assert.True(value.QualityGood); Assert.Equal("1.5", value.ValueText); Assert.Null(value.Error); } [Fact] public void TagValue_FromFailedReadResult_CarriesError() { BulkReadResult result = new() { TagAddress = "Galaxy!Area.Bad", WasSuccessful = false, Quality = 0, ErrorMessage = "invalid handle", }; DashboardTagValue value = DashboardTagValue.FromBulkReadResult(result); Assert.False(value.Ok); Assert.False(value.QualityGood); Assert.Equal("invalid handle", value.Error); } [Fact] public void ActiveAlarm_FromSnapshot_ParsesProviderAndAcknowledgementState() { ActiveAlarmSnapshot unacked = new() { AlarmFullReference = "Galaxy!TestArea.TestMachine_001.TestAlarm001", Category = "TestArea", CurrentState = AlarmConditionState.Active, Severity = 500, }; ActiveAlarmSnapshot acked = new() { AlarmFullReference = "Galaxy!TestArea.TestMachine_002.TestAlarm001", CurrentState = AlarmConditionState.ActiveAcked, }; DashboardActiveAlarm unackedRow = DashboardActiveAlarm.FromSnapshot(unacked); DashboardActiveAlarm ackedRow = DashboardActiveAlarm.FromSnapshot(acked); Assert.Equal("Galaxy", unackedRow.Provider); Assert.Equal("TestArea", unackedRow.Area); Assert.Equal(500, unackedRow.Severity); Assert.True(unackedRow.IsUnacknowledged); Assert.False(ackedRow.IsUnacknowledged); } }