6642c83cdb
Enable ConfigManager to validate runtime configuration (SecureStore secrets, connection strings, LDAP) using the same validators as the Host application. Adds AddInfrastructureValidators() extension for shared validator registration.
327 lines
11 KiB
C#
327 lines
11 KiB
C#
using JdeScoping.ConfigManager.Models;
|
|
using JdeScoping.ConfigManager.Services;
|
|
using JdeScoping.ConfigManager.Services.SecureStore;
|
|
using JdeScoping.ConfigManager.ViewModels;
|
|
using JdeScoping.ConfigManager.ViewModels.Forms;
|
|
using Microsoft.Extensions.Logging;
|
|
using NSubstitute;
|
|
|
|
namespace JdeScoping.ConfigManager.Tests.ViewModels;
|
|
|
|
public class MainWindowViewModelTests
|
|
{
|
|
private readonly IFileSystem _fileSystem;
|
|
private readonly IConfigFileService _configFileService;
|
|
private readonly IValidationService _validationService;
|
|
private readonly IBackupService _backupService;
|
|
private readonly IAutoDiscoveryService _autoDiscoveryService;
|
|
private readonly IDialogService _dialogService;
|
|
private readonly ISecureStoreManager _secureStoreManager;
|
|
private readonly IClipboardService _clipboardService;
|
|
private readonly IRuntimeConfigValidationService _runtimeValidationService;
|
|
private readonly ILogger<MainWindowViewModel> _logger;
|
|
|
|
public MainWindowViewModelTests()
|
|
{
|
|
_fileSystem = Substitute.For<IFileSystem>();
|
|
_configFileService = Substitute.For<IConfigFileService>();
|
|
_validationService = Substitute.For<IValidationService>();
|
|
_backupService = Substitute.For<IBackupService>();
|
|
_autoDiscoveryService = Substitute.For<IAutoDiscoveryService>();
|
|
_dialogService = Substitute.For<IDialogService>();
|
|
_secureStoreManager = Substitute.For<ISecureStoreManager>();
|
|
_clipboardService = Substitute.For<IClipboardService>();
|
|
_runtimeValidationService = Substitute.For<IRuntimeConfigValidationService>();
|
|
_logger = Substitute.For<ILogger<MainWindowViewModel>>();
|
|
|
|
_validationService.ValidateAppSettings(Arg.Any<ConfigModel>())
|
|
.Returns(new ValidationResult());
|
|
_validationService.ValidatePipelines(Arg.Any<PipelinesConfigModel>())
|
|
.Returns(new ValidationResult());
|
|
}
|
|
|
|
[Fact]
|
|
public void SelectingDataSyncNode_LoadsDataSyncFormViewModel()
|
|
{
|
|
// Arrange
|
|
var config = new ConfigModel { DataSync = new DataSyncSection { MaxDegreeOfParallelism = 8 } };
|
|
var sut = CreateViewModel();
|
|
sut.LoadConfigForTesting(config, null);
|
|
|
|
var dataSyncNode = sut.TreeNodes
|
|
.SelectMany(n => n.Children)
|
|
.First(n => n.SectionKey == "DataSync");
|
|
|
|
// Act
|
|
sut.SelectedNode = dataSyncNode;
|
|
|
|
// Assert
|
|
sut.SelectedFormViewModel.ShouldBeOfType<DataSyncFormViewModel>();
|
|
((DataSyncFormViewModel)sut.SelectedFormViewModel!).MaxDegreeOfParallelism.ShouldBe(8);
|
|
}
|
|
|
|
[Fact]
|
|
public void SelectingDataAccessNode_LoadsDataAccessFormViewModel()
|
|
{
|
|
// Arrange
|
|
var config = new ConfigModel { DataAccess = new DataAccessSection { ProductionSchema = "custom" } };
|
|
var sut = CreateViewModel();
|
|
sut.LoadConfigForTesting(config, null);
|
|
|
|
var dataAccessNode = sut.TreeNodes
|
|
.SelectMany(n => n.Children)
|
|
.First(n => n.SectionKey == "DataAccess");
|
|
|
|
// Act
|
|
sut.SelectedNode = dataAccessNode;
|
|
|
|
// Assert
|
|
sut.SelectedFormViewModel.ShouldBeOfType<DataAccessFormViewModel>();
|
|
((DataAccessFormViewModel)sut.SelectedFormViewModel!).ProductionSchema.ShouldBe("custom");
|
|
}
|
|
|
|
[Fact]
|
|
public void SelectingAuthNode_LoadsAuthFormViewModel()
|
|
{
|
|
// Arrange
|
|
var config = new ConfigModel { Auth = new AuthSection { CookieName = "TestCookie" } };
|
|
var sut = CreateViewModel();
|
|
sut.LoadConfigForTesting(config, null);
|
|
|
|
var authNode = sut.TreeNodes
|
|
.SelectMany(n => n.Children)
|
|
.First(n => n.SectionKey == "Auth");
|
|
|
|
// Act
|
|
sut.SelectedNode = authNode;
|
|
|
|
// Assert
|
|
sut.SelectedFormViewModel.ShouldBeOfType<AuthFormViewModel>();
|
|
((AuthFormViewModel)sut.SelectedFormViewModel!).CookieName.ShouldBe("TestCookie");
|
|
}
|
|
|
|
[Fact]
|
|
public void SelectingLdapNode_LoadsLdapFormViewModel()
|
|
{
|
|
// Arrange
|
|
var config = new ConfigModel { Ldap = new LdapSection { GroupDn = "CN=TestGroup" } };
|
|
var sut = CreateViewModel();
|
|
sut.LoadConfigForTesting(config, null);
|
|
|
|
var ldapNode = sut.TreeNodes
|
|
.SelectMany(n => n.Children)
|
|
.First(n => n.SectionKey == "Ldap");
|
|
|
|
// Act
|
|
sut.SelectedNode = ldapNode;
|
|
|
|
// Assert
|
|
sut.SelectedFormViewModel.ShouldBeOfType<LdapFormViewModel>();
|
|
((LdapFormViewModel)sut.SelectedFormViewModel!).GroupDn.ShouldBe("CN=TestGroup");
|
|
}
|
|
|
|
[Fact]
|
|
public void SelectingSearchNode_LoadsSearchFormViewModel()
|
|
{
|
|
// Arrange
|
|
var config = new ConfigModel { Search = new SearchSection { MaxResultRows = 50000 } };
|
|
var sut = CreateViewModel();
|
|
sut.LoadConfigForTesting(config, null);
|
|
|
|
var searchNode = sut.TreeNodes
|
|
.SelectMany(n => n.Children)
|
|
.First(n => n.SectionKey == "Search");
|
|
|
|
// Act
|
|
sut.SelectedNode = searchNode;
|
|
|
|
// Assert
|
|
sut.SelectedFormViewModel.ShouldBeOfType<SearchFormViewModel>();
|
|
((SearchFormViewModel)sut.SelectedFormViewModel!).MaxResultRows.ShouldBe(50000);
|
|
}
|
|
|
|
[Fact]
|
|
public void SelectingExcelExportNode_LoadsExcelExportFormViewModel()
|
|
{
|
|
// Arrange
|
|
var config = new ConfigModel { ExcelExport = new ExcelExportSection { TimezoneId = "America/New_York" } };
|
|
var sut = CreateViewModel();
|
|
sut.LoadConfigForTesting(config, null);
|
|
|
|
var excelNode = sut.TreeNodes
|
|
.SelectMany(n => n.Children)
|
|
.First(n => n.SectionKey == "ExcelExport");
|
|
|
|
// Act
|
|
sut.SelectedNode = excelNode;
|
|
|
|
// Assert
|
|
sut.SelectedFormViewModel.ShouldBeOfType<ExcelExportFormViewModel>();
|
|
((ExcelExportFormViewModel)sut.SelectedFormViewModel!).TimezoneId.ShouldBe("America/New_York");
|
|
}
|
|
|
|
[Fact]
|
|
public void SelectingPipelineNode_LoadsPipelineEditorViewModel()
|
|
{
|
|
// Arrange
|
|
var config = new ConfigModel();
|
|
var pipelines = new PipelinesConfigModel
|
|
{
|
|
Pipelines = new Dictionary<string, PipelineModel>
|
|
{
|
|
["WorkOrders"] = new PipelineModel
|
|
{
|
|
Source = new PipelineSource { Connection = "jde", Query = "SELECT * FROM WO" },
|
|
Destination = new PipelineDestination { Table = "WorkOrder_Curr" }
|
|
}
|
|
}
|
|
};
|
|
var sut = CreateViewModel();
|
|
sut.LoadConfigForTesting(config, pipelines);
|
|
|
|
var pipelineNode = sut.TreeNodes
|
|
.SelectMany(n => n.Children)
|
|
.First(n => n.SectionKey == "WorkOrders");
|
|
|
|
// Act
|
|
sut.SelectedNode = pipelineNode;
|
|
|
|
// Assert
|
|
sut.SelectedFormViewModel.ShouldBeOfType<PipelineEditorViewModel>();
|
|
var pipelineEditor = (PipelineEditorViewModel)sut.SelectedFormViewModel!;
|
|
pipelineEditor.Name.ShouldBe("WorkOrders");
|
|
pipelineEditor.Source.Connection.ShouldBe("jde");
|
|
}
|
|
|
|
[Fact]
|
|
public void ModifyingFormProperty_SetsHasUnsavedChanges()
|
|
{
|
|
// Arrange
|
|
var config = new ConfigModel();
|
|
var sut = CreateViewModel();
|
|
sut.LoadConfigForTesting(config, null);
|
|
|
|
var dataSyncNode = sut.TreeNodes
|
|
.SelectMany(n => n.Children)
|
|
.First(n => n.SectionKey == "DataSync");
|
|
sut.SelectedNode = dataSyncNode;
|
|
|
|
// Act
|
|
((DataSyncFormViewModel)sut.SelectedFormViewModel!).BatchSize = 10000;
|
|
|
|
// Assert
|
|
sut.HasUnsavedChanges.ShouldBeTrue();
|
|
}
|
|
|
|
[Fact]
|
|
public void ModifyingFormProperty_MarksNodeAsModified()
|
|
{
|
|
// Arrange
|
|
var config = new ConfigModel();
|
|
var sut = CreateViewModel();
|
|
sut.LoadConfigForTesting(config, null);
|
|
|
|
var dataSyncNode = sut.TreeNodes
|
|
.SelectMany(n => n.Children)
|
|
.First(n => n.SectionKey == "DataSync");
|
|
sut.SelectedNode = dataSyncNode;
|
|
|
|
// Act
|
|
((DataSyncFormViewModel)sut.SelectedFormViewModel!).MaxDegreeOfParallelism = 16;
|
|
|
|
// Assert
|
|
dataSyncNode.IsModified.ShouldBeTrue();
|
|
}
|
|
|
|
[Fact]
|
|
public void SelectingFolderNode_SetsSelectedFormViewModelToNull()
|
|
{
|
|
// Arrange
|
|
var config = new ConfigModel();
|
|
var sut = CreateViewModel();
|
|
sut.LoadConfigForTesting(config, null);
|
|
|
|
var folderNode = sut.TreeNodes.First(); // Settings folder
|
|
|
|
// Act
|
|
sut.SelectedNode = folderNode;
|
|
|
|
// Assert
|
|
sut.SelectedFormViewModel.ShouldBeNull();
|
|
}
|
|
|
|
[Fact]
|
|
public void SelectingNull_SetsSelectedFormViewModelToNull()
|
|
{
|
|
// Arrange
|
|
var config = new ConfigModel();
|
|
var sut = CreateViewModel();
|
|
sut.LoadConfigForTesting(config, null);
|
|
|
|
var dataSyncNode = sut.TreeNodes
|
|
.SelectMany(n => n.Children)
|
|
.First(n => n.SectionKey == "DataSync");
|
|
sut.SelectedNode = dataSyncNode;
|
|
|
|
// Act
|
|
sut.SelectedNode = null;
|
|
|
|
// Assert
|
|
sut.SelectedFormViewModel.ShouldBeNull();
|
|
}
|
|
|
|
[Fact]
|
|
public void LoadConfigForTesting_BuildsTreeNodes()
|
|
{
|
|
// Arrange
|
|
var config = new ConfigModel();
|
|
var sut = CreateViewModel();
|
|
|
|
// Act
|
|
sut.LoadConfigForTesting(config, null);
|
|
|
|
// Assert
|
|
sut.TreeNodes.Count.ShouldBe(3); // Settings, Pipelines, and Secure Stores folders
|
|
sut.TreeNodes[0].Name.ShouldBe("Settings");
|
|
sut.TreeNodes[0].Children.Count.ShouldBe(6); // DataSync, DataAccess, Auth, Ldap, Search, ExcelExport
|
|
}
|
|
|
|
[Fact]
|
|
public void LoadConfigForTesting_WithPipelines_BuildsPipelineNodes()
|
|
{
|
|
// Arrange
|
|
var config = new ConfigModel();
|
|
var pipelines = new PipelinesConfigModel
|
|
{
|
|
Pipelines = new Dictionary<string, PipelineModel>
|
|
{
|
|
["Pipeline1"] = new PipelineModel(),
|
|
["Pipeline2"] = new PipelineModel()
|
|
}
|
|
};
|
|
var sut = CreateViewModel();
|
|
|
|
// Act
|
|
sut.LoadConfigForTesting(config, pipelines);
|
|
|
|
// Assert
|
|
sut.TreeNodes[1].Name.ShouldBe("Pipelines");
|
|
sut.TreeNodes[1].Children.Count.ShouldBe(2);
|
|
}
|
|
|
|
private MainWindowViewModel CreateViewModel()
|
|
{
|
|
return new MainWindowViewModel(
|
|
_fileSystem,
|
|
_configFileService,
|
|
_validationService,
|
|
_backupService,
|
|
_autoDiscoveryService,
|
|
_dialogService,
|
|
_secureStoreManager,
|
|
_clipboardService,
|
|
_runtimeValidationService,
|
|
_logger);
|
|
}
|
|
}
|