using JdeScoping.DataSync.Services; namespace JdeScoping.DataSync.Tests.Services; public class MergeSqlBuilderTests { #region BuildCreateTempTable Tests [Fact] public void BuildCreateTempTable_ValidInputs_ReturnsSelectInto() { // Act var sql = MergeSqlBuilder.BuildCreateTempTable("#TEMP_WorkOrder", "WorkOrder"); // Assert Assert.Equal("SELECT TOP 0 * INTO [#TEMP_WorkOrder] FROM [WorkOrder]", sql); } [Theory] [InlineData(null, "WorkOrder")] [InlineData("", "WorkOrder")] [InlineData("#TEMP", null)] [InlineData("#TEMP", "")] public void BuildCreateTempTable_InvalidInputs_ThrowsArgumentException(string? tempTable, string? sourceTable) { // Act & Assert Assert.ThrowsAny(() => MergeSqlBuilder.BuildCreateTempTable(tempTable!, sourceTable!)); } #endregion #region BuildMergeSimple Tests [Fact] public void BuildMergeSimple_SingleMatchColumn_BuildsCorrectMerge() { // Arrange var matchColumns = new[] { "Id" }; var updateColumns = new[] { "Name", "Amount" }; var insertColumns = new[] { "Id", "Name", "Amount" }; // Act var sql = MergeSqlBuilder.BuildMergeSimple( "TestTable", "#TEMP_TestTable", matchColumns, updateColumns, null, insertColumns); // Assert Assert.Contains("MERGE INTO [TestTable] AS target", sql); Assert.Contains("USING [#TEMP_TestTable] AS source", sql); Assert.Contains("ON target.[Id] = source.[Id]", sql); Assert.Contains("WHEN MATCHED THEN", sql); Assert.Contains("UPDATE SET target.[Name] = source.[Name], target.[Amount] = source.[Amount]", sql); Assert.Contains("WHEN NOT MATCHED THEN", sql); Assert.Contains("INSERT ([Id], [Name], [Amount])", sql); Assert.Contains("VALUES (source.[Id], source.[Name], source.[Amount])", sql); } [Fact] public void BuildMergeSimple_CompositeKey_BuildsCorrectOnClause() { // Arrange var matchColumns = new[] { "WorkOrderNumber", "BranchCode" }; var updateColumns = new[] { "Status" }; var insertColumns = new[] { "WorkOrderNumber", "BranchCode", "Status" }; // Act var sql = MergeSqlBuilder.BuildMergeSimple( "WorkOrder", "#TEMP", matchColumns, updateColumns, null, insertColumns); // Assert Assert.Contains("ON target.[WorkOrderNumber] = source.[WorkOrderNumber] AND target.[BranchCode] = source.[BranchCode]", sql); } [Fact] public void BuildMergeSimple_WithUpdateWhen_IncludesCondition() { // Arrange var matchColumns = new[] { "Id" }; var updateColumns = new[] { "Name" }; var insertColumns = new[] { "Id", "Name" }; var updateWhen = "source.[LastUpdateDt] > target.[LastUpdateDt]"; // Act var sql = MergeSqlBuilder.BuildMergeSimple( "TestTable", "#TEMP", matchColumns, updateColumns, updateWhen, insertColumns); // Assert Assert.Contains("WHEN MATCHED AND source.[LastUpdateDt] > target.[LastUpdateDt] THEN", sql); } [Fact] public void BuildMergeSimple_NoUpdateColumns_OmitsUpdateClause() { // Arrange var matchColumns = new[] { "Id" }; var updateColumns = Array.Empty(); var insertColumns = new[] { "Id", "Name" }; // Act var sql = MergeSqlBuilder.BuildMergeSimple( "TestTable", "#TEMP", matchColumns, updateColumns, null, insertColumns); // Assert Assert.DoesNotContain("WHEN MATCHED", sql); Assert.Contains("WHEN NOT MATCHED THEN", sql); } [Fact] public void BuildMergeSimple_EmptyMatchColumns_ThrowsArgumentException() { // Arrange var matchColumns = Array.Empty(); var updateColumns = new[] { "Name" }; var insertColumns = new[] { "Id", "Name" }; // Act & Assert Assert.Throws(() => MergeSqlBuilder.BuildMergeSimple( "TestTable", "#TEMP", matchColumns, updateColumns, null, insertColumns)); } [Fact] public void BuildMergeSimple_EmptyInsertColumns_ThrowsArgumentException() { // Arrange var matchColumns = new[] { "Id" }; var updateColumns = new[] { "Name" }; var insertColumns = Array.Empty(); // Act & Assert Assert.Throws(() => MergeSqlBuilder.BuildMergeSimple( "TestTable", "#TEMP", matchColumns, updateColumns, null, insertColumns)); } #endregion #region BuildTruncateTempTable Tests [Fact] public void BuildTruncateTempTable_ValidInput_ReturnsTruncate() { // Act var sql = MergeSqlBuilder.BuildTruncateTempTable("#TEMP_WorkOrder"); // Assert Assert.Equal("TRUNCATE TABLE [#TEMP_WorkOrder]", sql); } #endregion #region BuildDropTempTable Tests [Fact] public void BuildDropTempTable_ValidInput_ReturnsDropWithCheck() { // Act var sql = MergeSqlBuilder.BuildDropTempTable("#TEMP_WorkOrder"); // Assert Assert.Contains("IF OBJECT_ID('tempdb..#TEMP_WorkOrder') IS NOT NULL", sql); Assert.Contains("DROP TABLE [#TEMP_WorkOrder]", sql); } #endregion }