using ZB.MOM.WW.ScadaBridge.Commons.Messages.Management; using ZB.MOM.WW.ScadaBridge.Commons.Types; namespace ZB.MOM.WW.ScadaBridge.CLI.Tests; /// /// Verifies the CSV parsing + entry-mapping behaviour that backs /// instance native-alarm-source import: parse errors block the apply step; /// valid CSV produces the list the /// consumes. /// public class ImportNativeAlarmSourceOverridesTests { // ── error path ─────────────────────────────────────────────────────────── /// Verifies that CSV input without a header row produces errors and no rows. [Fact] public void CsvWithMissingHeader_ProducesErrors() { var result = NativeAlarmSourceOverrideCsvParser.Parse("Pressure,ConnA,ref,Active"); Assert.NotEmpty(result.Errors); Assert.Empty(result.Rows); } /// Verifies that a CSV row with a blank source name produces an error and no rows. [Fact] public void CsvWithBlankSourceName_ProducesError() { const string csv = "SourceName,Connection,SourceReference,Filter\n,ConnA,ref,Active"; var result = NativeAlarmSourceOverrideCsvParser.Parse(csv); Assert.NotEmpty(result.Errors); Assert.Empty(result.Rows); } // ── happy path ─────────────────────────────────────────────────────────── /// Verifies that valid CSV input produces the expected list of override entries. [Fact] public void ValidCsv_ProducesCorrectEntryList() { const string csv = """ SourceName,Connection,SourceReference,Filter Pressure,ConnA,ns=2;s=Pump,Active Temp,,, """; var parseResult = NativeAlarmSourceOverrideCsvParser.Parse(csv); Assert.Empty(parseResult.Errors); Assert.Equal(2, parseResult.Rows.Count); // Build the same entry list that the CLI import action produces. var entries = parseResult.Rows .Select(r => new NativeAlarmSourceOverrideEntry( r.SourceName, r.Connection, r.SourceReference, r.Filter)) .ToList(); Assert.Equal("Pressure", entries[0].SourceCanonicalName); Assert.Equal("ConnA", entries[0].ConnectionNameOverride); Assert.Equal("ns=2;s=Pump", entries[0].SourceReferenceOverride); Assert.Equal("Active", entries[0].ConditionFilterOverride); // All-blank override fields → inherited (null) on every field. Assert.Equal("Temp", entries[1].SourceCanonicalName); Assert.Null(entries[1].ConnectionNameOverride); Assert.Null(entries[1].SourceReferenceOverride); Assert.Null(entries[1].ConditionFilterOverride); } // ── MES flag (ScadaBridge#104) ─────────────────────────────────────────── /// A legacy 4-column file leaves the MES flag unspecified, so the server keeps it. [Fact] public void FourColumnCsv_EntryKeepsStoredMesFlag() { var parsed = NativeAlarmSourceOverrideCsvParser.Parse("SourceName,Connection,SourceReference,Filter\nPressure,ConnA,,"); var entry = Assert.Single(parsed.Rows).ToOverrideEntry(); Assert.True(entry.KeepStoredMesReportable); Assert.Null(entry.IsMesReportableOverride); Assert.Equal("ConnA", entry.ConnectionNameOverride); } /// A file with the MesReportable column is authoritative, blank included (= inherit). [Fact] public void FiveColumnCsv_EntrySpecifiesMesFlag() { var parsed = NativeAlarmSourceOverrideCsvParser.Parse( "SourceName,Connection,SourceReference,Filter,MesReportable\nPressure,,,,false\nTemp,,,,"); var pressure = parsed.Rows[0].ToOverrideEntry(); var temp = parsed.Rows[1].ToOverrideEntry(); Assert.False(pressure.KeepStoredMesReportable); Assert.False(pressure.IsMesReportableOverride); Assert.False(temp.KeepStoredMesReportable); Assert.Null(temp.IsMesReportableOverride); } }