Initial commit: JDE Scoping Tool migration project
Set up repository with legacy .NET Framework 4.8 source (OLD/), new .NET 10 Blazor solution (NEW/), OpenSpec specifications, documentation, and project configuration.
This commit is contained in:
@@ -0,0 +1,194 @@
|
||||
using System.Linq.Expressions;
|
||||
using JdeScoping.DataSync.Services;
|
||||
|
||||
namespace JdeScoping.DataSync.Tests.Services;
|
||||
|
||||
public class ExpressionParserTests
|
||||
{
|
||||
private class TestEntity
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string Name { get; set; } = string.Empty;
|
||||
public DateTime? LastUpdateDt { get; set; }
|
||||
public decimal Amount { get; set; }
|
||||
}
|
||||
|
||||
#region GetColumnNames Tests
|
||||
|
||||
[Fact]
|
||||
public void GetColumnNames_SingleProperty_ReturnsSingleColumn()
|
||||
{
|
||||
// Arrange
|
||||
Expression<Func<TestEntity, object>> expr = x => x.Id;
|
||||
|
||||
// Act
|
||||
var columns = ExpressionParser.GetColumnNames(expr);
|
||||
|
||||
// Assert
|
||||
Assert.Single(columns);
|
||||
Assert.Equal("Id", columns[0]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetColumnNames_SingleStringProperty_ReturnsSingleColumn()
|
||||
{
|
||||
// Arrange
|
||||
Expression<Func<TestEntity, object>> expr = x => x.Name;
|
||||
|
||||
// Act
|
||||
var columns = ExpressionParser.GetColumnNames(expr);
|
||||
|
||||
// Assert
|
||||
Assert.Single(columns);
|
||||
Assert.Equal("Name", columns[0]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetColumnNames_AnonymousType_ReturnsAllColumns()
|
||||
{
|
||||
// Arrange
|
||||
Expression<Func<TestEntity, object>> expr = x => new { x.Id, x.Name };
|
||||
|
||||
// Act
|
||||
var columns = ExpressionParser.GetColumnNames(expr);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(2, columns.Count);
|
||||
Assert.Equal("Id", columns[0]);
|
||||
Assert.Equal("Name", columns[1]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetColumnNames_AnonymousTypeWithMultipleProperties_ReturnsAllColumns()
|
||||
{
|
||||
// Arrange
|
||||
Expression<Func<TestEntity, object>> expr = x => new { x.Id, x.Name, x.Amount, x.LastUpdateDt };
|
||||
|
||||
// Act
|
||||
var columns = ExpressionParser.GetColumnNames(expr);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(4, columns.Count);
|
||||
Assert.Equal("Id", columns[0]);
|
||||
Assert.Equal("Name", columns[1]);
|
||||
Assert.Equal("Amount", columns[2]);
|
||||
Assert.Equal("LastUpdateDt", columns[3]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetColumnNames_NullExpression_ThrowsArgumentNullException()
|
||||
{
|
||||
// Act & Assert
|
||||
Assert.Throws<ArgumentNullException>(() =>
|
||||
ExpressionParser.GetColumnNames<TestEntity>(null!));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region BuildUpdateWhenSql Tests
|
||||
|
||||
[Fact]
|
||||
public void BuildUpdateWhenSql_NullExpression_ReturnsNull()
|
||||
{
|
||||
// Act
|
||||
var result = ExpressionParser.BuildUpdateWhenSql<TestEntity>(null);
|
||||
|
||||
// Assert
|
||||
Assert.Null(result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BuildUpdateWhenSql_GreaterThan_ReturnsSqlCondition()
|
||||
{
|
||||
// Arrange
|
||||
Expression<Func<TestEntity, TestEntity, bool>> expr = (src, tgt) => src.LastUpdateDt > tgt.LastUpdateDt;
|
||||
|
||||
// Act
|
||||
var result = ExpressionParser.BuildUpdateWhenSql(expr);
|
||||
|
||||
// Assert
|
||||
Assert.Equal("source.[LastUpdateDt] > target.[LastUpdateDt]", result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BuildUpdateWhenSql_GreaterThanOrEqual_ReturnsSqlCondition()
|
||||
{
|
||||
// Arrange
|
||||
Expression<Func<TestEntity, TestEntity, bool>> expr = (src, tgt) => src.Id >= tgt.Id;
|
||||
|
||||
// Act
|
||||
var result = ExpressionParser.BuildUpdateWhenSql(expr);
|
||||
|
||||
// Assert
|
||||
Assert.Equal("source.[Id] >= target.[Id]", result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BuildUpdateWhenSql_Equal_ReturnsSqlCondition()
|
||||
{
|
||||
// Arrange
|
||||
Expression<Func<TestEntity, TestEntity, bool>> expr = (src, tgt) => src.Name == tgt.Name;
|
||||
|
||||
// Act
|
||||
var result = ExpressionParser.BuildUpdateWhenSql(expr);
|
||||
|
||||
// Assert
|
||||
Assert.Equal("source.[Name] = target.[Name]", result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BuildUpdateWhenSql_NotEqual_ReturnsSqlCondition()
|
||||
{
|
||||
// Arrange
|
||||
Expression<Func<TestEntity, TestEntity, bool>> expr = (src, tgt) => src.Amount != tgt.Amount;
|
||||
|
||||
// Act
|
||||
var result = ExpressionParser.BuildUpdateWhenSql(expr);
|
||||
|
||||
// Assert
|
||||
Assert.Equal("source.[Amount] <> target.[Amount]", result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BuildUpdateWhenSql_AndCondition_ReturnsSqlCondition()
|
||||
{
|
||||
// Arrange
|
||||
Expression<Func<TestEntity, TestEntity, bool>> expr =
|
||||
(src, tgt) => src.LastUpdateDt > tgt.LastUpdateDt && src.Id == tgt.Id;
|
||||
|
||||
// Act
|
||||
var result = ExpressionParser.BuildUpdateWhenSql(expr);
|
||||
|
||||
// Assert
|
||||
Assert.Equal("(source.[LastUpdateDt] > target.[LastUpdateDt] AND source.[Id] = target.[Id])", result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BuildUpdateWhenSql_OrCondition_ReturnsSqlCondition()
|
||||
{
|
||||
// Arrange
|
||||
Expression<Func<TestEntity, TestEntity, bool>> expr =
|
||||
(src, tgt) => src.LastUpdateDt > tgt.LastUpdateDt || src.Amount > tgt.Amount;
|
||||
|
||||
// Act
|
||||
var result = ExpressionParser.BuildUpdateWhenSql(expr);
|
||||
|
||||
// Assert
|
||||
Assert.Equal("(source.[LastUpdateDt] > target.[LastUpdateDt] OR source.[Amount] > target.[Amount])", result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BuildUpdateWhenSql_CustomAliases_UsesProvidedAliases()
|
||||
{
|
||||
// Arrange
|
||||
Expression<Func<TestEntity, TestEntity, bool>> expr = (src, tgt) => src.Id > tgt.Id;
|
||||
|
||||
// Act
|
||||
var result = ExpressionParser.BuildUpdateWhenSql(expr, "s", "t");
|
||||
|
||||
// Assert
|
||||
Assert.Equal("s.[Id] > t.[Id]", result);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
Reference in New Issue
Block a user