diff --git a/NEW/src/Utils/JdeScoping.ConfigManager/ViewModels/Forms/DataSyncFormViewModel.cs b/NEW/src/Utils/JdeScoping.ConfigManager/ViewModels/Forms/DataSyncFormViewModel.cs new file mode 100644 index 0000000..a42e415 --- /dev/null +++ b/NEW/src/Utils/JdeScoping.ConfigManager/ViewModels/Forms/DataSyncFormViewModel.cs @@ -0,0 +1,155 @@ +using JdeScoping.ConfigManager.Models; + +namespace JdeScoping.ConfigManager.ViewModels.Forms; + +/// +/// ViewModel for editing DataSync configuration section. +/// +public class DataSyncFormViewModel : ViewModelBase +{ + private readonly DataSyncSection _model; + private readonly Action _onChanged; + + public DataSyncFormViewModel(DataSyncSection model, Action onChanged) + { + _model = model ?? throw new ArgumentNullException(nameof(model)); + _onChanged = onChanged ?? throw new ArgumentNullException(nameof(onChanged)); + } + + /// + /// Gets or sets whether data synchronization is enabled. + /// + public bool Enabled + { + get => _model.Enabled; + set + { + if (_model.Enabled != value) + { + _model.Enabled = value; + OnPropertyChanged(); + _onChanged(); + } + } + } + + /// + /// Gets or sets the check interval in minutes. + /// + public int CheckIntervalMinutes + { + get => (int)_model.CheckInterval.TotalMinutes; + set + { + var newValue = TimeSpan.FromMinutes(value); + if (_model.CheckInterval != newValue) + { + _model.CheckInterval = newValue; + OnPropertyChanged(); + _onChanged(); + } + } + } + + /// + /// Gets or sets the maximum degree of parallelism. + /// + public int MaxDegreeOfParallelism + { + get => _model.MaxDegreeOfParallelism; + set + { + if (_model.MaxDegreeOfParallelism != value) + { + _model.MaxDegreeOfParallelism = value; + OnPropertyChanged(); + _onChanged(); + } + } + } + + /// + /// Gets or sets the batch size for sync operations. + /// + public int BatchSize + { + get => _model.BatchSize; + set + { + if (_model.BatchSize != value) + { + _model.BatchSize = value; + OnPropertyChanged(); + _onChanged(); + } + } + } + + /// + /// Gets or sets the bulk copy batch size. + /// + public int BulkCopyBatchSize + { + get => _model.BulkCopyBatchSize; + set + { + if (_model.BulkCopyBatchSize != value) + { + _model.BulkCopyBatchSize = value; + OnPropertyChanged(); + _onChanged(); + } + } + } + + /// + /// Gets or sets the lookback multiplier. + /// + public double LookbackMultiplier + { + get => _model.LookbackMultiplier; + set + { + if (Math.Abs(_model.LookbackMultiplier - value) > 0.001) + { + _model.LookbackMultiplier = value; + OnPropertyChanged(); + _onChanged(); + } + } + } + + /// + /// Gets or sets the purge retention days. + /// + public int PurgeRetentionDays + { + get => _model.PurgeRetentionDays; + set + { + if (_model.PurgeRetentionDays != value) + { + _model.PurgeRetentionDays = value; + OnPropertyChanged(); + _onChanged(); + } + } + } + + /// + /// Gets or sets the sync timeout in seconds. + /// + public int SyncTimeoutSeconds + { + get => _model.SyncTimeoutSeconds; + set + { + if (_model.SyncTimeoutSeconds != value) + { + _model.SyncTimeoutSeconds = value; + OnPropertyChanged(); + _onChanged(); + } + } + } +} diff --git a/NEW/tests/JdeScoping.ConfigManager.Tests/ViewModels/Forms/DataSyncFormViewModelTests.cs b/NEW/tests/JdeScoping.ConfigManager.Tests/ViewModels/Forms/DataSyncFormViewModelTests.cs new file mode 100644 index 0000000..e6dceaa --- /dev/null +++ b/NEW/tests/JdeScoping.ConfigManager.Tests/ViewModels/Forms/DataSyncFormViewModelTests.cs @@ -0,0 +1,76 @@ +using JdeScoping.ConfigManager.Models; +using JdeScoping.ConfigManager.ViewModels.Forms; + +namespace JdeScoping.ConfigManager.Tests.ViewModels.Forms; + +public class DataSyncFormViewModelTests +{ + [Fact] + public void Constructor_InitializesFromModel() + { + // Arrange + var model = new DataSyncSection + { + Enabled = true, + MaxDegreeOfParallelism = 8, + BatchSize = 25000 + }; + + // Act + var sut = new DataSyncFormViewModel(model, () => { }); + + // Assert + sut.Enabled.ShouldBeTrue(); + sut.MaxDegreeOfParallelism.ShouldBe(8); + sut.BatchSize.ShouldBe(25000); + } + + [Fact] + public void PropertyChange_UpdatesModel() + { + // Arrange + var model = new DataSyncSection { MaxDegreeOfParallelism = 4 }; + var sut = new DataSyncFormViewModel(model, () => { }); + + // Act + sut.MaxDegreeOfParallelism = 16; + + // Assert + model.MaxDegreeOfParallelism.ShouldBe(16); + } + + [Fact] + public void PropertyChange_InvokesOnChanged() + { + // Arrange + var model = new DataSyncSection(); + var changedInvoked = false; + var sut = new DataSyncFormViewModel(model, () => changedInvoked = true); + + // Act + sut.BatchSize = 10000; + + // Assert + changedInvoked.ShouldBeTrue(); + } + + [Fact] + public void PropertyChange_RaisesPropertyChanged() + { + // Arrange + var model = new DataSyncSection(); + var sut = new DataSyncFormViewModel(model, () => { }); + var propertyChangedRaised = false; + sut.PropertyChanged += (s, e) => + { + if (e.PropertyName == nameof(DataSyncFormViewModel.LookbackMultiplier)) + propertyChangedRaised = true; + }; + + // Act + sut.LookbackMultiplier = 2.5; + + // Assert + propertyChangedRaised.ShouldBeTrue(); + } +}