using JdeScoping.ConfigManager.Models; using JdeScoping.ConfigManager.ViewModels.Forms; namespace JdeScoping.ConfigManager.Tests.ViewModels.Forms; public class PipelineFormViewModelTests { [Fact] public void Constructor_InitializesFromModel() { // Arrange var model = new PipelineModel { Source = new PipelineSource { Connection = "jde", Query = "SELECT * FROM Test" }, Destination = new PipelineDestination { Table = "TestTable", MatchColumns = ["Id", "Name"] } }; // Act var sut = new PipelineFormViewModel("TestPipeline", model, () => { }); // Assert sut.Name.ShouldBe("TestPipeline"); sut.Connection.ShouldBe("jde"); sut.Query.ShouldBe("SELECT * FROM Test"); sut.DestinationTable.ShouldBe("TestTable"); sut.MatchColumnsText.ShouldBe("Id\nName"); } [Fact] public void PropertyChange_UpdatesModelAndInvokesOnChanged() { // Arrange var model = new PipelineModel(); var changedInvoked = false; var sut = new PipelineFormViewModel("Test", model, () => changedInvoked = true); // Act sut.Connection = "cms"; // Assert model.Source.Connection.ShouldBe("cms"); changedInvoked.ShouldBeTrue(); } [Fact] public void MatchColumnsText_SplitsIntoArray() { // Arrange var model = new PipelineModel(); var sut = new PipelineFormViewModel("Test", model, () => { }); // Act sut.MatchColumnsText = "Col1\nCol2\nCol3"; // Assert model.Destination.MatchColumns.Length.ShouldBe(3); model.Destination.MatchColumns[0].ShouldBe("Col1"); } [Fact] public void Schedules_AreInitialized() { // Arrange var model = new PipelineModel { Schedules = new PipelineSchedules { Mass = new ScheduleModel { Enabled = true, IntervalMinutes = 10080 } } }; // Act var sut = new PipelineFormViewModel("Test", model, () => { }); // Assert sut.MassSchedule.ShouldNotBeNull(); sut.MassSchedule.Enabled.ShouldBeTrue(); sut.MassSchedule.IntervalMinutes.ShouldBe(10080); } [Fact] public void NullSchedules_AreInitializedToDefault() { // Arrange var model = new PipelineModel { Schedules = new PipelineSchedules { Mass = null, Daily = null, Hourly = null } }; // Act var sut = new PipelineFormViewModel("Test", model, () => { }); // Assert sut.MassSchedule.ShouldNotBeNull(); sut.DailySchedule.ShouldNotBeNull(); sut.HourlySchedule.ShouldNotBeNull(); } [Fact] public void ExcludeFromUpdateText_JoinsAndSplits() { // Arrange var model = new PipelineModel { Destination = new PipelineDestination { ExcludeFromUpdate = ["CreatedDate", "ModifiedDate"] } }; var sut = new PipelineFormViewModel("Test", model, () => { }); // Assert - verify getter joins correctly sut.ExcludeFromUpdateText.ShouldBe("CreatedDate\nModifiedDate"); // Act - verify setter splits correctly sut.ExcludeFromUpdateText = "Col1\nCol2"; model.Destination.ExcludeFromUpdate.Length.ShouldBe(2); model.Destination.ExcludeFromUpdate[0].ShouldBe("Col1"); } [Fact] public void PostScriptsText_HandlesNullable() { // Arrange var model = new PipelineModel { PostScripts = null }; var sut = new PipelineFormViewModel("Test", model, () => { }); // Assert - null should return empty string sut.PostScriptsText.ShouldBe(string.Empty); // Act - set some scripts sut.PostScriptsText = "script1.sql\nscript2.sql"; model.PostScripts.ShouldNotBeNull(); model.PostScripts!.Length.ShouldBe(2); // Act - clear scripts by setting empty sut.PostScriptsText = ""; model.PostScripts.ShouldBeNull(); } [Fact] public void MassQuery_Property_ReadsAndWrites() { // Arrange var model = new PipelineModel { Source = new PipelineSource { MassQuery = "SELECT * FROM Test WHERE All = 1" } }; var changedInvoked = false; var sut = new PipelineFormViewModel("Test", model, () => changedInvoked = true); // Assert - verify getter sut.MassQuery.ShouldBe("SELECT * FROM Test WHERE All = 1"); // Act - verify setter sut.MassQuery = "SELECT * FROM NewTable"; model.Source.MassQuery.ShouldBe("SELECT * FROM NewTable"); changedInvoked.ShouldBeTrue(); } [Fact] public void PropertyChange_RaisesPropertyChanged() { // Arrange var model = new PipelineModel(); var sut = new PipelineFormViewModel("Test", model, () => { }); var propertyChangedRaised = false; sut.PropertyChanged += (s, e) => { if (e.PropertyName == nameof(PipelineFormViewModel.Query)) propertyChangedRaised = true; }; // Act sut.Query = "SELECT * FROM NewQuery"; // Assert propertyChangedRaised.ShouldBeTrue(); } [Fact] public void ScheduleChange_InvokesOnChanged() { // Arrange var model = new PipelineModel(); var changedInvoked = false; var sut = new PipelineFormViewModel("Test", model, () => changedInvoked = true); // Act - change schedule property (Enabled defaults to true, so set to false) sut.MassSchedule.Enabled = false; // Assert changedInvoked.ShouldBeTrue(); } } public class ScheduleFormViewModelTests { [Fact] public void Constructor_InitializesFromModel() { // Arrange var model = new ScheduleModel { Enabled = true, IntervalMinutes = 1440, PrePurge = true, ReIndex = false }; // Act var sut = new ScheduleFormViewModel(model, () => { }); // Assert sut.Enabled.ShouldBeTrue(); sut.IntervalMinutes.ShouldBe(1440); sut.PrePurge.ShouldBeTrue(); sut.ReIndex.ShouldBeFalse(); } [Fact] public void PropertyChange_UpdatesModelAndInvokesOnChanged() { // Arrange var model = new ScheduleModel(); var changedInvoked = false; var sut = new ScheduleFormViewModel(model, () => changedInvoked = true); // Act sut.IntervalMinutes = 120; // Assert model.IntervalMinutes.ShouldBe(120); changedInvoked.ShouldBeTrue(); } [Fact] public void PropertyChange_RaisesPropertyChanged() { // Arrange var model = new ScheduleModel(); var sut = new ScheduleFormViewModel(model, () => { }); var propertyChangedRaised = false; sut.PropertyChanged += (s, e) => { if (e.PropertyName == nameof(ScheduleFormViewModel.PrePurge)) propertyChangedRaised = true; }; // Act sut.PrePurge = true; // Assert propertyChangedRaised.ShouldBeTrue(); } [Fact] public void SameValue_DoesNotInvokeOnChanged() { // Arrange var model = new ScheduleModel { Enabled = true }; var changedInvoked = false; var sut = new ScheduleFormViewModel(model, () => changedInvoked = true); // Act - set same value sut.Enabled = true; // Assert changedInvoked.ShouldBeFalse(); } }