042e036c35
- Add IFileSystem and IDialogService dependencies to constructor - Implement OnSelectedNodeChanged to create appropriate form ViewModels - Add LoadConfigForTesting helper for unit testing - Add MarkAsChanged helper to track unsaved changes - Update OpenFolderAsync to use IDialogService - Add comprehensive unit tests for form selection
317 lines
10 KiB
C#
317 lines
10 KiB
C#
using JdeScoping.ConfigManager.Models;
|
|
using JdeScoping.ConfigManager.Services;
|
|
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 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>();
|
|
_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_LoadsPipelineFormViewModel()
|
|
{
|
|
// 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<PipelineFormViewModel>();
|
|
var pipelineForm = (PipelineFormViewModel)sut.SelectedFormViewModel!;
|
|
pipelineForm.Name.ShouldBe("WorkOrders");
|
|
pipelineForm.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(2); // Settings and Pipelines 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,
|
|
_logger);
|
|
}
|
|
}
|