diff --git a/NEW/src/Utils/JdeScoping.ConfigManager/ViewModels/Forms/SearchFormViewModel.cs b/NEW/src/Utils/JdeScoping.ConfigManager/ViewModels/Forms/SearchFormViewModel.cs new file mode 100644 index 0000000..e2f6d20 --- /dev/null +++ b/NEW/src/Utils/JdeScoping.ConfigManager/ViewModels/Forms/SearchFormViewModel.cs @@ -0,0 +1,69 @@ +using JdeScoping.ConfigManager.Models; + +namespace JdeScoping.ConfigManager.ViewModels.Forms; + +/// +/// ViewModel for editing Search configuration section. +/// +public class SearchFormViewModel : ViewModelBase +{ + private readonly SearchSection _model; + private readonly Action _onChanged; + + public SearchFormViewModel(SearchSection model, Action onChanged) + { + _model = model ?? throw new ArgumentNullException(nameof(model)); + _onChanged = onChanged ?? throw new ArgumentNullException(nameof(onChanged)); + } + + /// + /// Gets or sets the maximum number of result rows returned by a search. + /// + public int MaxResultRows + { + get => _model.MaxResultRows; + set + { + if (_model.MaxResultRows != value) + { + _model.MaxResultRows = value; + OnPropertyChanged(); + _onChanged(); + } + } + } + + /// + /// Gets or sets the timeout in seconds for search operations. + /// + public int TimeoutSeconds + { + get => _model.TimeoutSeconds; + set + { + if (_model.TimeoutSeconds != value) + { + _model.TimeoutSeconds = value; + OnPropertyChanged(); + _onChanged(); + } + } + } + + /// + /// Gets or sets the maximum number of concurrent search operations allowed. + /// + public int MaxConcurrentSearches + { + get => _model.MaxConcurrentSearches; + set + { + if (_model.MaxConcurrentSearches != value) + { + _model.MaxConcurrentSearches = value; + OnPropertyChanged(); + _onChanged(); + } + } + } +} diff --git a/NEW/tests/JdeScoping.ConfigManager.Tests/ViewModels/Forms/SearchFormViewModelTests.cs b/NEW/tests/JdeScoping.ConfigManager.Tests/ViewModels/Forms/SearchFormViewModelTests.cs new file mode 100644 index 0000000..342968d --- /dev/null +++ b/NEW/tests/JdeScoping.ConfigManager.Tests/ViewModels/Forms/SearchFormViewModelTests.cs @@ -0,0 +1,108 @@ +using JdeScoping.ConfigManager.Models; +using JdeScoping.ConfigManager.ViewModels.Forms; + +namespace JdeScoping.ConfigManager.Tests.ViewModels.Forms; + +public class SearchFormViewModelTests +{ + [Fact] + public void Constructor_InitializesFromModel() + { + // Arrange + var model = new SearchSection + { + MaxResultRows = 50000, + TimeoutSeconds = 600, + MaxConcurrentSearches = 10 + }; + + // Act + var sut = new SearchFormViewModel(model, () => { }); + + // Assert + sut.MaxResultRows.ShouldBe(50000); + sut.TimeoutSeconds.ShouldBe(600); + sut.MaxConcurrentSearches.ShouldBe(10); + } + + [Fact] + public void PropertyChange_UpdatesModel() + { + // Arrange + var model = new SearchSection { MaxResultRows = 100000 }; + var sut = new SearchFormViewModel(model, () => { }); + + // Act + sut.MaxResultRows = 25000; + + // Assert + model.MaxResultRows.ShouldBe(25000); + } + + [Fact] + public void PropertyChange_InvokesOnChanged() + { + // Arrange + var model = new SearchSection(); + var changedInvoked = false; + var sut = new SearchFormViewModel(model, () => changedInvoked = true); + + // Act + sut.TimeoutSeconds = 120; + + // Assert + changedInvoked.ShouldBeTrue(); + } + + [Fact] + public void PropertyChange_RaisesPropertyChanged() + { + // Arrange + var model = new SearchSection(); + var sut = new SearchFormViewModel(model, () => { }); + var propertyChangedRaised = false; + sut.PropertyChanged += (s, e) => + { + if (e.PropertyName == nameof(SearchFormViewModel.MaxConcurrentSearches)) + propertyChangedRaised = true; + }; + + // Act + sut.MaxConcurrentSearches = 8; + + // Assert + propertyChangedRaised.ShouldBeTrue(); + } + + [Fact] + public void Constructor_ThrowsOnNullModel() + { + // Act & Assert + Should.Throw(() => new SearchFormViewModel(null!, () => { })); + } + + [Fact] + public void Constructor_ThrowsOnNullCallback() + { + // Arrange + var model = new SearchSection(); + + // Act & Assert + Should.Throw(() => new SearchFormViewModel(model, null!)); + } + + [Fact] + public void PropertyChange_DoesNotInvokeOnChangedWhenValueUnchanged() + { + // Arrange + var model = new SearchSection { MaxResultRows = 50000 }; + var changedCount = 0; + var sut = new SearchFormViewModel(model, () => changedCount++); + + // Act - set to same value + sut.MaxResultRows = 50000; + + // Assert + changedCount.ShouldBe(0); + } +}