diff --git a/tests/ReC.Tests/Application/Behaviors/InvokeActionTests.cs b/tests/ReC.Tests/Application/Behaviors/InvokeActionTests.cs new file mode 100644 index 0000000..73d00ea --- /dev/null +++ b/tests/ReC.Tests/Application/Behaviors/InvokeActionTests.cs @@ -0,0 +1,257 @@ +using System.ComponentModel.DataAnnotations.Schema; +using ReC.Application.Common.Behaviors.InvokeAction; +using ReC.Application.Common.Exceptions; + +namespace ReC.Tests.Application.Behaviors; + +#region Test Models + +public class Foo +{ + [Column("BAZ")] + public int Baz { get; set; } + + [Column("FOO_NAME")] + public string FooName { get; set; } = string.Empty; +} + +public class Bar +{ + [Column("QUX")] + public bool Qux { get; set; } + + [Column("BAR_DATE")] + public DateTime BarDate { get; set; } +} + +public class Fuz +{ + [Column("QUZ")] + public string Quz { get; set; } = string.Empty; + + [Column("FUZ_OFFSET")] + public DateTimeOffset FuzOffset { get; set; } +} + +public class NoColumnModel +{ + public int Id { get; set; } + public string Name { get; set; } = string.Empty; +} + +#endregion + +[TestFixture] +public class InvokeActionTests +{ + private Foo _foo = null!; + private Bar _bar = null!; + private Fuz _fuz = null!; + + [SetUp] + public void Setup() + { + _foo = new Foo { Baz = 2, FooName = "TestFoo" }; + _bar = new Bar { Qux = true, BarDate = new DateTime(2025, 6, 15, 14, 30, 0) }; + _fuz = new Fuz { Quz = "QuZ", FuzOffset = new DateTimeOffset(2025, 6, 15, 14, 30, 0, TimeSpan.FromHours(3)) }; + } + + #region GetValueByColumnName Tests + + [Test] + public void GetValueByColumnName_ExistingColumn_ReturnsValue() + { + var result = _foo.GetValueByColumnName("BAZ"); + Assert.That(result, Is.EqualTo(2)); + } + + [Test] + public void GetValueByColumnName_NonExistingColumn_ReturnsNull() + { + var result = _foo.GetValueByColumnName("NON_EXISTING"); + Assert.That(result, Is.Null); + } + + [Test] + public void GetValueByColumnName_PropertyNameInsteadOfColumnName_ReturnsNull() + { + var result = _foo.GetValueByColumnName("Baz"); + Assert.That(result, Is.Null); + } + + [Test] + public void GetValueByColumnName_ModelWithoutColumnAttribute_ReturnsNull() + { + var model = new NoColumnModel { Id = 1, Name = "Test" }; + var result = model.GetValueByColumnName("Id"); + Assert.That(result, Is.Null); + } + + #endregion + + #region ReplacePlaceholders - Basic Type Tests + + [TestCase("SELECT * FROM T WHERE BAZ = {#INT#BAZ}", "SELECT * FROM T WHERE BAZ = 2")] + [TestCase("... WHERE BAZ = {#INT#BAZ}", "... WHERE BAZ = 2")] + public void ReplacePlaceholders_IntValue_ReplacesCorrectly(string input, string expected) + { + var result = input.ReplacePlaceholders(_foo, _bar, _fuz); + Assert.That(result, Is.EqualTo(expected)); + } + + [TestCase("SELECT * FROM T WHERE QUX = {#BOOL#QUX}", "SELECT * FROM T WHERE QUX = TRUE")] + [TestCase("... WHERE QUX = {#INT#QUX}", "... WHERE QUX = TRUE")] + public void ReplacePlaceholders_BoolTrueValue_ReplacesWithTRUE(string input, string expected) + { + var result = input.ReplacePlaceholders(_foo, _bar, _fuz); + Assert.That(result, Is.EqualTo(expected)); + } + + [Test] + public void ReplacePlaceholders_BoolFalseValue_ReplacesWithFALSE() + { + var bar = new Bar { Qux = false }; + var result = "WHERE QUX = {#BOOL#QUX}".ReplacePlaceholders(bar); + Assert.That(result, Is.EqualTo("WHERE QUX = FALSE")); + } + + [TestCase("... WHERE QUZ <> '{#STR#QUZ}'", "... WHERE QUZ <> 'QuZ'")] + [TestCase("SELECT * FROM T WHERE QUZ = '{#TEXT#QUZ}'", "SELECT * FROM T WHERE QUZ = 'QuZ'")] + public void ReplacePlaceholders_StringValue_ReplacesCorrectly(string input, string expected) + { + var result = input.ReplacePlaceholders(_foo, _bar, _fuz); + Assert.That(result, Is.EqualTo(expected)); + } + + [Test] + public void ReplacePlaceholders_DateTimeValue_FormatsAsSqlDateTime() + { + var result = "WHERE D = '{#DATE#BAR_DATE}'".ReplacePlaceholders(_bar); + Assert.That(result, Is.EqualTo("WHERE D = '2025-06-15 14:30:00'")); + } + + [Test] + public void ReplacePlaceholders_DateTimeOffsetValue_FormatsWithOffset() + { + var result = "WHERE D = '{#DTO#FUZ_OFFSET}'".ReplacePlaceholders(_fuz); + Assert.That(result, Is.EqualTo("WHERE D = '2025-06-15 14:30:00 +03:00'")); + } + + #endregion + + #region ReplacePlaceholders - Multiple Placeholders + + [Test] + public void ReplacePlaceholders_MultiplePlaceholdersInSameString_ReplacesAll() + { + var input = "WHERE BAZ = {#INT#BAZ} AND QUX = {#BOOL#QUX} AND QUZ = '{#STR#QUZ}'"; + var expected = "WHERE BAZ = 2 AND QUX = TRUE AND QUZ = 'QuZ'"; + + var result = input.ReplacePlaceholders(_foo, _bar, _fuz); + Assert.That(result, Is.EqualTo(expected)); + } + + [Test] + public void ReplacePlaceholders_SamePlaceholderTwice_ReplacesBoth() + { + var input = "WHERE BAZ = {#INT#BAZ} OR BAZ = {#INT#BAZ}"; + var expected = "WHERE BAZ = 2 OR BAZ = 2"; + + var result = input.ReplacePlaceholders(_foo); + Assert.That(result, Is.EqualTo(expected)); + } + + #endregion + + #region ReplacePlaceholders - Object Resolution Order + + [Test] + public void ReplacePlaceholders_ValueFoundInSecondObject_ReturnsValueFromSecondObject() + { + var result = "WHERE QUX = {#BOOL#QUX}".ReplacePlaceholders(_foo, _bar); + Assert.That(result, Is.EqualTo("WHERE QUX = TRUE")); + } + + [Test] + public void ReplacePlaceholders_ValueFoundInThirdObject_ReturnsValueFromThirdObject() + { + var result = "WHERE QUZ = '{#STR#QUZ}'".ReplacePlaceholders(_foo, _bar, _fuz); + Assert.That(result, Is.EqualTo("WHERE QUZ = 'QuZ'")); + } + + #endregion + + #region ReplacePlaceholders - No Placeholder + + [TestCase("SELECT * FROM T WHERE X = 1")] + [TestCase("")] + [TestCase("some random text")] + public void ReplacePlaceholders_NoPlaceholders_ReturnsOriginalString(string input) + { + var result = input.ReplacePlaceholders(_foo, _bar, _fuz); + Assert.That(result, Is.EqualTo(input)); + } + + #endregion + + #region ReplacePlaceholders - Different Prefix Strings + + [TestCase("WHERE BAZ = {#VAR#BAZ}", "WHERE BAZ = 2")] + [TestCase("WHERE BAZ = {#PARAM#BAZ}", "WHERE BAZ = 2")] + [TestCase("WHERE BAZ = {#X#BAZ}", "WHERE BAZ = 2")] + [TestCase("WHERE BAZ = {#SOME_LONG_PREFIX#BAZ}", "WHERE BAZ = 2")] + public void ReplacePlaceholders_DifferentPrefixes_AllResolveCorrectly(string input, string expected) + { + var result = input.ReplacePlaceholders(_foo); + Assert.That(result, Is.EqualTo(expected)); + } + + #endregion + + #region ReplacePlaceholders - Exception Tests + + [Test] + public void ReplacePlaceholders_UnresolvableColumn_ThrowsPlaceholderResolutionException() + { + var input = "WHERE X = {#INT#NON_EXISTING}"; + + var ex = Assert.Throws(() => + input.ReplacePlaceholders(_foo, _bar, _fuz)); + + Assert.That(ex!.ColumnName, Is.EqualTo("NON_EXISTING")); + Assert.That(ex.Placeholder, Is.EqualTo("{#INT#NON_EXISTING}")); + Assert.That(ex.Input, Is.EqualTo(input)); + } + + [Test] + public void ReplacePlaceholders_NoObjectsProvided_ThrowsPlaceholderResolutionException() + { + var input = "WHERE X = {#INT#BAZ}"; + + Assert.Throws(() => + input.ReplacePlaceholders()); + } + + [Test] + public void ReplacePlaceholders_ObjectWithoutColumnAttributes_ThrowsPlaceholderResolutionException() + { + var model = new NoColumnModel { Id = 1, Name = "Test" }; + var input = "WHERE X = {#INT#Id}"; + + Assert.Throws(() => + input.ReplacePlaceholders(model)); + } + + [Test] + public void ReplacePlaceholders_MixedResolvableAndUnresolvable_ThrowsOnUnresolvable() + { + var input = "WHERE BAZ = {#INT#BAZ} AND X = {#INT#UNKNOWN}"; + + var ex = Assert.Throws(() => + input.ReplacePlaceholders(_foo, _bar, _fuz)); + + Assert.That(ex!.ColumnName, Is.EqualTo("UNKNOWN")); + } + + #endregion +}