using System.Data; using System.Text.RegularExpressions; using JdeScoping.DataSync.Etl.Transformers; using NSubstitute; namespace JdeScoping.DataSync.Tests.Etl.Transformers; public class RegexTransformerTests { [Fact] public void FindReplace_RemovesPrefix() { // Arrange var source = CreateMockReader( columns: new[] { "BatchID", "Name" }, values: new object[] { "IIS_12345", "Test" }); var transformer = new RegexTransformer( columnName: "BatchID", pattern: "^IIS_", replacement: ""); // Act var reader = transformer.Transform(source); source.Read().Returns(true); reader.Read(); // Assert Assert.Equal("12345", reader.GetValue(0)); Assert.Equal("Test", reader.GetValue(1)); // Other column unchanged } [Fact] public void MatchExtract_ExtractsFirstCaptureGroup() { // Arrange var source = CreateMockReader( columns: new[] { "Code" }, values: new object[] { "ID_12345" }); var transformer = new RegexTransformer( columnName: "Code", pattern: @"ID_(\d+)", replacement: null); // null = Match & Extract mode // Act var reader = transformer.Transform(source); source.Read().Returns(true); reader.Read(); // Assert Assert.Equal("12345", reader.GetValue(0)); } [Fact] public void MatchExtract_NoMatch_KeepOriginal() { // Arrange var source = CreateMockReader( columns: new[] { "Code" }, values: new object[] { "UNKNOWN" }); var transformer = new RegexTransformer( columnName: "Code", pattern: @"ID_(\d+)", replacement: null, nonMatchBehavior: NonMatchBehavior.KeepOriginal); // Act var reader = transformer.Transform(source); source.Read().Returns(true); reader.Read(); // Assert Assert.Equal("UNKNOWN", reader.GetValue(0)); } [Fact] public void MatchExtract_NoMatch_ReturnNull() { // Arrange var source = CreateMockReader( columns: new[] { "Code" }, values: new object[] { "UNKNOWN" }); var transformer = new RegexTransformer( columnName: "Code", pattern: @"ID_(\d+)", replacement: null, nonMatchBehavior: NonMatchBehavior.ReturnNull); // Act var reader = transformer.Transform(source); source.Read().Returns(true); reader.Read(); // Assert Assert.Equal(DBNull.Value, reader.GetValue(0)); } [Fact] public void MatchExtract_NoMatch_ReturnEmpty() { // Arrange var source = CreateMockReader( columns: new[] { "Code" }, values: new object[] { "UNKNOWN" }); var transformer = new RegexTransformer( columnName: "Code", pattern: @"ID_(\d+)", replacement: null, nonMatchBehavior: NonMatchBehavior.ReturnEmpty); // Act var reader = transformer.Transform(source); source.Read().Returns(true); reader.Read(); // Assert Assert.Equal(string.Empty, reader.GetValue(0)); } [Fact] public void FindReplace_UseCaptureGroups() { // Arrange - swap two numbers var source = CreateMockReader( columns: new[] { "Value" }, values: new object[] { "123-456" }); var transformer = new RegexTransformer( columnName: "Value", pattern: @"(\d+)-(\d+)", replacement: "$2-$1"); // Act var reader = transformer.Transform(source); source.Read().Returns(true); reader.Read(); // Assert Assert.Equal("456-123", reader.GetValue(0)); } [Fact] public void IgnoreCase_MatchesDifferentCase() { // Arrange var source = CreateMockReader( columns: new[] { "BatchID" }, values: new object[] { "IIS_12345" }); var transformer = new RegexTransformer( columnName: "BatchID", pattern: "^iis_", // lowercase pattern replacement: "", ignoreCase: true); // Act var reader = transformer.Transform(source); source.Read().Returns(true); reader.Read(); // Assert Assert.Equal("12345", reader.GetValue(0)); } [Fact] public void NullValue_PassesThrough() { // Arrange var source = CreateMockReader( columns: new[] { "BatchID" }, values: new object[] { DBNull.Value }); var transformer = new RegexTransformer( columnName: "BatchID", pattern: "^IIS_", replacement: ""); // Act var reader = transformer.Transform(source); source.Read().Returns(true); reader.Read(); // Assert Assert.Equal(DBNull.Value, reader.GetValue(0)); } [Fact] public void NonTargetColumn_Unchanged() { // Arrange var source = CreateMockReader( columns: new[] { "BatchID", "OtherColumn" }, values: new object[] { "IIS_12345", "IIS_Should_Not_Change" }); var transformer = new RegexTransformer( columnName: "BatchID", pattern: "^IIS_", replacement: ""); // Act var reader = transformer.Transform(source); source.Read().Returns(true); reader.Read(); // Assert Assert.Equal("12345", reader.GetValue(0)); Assert.Equal("IIS_Should_Not_Change", reader.GetValue(1)); } [Fact] public void InvalidRegex_ThrowsOnTransform() { // Arrange var source = CreateMockReader( columns: new[] { "Value" }, values: new object[] { "test" }); var transformer = new RegexTransformer( columnName: "Value", pattern: "[invalid(regex", replacement: ""); // Act & Assert var ex = Assert.Throws(() => transformer.Transform(source)); Assert.Contains("Invalid", ex.Message, StringComparison.OrdinalIgnoreCase); } [Fact] public void ColumnNotFound_ThrowsOnTransform() { // Arrange var source = CreateMockReader( columns: new[] { "Value" }, values: new object[] { "test" }); source.GetOrdinal("NonExistent").Returns(_ => throw new IndexOutOfRangeException("Column not found")); var transformer = new RegexTransformer( columnName: "NonExistent", pattern: "test", replacement: ""); // Act & Assert Assert.Throws(() => transformer.Transform(source)); } private static IDataReader CreateMockReader(string[] columns, object[] values) { var reader = Substitute.For(); reader.FieldCount.Returns(columns.Length); for (int i = 0; i < columns.Length; i++) { var index = i; reader.GetName(index).Returns(columns[index]); reader.GetOrdinal(columns[index]).Returns(index); reader.GetFieldType(index).Returns(values[index]?.GetType() ?? typeof(object)); reader.GetValue(index).Returns(values[index]); reader.IsDBNull(index).Returns(values[index] == null || values[index] == DBNull.Value); } return reader; } }