1fc7792cd1
Rename ConfigManager to ConfigManager.Ui to match the Core/CLI/UI project structure, and split the monolithic test project into Core.Tests, Cli.Tests, and Ui.Tests to align with the source project organization.
207 lines
5.9 KiB
C#
207 lines
5.9 KiB
C#
using JdeScoping.ConfigManager.Core.Models;
|
|
using JdeScoping.ConfigManager.Core.Services;
|
|
using JdeScoping.DataSync.Configuration;
|
|
|
|
namespace JdeScoping.ConfigManager.Core.Tests.Services;
|
|
|
|
public class ValidationServiceTests
|
|
{
|
|
private readonly ValidationService _sut;
|
|
|
|
public ValidationServiceTests()
|
|
{
|
|
_sut = new ValidationService();
|
|
}
|
|
|
|
[Fact]
|
|
public void ValidateAppSettings_WithValidConfig_ReturnsNoErrors()
|
|
{
|
|
// Arrange
|
|
var config = new ConfigModel
|
|
{
|
|
DataSync = new DataSyncSection { MaxDegreeOfParallelism = 4 }
|
|
};
|
|
|
|
// Act
|
|
var result = _sut.ValidateAppSettings(config);
|
|
|
|
// Assert
|
|
result.IsValid.ShouldBeTrue();
|
|
result.Errors.ShouldBeEmpty();
|
|
}
|
|
|
|
[Fact]
|
|
public void ValidateAppSettings_WithInvalidParallelism_ReturnsError()
|
|
{
|
|
// Arrange
|
|
var config = new ConfigModel
|
|
{
|
|
DataSync = new DataSyncSection { MaxDegreeOfParallelism = 0 }
|
|
};
|
|
|
|
// Act
|
|
var result = _sut.ValidateAppSettings(config);
|
|
|
|
// Assert
|
|
result.IsValid.ShouldBeFalse();
|
|
result.Errors.ShouldContain(e => e.Contains("MaxDegreeOfParallelism"));
|
|
}
|
|
|
|
[Fact]
|
|
public void ValidatePipelines_WithEmptyName_ReturnsError()
|
|
{
|
|
// Arrange
|
|
var pipelines = new Dictionary<string, EtlPipelineConfig>
|
|
{
|
|
[""] = new EtlPipelineConfig()
|
|
};
|
|
|
|
// Act
|
|
var result = _sut.ValidatePipelines(pipelines);
|
|
|
|
// Assert
|
|
result.IsValid.ShouldBeFalse();
|
|
}
|
|
|
|
[Fact]
|
|
public void ValidatePipelines_WithInvalidConnection_ReturnsError()
|
|
{
|
|
// Arrange
|
|
var pipelines = new Dictionary<string, EtlPipelineConfig>
|
|
{
|
|
["Test"] = new EtlPipelineConfig
|
|
{
|
|
Source = new SourceElement { Connection = "invalid" }
|
|
}
|
|
};
|
|
|
|
// Act
|
|
var result = _sut.ValidatePipelines(pipelines);
|
|
|
|
// Assert
|
|
result.IsValid.ShouldBeFalse();
|
|
result.Errors.ShouldContain(e => e.Contains("Connection"));
|
|
}
|
|
|
|
[Fact]
|
|
public void ValidatePipeline_WithValidConfig_ReturnsNoErrors()
|
|
{
|
|
// Arrange
|
|
var pipeline = new EtlPipelineConfig
|
|
{
|
|
Name = "Test",
|
|
IsEnabled = true,
|
|
Source = new SourceElement
|
|
{
|
|
Connection = "jde",
|
|
Query = "SELECT * FROM Test"
|
|
},
|
|
Destination = new DestinationElement
|
|
{
|
|
Table = "TestTable",
|
|
MatchColumns = ["Id"]
|
|
},
|
|
HourlySyncIntervalMinutes = 60
|
|
};
|
|
|
|
// Act
|
|
var result = _sut.ValidatePipeline(pipeline, "Test");
|
|
|
|
// Assert
|
|
result.IsValid.ShouldBeTrue();
|
|
result.Errors.ShouldBeEmpty();
|
|
}
|
|
|
|
[Fact]
|
|
public void ValidatePipeline_WithMissingQuery_ReturnsError()
|
|
{
|
|
// Arrange
|
|
var pipeline = new EtlPipelineConfig
|
|
{
|
|
Source = new SourceElement { Connection = "jde", Query = "" },
|
|
Destination = new DestinationElement { Table = "TestTable" },
|
|
IsManualOnly = true
|
|
};
|
|
|
|
// Act
|
|
var result = _sut.ValidatePipeline(pipeline, "Test");
|
|
|
|
// Assert
|
|
result.IsValid.ShouldBeFalse();
|
|
result.Errors.ShouldContain(e => e.Contains("Query"));
|
|
}
|
|
|
|
[Fact]
|
|
public void ValidatePipeline_WithNoScheduleAndNotManual_ReturnsWarning()
|
|
{
|
|
// Arrange
|
|
var pipeline = new EtlPipelineConfig
|
|
{
|
|
Source = new SourceElement { Connection = "jde", Query = "SELECT 1" },
|
|
Destination = new DestinationElement { Table = "TestTable", MatchColumns = ["Id"] },
|
|
IsManualOnly = false // No schedules and not manual-only
|
|
};
|
|
|
|
// Act
|
|
var result = _sut.ValidatePipeline(pipeline, "Test");
|
|
|
|
// Assert
|
|
result.Warnings.ShouldContain(w => w.Contains("No sync schedule"));
|
|
}
|
|
|
|
[Fact]
|
|
public void ValidatePipeline_ManualOnly_DoesNotRequireSchedule()
|
|
{
|
|
// Arrange
|
|
var pipeline = new EtlPipelineConfig
|
|
{
|
|
Source = new SourceElement { Connection = "jde", Query = "SELECT 1" },
|
|
Destination = new DestinationElement { Table = "TestTable", MatchColumns = ["Id"] },
|
|
IsManualOnly = true
|
|
};
|
|
|
|
// Act
|
|
var result = _sut.ValidatePipeline(pipeline, "Test");
|
|
|
|
// Assert
|
|
result.Warnings.ShouldNotContain(w => w.Contains("No sync schedule"));
|
|
}
|
|
|
|
[Fact]
|
|
public void ValidatePipeline_WithIntervalBelowMinimum_ReturnsError()
|
|
{
|
|
// Arrange
|
|
var pipeline = new EtlPipelineConfig
|
|
{
|
|
Source = new SourceElement { Connection = "jde", Query = "SELECT 1" },
|
|
Destination = new DestinationElement { Table = "TestTable" },
|
|
HourlySyncIntervalMinutes = 5 // Below minimum of 15
|
|
};
|
|
|
|
// Act
|
|
var result = _sut.ValidatePipeline(pipeline, "Test");
|
|
|
|
// Assert
|
|
result.IsValid.ShouldBeFalse();
|
|
result.Errors.ShouldContain(e => e.Contains("Hourly sync interval"));
|
|
}
|
|
|
|
[Fact]
|
|
public void ValidatePipeline_WithNoMatchColumns_ReturnsWarning()
|
|
{
|
|
// Arrange
|
|
var pipeline = new EtlPipelineConfig
|
|
{
|
|
Source = new SourceElement { Connection = "jde", Query = "SELECT 1" },
|
|
Destination = new DestinationElement { Table = "TestTable", MatchColumns = [] },
|
|
IsManualOnly = true
|
|
};
|
|
|
|
// Act
|
|
var result = _sut.ValidatePipeline(pipeline, "Test");
|
|
|
|
// Assert
|
|
result.Warnings.ShouldContain(w => w.Contains("No MatchColumns"));
|
|
}
|
|
}
|