PageRenderTime 39ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/Tests/DynamicWhereClause/DynamicWhereClauseTests.cs

http://tgh.codeplex.com
C# | 2149 lines | 1619 code | 383 blank | 147 comment | 288 complexity | 014102bfd85c1adf0ad223d540d174d2 MD5 | raw file
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq.Expressions;
  4. using AutoMapper;
  5. using FluentAssertions;
  6. using NUnit.Framework;
  7. using Telerik.Web.Mvc;
  8. using TelerikMvcGridCustomBindingHelper;
  9. using TelerikMvcGridCustomBindingHelper.DynamicQuery;
  10. using TelerikMvcGridCustomBindingHelper.Mapper;
  11. using TelerikMvcGridCustomBindingHelper.Util;
  12. using Tests.Entity;
  13. using Tests.ViewModel;
  14. namespace Tests.DynamicWhereClause
  15. {
  16. public class ExpressionWhereClauseWithBooleanSubstituteTests
  17. {
  18. //todo: CustomExpressions
  19. [SetUp]
  20. public void SetUp()
  21. {
  22. Mapper.Reset();
  23. GridModelMapper.Reset();
  24. GridModelMapper.CreateMap<Foo, FooModel>()
  25. // Add a BooleanSubstitute to a single property
  26. .MapProperty(foo => foo.EnabledFlag, model => model.Enabled, options => options.SetBooleanSubstitute<BooleanSubstitute>());
  27. //todo: .MapProperty(foo => foo.EnabledFlag == "" && foo.EnabledFlag == "", model => model.ComplexEnabled, options => options.SetBooleanSubstitute<BooleanSubstitute>());
  28. // GlobalBooleanSubstitutes have lower precedence
  29. GridModelMapper.Configuration.SetGlobalBooleanSubstitute<EfBooleanSubstitute>();
  30. }
  31. private class BooleanSubstitute : IBooleanSubstitute
  32. {
  33. public IList<object> TrueValues()
  34. {
  35. return new[] { "Y" };
  36. }
  37. public IList<object> FalseValues()
  38. {
  39. return new[] { "N", null };
  40. }
  41. }
  42. private class EfBooleanSubstitute : IBooleanSubstitute
  43. {
  44. public IList<object> TrueValues()
  45. {
  46. return new object[] { true };
  47. }
  48. public IList<object> FalseValues()
  49. {
  50. return new object[] { false, null };
  51. }
  52. }
  53. #region ExpressionCases
  54. // ReSharper disable InconsistentNaming
  55. // ReSharper disable NegativeEqualityExpression
  56. static readonly Expression<Func<Foo, bool>> Exp_IsEqualToTrue = foo => foo.EnabledFlag == "Y";
  57. static readonly Expression<Func<Foo, bool>> Exp_IsNotEqualToTrue = foo => !(foo.EnabledFlag == "Y");
  58. static readonly Expression<Func<Foo, bool>> Exp_IsEqualToFalse = foo => foo.EnabledFlag == null || foo.EnabledFlag == "N";
  59. static readonly Expression<Func<Foo, bool>> Exp_IsNotEqualToFalse = foo => !(foo.EnabledFlag == null) || !(foo.EnabledFlag == "N");
  60. static readonly Expression<Func<Foo, bool>> Exp_EfIsEqualToTrue = foo => foo.EfEnabled == true;
  61. static readonly Expression<Func<Foo, bool>> Exp_EfIsNotEqualToTrue = foo => !(foo.EfEnabled == true);
  62. static readonly Expression<Func<Foo, bool>> Exp_EfIsEqualToFalse = foo => foo.EfEnabled == null || foo.EfEnabled == false;
  63. static readonly Expression<Func<Foo, bool>> Exp_EfIsNotEqualToFalse = foo => !(foo.EfEnabled == null) || !(foo.EfEnabled == false);
  64. static readonly object[] ExpressionCases =
  65. {
  66. new object[] { "EnabledFlag", FilterOperator.IsEqualTo, Exp_IsEqualToTrue, true },
  67. new object[] { "EnabledFlag", FilterOperator.IsNotEqualTo, Exp_IsNotEqualToTrue, true},
  68. new object[] { "EnabledFlag", FilterOperator.IsEqualTo, Exp_IsEqualToFalse, false },
  69. new object[] { "EnabledFlag", FilterOperator.IsNotEqualTo, Exp_IsNotEqualToFalse, false},
  70. new object[] { "EnabledFlag", FilterOperator.IsEqualTo, Exp_IsEqualToFalse, null},
  71. new object[] { "EnabledFlag", FilterOperator.IsNotEqualTo, Exp_IsNotEqualToFalse, null},
  72. new object[] { "EfEnabled", FilterOperator.IsEqualTo, Exp_EfIsEqualToTrue, true },
  73. new object[] { "EfEnabled", FilterOperator.IsNotEqualTo, Exp_EfIsNotEqualToTrue, true},
  74. new object[] { "EfEnabled", FilterOperator.IsEqualTo, Exp_EfIsEqualToFalse, false },
  75. new object[] { "EfEnabled", FilterOperator.IsNotEqualTo, Exp_EfIsNotEqualToFalse, false},
  76. new object[] { "EfEnabled", FilterOperator.IsEqualTo, Exp_EfIsEqualToFalse, null},
  77. new object[] { "EfEnabled", FilterOperator.IsNotEqualTo, Exp_EfIsNotEqualToFalse, null}
  78. };
  79. // ReSharper restore NegativeEqualityExpression
  80. // ReSharper restore InconsistentNaming
  81. #endregion
  82. [TestCaseSource("ExpressionCases")]
  83. public void expressionWhereClause_single_expressions_with_booleanSubstitute(string member, FilterOperator @operator, Expression<Func<Foo, bool>> exp, object value)
  84. {
  85. var filter = new FilterDescriptor(member, @operator, value);
  86. var expressionWhereClause = new ExpressionWhereClause<Foo, FooModel>(filter, null, false, null);
  87. expressionWhereClause.Predicate.ToString().Replace("Tests.DynamicWhereClause.ExpressionWhereClauseWithBooleanSubstituteTests+Foo", "foo").Should().Be(exp.ToString());
  88. }
  89. [TestCaseSource("ExpressionCases")]
  90. public void expressionWhereClause_double_expressions_with_orElse_operator(string member, FilterOperator @operator, Expression<Func<Foo, bool>> exp, object value)
  91. {
  92. var filter = new FilterDescriptor(member, @operator, value);
  93. var expressionWhereClause = new ExpressionWhereClause<Foo, FooModel>(filter, null, false, null);
  94. expressionWhereClause.Predicate.ToString().Replace("Tests.DynamicWhereClause.ExpressionWhereClauseWithBooleanSubstituteTests+Foo", "foo").Should().Be(exp.ToString());
  95. expressionWhereClause.OrElse(expressionWhereClause);
  96. expressionWhereClause.Predicate.ToString().Replace("Tests.DynamicWhereClause.ExpressionWhereClauseWithBooleanSubstituteTests+Foo", "foo").Should().Be(exp.OrElse(exp).ToString());
  97. }
  98. [TestCaseSource("ExpressionCases")]
  99. public void expressionWhereClause_double_expressions_with_andAlso_operator(string member, FilterOperator @operator, Expression<Func<Foo, bool>> exp, object value)
  100. {
  101. var filter = new FilterDescriptor(member, @operator, value);
  102. var expressionWhereClause = new ExpressionWhereClause<Foo, FooModel>(filter, null, false, null);
  103. expressionWhereClause.Predicate.ToString().Replace("Tests.DynamicWhereClause.ExpressionWhereClauseWithBooleanSubstituteTests+Foo", "foo").Should().Be(exp.ToString());
  104. expressionWhereClause.AndAlso(expressionWhereClause);
  105. expressionWhereClause.Predicate.ToString().Replace("Tests.DynamicWhereClause.ExpressionWhereClauseWithBooleanSubstituteTests+Foo", "foo").Should().Be(exp.AndAlso(exp).ToString());
  106. }
  107. #region Test models
  108. // ReSharper disable ClassNeverInstantiated.Global
  109. // ReSharper disable UnusedAutoPropertyAccessor.Global
  110. // ReSharper disable ClassNeverInstantiated.Local
  111. // ReSharper disable UnusedAutoPropertyAccessor.Local
  112. // ReSharper disable UnusedMember.Local
  113. public class Foo
  114. {
  115. public bool? EfEnabled { get; set; }
  116. public string EnabledFlag { get; set; }
  117. }
  118. private class FooModel
  119. {
  120. public bool? EfEnabled { get; set; }
  121. public bool Enabled { get; set; }
  122. public bool ComplexEnabled { get; set; }
  123. }
  124. // ReSharper restore UnusedMember.Local
  125. // ReSharper restore UnusedAutoPropertyAccessor.Local
  126. // ReSharper restore ClassNeverInstantiated.Local
  127. // ReSharper restore UnusedAutoPropertyAccessor.Global
  128. // ReSharper restore ClassNeverInstantiated.Global
  129. #endregion
  130. }
  131. public class ExpressionWhereClauseWithNullSubstituteTests
  132. {
  133. //todo: CustomExpressions
  134. [SetUp]
  135. public void SetUp()
  136. {
  137. Mapper.Reset(); GridModelMapper.Reset();
  138. //GridModelMapper.CreateMap<Foo, FooModel>()
  139. // .MapProperty(foo => foo.FirstName + " " + foo.LastName, model => model.FullName)
  140. // .MapProperty(foo => foo.UnitPrice + foo.UnitsInStock, model => model.TotalPrice);
  141. GridModelMapper.CreateMap<Foo, FooModel>();
  142. // Can be set globally, per property, or in per query basis
  143. GridModelMapper.Configuration.SetGlobalNullSubstitute<NullSubstitute>();
  144. }
  145. private class NullSubstitute : INullSubstitute
  146. {
  147. public bool IsCaseInsensitive { get { return false; } }
  148. public IList<object> NullValues()
  149. {
  150. return new object[] { "none", string.Empty, 0, new DateTime(), null };
  151. }
  152. }
  153. #region ExpressionCases
  154. // ReSharper disable InconsistentNaming
  155. // ReSharper disable NegativeEqualityExpression
  156. static readonly Expression<Func<Foo, bool>> Exp_NullableIsEqualTo = foo => foo.NullableDecimal == null || foo.NullableDecimal.Value == 0;
  157. static readonly Expression<Func<Foo, bool>> Exp_StringIsEqualTo = foo => foo.Name == "none" || foo.Name == "" || foo.Name == "0" || foo.Name == "01/01/0001 00:00:00" || foo.Name == null;
  158. static readonly Expression<Func<Foo, bool>> Exp_StringIsNotEqualTo = foo => !(foo.Name == "none") || !(foo.Name == "") || !(foo.Name == "0") || !(foo.Name == "01/01/0001 00:00:00") || !(foo.Name == null);
  159. static readonly Expression<Func<Foo, bool>> Exp_NotNullableIsEqualTo = foo => foo.NotNullableDecimal == 0;
  160. static readonly Expression<Func<Foo, bool>> Exp_NotNullableIsNotEqualTo = foo => foo.NotNullableDecimal != 0;
  161. static readonly Expression<Func<Foo, bool>> Exp_NotSubstituteIsEqualTo = foo => foo.Name == "value";
  162. static readonly Expression<Func<Foo, bool>> Exp_NotSubstituteIsNotEqualTo = foo => foo.Name != "value";
  163. static readonly Expression<Func<Foo, bool>> Exp_DateTimeIsEqualTo = foo => foo.DateTime == new DateTime(2012, 10, 19);
  164. static readonly Expression<Func<Foo, bool>> Exp_DateTimeIsNotEqualTo = foo => foo.DateTime != new DateTime(2012, 10, 19);
  165. static readonly object[] ExpressionCases =
  166. {
  167. new object[] { "NullableDecimal", FilterOperator.IsLessThan, Exp_NullableIsEqualTo, null },
  168. new object[] { "NullableDecimal", FilterOperator.IsLessThanOrEqualTo, Exp_NullableIsEqualTo, null },
  169. new object[] { "NullableDecimal", FilterOperator.IsGreaterThanOrEqualTo, Exp_NullableIsEqualTo, null },
  170. new object[] { "NullableDecimal", FilterOperator.IsGreaterThan, Exp_NullableIsEqualTo, null },
  171. new object[] { "Name", FilterOperator.StartsWith, Exp_StringIsEqualTo, null },
  172. new object[] { "Name", FilterOperator.EndsWith, Exp_StringIsEqualTo, null },
  173. new object[] { "Name", FilterOperator.Contains, Exp_StringIsEqualTo, null },
  174. new object[] { "Name", FilterOperator.DoesNotContain, Exp_StringIsNotEqualTo, null },
  175. new object[] { "Name", FilterOperator.IsEqualTo, Exp_StringIsEqualTo, null },
  176. new object[] { "Name", FilterOperator.IsNotEqualTo, Exp_StringIsNotEqualTo, null },
  177. new object[] { "NotNullableDecimal", FilterOperator.IsEqualTo, Exp_NotNullableIsEqualTo, null },
  178. new object[] { "NotNullableDecimal", FilterOperator.IsNotEqualTo, Exp_NotNullableIsNotEqualTo, null },
  179. new object[] { "Name", FilterOperator.IsEqualTo, Exp_NotSubstituteIsEqualTo, "value" },
  180. new object[] { "Name", FilterOperator.IsNotEqualTo, Exp_NotSubstituteIsNotEqualTo, "value" },
  181. new object[] { "DateTime", FilterOperator.IsEqualTo, Exp_DateTimeIsEqualTo, new DateTime(2012, 10, 19) },
  182. new object[] { "DateTime", FilterOperator.IsNotEqualTo, Exp_DateTimeIsNotEqualTo, new DateTime(2012, 10, 19) }
  183. };
  184. // ReSharper restore NegativeEqualityExpression
  185. // ReSharper restore InconsistentNaming
  186. #endregion
  187. [TestCaseSource("ExpressionCases")]
  188. public void expressionWhereClause_single_expressions_with_booleanSubstitute(string member, FilterOperator @operator, Expression<Func<Foo, bool>> exp, object value)
  189. {
  190. var filter = new FilterDescriptor(member, @operator, value);
  191. var expressionWhereClause = new ExpressionWhereClause<Foo, FooModel>(filter, null, false, null);
  192. expressionWhereClause.Predicate.ToString()
  193. .Replace("Tests.DynamicWhereClause.ExpressionWhereClauseWithNullSubstituteTests+Foo", "foo")
  194. .Should().Be(exp.ToString().Replace(".Value", "").Replace("new DateTime(2012, 10, 19)", "19/10/2012 00:00:00"));
  195. }
  196. [TestCaseSource("ExpressionCases")]
  197. public void expressionWhereClause_double_expressions_with_orElse_operator(string member, FilterOperator @operator, Expression<Func<Foo, bool>> exp, object value)
  198. {
  199. var filter = new FilterDescriptor(member, @operator, value);
  200. var expressionWhereClause = new ExpressionWhereClause<Foo, FooModel>(filter, null, false, null);
  201. expressionWhereClause.Predicate.ToString()
  202. .Replace("Tests.DynamicWhereClause.ExpressionWhereClauseWithNullSubstituteTests+Foo", "foo")
  203. .Should().Be(exp.ToString().Replace(".Value", "").Replace("new DateTime(2012, 10, 19)", "19/10/2012 00:00:00"));
  204. expressionWhereClause.OrElse(expressionWhereClause);
  205. expressionWhereClause.Predicate.ToString()
  206. .Replace("Tests.DynamicWhereClause.ExpressionWhereClauseWithNullSubstituteTests+Foo", "foo")
  207. .Should().Be(exp.OrElse(exp).ToString().Replace(".Value", "").Replace("new DateTime(2012, 10, 19)", "19/10/2012 00:00:00"));
  208. }
  209. [TestCaseSource("ExpressionCases")]
  210. public void expressionWhereClause_double_expressions_with_andAlso_operator(string member, FilterOperator @operator, Expression<Func<Foo, bool>> exp, object value)
  211. {
  212. var filter = new FilterDescriptor(member, @operator, value);
  213. var expressionWhereClause = new ExpressionWhereClause<Foo, FooModel>(filter, null, false, null);
  214. expressionWhereClause.Predicate.ToString()
  215. .Replace("Tests.DynamicWhereClause.ExpressionWhereClauseWithNullSubstituteTests+Foo", "foo")
  216. .Should().Be(exp.ToString().Replace(".Value", "").Replace("new DateTime(2012, 10, 19)", "19/10/2012 00:00:00"));
  217. expressionWhereClause.AndAlso(expressionWhereClause);
  218. expressionWhereClause.Predicate.ToString()
  219. .Replace("Tests.DynamicWhereClause.ExpressionWhereClauseWithNullSubstituteTests+Foo", "foo")
  220. .Should().Be(exp.AndAlso(exp).ToString().Replace(".Value", "").Replace("new DateTime(2012, 10, 19)", "19/10/2012 00:00:00"));
  221. }
  222. #region Test models
  223. // ReSharper disable ClassNeverInstantiated.Global
  224. // ReSharper disable UnusedAutoPropertyAccessor.Global
  225. // ReSharper disable ClassNeverInstantiated.Local
  226. // ReSharper disable UnusedAutoPropertyAccessor.Local
  227. // ReSharper disable UnusedMember.Local
  228. public class Foo
  229. {
  230. public string Name { get; set; }
  231. public decimal? NullableDecimal { get; set; }
  232. public decimal NotNullableDecimal { get; set; }
  233. public DateTime DateTime { get; set; }
  234. }
  235. private class FooModel
  236. {
  237. public string Name { get; set; }
  238. public decimal? NullableDecimal { get; set; }
  239. public decimal NotNullableDecimal { get; set; }
  240. public DateTime DateTime { get; set; }
  241. }
  242. // ReSharper restore UnusedMember.Local
  243. // ReSharper restore UnusedAutoPropertyAccessor.Local
  244. // ReSharper restore ClassNeverInstantiated.Local
  245. // ReSharper restore UnusedAutoPropertyAccessor.Global
  246. // ReSharper restore ClassNeverInstantiated.Global
  247. #endregion
  248. }
  249. public class ExpressionWhereClauseWithNullSubstituteWithCaseInsensitiveTests
  250. {
  251. //todo: CustomExpressions
  252. [SetUp]
  253. public void SetUp()
  254. {
  255. Mapper.Reset(); GridModelMapper.Reset();
  256. //GridModelMapper.CreateMap<Foo, FooModel>()
  257. // .MapProperty(foo => foo.FirstName + " " + foo.LastName, model => model.FullName)
  258. // .MapProperty(foo => foo.UnitPrice + foo.UnitsInStock, model => model.TotalPrice);
  259. GridModelMapper.CreateMap<Foo, FooModel>();
  260. // Can be set globally, per property, or in per query basis
  261. GridModelMapper.Configuration.SetGlobalNullSubstitute<NullSubstitute>();
  262. }
  263. private class NullSubstitute : INullSubstitute
  264. {
  265. public bool IsCaseInsensitive { get { return true; } }
  266. public IList<object> NullValues()
  267. {
  268. return new object[] { "NoNe", string.Empty, 0, new DateTime(), null };
  269. }
  270. }
  271. #region ExpressionCases
  272. // ReSharper disable InconsistentNaming
  273. // ReSharper disable NegativeEqualityExpression
  274. static readonly Expression<Func<Foo, bool>> Exp_NullableIsEqualTo = foo => foo.NullableDecimal == null || foo.NullableDecimal.Value == 0;
  275. static readonly Expression<Func<Foo, bool>> Exp_StringIsEqualTo = foo => foo.Name.ToLowerInvariant() == "none" || foo.Name.ToLowerInvariant() == "" || foo.Name.ToLowerInvariant() == "0" || foo.Name.ToLowerInvariant() == "01/01/0001 00:00:00" || foo.Name == null;
  276. static readonly Expression<Func<Foo, bool>> Exp_StringIsNotEqualTo = foo => !(foo.Name.ToLowerInvariant() == "none") || !(foo.Name.ToLowerInvariant() == "") || !(foo.Name.ToLowerInvariant() == "0") || !(foo.Name.ToLowerInvariant() == "01/01/0001 00:00:00") || !(foo.Name == null);
  277. static readonly Expression<Func<Foo, bool>> Exp_NotNullableIsEqualTo = foo => foo.NotNullableDecimal == 0;
  278. static readonly Expression<Func<Foo, bool>> Exp_NotNullableIsNotEqualTo = foo => foo.NotNullableDecimal != 0;
  279. static readonly Expression<Func<Foo, bool>> Exp_NotSubstituteIsEqualTo = foo => foo.Name == "value";
  280. static readonly Expression<Func<Foo, bool>> Exp_NotSubstituteIsNotEqualTo = foo => foo.Name != "value";
  281. static readonly Expression<Func<Foo, bool>> Exp_DateTimeIsEqualTo = foo => foo.DateTime == new DateTime(2012, 10, 19);
  282. static readonly Expression<Func<Foo, bool>> Exp_DateTimeIsNotEqualTo = foo => foo.DateTime != new DateTime(2012, 10, 19);
  283. static readonly object[] ExpressionCases =
  284. {
  285. new object[] { "NullableDecimal", FilterOperator.IsLessThan, Exp_NullableIsEqualTo, null },
  286. new object[] { "NullableDecimal", FilterOperator.IsLessThanOrEqualTo, Exp_NullableIsEqualTo, null },
  287. new object[] { "NullableDecimal", FilterOperator.IsGreaterThanOrEqualTo, Exp_NullableIsEqualTo, null },
  288. new object[] { "NullableDecimal", FilterOperator.IsGreaterThan, Exp_NullableIsEqualTo, null },
  289. new object[] { "Name", FilterOperator.StartsWith, Exp_StringIsEqualTo, null },
  290. new object[] { "Name", FilterOperator.EndsWith, Exp_StringIsEqualTo, null },
  291. new object[] { "Name", FilterOperator.Contains, Exp_StringIsEqualTo, null },
  292. new object[] { "Name", FilterOperator.DoesNotContain, Exp_StringIsNotEqualTo, null },
  293. new object[] { "Name", FilterOperator.IsEqualTo, Exp_StringIsEqualTo, null },
  294. new object[] { "Name", FilterOperator.IsNotEqualTo, Exp_StringIsNotEqualTo, null },
  295. new object[] { "NotNullableDecimal", FilterOperator.IsEqualTo, Exp_NotNullableIsEqualTo, null },
  296. new object[] { "NotNullableDecimal", FilterOperator.IsNotEqualTo, Exp_NotNullableIsNotEqualTo, null },
  297. new object[] { "Name", FilterOperator.IsEqualTo, Exp_NotSubstituteIsEqualTo, "value" },
  298. new object[] { "Name", FilterOperator.IsNotEqualTo, Exp_NotSubstituteIsNotEqualTo, "value" },
  299. new object[] { "DateTime", FilterOperator.IsEqualTo, Exp_DateTimeIsEqualTo, new DateTime(2012, 10, 19) },
  300. new object[] { "DateTime", FilterOperator.IsNotEqualTo, Exp_DateTimeIsNotEqualTo, new DateTime(2012, 10, 19) }
  301. };
  302. // ReSharper restore NegativeEqualityExpression
  303. // ReSharper restore InconsistentNaming
  304. #endregion
  305. [TestCaseSource("ExpressionCases")]
  306. public void expressionWhereClause_single_expressions_with_booleanSubstitute(string member, FilterOperator @operator, Expression<Func<Foo, bool>> exp, object value)
  307. {
  308. var filter = new FilterDescriptor(member, @operator, value);
  309. var expressionWhereClause = new ExpressionWhereClause<Foo, FooModel>(filter, null, false, null);
  310. expressionWhereClause.Predicate.ToString()
  311. .Replace("Tests.DynamicWhereClause.ExpressionWhereClauseWithNullSubstituteWithCaseInsensitiveTests+Foo", "foo")
  312. .Should().Be(exp.ToString().Replace(".Value", "").Replace("new DateTime(2012, 10, 19)", "19/10/2012 00:00:00"));
  313. }
  314. [TestCaseSource("ExpressionCases")]
  315. public void expressionWhereClause_double_expressions_with_orElse_operator(string member, FilterOperator @operator, Expression<Func<Foo, bool>> exp, object value)
  316. {
  317. var filter = new FilterDescriptor(member, @operator, value);
  318. var expressionWhereClause = new ExpressionWhereClause<Foo, FooModel>(filter, null, false, null);
  319. expressionWhereClause.Predicate.ToString()
  320. .Replace("Tests.DynamicWhereClause.ExpressionWhereClauseWithNullSubstituteWithCaseInsensitiveTests+Foo", "foo")
  321. .Should().Be(exp.ToString().Replace(".Value", "").Replace("new DateTime(2012, 10, 19)", "19/10/2012 00:00:00"));
  322. expressionWhereClause.OrElse(expressionWhereClause);
  323. expressionWhereClause.Predicate.ToString()
  324. .Replace("Tests.DynamicWhereClause.ExpressionWhereClauseWithNullSubstituteWithCaseInsensitiveTests+Foo", "foo")
  325. .Should().Be(exp.OrElse(exp).ToString().Replace(".Value", "").Replace("new DateTime(2012, 10, 19)", "19/10/2012 00:00:00"));
  326. }
  327. [TestCaseSource("ExpressionCases")]
  328. public void expressionWhereClause_double_expressions_with_andAlso_operator(string member, FilterOperator @operator, Expression<Func<Foo, bool>> exp, object value)
  329. {
  330. var filter = new FilterDescriptor(member, @operator, value);
  331. var expressionWhereClause = new ExpressionWhereClause<Foo, FooModel>(filter, null, false, null);
  332. expressionWhereClause.Predicate.ToString()
  333. .Replace("Tests.DynamicWhereClause.ExpressionWhereClauseWithNullSubstituteWithCaseInsensitiveTests+Foo", "foo")
  334. .Should().Be(exp.ToString().Replace(".Value", "").Replace("new DateTime(2012, 10, 19)", "19/10/2012 00:00:00"));
  335. expressionWhereClause.AndAlso(expressionWhereClause);
  336. expressionWhereClause.Predicate.ToString()
  337. .Replace("Tests.DynamicWhereClause.ExpressionWhereClauseWithNullSubstituteWithCaseInsensitiveTests+Foo", "foo")
  338. .Should().Be(exp.AndAlso(exp).ToString().Replace(".Value", "").Replace("new DateTime(2012, 10, 19)", "19/10/2012 00:00:00"));
  339. }
  340. #region Test models
  341. // ReSharper disable ClassNeverInstantiated.Global
  342. // ReSharper disable UnusedAutoPropertyAccessor.Global
  343. // ReSharper disable ClassNeverInstantiated.Local
  344. // ReSharper disable UnusedAutoPropertyAccessor.Local
  345. // ReSharper disable UnusedMember.Local
  346. public class Foo
  347. {
  348. public string Name { get; set; }
  349. public decimal? NullableDecimal { get; set; }
  350. public decimal NotNullableDecimal { get; set; }
  351. public DateTime DateTime { get; set; }
  352. }
  353. private class FooModel
  354. {
  355. public string Name { get; set; }
  356. public decimal? NullableDecimal { get; set; }
  357. public decimal NotNullableDecimal { get; set; }
  358. public DateTime DateTime { get; set; }
  359. }
  360. // ReSharper restore UnusedMember.Local
  361. // ReSharper restore UnusedAutoPropertyAccessor.Local
  362. // ReSharper restore ClassNeverInstantiated.Local
  363. // ReSharper restore UnusedAutoPropertyAccessor.Global
  364. // ReSharper restore ClassNeverInstantiated.Global
  365. #endregion
  366. }
  367. public class ExpressionWhereClauseWithNullAliasTests
  368. {
  369. //todo: CustomExpressions
  370. [SetUp]
  371. public void SetUp()
  372. {
  373. Mapper.Reset(); GridModelMapper.Reset();
  374. //GridModelMapper.CreateMap<Foo, FooModel>()
  375. // .MapProperty(foo => foo.FirstName + " " + foo.LastName, model => model.FullName)
  376. // .MapProperty(foo => foo.UnitPrice + foo.UnitsInStock, model => model.TotalPrice);
  377. GridModelMapper.CreateMap<Foo, FooModel>();
  378. GridModelMapper.Configuration.SetGlobalNullAlias<NullAlias>();
  379. }
  380. private class NullAlias : INullAlias
  381. {
  382. public bool IsCaseInsensitive { get { return false; } }
  383. //the query should contain these aliases explicitly?
  384. public bool SearchExplicit { get { return false; } }
  385. public IList<object> Aliases()
  386. {
  387. return new object[] { "none", "empty", -1, null };
  388. }
  389. }
  390. #region ExpressionCases
  391. // ReSharper disable InconsistentNaming
  392. // ReSharper disable NegativeEqualityExpression
  393. static readonly Expression<Func<Foo, bool>> Exp_NullableIsEqualTo = foo => foo.NullableDecimal == null;
  394. static readonly Expression<Func<Foo, bool>> Exp_NullableValidValueIsLessThan = foo => foo.NullableDecimal.Value < 10;
  395. static readonly Expression<Func<Foo, bool>> Exp_NullableValidValueIsLessThanOrEqualTo = foo => foo.NullableDecimal.Value <= 10;
  396. static readonly Expression<Func<Foo, bool>> Exp_NullableValidValueIsGreaterThanOrEqualTo = foo => foo.NullableDecimal.Value >= 10;
  397. static readonly Expression<Func<Foo, bool>> Exp_NullableValidValueIsGreaterThan = foo => foo.NullableDecimal.Value > 10;
  398. static readonly Expression<Func<Foo, bool>> Exp_NullableValidValueIsEqualTo = foo => foo.NullableDecimal.Value == 10;
  399. static readonly Expression<Func<Foo, bool>> Exp_NullableValidValueIsNotEqualTo = foo => foo.NullableDecimal.Value != 10;
  400. static readonly Expression<Func<Foo, bool>> Exp_IsEqualTo = foo => foo.Name == null;
  401. static readonly Expression<Func<Foo, bool>> Exp_IsNotEqualTo = foo => !(foo.Name == null);
  402. static readonly Expression<Func<Foo, bool>> Exp_NotValidAliasIsEqualTo = foo => foo.Name == "value";
  403. static readonly Expression<Func<Foo, bool>> Exp_NotValidAliasIsNotEqualTo = foo => foo.Name != "value";
  404. static readonly Expression<Func<Foo, bool>> Exp_CaseSensitiveIsEqualTo = foo => foo.Name == "NoNe";
  405. static readonly Expression<Func<Foo, bool>> Exp_CaseSensitiveIsNotEqualTo = foo => foo.Name != "EmPtY";
  406. static readonly Expression<Func<Foo, bool>> Exp_NotNullableNullValueIsEqualTo = foo => foo.NotNullableDecimal == 0;
  407. static readonly Expression<Func<Foo, bool>> Exp_NotNullableNullValueIsNotEqualTo = foo => foo.NotNullableDecimal != 0;
  408. static readonly Expression<Func<Foo, bool>> Exp_NotNullableValidValueIsEqualTo = foo => foo.NotNullableDecimal == -1;
  409. static readonly Expression<Func<Foo, bool>> Exp_NotNullableValidValueIsNotEqualTo = foo => foo.NotNullableDecimal != -1;
  410. static readonly Expression<Func<Foo, bool>> Exp_NotNullableIsEqualTo = foo => foo.NotNullableDecimal == 10;
  411. static readonly Expression<Func<Foo, bool>> Exp_NotNullableIsNotEqualTo = foo => foo.NotNullableDecimal != 10;
  412. static readonly object[] ExpressionCases =
  413. {
  414. new object[] { "NullableDecimal", FilterOperator.IsLessThan, Exp_NullableIsEqualTo, null },
  415. new object[] { "NullableDecimal", FilterOperator.IsLessThanOrEqualTo, Exp_NullableIsEqualTo, null },
  416. new object[] { "NullableDecimal", FilterOperator.IsGreaterThanOrEqualTo, Exp_NullableIsEqualTo, null },
  417. new object[] { "NullableDecimal", FilterOperator.IsGreaterThan, Exp_NullableIsEqualTo, null },
  418. new object[] { "NullableDecimal", FilterOperator.IsLessThan, Exp_NullableIsEqualTo, -1 },
  419. new object[] { "NullableDecimal", FilterOperator.IsLessThanOrEqualTo, Exp_NullableIsEqualTo, -1 },
  420. new object[] { "NullableDecimal", FilterOperator.IsGreaterThanOrEqualTo, Exp_NullableIsEqualTo, -1 },
  421. new object[] { "NullableDecimal", FilterOperator.IsGreaterThan, Exp_NullableIsEqualTo, -1 },
  422. new object[] { "NullableDecimal", FilterOperator.IsLessThan, Exp_NullableValidValueIsLessThan, 10 },
  423. new object[] { "NullableDecimal", FilterOperator.IsLessThanOrEqualTo, Exp_NullableValidValueIsLessThanOrEqualTo, 10 },
  424. new object[] { "NullableDecimal", FilterOperator.IsGreaterThanOrEqualTo, Exp_NullableValidValueIsGreaterThanOrEqualTo, 10 },
  425. new object[] { "NullableDecimal", FilterOperator.IsGreaterThan, Exp_NullableValidValueIsGreaterThan, 10 },
  426. new object[] { "NullableDecimal", FilterOperator.IsEqualTo, Exp_NullableValidValueIsEqualTo, 10 },
  427. new object[] { "NullableDecimal", FilterOperator.IsNotEqualTo, Exp_NullableValidValueIsNotEqualTo, 10 },
  428. new object[] { "NotNullableDecimal", FilterOperator.IsEqualTo, Exp_NotNullableNullValueIsEqualTo, null },
  429. new object[] { "NotNullableDecimal", FilterOperator.IsNotEqualTo, Exp_NotNullableNullValueIsNotEqualTo, null },
  430. new object[] { "NotNullableDecimal", FilterOperator.IsEqualTo, Exp_NotNullableNullValueIsEqualTo, "invalid-value" },
  431. new object[] { "NotNullableDecimal", FilterOperator.IsNotEqualTo, Exp_NotNullableNullValueIsNotEqualTo, "invalid-value" },
  432. new object[] { "NotNullableDecimal", FilterOperator.IsEqualTo, Exp_NotNullableValidValueIsEqualTo, -1 },
  433. new object[] { "NotNullableDecimal", FilterOperator.IsNotEqualTo, Exp_NotNullableValidValueIsNotEqualTo, -1 },
  434. new object[] { "NotNullableDecimal", FilterOperator.IsEqualTo, Exp_NotNullableIsEqualTo, 10 },
  435. new object[] { "NotNullableDecimal", FilterOperator.IsNotEqualTo, Exp_NotNullableIsNotEqualTo, 10 },
  436. new object[] { "Name", FilterOperator.StartsWith, Exp_IsEqualTo, "none" },
  437. new object[] { "Name", FilterOperator.EndsWith, Exp_IsEqualTo, "none" },
  438. new object[] { "Name", FilterOperator.Contains, Exp_IsEqualTo, "none" },
  439. new object[] { "Name", FilterOperator.DoesNotContain, Exp_IsNotEqualTo, "none" },
  440. new object[] { "Name", FilterOperator.IsEqualTo, Exp_IsEqualTo, null },
  441. new object[] { "Name", FilterOperator.IsNotEqualTo, Exp_IsNotEqualTo, null },
  442. new object[] { "Name", FilterOperator.IsEqualTo, Exp_IsEqualTo, "none" },
  443. new object[] { "Name", FilterOperator.IsEqualTo, Exp_IsEqualTo, "empty" },
  444. new object[] { "Name", FilterOperator.IsNotEqualTo, Exp_IsNotEqualTo, "none" },
  445. new object[] { "Name", FilterOperator.IsNotEqualTo, Exp_IsNotEqualTo, "empty" },
  446. new object[] { "Name", FilterOperator.IsEqualTo, Exp_NotValidAliasIsEqualTo, "value" },
  447. new object[] { "Name", FilterOperator.IsNotEqualTo, Exp_NotValidAliasIsNotEqualTo, "value" },
  448. new object[] { "Name", FilterOperator.IsEqualTo, Exp_CaseSensitiveIsEqualTo, "NoNe" },
  449. new object[] { "Name", FilterOperator.IsNotEqualTo, Exp_CaseSensitiveIsNotEqualTo, "EmPtY" }
  450. };
  451. // ReSharper restore NegativeEqualityExpression
  452. // ReSharper restore InconsistentNaming
  453. #endregion
  454. [TestCaseSource("ExpressionCases")]
  455. public void single_expressions(string member, FilterOperator @operator, Expression<Func<Foo, bool>> exp, object value)
  456. {
  457. var filter = new FilterDescriptor(member, @operator, value);
  458. var expressionWhereClause = new ExpressionWhereClause<Foo, FooModel>(filter, null, false, null);
  459. expressionWhereClause.Predicate.ToString()
  460. .Replace("Tests.DynamicWhereClause.ExpressionWhereClauseWithNullAliasTests+Foo", "foo")
  461. .Should().Be(exp.ToString().Replace(".Value", ""));
  462. }
  463. [TestCaseSource("ExpressionCases")]
  464. public void double_expressions_with_orElse_operator(string member, FilterOperator @operator, Expression<Func<Foo, bool>> exp, object value)
  465. {
  466. var filter = new FilterDescriptor(member, @operator, value);
  467. var expressionWhereClause = new ExpressionWhereClause<Foo, FooModel>(filter, null, false, null);
  468. expressionWhereClause.Predicate.ToString()
  469. .Replace("Tests.DynamicWhereClause.ExpressionWhereClauseWithNullAliasTests+Foo", "foo")
  470. .Should().Be(exp.ToString().Replace(".Value", ""));
  471. expressionWhereClause.OrElse(expressionWhereClause);
  472. expressionWhereClause.Predicate.ToString()
  473. .Replace("Tests.DynamicWhereClause.ExpressionWhereClauseWithNullAliasTests+Foo", "foo")
  474. .Should().Be(exp.OrElse(exp).ToString().Replace(".Value", ""));
  475. }
  476. [TestCaseSource("ExpressionCases")]
  477. public void double_expressions_with_andAlso_operator(string member, FilterOperator @operator, Expression<Func<Foo, bool>> exp, object value)
  478. {
  479. var filter = new FilterDescriptor(member, @operator, value);
  480. var expressionWhereClause = new ExpressionWhereClause<Foo, FooModel>(filter, null, false, null);
  481. expressionWhereClause.Predicate.ToString()
  482. .Replace("Tests.DynamicWhereClause.ExpressionWhereClauseWithNullAliasTests+Foo", "foo")
  483. .Should().Be(exp.ToString().Replace(".Value", ""));
  484. expressionWhereClause.AndAlso(expressionWhereClause);
  485. expressionWhereClause.Predicate.ToString()
  486. .Replace("Tests.DynamicWhereClause.ExpressionWhereClauseWithNullAliasTests+Foo", "foo")
  487. .Should().Be(exp.AndAlso(exp).ToString().Replace(".Value", ""));
  488. }
  489. #region Test models
  490. // ReSharper disable ClassNeverInstantiated.Global
  491. // ReSharper disable UnusedAutoPropertyAccessor.Global
  492. // ReSharper disable ClassNeverInstantiated.Local
  493. // ReSharper disable UnusedAutoPropertyAccessor.Local
  494. // ReSharper disable UnusedMember.Local
  495. // ReSharper disable UnusedMember.Global
  496. public class Foo
  497. {
  498. public string Name { get; set; }
  499. public decimal? NullableDecimal { get; set; }
  500. public decimal NotNullableDecimal { get; set; }
  501. public DateTime DateTime { get; set; }
  502. }
  503. private class FooModel
  504. {
  505. public string Name { get; set; }
  506. public decimal? NullableDecimal { get; set; }
  507. public decimal NotNullableDecimal { get; set; }
  508. public DateTime DateTime { get; set; }
  509. }
  510. // ReSharper restore UnusedMember.Global
  511. // ReSharper restore UnusedMember.Local
  512. // ReSharper restore UnusedAutoPropertyAccessor.Local
  513. // ReSharper restore ClassNeverInstantiated.Local
  514. // ReSharper restore UnusedAutoPropertyAccessor.Global
  515. // ReSharper restore ClassNeverInstantiated.Global
  516. #endregion
  517. }
  518. public class ExpressionWhereClauseWithNullAliasAndSearchExplicitTests
  519. {
  520. //todo: CustomExpressions
  521. [SetUp]
  522. public void SetUp()
  523. {
  524. Mapper.Reset(); GridModelMapper.Reset();
  525. //GridModelMapper.CreateMap<Foo, FooModel>()
  526. // .MapProperty(foo => foo.FirstName + " " + foo.LastName, model => model.FullName)
  527. // .MapProperty(foo => foo.UnitPrice + foo.UnitsInStock, model => model.TotalPrice);
  528. GridModelMapper.CreateMap<Foo, FooModel>();
  529. GridModelMapper.Configuration.SetGlobalNullAlias<NullAlias>();
  530. }
  531. private class NullAlias : INullAlias
  532. {
  533. public bool IsCaseInsensitive { get { return false; } }
  534. //the query should contain these aliases explicitly?
  535. public bool SearchExplicit { get { return true; } }
  536. public IList<object> Aliases()
  537. {
  538. return new object[] { "none", "empty", -1, null };
  539. }
  540. }
  541. #region ExpressionCases
  542. // ReSharper disable InconsistentNaming
  543. // ReSharper disable NegativeEqualityExpression
  544. static readonly Expression<Func<Foo, bool>> Exp_NullableValidValueIsEqualTo = foo => foo.NullableDecimal.Value == 10;
  545. static readonly Expression<Func<Foo, bool>> Exp_NullableIsEqualTo = foo => foo.NullableDecimal == null || foo.NullableDecimal.Value == -1;
  546. static readonly Expression<Func<Foo, bool>> Exp_NullableIsLessThan = foo => foo.NullableDecimal == null || foo.NullableDecimal.Value < -1;
  547. static readonly Expression<Func<Foo, bool>> Exp_NullableIsLessThanOrEqualTo = foo => foo.NullableDecimal == null || foo.NullableDecimal.Value <= -1;
  548. static readonly Expression<Func<Foo, bool>> Exp_NullableIsGreaterThan = foo => foo.NullableDecimal == null || foo.NullableDecimal.Value > -1;
  549. static readonly Expression<Func<Foo, bool>> Exp_NullableIsGreaterThanOrEqualTo = foo => foo.NullableDecimal == null || foo.NullableDecimal.Value >= -1;
  550. static readonly Expression<Func<Foo, bool>> Exp_NullableIsNotEqualTo = foo => !(foo.NullableDecimal == null) && foo.NullableDecimal.Value != -1;
  551. static readonly Expression<Func<Foo, bool>> Exp_IsEqualTo = foo => foo.Name == null || (foo.Name == "none" || foo.Name == "empty");
  552. static readonly Expression<Func<Foo, bool>> Exp_Contains = foo => foo.Name == null || (foo.Name.Contains("none") || foo.Name.Contains("empty"));
  553. static readonly Expression<Func<Foo, bool>> Exp_EndsWith = foo => foo.Name == null || (foo.Name.EndsWith("none") || foo.Name.EndsWith("empty"));
  554. static readonly Expression<Func<Foo, bool>> Exp_DoesNotContain = foo => !(foo.Name == null) && (!(foo.Name.Contains("none")) && !(foo.Name.Contains("empty")));
  555. static readonly Expression<Func<Foo, bool>> Exp_StartsWith = foo => foo.Name == null || (foo.Name.StartsWith("none") || foo.Name.StartsWith("empty"));
  556. static readonly Expression<Func<Foo, bool>> Exp_IsNotEqualTo = foo => !(foo.Name == null) && (foo.Name != "none" && foo.Name != "empty");
  557. static readonly Expression<Func<Foo, bool>> Exp_NotValidAliasIsEqualTo = foo => foo.Name == "value";
  558. static readonly Expression<Func<Foo, bool>> Exp_NotValidAliasIsNotEqualTo = foo => foo.Name != "value";
  559. static readonly Expression<Func<Foo, bool>> Exp_CaseSensitiveIsEqualTo = foo => foo.Name == "NoNe";
  560. static readonly Expression<Func<Foo, bool>> Exp_CaseSensitiveIsNotEqualTo = foo => foo.Name != "EmPtY";
  561. static readonly Expression<Func<Foo, bool>> Exp_NotNullableDefaultValueIsEqualTo = foo => foo.NotNullableDecimal == 0;
  562. static readonly Expression<Func<Foo, bool>> Exp_NotNullableIsEqualTo = foo => foo.NotNullableDecimal == -1;
  563. static readonly Expression<Func<Foo, bool>> Exp_NotNullableValidValueIsEqualTo = foo => foo.NotNullableDecimal == 10;
  564. static readonly Expression<Func<Foo, bool>> Exp_NotNullableIsNotEqualTo = foo => foo.NotNullableDecimal != 0;
  565. static readonly object[] ExpressionCases =
  566. {
  567. new object[] { "NullableDecimal", FilterOperator.IsLessThan, Exp_NullableIsLessThan, null },
  568. new object[] { "NullableDecimal", FilterOperator.IsLessThan, Exp_NullableIsLessThan, -1 },
  569. new object[] { "NullableDecimal", FilterOperator.IsLessThanOrEqualTo, Exp_NullableIsLessThanOrEqualTo, null },
  570. new object[] { "NullableDecimal", FilterOperator.IsLessThanOrEqualTo, Exp_NullableIsLessThanOrEqualTo, -1 },
  571. new object[] { "NullableDecimal", FilterOperator.IsGreaterThan, Exp_NullableIsGreaterThan, null },
  572. new object[] { "NullableDecimal", FilterOperator.IsGreaterThan, Exp_NullableIsGreaterThan, -1 },
  573. new object[] { "NullableDecimal", FilterOperator.IsGreaterThanOrEqualTo, Exp_NullableIsGreaterThanOrEqualTo, null },
  574. new object[] { "NullableDecimal", FilterOperator.IsGreaterThanOrEqualTo, Exp_NullableIsGreaterThanOrEqualTo, -1 },
  575. new object[] { "NullableDecimal", FilterOperator.IsEqualTo, Exp_NullableIsEqualTo, null },
  576. new object[] { "NullableDecimal", FilterOperator.IsEqualTo, Exp_NullableIsEqualTo, -1 },
  577. new object[] { "NullableDecimal", FilterOperator.IsNotEqualTo, Exp_NullableIsNotEqualTo, null },
  578. new object[] { "NullableDecimal", FilterOperator.IsNotEqualTo, Exp_NullableIsNotEqualTo, -1 },
  579. new object[] { "NullableDecimal", FilterOperator.IsEqualTo, Exp_NullableValidValueIsEqualTo, 10 },
  580. new object[] { "NotNullableDecimal", FilterOperator.IsEqualTo, Exp_NotNullableValidValueIsEqualTo, 10 },
  581. new object[] { "NotNullableDecimal", FilterOperator.IsEqualTo, Exp_NotNullableIsEqualTo, -1 },
  582. new object[] { "NotNullableDecimal", FilterOperator.IsEqualTo, Exp_NotNullableDefaultValueIsEqualTo, null },
  583. new object[] { "NotNullableDecimal", FilterOperator.IsEqualTo, Exp_NotNullableDefaultValueIsEqualTo, "none" },
  584. new object[] { "NotNullableDecimal", FilterOperator.IsNotEqualTo, Exp_NotNullableIsNotEqualTo, null },
  585. new object[] { "Name", FilterOperator.StartsWith, Exp_StartsWith, "none" },
  586. new object[] { "Name", FilterOperator.EndsWith, Exp_EndsWith, "none" },
  587. new object[] { "Name", FilterOperator.Contains, Exp_Contains, "none" },
  588. new object[] { "Name", FilterOperator.DoesNotContain, Exp_DoesNotContain, "none" },
  589. new object[] { "Name", FilterOperator.IsEqualTo, Exp_IsEqualTo, null },
  590. new object[] { "Name", FilterOperator.IsNotEqualTo, Exp_IsNotEqualTo, null },
  591. new object[] { "Name", FilterOperator.IsEqualTo, Exp_IsEqualTo, "none" },
  592. new object[] { "Name", FilterOperator.IsEqualTo, Exp_IsEqualTo, "empty" },
  593. new object[] { "Name", FilterOperator.IsNotEqualTo, Exp_IsNotEqualTo, "none" },
  594. new object[] { "Name", FilterOperator.IsNotEqualTo, Exp_IsNotEqualTo, "empty" },
  595. new object[] { "Name", FilterOperator.IsEqualTo, Exp_NotValidAliasIsEqualTo, "value" },
  596. new object[] { "Name", FilterOperator.IsNotEqualTo, Exp_NotValidAliasIsNotEqualTo, "value" },
  597. new object[] { "Name", FilterOperator.IsEqualTo, Exp_CaseSensitiveIsEqualTo, "NoNe" },
  598. new object[] { "Name", FilterOperator.IsNotEqualTo, Exp_CaseSensitiveIsNotEqualTo, "EmPtY" }
  599. };
  600. // ReSharper restore NegativeEqualityExpression
  601. // ReSharper restore InconsistentNaming
  602. #endregion
  603. [TestCaseSource("ExpressionCases")]
  604. public void single_expressions(string member, FilterOperator @operator, Expression<Func<Foo, bool>> exp, object value)
  605. {
  606. var filter = new FilterDescriptor(member, @operator, value);
  607. var expressionWhereClause = new ExpressionWhereClause<Foo, FooModel>(filter, null, false, null);
  608. expressionWhereClause.Predicate.ToString()
  609. .Replace("Tests.DynamicWhereClause.ExpressionWhereClauseWithNullAliasAndSearchExplicitTests+Foo", "foo")
  610. .Should().Be(exp.ToString().Replace(".Value", ""));
  611. }
  612. [TestCaseSource("ExpressionCases")]
  613. public void double_expressions_with_orElse_operator(string member, FilterOperator @operator, Expression<Func<Foo, bool>> exp, object value)
  614. {
  615. var filter = new FilterDescriptor(member, @operator, value);
  616. var expressionWhereClause = new ExpressionWhereClause<Foo, FooModel>(filter, null, false, null);
  617. expressionWhereClause.Predicate.ToString()
  618. .Replace("Tests.DynamicWhereClause.ExpressionWhereClauseWithNullAliasAndSearchExplicitTests+Foo", "foo")
  619. .Should().Be(exp.ToString().Replace(".Value", ""));
  620. expressionWhereClause.OrElse(expressionWhereClause);
  621. expressionWhereClause.Predicate.ToString()
  622. .Replace("Tests.DynamicWhereClause.ExpressionWhereClauseWithNullAliasAndSearchExplicitTests+Foo", "foo")
  623. .Should().Be(exp.OrElse(exp).ToString().Replace(".Value", ""));
  624. }
  625. [TestCaseSource("ExpressionCases")]
  626. public void double_expressions_with_andAlso_operator(string member, FilterOperator @operator, Expression<Func<Foo, bool>> exp, object value)
  627. {
  628. var filter = new FilterDescriptor(member, @operator, value);
  629. var expressionWhereClause = new ExpressionWhereClause<Foo, FooModel>(filter, null, false, null);
  630. expressionWhereClause.Predicate.ToString()
  631. .Replace("Tests.DynamicWhereClause.ExpressionWhereClauseWithNullAliasAndSearchExplicitTests+Foo", "foo")
  632. .Should().Be(exp.ToString().Replace(".Value", ""));
  633. expressionWhereClause.AndAlso(expressionWhereClause);
  634. expressionWhereClause.Predicate.ToString()
  635. .Replace("Tests.DynamicWhereClause.ExpressionWhereClauseWithNullAliasAndSearchExplicitTests+Foo", "foo")
  636. .Should().Be(exp.AndAlso(exp).ToString().Replace(".Value", ""));
  637. }
  638. #region Test models
  639. // ReSharper disable ClassNeverInstantiated.Global
  640. // ReSharper disable UnusedAutoPropertyAccessor.Global
  641. // ReSharper disable ClassNeverInstantiated.Local
  642. // ReSharper disable UnusedAutoPropertyAccessor.Local
  643. // ReSharper disable UnusedMember.Local
  644. // ReSharper disable UnusedMember.Global
  645. public class Foo
  646. {
  647. public string Name { get; set; }
  648. public decimal? NullableDecimal { get; set; }
  649. public decimal NotNullableDecimal { get; set; }
  650. public DateTime DateTime { get; set; }
  651. }
  652. private class FooModel
  653. {
  654. public string Name { get; set; }
  655. public decimal? NullableDecimal { get; set; }
  656. public decimal NotNullableDecimal { get; set; }
  657. public DateTime DateTime { get; set; }
  658. }
  659. // ReSharper restore UnusedMember.Global
  660. // ReSharper restore UnusedMember.Local
  661. // ReSharper restore UnusedAutoPropertyAccessor.Local
  662. // ReSharper restore ClassNeverInstantiated.Local
  663. // ReSharper restore UnusedAutoPropertyAccessor.Global
  664. // ReSharper restore ClassNeverInstantiated.Global
  665. #endregion
  666. }
  667. public class ExpressionWhereClauseWithNullAliasAndCaseInsensitiveTests
  668. {
  669. [SetUp]
  670. public void SetUp()
  671. {
  672. Mapper.Reset();
  673. GridModelMapper.Reset();
  674. GridModelMapper.CreateMap<Foo, FooModel>()
  675. .MapProperty(foo => foo.FirstName + " " + foo.LastName, model => model.FullName)
  676. .MapProperty(foo => foo.NullableDecimal + foo.NullableDecimal, model => model.NullableTotalPrice)
  677. .MapProperty(foo => foo.NotNullableDecimal + foo.NotNullableDecimal, model => model.NotNullableTotalPrice);
  678. GridModelMapper.Configuration.SetGlobalNullAlias<NullAlias>();
  679. }
  680. private class NullAlias : INullAlias
  681. {
  682. public bool IsCaseInsensitive { get { return true; } }
  683. //the query should contain these aliases explicitly?
  684. public bool SearchExplicit { get { return false; } }
  685. public IList<object> Aliases()
  686. {
  687. return new object[] { "NoNe", "eMpTy", -1, null };
  688. }
  689. }
  690. #region ExpressionCases
  691. // ReSharper disable InconsistentNaming
  692. // ReSharper disable NegativeEqualityExpression
  693. static readonly Expression<Func<Foo, bool>> Exp_NullableIsEqualTo = foo => foo.NullableDecimal == null;
  694. static readonly Expression<Func<Foo, bool>> Exp_IsEqualTo = foo => foo.Name == null;
  695. static readonly Expression<Func<Foo, bool>> Exp_IsNotEqualTo = foo => !(foo.Name == null);
  696. static readonly Expression<Func<Foo, bool>> Exp_NotValidAliasIsEqualTo = foo => foo.Name == "value";
  697. static readonly Expression<Func<Foo, bool>> Exp_NotValidAliasIsNotEqualTo = foo => foo.Name != "value";
  698. static readonly Expression<Func<Foo, bool>> Exp_NotNullableWithNullValueIsEqualTo = foo => foo.NotNullableDecimal == 0;
  699. static readonly Expression<Func<Foo, bool>> Exp_NotNullableWithNullValueIsNotEqualTo = foo => foo.NotNullableDecimal != 0;
  700. static readonly Expression<Func<Foo, bool>> Exp_NotNullableIsEqualTo = foo => foo.NotNullableDecimal == -1;
  701. static readonly Expression<Func<Foo, bool>> Exp_NotNullableIsNotEqualTo = foo => foo.NotNullableDecimal != -1;
  702. static readonly Expression<Func<Foo, bool>> Exp_NotNullableValidValueIsEqualTo = foo => foo.NotNullableDecimal == 10;
  703. static readonly Expression<Func<Foo, bool>> Exp_NotNullableValidValueIsNotEqualTo = foo => foo.NotNullableDecimal != 10;
  704. static readonly object[] ExpressionCases =
  705. {
  706. new object[] { "NullableDecimal", FilterOperator.IsLessThan, Exp_NullableIsEqualTo, null },
  707. new object[] { "NullableDecimal", FilterOperator.IsLessThan, Exp_NullableIsEqualTo, -1 },
  708. new object[] { "NullableDecimal", FilterOperator.IsLessThanOrEqualTo, Exp_NullableIsEqualTo, null },
  709. new object[] { "NullableDecimal", FilterOperator.IsLessThanOrEqualTo, Exp_NullableIsEqualTo, -1 },
  710. new object[] { "NullableDecimal", FilterOperator.IsGreaterThanOrEqualTo, Exp_NullableIsEqualTo, null },
  711. new object[] { "NullableDecimal", FilterOperator.IsGreaterThanOrEqualTo, Exp_NullableIsEqualTo, -1 },
  712. new object[] { "NullableDecimal", FilterOperator.IsGreaterThan, Exp_NullableIsEqualTo, null },
  713. new object[] { "NullableDecimal", FilterOperator.IsGreaterThan, Exp_NullableIsEqualTo, -1 },
  714. new object[] { "NotNullableDecimal", FilterOperator.IsEqualTo, Exp_NotNullableWithNullValueIsEqualTo, null },
  715. new object[] { "NotNullableDecimal", FilterOperator.IsNotEqualTo, Exp_NotNullableWithNullValueIsNotEqualTo, null },
  716. new object[] { "NotNullableDecimal", FilterOperator.IsEqualTo, Exp_NotNullableIsEqualTo, -1 },
  717. new object[] { "NotNullableDecimal", FilterOperator.IsNotEqualTo, Exp_NotNullableIsNotEqualTo, -1 },
  718. new object[] { "NotNullableDecimal", FilterOperator.IsEqualTo, Exp_NotNullableValidValueIsEqualTo, 10 },
  719. new object[] { "NotNullableDecimal", FilterOperator.IsNotEqualTo, Exp_NotNullableValidValueIsNotEqualTo, 10 },
  720. new object[] { "NotNullableDecimal", FilterOperator.IsEqualTo, Exp_NotNullableWithNullValueIsEqualTo, "none" },
  721. new object[] { "NotNullableDecimal", FilterOperator.IsNotEqualTo, Exp_NotNullableWithNullValueIsNotEqualTo, "none" },
  722. new object[] { "NotNullableDecimal", FilterOperator.IsEqualTo, Exp_NotNullableWithNullValueIsEqualTo, "invalid-value" },
  723. new object[] { "NotNullableDecimal", FilterOperator.IsNotEqualTo, Exp_NotNullableWithNullValueIsNotEqualTo, "invalid-value" },
  724. new object[] { "Name", FilterOperator.StartsWith, Exp_IsEqualTo, "none" },
  725. new object[] { "Name", FilterOperator.EndsWith, Exp_IsEqualTo, "none" },
  726. new object[] { "Name", FilterOperator.Contains, Exp_IsEqualTo, "none" },
  727. new object[] { "Name", FilterOperator.DoesNotContain, Exp_IsNotEqualTo, "none" },
  728. new object[] { "Name", FilterOperator.IsEqualTo, Exp_IsEqualTo, null },
  729. new object[] { "Name", FilterOperator.IsNotEqualTo, Exp_IsNotEqualTo, null },
  730. new object[] { "Name", FilterOperator.IsEqualTo, Exp_IsEqualTo, "none" },
  731. new object[] { "Name", FilterOperator.IsEqualTo, Exp_IsEqualTo, "nOnE" },
  732. new object[] { "Name", FilterOperator.IsEqualTo, Exp_IsEqualTo, "empty" },
  733. new object[] { "Name", FilterOperator.IsNotEqualTo, Exp_IsNotEqualTo, "none" },
  734. new object[] { "Name", FilterOperator.IsNotEqualTo, Exp_IsNotEqualTo, "empty" },
  735. new object[] { "Name", FilterOperator.IsEqualTo, Exp_NotValidAliasIsEqualTo, "value" },
  736. new object[] { "Name", FilterOperator.IsNotEqualTo, Exp_NotValidAliasIsNotEqualTo, "value" }
  737. };
  738. // ReSharper restore NegativeEqualityExpression
  739. // ReSharper restore InconsistentNaming
  740. #endregion
  741. [TestCaseSource("ExpressionCases")]
  742. public void single_expressions(string member, FilterOperator @operator, Expression<Func<Foo, bool>> exp, object value)
  743. {
  744. var filter = new FilterDescriptor(member, @operator, value);
  745. var expressionWhereClause = new ExpressionWhereClause<Foo, FooModel>(filter, null, false, null);
  746. expressionWhereClause.Predicate.ToString()
  747. .Replace("Tests.DynamicWhereClause.ExpressionWhereClauseWithNullAliasAndCaseInsensitiveTests+Foo", "foo")
  748. .Should().Be(exp.ToString().Replace(".Value", ""));
  749. }
  750. [TestCaseSource("ExpressionCases")]
  751. public void double_expressions_with_orElse_operator(string member, FilterOperator @operator, Expression<Func<Foo, bool>> exp, object value)
  752. {
  753. var filter = new FilterDescriptor(member, @operator, value);
  754. var expressionWhereClause = new ExpressionWhereClause<Foo, FooModel>(filter, null, false, null);
  755. expressionWhereClause.Predicate.ToString()
  756. .Replace("Tests.DynamicWhereClause.ExpressionWhereClauseWithNullAliasAndCaseInsensitiveTests+Foo", "foo")
  757. .Should().Be(exp.ToString().Replace(".Value", ""));
  758. expressionWhereClause.OrElse(expressionWhereClause);
  759. expressionWhereClause.Predicate.ToString()
  760. .Replace("Tests.DynamicWhereClause.ExpressionWhereClauseWithNullAliasAndCaseInsensitiveTests+Foo", "foo")
  761. .Should().Be(exp.OrElse(exp).ToString().Replace(".Value", ""));
  762. }
  763. [TestCaseSource("ExpressionCases")]
  764. public void double_expressions_with_andAlso_operator(string member, FilterOperator @operator, Expression<Func<Foo, bool>> exp, object value)
  765. {
  766. var filter = new FilterDescriptor(member, @operator, value);
  767. var expressionWhereClause = new ExpressionWhereClause<Foo, FooModel>(filter, null, false, null);
  768. expressionWhereClause.Predicate.ToString()
  769. .Replace("Tests.DynamicWhereClause.ExpressionWhereClauseWithNullAliasAndCaseInsensitiveTests+Foo", "foo")
  770. .Should().Be(exp.ToString().Replace(".Value", ""));
  771. expressionWhereClause.AndAlso(expressionWhereClause);
  772. expressionWhereClause.Predicate.ToString()
  773. .Replace("Tests.DynamicWhereClause.ExpressionWhereClauseWithNullAliasAndCaseInsensitiveTests+Foo", "foo")
  774. .Should().Be(exp.AndAlso(exp).ToString().Replace(".Value", ""));
  775. }
  776. #region CustomExpression_Cases
  777. // ReSharper disable InconsistentNaming
  778. // ReSharper disable NegativeEqualityExpression
  779. static readonly Expression<Func<Foo, bool>> CustomExpression_NullableIsEqualTo = foo => foo.NullableDecimal + foo.NullableDecimal == null;
  780. static readonly Expression<Func<Foo, bool>> CustomExpression_IsEqualTo = foo => foo.FirstName + " " + foo.LastName == null;
  781. static readonly Expression<Func<Foo, bool>> CustomExpression_IsNotEqualTo = foo => !(foo.FirstName + " " + foo.LastName == null);
  782. static readonly Expression<Func<Foo, bool>> CustomExpression_NotValidAliasIsEqualTo = foo => foo.FirstName + " " + foo.LastName == "value";
  783. static readonly Expression<Func<Foo, bool>> CustomExpression_NotValidAliasIsNotEqualTo = foo => foo.FirstName + " " + foo.LastName != "value";
  784. static readonly Expression<Func<Foo, bool>> CustomExpression_NotNullableWithNullValueIsEqualTo = foo => foo.NotNullableDecimal + foo.NotNullableDecimal == 0;
  785. static readonly Expression<Func<Foo, bool>> CustomExpression_NotNullableWithNullValueIsNotEqualTo = foo => foo.NotNullableDecimal + foo.NotNullableDecimal != 0;
  786. static readonly Expression<Func<Foo, bool>> CustomExpression_NotNullableIsEqualTo = foo => foo.NotNullableDecimal + foo.NotNullableDecimal == -1;
  787. static readonly Expression<Func<Foo, bool>> CustomExpression_NotNullableIsNotEqualTo = foo => foo.NotNullableDecimal + foo.NotNullableDecimal != -1;
  788. static readonly Expression<Func<Foo, bool>> CustomExpression_NotNullableValidValueIsEqualTo = foo => foo.NotNullableDecimal + foo.NotNullableDecimal == 10;
  789. static readonly Expression<Func<Foo, bool>> CustomExpression_NotNullableValidValueIsNotEqualTo = foo => foo.NotNullableDecimal + foo.NotNullableDecimal != 10;
  790. static readonly object[] CustomExpression_Cases =
  791. {
  792. new object[] { "NullableTotalPrice", FilterOperator.IsLessThan, CustomExpression_NullableIsEqualTo, null },
  793. new object[] { "NullableTotalPrice", FilterOperator.IsLessThan, CustomExpression_NullableIsEqualTo, -1 },
  794. new object[] { "NullableTotalPrice", FilterOperator.IsLessThanOrEqualTo, CustomExpression_NullableIsEqualTo, null },
  795. new object[] { "NullableTotalPrice", FilterOperator.IsLessThanOrEqualTo, CustomExpression_NullableIsEqualTo, -1 },
  796. new object[] { "NullableTotalPrice", FilterOperator.IsGreaterThanOrEqualTo, CustomExpression_NullableIsEqualTo, null },
  797. new object[] { "NullableTotalPrice", FilterOperator.IsGreaterThanOrEqualTo, CustomExpression_NullableIsEqualTo, -1 },
  798. new object[] { "NullableTotalPrice", FilterOperator.IsGreaterThan, CustomExpression_NullableIsEqualTo, null },
  799. new object[] { "NullableTotalPrice", FilterOperator.IsGreaterThan, CustomExpression_NullableIsEqualTo, -1 },
  800. new object[] { "NotNullableTotalPrice", FilterOperator.IsEqualTo, CustomExpression_NotNullableWithNullValueIsEqualTo, null },
  801. new object[] { "NotNullableTotalPrice", FilterOperator.IsNotEqualTo, CustomExpression_NotNullableWithNullValueIsNotEqualTo, null },
  802. new object[] { "NotNullableTotalPrice", FilterOperator.IsEqualTo, CustomExpression_NotNullableIsEqualTo, -1 },
  803. new object[] { "NotNullableTotalPrice", FilterOperator.IsNotEqualTo, CustomExpression_NotNullableIsNotEqualTo, -1 },
  804. new object[] { "NotNullableTotalPrice", FilterOperator.IsEqualTo, CustomExpression_NotNullableValidValueIsEqualTo, 10 },
  805. new object[] { "NotNullableTotalPrice", FilterOperator.IsNotEqualTo, CustomExpression_NotNullableValidValueIsNotEqualTo, 10 },
  806. new object[] { "NotNullableTotalPrice", FilterOperator.IsEqualTo, CustomExpression_NotNullableWithNullValueIsEqualTo, "none" },
  807. new object[] { "NotNullableTotalPrice", FilterOperator.IsNotEqualTo, CustomExpression_NotNullableWithNullValueIsNotEqualTo, "none" },
  808. new object[] { "NotNullableTotalPrice", FilterOperator.IsEqualTo, CustomExpression_NotNullableWithNullValueIsEqualTo, "invalid-value" },
  809. new object[] { "NotNullableTotalPrice", FilterOperator.IsNotEqualTo, CustomExpression_NotNullableWithNullValueIsNotEqualTo, "invalid-value" },
  810. new object[] { "FullName", FilterOperator.StartsWith, CustomExpression_IsEqualTo, "none" },
  811. new object[] { "FullName", FilterOperator.EndsWith, CustomExpression_IsEqualTo, "none" },
  812. new object[] { "FullName", FilterOperator.Contains, CustomExpression_IsEqualTo, "none" },
  813. new object[] { "FullName", FilterOperator.DoesNotContain, CustomExpression_IsNotEqualTo, "none" },
  814. new object[] { "FullName", FilterOperator.IsEqualTo, CustomExpression_IsEqualTo, null },
  815. new object[] { "FullName", FilterOperator.IsNotEqualTo, CustomExpression_IsNotEqualTo, null },
  816. new object[] { "FullName", FilterOperator.IsEqualTo, CustomExpression_IsEqualTo, "none" },
  817. new object[] { "FullName", FilterOperator.IsEqualTo, CustomExpression_IsEqualTo, "nOnE" },
  818. new object[] { "FullName", FilterOperator.IsEqualTo, CustomExpression_IsEqualTo, "empty" },
  819. new object[] { "FullName", FilterOperator.IsNotEqualTo, CustomExpression_IsNotEqualTo, "none" },
  820. new object[] { "FullName", FilterOperator.IsNotEqualTo, CustomExpression_IsNotEqualTo, "empty" },
  821. new object[] { "FullName", FilterOperator.IsEqualTo, CustomExpression_NotValidAliasIsEqualTo, "value" },
  822. new object[] { "FullName", FilterOperator.IsNotEqualTo, CustomExpression_NotValidAliasIsNotEqualTo, "value" }
  823. };
  824. // ReSharper restore NegativeEqualityExpression
  825. // ReSharper restore InconsistentNaming
  826. #endregion
  827. [TestCaseSource("CustomExpression_Cases")]
  828. public void single_expressions_with_gridModelMapper_customExpression(string member, FilterOperator @operator, Expression<Func<Foo, bool>> exp, object value)
  829. {
  830. var filter = new FilterDescriptor(member, @operator, value);
  831. var expressionWhereClause = new ExpressionWhereClause<Foo, FooModel>(filter, null, false, null);
  832. expressionWhereClause.Predicate.ToString()
  833. .Replace("Tests.DynamicWhereClause.ExpressionWhereClauseWithNullAliasAndCaseInsensitiveTests+Foo", "foo")
  834. .Should().Be(exp.ToString());
  835. }
  836. [TestCaseSource("CustomExpression_Cases")]
  837. public void double_expressions_with_gridModelMapper_customExpression_and_orElse_operator(string member, FilterOperator @operator, Expression<Func<Foo, bool>> exp, object value)
  838. {
  839. var filter = new FilterDescriptor(member, @operator, value);
  840. var expressionWhereClause = new ExpressionWhereClause<Foo, FooModel>(filter, null, false, null);
  841. expressionWhereClause.Predicate.ToString()
  842. .Replace("Tests.DynamicWhereClause.ExpressionWhereClauseWithNullAliasAndCaseInsensitiveTests+Foo", "foo")
  843. .Should().Be(exp.ToString());
  844. expressionWhereClause.OrElse(expressionWhereClause);
  845. expressionWhereClause.Predicate.ToString()
  846. .Replace("Tests.DynamicWhereClause.ExpressionWhereClauseWithNullAliasAndCaseInsensitiveTests+Foo", "foo")
  847. .Should().Be(exp.OrElse(exp).ToString());
  848. }
  849. [TestCaseSource("CustomExpression_Cases")]
  850. public void double_expressions_with_gridModelMapper_customExpression_and_andAlso_operator(string member, FilterOperator @operator, Expression<Func<Foo, bool>> exp, object value)
  851. {
  852. var filter = new FilterDescriptor(member, @operator, value);
  853. var expressionWhereClause = new ExpressionWhereClause<Foo, FooModel>(filter, null, false, null);
  854. expressionWhereClause.Predicate.ToString()
  855. .Replace("Tests.DynamicWhereClause.ExpressionWhereClauseWithNullAliasAndCaseInsensitiveTests+Foo", "foo")
  856. .Should().Be(exp.ToString());
  857. expressionWhereClause.AndAlso(expressionWhereClause);
  858. expressionWhereClause.Predicate.ToString()
  859. .Replace("Tests.DynamicWhereClause.ExpressionWhereClauseWithNullAliasAndCaseInsensitiveTests+Foo", "foo")
  860. .Should().Be(exp.AndAlso(exp).ToString());
  861. }
  862. #region Test models
  863. // ReSharper disable ClassNeverInstantiated.Global
  864. // ReSharper disable UnusedAutoPropertyAccessor.Global
  865. // ReSharper disable ClassNeverInstantiated.Local
  866. // ReSharper disable UnusedAutoPropertyAccessor.Local
  867. // ReSharper disable UnusedMember.Local
  868. // ReSharper disable UnusedMember.Global
  869. public class Foo
  870. {
  871. public string Name { get; set; }
  872. public decimal? NullableDecimal { get; set; }
  873. public decimal NotNullableDecimal { get; set; }
  874. public DateTime DateTime { get; set; }
  875. public string FirstName { get; set; }
  876. public string LastName { get; set; }
  877. }
  878. private class FooModel
  879. {
  880. public string Name { get; set; }
  881. public decimal? NullableDecimal { get; set; }
  882. public decimal NotNullableDecimal { get; set; }
  883. public DateTime DateTime { get; set; }
  884. public string FullName { get; set; }
  885. public string NullableTotalPrice { get; set; }
  886. public decimal NotNullableTotalPrice { get; set; }
  887. }
  888. // ReSharper restore UnusedMember.Global
  889. // ReSharper restore UnusedMember.Local
  890. // ReSharper restore UnusedAutoPropertyAccessor.Local
  891. // ReSharper restore ClassNeverInstantiated.Local
  892. // ReSharper restore UnusedAutoPropertyAccessor.Global
  893. // ReSharper restore ClassNeverInstantiated.Global
  894. #endregion
  895. }
  896. public class ExpressionWhereClauseWithAcceptNullValuesAndCaseInsensitiveTests
  897. {
  898. [SetUp]
  899. public void SetUp()
  900. {
  901. Mapper.Reset();
  902. GridModelMapper.Reset();
  903. GridModelMapper.CreateMap<Foo, FooModel>()
  904. .MapProperty(foo => foo.FirstName + " " + foo.LastName, model => model.FullName)
  905. .MapProperty(foo => foo.NullableDecimal + foo.NullableDecimal, model => model.TotalPrice);
  906. }
  907. #region ExpressionCases
  908. // ReSharper disable InconsistentNaming
  909. static readonly Expression<Func<Foo, bool>> Exp_IsLessThan = foo => foo.NullableDecimal == null || foo.NullableDecimal.Value < 5;
  910. static readonly Expression<Func<Foo, bool>> Exp_IsLessThanOrEqualTo = foo => foo.NullableDecimal == null || foo.NullableDecimal.Value <= 5;
  911. static readonly Expression<Func<Foo, bool>> Exp_IsGreaterThanOrEqualTo = foo => foo.NullableDecimal == null || foo.NullableDecimal.Value >= 5;
  912. static readonly Expression<Func<Foo, bool>> Exp_IsGreaterThan = foo => foo.NullableDecimal == null || foo.NullableDecimal.Value > 5;
  913. static readonly Expression<Func<Foo, bool>> Exp_StartsWith = foo => foo.Name == null || foo.Name.ToLowerInvariant().StartsWith("luis");
  914. static readonly Expression<Func<Foo, bool>> Exp_EndsWith = foo => foo.Name == null || foo.Name.ToLowerInvariant().EndsWith("luis");
  915. static readonly Expression<Func<Foo, bool>> Exp_Contains = foo => foo.Name == null || foo.Name.ToLowerInvariant().Contains("luis");
  916. static readonly Expression<Func<Foo, bool>> Exp_DoesNotContains = foo => foo.Name == null || !foo.Name.ToLowerInvariant().Contains("luis");
  917. static readonly Expression<Func<Foo, bool>> Exp_IsEqualTo = foo => foo.Name == null || foo.Name.ToLowerInvariant() == "luis";
  918. static readonly Expression<Func<Foo, bool>> Exp_IsNotEqualTo = foo => foo.Name == null || foo.Name.ToLowerInvariant() != "luis";
  919. static readonly Expression<Func<Foo, bool>> Exp_NullLiteralIsEqualTo = foo => foo.Name == null;
  920. static readonly Expression<Func<Foo, bool>> Exp_NullLiteralIsNotEqualTo = foo => foo.Name != null;
  921. static readonly object[] ExpressionCases =
  922. {
  923. new object[] { "NullableDecimal", FilterOperator.IsLessThan, Exp_IsLessThan, 5 },
  924. new object[] { "NullableDecimal", FilterOperator.IsLessThanOrEqualTo, Exp_IsLessThanOrEqualTo, "5" },
  925. new object[] { "NullableDecimal", FilterOperator.IsGreaterThanOrEqualTo, Exp_IsGreaterThanOrEqualTo, "5" },
  926. new object[] { "NullableDecimal", FilterOperator.IsGreaterThan, Exp_IsGreaterThan, "5" },
  927. new object[] { "Name", FilterOperator.StartsWith, Exp_StartsWith, "Luis" },
  928. new object[] { "Name", FilterOperator.EndsWith, Exp_EndsWith, "Luis" },
  929. new object[] { "Name", FilterOperator.Contains, Exp_Contains, "Luis" },
  930. new object[] { "Name", FilterOperator.DoesNotContain, Exp_DoesNotContains, "Luis" },
  931. new object[] { "Name", FilterOperator.IsEqualTo, Exp_IsEqualTo, "Luis" },
  932. new object[] { "Name", FilterOperator.IsNotEqualTo, Exp_IsNotEqualTo, "Luis" },
  933. new object[] { "Name", FilterOperator.IsNotEqualTo, Exp_NullLiteralIsNotEqualTo, null },
  934. new object[] { "Name", FilterOperator.IsEqualTo, Exp_NullLiteralIsEqualTo, null }
  935. };
  936. // ReSharper restore InconsistentNaming
  937. #endregion
  938. [TestCaseSource("ExpressionCases")]
  939. public void single_expressions(string member, FilterOperator @operator, Expression<Func<Foo, bool>> exp, object value)
  940. {
  941. var filter = new FilterDescriptor(member, @operator, value);
  942. var expressionWhereClause = new ExpressionWhereClause<Foo, FooModel>(filter, new CaseInsensitive<Foo>(true, true), true, null);
  943. expressionWhereClause.Predicate.ToString().Replace("Tests.Entity.Foo", "foo").Should().Be(exp.ToString().Replace(".Value", ""));
  944. }
  945. [TestCaseSource("ExpressionCases")]
  946. public void double_expressions_with_orElse_operator(string member, FilterOperator @operator, Expression<Func<Foo, bool>> exp, object value)
  947. {
  948. var filter = new FilterDescriptor(member, @operator, value);
  949. var expressionWhereClause = new ExpressionWhereClause<Foo, FooModel>(filter, new CaseInsensitive<Foo>(true, true), true, null);
  950. expressionWhereClause.Predicate.ToString().Replace("Tests.Entity.Foo", "foo").Should().Be(exp.ToString().Replace(".Value", ""));
  951. expressionWhereClause.OrElse(expressionWhereClause);
  952. expressionWhereClause.Predicate.ToString().Replace("Tests.Entity.Foo", "foo").Should().Be(exp.OrElse(exp).ToString().Replace(".Value", ""));
  953. }
  954. [TestCaseSource("ExpressionCases")]
  955. public void double_expressions_with_andAlso_operator(string member, FilterOperator @operator, Expression<Func<Foo, bool>> exp, object value)
  956. {
  957. var filter = new FilterDescriptor(member, @operator, value);
  958. var expressionWhereClause = new ExpressionWhereClause<Foo, FooModel>(filter, new CaseInsensitive<Foo>(true, true), true, null);
  959. expressionWhereClause.Predicate.ToString().Replace("Tests.Entity.Foo", "foo").Should().Be(exp.ToString().Replace(".Value", ""));
  960. expressionWhereClause.AndAlso(expressionWhereClause);
  961. expressionWhereClause.Predicate.ToString().Replace("Tests.Entity.Foo", "foo").Should().Be(exp.AndAlso(exp).ToString().Replace(".Value", ""));
  962. }
  963. #region CustomExpression_Cases
  964. // ReSharper disable InconsistentNaming
  965. static readonly Expression<Func<Foo, bool>> CustomExpression_IsLessThan = foo => (foo.NullableDecimal + foo.NullableDecimal) == null || foo.NullableDecimal + foo.NullableDecimal < 5;
  966. static readonly Expression<Func<Foo, bool>> CustomExpression_IsLessThanOrEqualTo = foo => (foo.NullableDecimal + foo.NullableDecimal) == null || foo.NullableDecimal + foo.NullableDecimal <= 5;
  967. static readonly Expression<Func<Foo, bool>> CustomExpression_IsGreaterThanOrEqualTo = foo => (foo.NullableDecimal + foo.NullableDecimal) == null || foo.NullableDecimal + foo.NullableDecimal >= 5;
  968. static readonly Expression<Func<Foo, bool>> CustomExpression_IsGreaterThan = foo => (foo.NullableDecimal + foo.NullableDecimal) == null || foo.NullableDecimal + foo.NullableDecimal > 5;
  969. static readonly Expression<Func<Foo, bool>> CustomExpression_StartsWith = foo => (foo.FirstName + " " + foo.LastName) == null || (foo.FirstName + " " + foo.LastName).ToLowerInvariant().StartsWith("luis fernando");
  970. static readonly Expression<Func<Foo, bool>> CustomExpression_EndsWith = foo => (foo.FirstName + " " + foo.LastName) == null || (foo.FirstName + " " + foo.LastName).ToLowerInvariant().EndsWith("luis fernando");
  971. static readonly Expression<Func<Foo, bool>> CustomExpression_Contains = foo => (foo.FirstName + " " + foo.LastName) == null || (foo.FirstName + " " + foo.LastName).ToLowerInvariant().Contains("luis fernando");
  972. static readonly Expression<Func<Foo, bool>> CustomExpression_DoesNotContains = foo => (foo.FirstName + " " + foo.LastName) == null || !(foo.FirstName + " " + foo.LastName).ToLowerInvariant().Contains("luis fernando");
  973. static readonly Expression<Func<Foo, bool>> CustomExpression_IsEqualTo = foo => (foo.FirstName + " " + foo.LastName) == null || (foo.FirstName + " " + foo.LastName).ToLowerInvariant() == "luis fernando";
  974. static readonly Expression<Func<Foo, bool>> CustomExpression_IsNotEqualTo = foo => (foo.FirstName + " " + foo.LastName) == null || (foo.FirstName + " " + foo.LastName).ToLowerInvariant() != "luis fernando";
  975. static readonly Expression<Func<Foo, bool>> CustomExpression_NullLiteralIsEqualTo = foo => foo.FirstName + " " + foo.LastName == null;
  976. static readonly Expression<Func<Foo, bool>> CustomExpression_NullLiteralIsNotEqualTo = foo => foo.FirstName + " " + foo.LastName != null;
  977. static readonly object[] CustomExpression_Cases =
  978. {
  979. new object[] { "TotalPrice", FilterOperator.IsLessThan, CustomExpression_IsLessThan, 5 },
  980. new object[] { "TotalPrice", FilterOperator.IsLessThanOrEqualTo, CustomExpression_IsLessThanOrEqualTo, "5" },
  981. new object[] { "TotalPrice", FilterOperator.IsGreaterThanOrEqualTo, CustomExpression_IsGreaterThanOrEqualTo, "5" },
  982. new object[] { "TotalPrice", FilterOperator.IsGreaterThan, CustomExpression_IsGreaterThan, "5" },
  983. new object[] { "FullName", FilterOperator.StartsWith, CustomExpression_StartsWith, "Luis Fernando" },
  984. new object[] { "FullName", FilterOperator.EndsWith, CustomExpression_EndsWith, "Luis Fernando" },
  985. new object[] { "FullName", FilterOperator.Contains, CustomExpression_Contains, "Luis Fernando" },
  986. new object[] { "FullName", FilterOperator.DoesNotContain, CustomExpression_DoesNotContains, "Luis Fernando" },
  987. new object[] { "FullName", FilterOperator.IsEqualTo, CustomExpression_IsEqualTo, "Luis Fernando" },
  988. new object[] { "FullName", FilterOperator.IsNotEqualTo, CustomExpression_IsNotEqualTo, "Luis Fernando" },
  989. new object[] { "FullName", FilterOperator.IsEqualTo, CustomExpression_NullLiteralIsEqualTo, null },
  990. new object[] { "FullName", FilterOperator.IsNotEqualTo, CustomExpression_NullLiteralIsNotEqualTo, null }
  991. };
  992. // ReSharper restore InconsistentNaming
  993. #endregion
  994. [TestCaseSource("CustomExpression_Cases")]
  995. public void single_expressions_with_gridModelMapper_customExpression(string member, FilterOperator @operator, Expression<Func<Foo, bool>> exp, object value)
  996. {
  997. var filter = new FilterDescriptor(member, @operator, value);
  998. var expressionWhereClause = new ExpressionWhereClause<Foo, FooModel>(filter, new CaseInsensitive<Foo>(true, true), true, null);
  999. expressionWhereClause.Predicate.ToString().Should().Be(exp.ToString().Replace("Convert(5)", "5"));
  1000. }
  1001. [TestCaseSource("CustomExpression_Cases")]
  1002. public void double_expressions_with_gridModelMapper_customExpression_and_orElse_operator(string member, FilterOperator @operator, Expression<Func<Foo, bool>> exp, object value)
  1003. {
  1004. var filter = new FilterDescriptor(member, @operator, value);
  1005. var expressionWhereClause = new ExpressionWhereClause<Foo, FooModel>(filter, new CaseInsensitive<Foo>(true, true), true, null);
  1006. expressionWhereClause.Predicate.ToString().Should().Be(exp.ToString().Replace("Convert(5)", "5"));
  1007. expressionWhereClause.OrElse(expressionWhereClause);
  1008. expressionWhereClause.Predicate.ToString().Should().Be(exp.OrElse(exp).ToString().Replace("Convert(5)", "5"));
  1009. }
  1010. [TestCaseSource("CustomExpression_Cases")]
  1011. public void double_expressions_with_gridModelMapper_customExpression_and_andAlso_operator(string member, FilterOperator @operator, Expression<Func<Foo, bool>> exp, object value)
  1012. {
  1013. var filter = new FilterDescriptor(member, @operator, value);
  1014. var expressionWhereClause = new ExpressionWhereClause<Foo, FooModel>(filter, new CaseInsensitive<Foo>(true, true), true, null);
  1015. expressionWhereClause.Predicate.ToString().Should().Be(exp.ToString().Replace("Convert(5)", "5"));
  1016. expressionWhereClause.AndAlso(expressionWhereClause);
  1017. expressionWhereClause.Predicate.ToString().Should().Be(exp.AndAlso(exp).ToString().Replace("Convert(5)", "5"));
  1018. }
  1019. }
  1020. public class ExpressionWhereClauseWithAcceptNullValuesTests
  1021. {
  1022. [SetUp]
  1023. public void SetUp()
  1024. {
  1025. Mapper.Reset();
  1026. GridModelMapper.Reset();
  1027. GridModelMapper.CreateMap<Foo, FooModel>()
  1028. .MapProperty(foo => foo.FirstName + " " + foo.LastName, model => model.FullName)
  1029. .MapProperty(foo => foo.NullableDecimal + foo.NullableDecimal, model => model.TotalPrice);
  1030. }
  1031. #region ExpressionCases
  1032. // ReSharper disable InconsistentNaming
  1033. static readonly Expression<Func<Foo, bool>> Exp_IsLessThan = foo => foo.NullableDecimal == null || foo.NullableDecimal.Value < 5;
  1034. static readonly Expression<Func<Foo, bool>> Exp_IsLessThanOrEqualTo = foo => foo.NullableDecimal == null || foo.NullableDecimal.Value <= 5;
  1035. static readonly Expression<Func<Foo, bool>> Exp_IsGreaterThanOrEqualTo = foo => foo.NullableDecimal == null || foo.NullableDecimal.Value >= 5;
  1036. static readonly Expression<Func<Foo, bool>> Exp_IsGreaterThan = foo => foo.NullableDecimal == null || foo.NullableDecimal.Value > 5;
  1037. static readonly Expression<Func<Foo, bool>> Exp_StartsWith = foo => foo.Name == null || foo.Name.StartsWith("Luis");
  1038. static readonly Expression<Func<Foo, bool>> Exp_EndsWith = foo => foo.Name == null || foo.Name.EndsWith("Luis");
  1039. static readonly Expression<Func<Foo, bool>> Exp_Contains = foo => foo.Name == null || foo.Name.Contains("Luis");
  1040. static readonly Expression<Func<Foo, bool>> Exp_DoesNotContains = foo => foo.Name == null || !foo.Name.Contains("Luis");
  1041. static readonly Expression<Func<Foo, bool>> Exp_IsEqualTo = foo => foo.Name == null || foo.Name == "Luis";
  1042. static readonly Expression<Func<Foo, bool>> Exp_IsNotEqualTo = foo => foo.Name == null || foo.Name != "Luis";
  1043. static readonly Expression<Func<Foo, bool>> Exp_NullLiteralIsEqualTo = foo => foo.Name == null;
  1044. static readonly Expression<Func<Foo, bool>> Exp_NullLiteralIsNotEqualTo = foo => foo.Name != null;
  1045. static readonly object[] ExpressionCases =
  1046. {
  1047. new object[] { "NullableDecimal", FilterOperator.IsLessThan, Exp_IsLessThan, 5 },
  1048. new object[] { "NullableDecimal", FilterOperator.IsLessThanOrEqualTo, Exp_IsLessThanOrEqualTo, "5" },
  1049. new object[] { "NullableDecimal", FilterOperator.IsGreaterThanOrEqualTo, Exp_IsGreaterThanOrEqualTo, "5" },
  1050. new object[] { "NullableDecimal", FilterOperator.IsGreaterThan, Exp_IsGreaterThan, "5" },
  1051. new object[] { "Name", FilterOperator.StartsWith, Exp_StartsWith, "Luis" },
  1052. new object[] { "Name", FilterOperator.EndsWith, Exp_EndsWith, "Luis" },
  1053. new object[] { "Name", FilterOperator.Contains, Exp_Contains, "Luis" },
  1054. new object[] { "Name", FilterOperator.DoesNotContain, Exp_DoesNotContains, "Luis" },
  1055. new object[] { "Name", FilterOperator.IsEqualTo, Exp_IsEqualTo, "Luis" },
  1056. new object[] { "Name", FilterOperator.IsNotEqualTo, Exp_IsNotEqualTo, "Luis" },
  1057. new object[] { "Name", FilterOperator.IsNotEqualTo, Exp_NullLiteralIsNotEqualTo, null },
  1058. new object[] { "Name", FilterOperator.IsEqualTo, Exp_NullLiteralIsEqualTo, null }
  1059. };
  1060. // ReSharper restore InconsistentNaming
  1061. #endregion
  1062. [TestCaseSource("ExpressionCases")]
  1063. public void single_expressions(string member, FilterOperator @operator, Expression<Func<Foo, bool>> exp, object value)
  1064. {
  1065. var filter = new FilterDescriptor(member, @operator, value);
  1066. var expressionWhereClause = new ExpressionWhereClause<Foo, FooModel>(filter, null, true, null);
  1067. expressionWhereClause.Predicate.ToString().Replace("Tests.Entity.Foo", "foo").Should().Be(exp.ToString().Replace(".Value", ""));
  1068. }
  1069. [TestCaseSource("ExpressionCases")]
  1070. public void double_expressions_with_orElse_operator(string member, FilterOperator @operator, Expression<Func<Foo, bool>> exp, object value)
  1071. {
  1072. var filter = new FilterDescriptor(member, @operator, value);
  1073. var expressionWhereClause = new ExpressionWhereClause<Foo, FooModel>(filter, null, true, null);
  1074. expressionWhereClause.Predicate.ToString().Replace("Tests.Entity.Foo", "foo").Should().Be(exp.ToString().Replace(".Value", ""));
  1075. expressionWhereClause.OrElse(expressionWhereClause);
  1076. expressionWhereClause.Predicate.ToString().Replace("Tests.Entity.Foo", "foo").Should().Be(exp.OrElse(exp).ToString().Replace(".Value", ""));
  1077. }
  1078. [TestCaseSource("ExpressionCases")]
  1079. public void double_expressions_with_andAlso_operator(string member, FilterOperator @operator, Expression<Func<Foo, bool>> exp, object value)
  1080. {
  1081. var filter = new FilterDescriptor(member, @operator, value);
  1082. var expressionWhereClause = new ExpressionWhereClause<Foo, FooModel>(filter, null, true, null);
  1083. expressionWhereClause.Predicate.ToString().Replace("Tests.Entity.Foo", "foo").Should().Be(exp.ToString().Replace(".Value", ""));
  1084. expressionWhereClause.AndAlso(expressionWhereClause);
  1085. expressionWhereClause.Predicate.ToString().Replace("Tests.Entity.Foo", "foo").Should().Be(exp.AndAlso(exp).ToString().Replace(".Value", ""));
  1086. }
  1087. #region CustomExpression_Cases
  1088. // ReSharper disable InconsistentNaming
  1089. static readonly Expression<Func<Foo, bool>> CustomExpression_IsLessThan = foo => (foo.NullableDecimal + foo.NullableDecimal) == null || foo.NullableDecimal + foo.NullableDecimal < 5;
  1090. static readonly Expression<Func<Foo, bool>> CustomExpression_IsLessThanOrEqualTo = foo => (foo.NullableDecimal + foo.NullableDecimal) == null || foo.NullableDecimal + foo.NullableDecimal <= 5;
  1091. static readonly Expression<Func<Foo, bool>> CustomExpression_IsGreaterThanOrEqualTo = foo => (foo.NullableDecimal + foo.NullableDecimal) == null || foo.NullableDecimal + foo.NullableDecimal >= 5;
  1092. static readonly Expression<Func<Foo, bool>> CustomExpression_IsGreaterThan = foo => (foo.NullableDecimal + foo.NullableDecimal) == null || foo.NullableDecimal + foo.NullableDecimal > 5;
  1093. static readonly Expression<Func<Foo, bool>> CustomExpression_StartsWith = foo => (foo.FirstName + " " + foo.LastName) == null || (foo.FirstName + " " + foo.LastName).StartsWith("Luis Fernando");
  1094. static readonly Expression<Func<Foo, bool>> CustomExpression_EndsWith = foo => (foo.FirstName + " " + foo.LastName) == null || (foo.FirstName + " " + foo.LastName).EndsWith("Luis Fernando");
  1095. static readonly Expression<Func<Foo, bool>> CustomExpression_Contains = foo => (foo.FirstName + " " + foo.LastName) == null || (foo.FirstName + " " + foo.LastName).Contains("Luis Fernando");
  1096. static readonly Expression<Func<Foo, bool>> CustomExpression_DoesNotContains = foo => (foo.FirstName + " " + foo.LastName) == null || !(foo.FirstName + " " + foo.LastName).Contains("Luis Fernando");
  1097. static readonly Expression<Func<Foo, bool>> CustomExpression_IsEqualTo = foo => (foo.FirstName + " " + foo.LastName) == null || foo.FirstName + " " + foo.LastName == "Luis Fernando";
  1098. static readonly Expression<Func<Foo, bool>> CustomExpression_IsNotEqualTo = foo => (foo.FirstName + " " + foo.LastName) == null || foo.FirstName + " " + foo.LastName != "Luis Fernando";
  1099. static readonly Expression<Func<Foo, bool>> CustomExpression_NullLiteralIsEqualTo = foo => foo.FirstName + " " + foo.LastName == null;
  1100. static readonly Expression<Func<Foo, bool>> CustomExpression_NullLiteralIsNotEqualTo = foo => foo.FirstName + " " + foo.LastName != null;
  1101. static readonly object[] CustomExpression_Cases =
  1102. {
  1103. new object[] { "TotalPrice", FilterOperator.IsLessThan, CustomExpression_IsLessThan, 5 },
  1104. new object[] { "TotalPrice", FilterOperator.IsLessThanOrEqualTo, CustomExpression_IsLessThanOrEqualTo, "5" },
  1105. new object[] { "TotalPrice", FilterOperator.IsGreaterThanOrEqualTo, CustomExpression_IsGreaterThanOrEqualTo, "5" },
  1106. new object[] { "TotalPrice", FilterOperator.IsGreaterThan, CustomExpression_IsGreaterThan, "5" },
  1107. new object[] { "FullName", FilterOperator.StartsWith, CustomExpression_StartsWith, "Luis Fernando" },
  1108. new object[] { "FullName", FilterOperator.EndsWith, CustomExpression_EndsWith, "Luis Fernando" },
  1109. new object[] { "FullName", FilterOperator.Contains, CustomExpression_Contains, "Luis Fernando" },
  1110. new object[] { "FullName", FilterOperator.DoesNotContain, CustomExpression_DoesNotContains, "Luis Fernando" },
  1111. new object[] { "FullName", FilterOperator.IsEqualTo, CustomExpression_IsEqualTo, "Luis Fernando" },
  1112. new object[] { "FullName", FilterOperator.IsNotEqualTo, CustomExpression_IsNotEqualTo, "Luis Fernando" },
  1113. new object[] { "FullName", FilterOperator.IsEqualTo, CustomExpression_NullLiteralIsEqualTo, null },
  1114. new object[] { "FullName", FilterOperator.IsNotEqualTo, CustomExpression_NullLiteralIsNotEqualTo, null }
  1115. };
  1116. // ReSharper restore InconsistentNaming
  1117. #endregion
  1118. [TestCaseSource("CustomExpression_Cases")]
  1119. public void single_expressions_with_gridModelMapper_customExpression(string member, FilterOperator @operator, Expression<Func<Foo, bool>> exp, object value)
  1120. {
  1121. var filter = new FilterDescriptor(member, @operator, value);
  1122. var expressionWhereClause = new ExpressionWhereClause<Foo, FooModel>(filter, null, true, null);
  1123. expressionWhereClause.Predicate.ToString().Should().Be(exp.ToString().Replace("Convert(5)", "5"));
  1124. }
  1125. [TestCaseSource("CustomExpression_Cases")]
  1126. public void double_expressions_with_gridModelMapper_customExpression_and_orElse_operator(string member, FilterOperator @operator, Expression<Func<Foo, bool>> exp, object value)
  1127. {
  1128. var filter = new FilterDescriptor(member, @operator, value);
  1129. var expressionWhereClause = new ExpressionWhereClause<Foo, FooModel>(filter, null, true, null);
  1130. expressionWhereClause.Predicate.ToString().Should().Be(exp.ToString().Replace("Convert(5)", "5"));
  1131. expressionWhereClause.OrElse(expressionWhereClause);
  1132. expressionWhereClause.Predicate.ToString().Should().Be(exp.OrElse(exp).ToString().Replace("Convert(5)", "5"));
  1133. }
  1134. [TestCaseSource("CustomExpression_Cases")]
  1135. public void double_expressions_with_gridModelMapper_customExpression_and_andAlso_operator(string member, FilterOperator @operator, Expression<Func<Foo, bool>> exp, object value)
  1136. {
  1137. var filter = new FilterDescriptor(member, @operator, value);
  1138. var expressionWhereClause = new ExpressionWhereClause<Foo, FooModel>(filter, null, true, null);
  1139. expressionWhereClause.Predicate.ToString().Should().Be(exp.ToString().Replace("Convert(5)", "5"));
  1140. expressionWhereClause.AndAlso(expressionWhereClause);
  1141. expressionWhereClause.Predicate.ToString().Should().Be(exp.AndAlso(exp).ToString().Replace("Convert(5)", "5"));
  1142. }
  1143. }
  1144. public class ExpressionWhereClauseWithCaseInsensitiveTests
  1145. {
  1146. [SetUp]
  1147. public void SetUp()
  1148. {
  1149. Mapper.Reset();
  1150. GridModelMapper.Reset();
  1151. GridModelMapper.CreateMap<Foo, FooModel>()
  1152. .MapProperty(foo => foo.FirstName + " " + foo.LastName, model => model.FullName)
  1153. .MapProperty(foo => foo.UnitPrice + foo.UnitsInStock, model => model.TotalPrice);
  1154. }
  1155. #region ExpressionCases
  1156. // ReSharper disable InconsistentNaming
  1157. static readonly Expression<Func<Foo, bool>> Exp_IsLessThan = foo => foo.UnitPrice < 5;
  1158. static readonly Expression<Func<Foo, bool>> Exp_IsLessThanOrEqualTo = foo => foo.UnitPrice <= 5;
  1159. static readonly Expression<Func<Foo, bool>> Exp_IsGreaterThanOrEqualTo = foo => foo.UnitPrice >= 5;
  1160. static readonly Expression<Func<Foo, bool>> Exp_IsGreaterThan = foo => foo.UnitPrice > 5;
  1161. static readonly Expression<Func<Foo, bool>> Exp_StartsWith = foo => foo.Name.ToLowerInvariant().StartsWith("luis");
  1162. static readonly Expression<Func<Foo, bool>> Exp_EndsWith = foo => foo.Name.ToLowerInvariant().EndsWith("luis");
  1163. static readonly Expression<Func<Foo, bool>> Exp_Contains = foo => foo.Name.ToLowerInvariant().Contains("luis");
  1164. static readonly Expression<Func<Foo, bool>> Exp_DoesNotContains = foo => !foo.Name.ToLowerInvariant().Contains("luis");
  1165. static readonly Expression<Func<Foo, bool>> Exp_IsEqualTo = foo => foo.Name.ToLowerInvariant() == "luis";
  1166. static readonly Expression<Func<Foo, bool>> Exp_IsNotEqualTo = foo => foo.Name.ToLowerInvariant() != "luis";
  1167. static readonly Expression<Func<Foo, bool>> Exp_NullLiteralIsEqualTo = foo => foo.Name == null;
  1168. static readonly Expression<Func<Foo, bool>> Exp_NullLiteralIsNotEqualTo = foo => foo.Name != null;
  1169. static readonly object[] ExpressionCases =
  1170. {
  1171. new object[] { "UnitPrice", FilterOperator.IsLessThan, Exp_IsLessThan, 5 },
  1172. new object[] { "UnitPrice", FilterOperator.IsLessThanOrEqualTo, Exp_IsLessThanOrEqualTo, "5" },
  1173. new object[] { "UnitPrice", FilterOperator.IsGreaterThanOrEqualTo, Exp_IsGreaterThanOrEqualTo, "5" },
  1174. new object[] { "UnitPrice", FilterOperator.IsGreaterThan, Exp_IsGreaterThan, "5" },
  1175. new object[] { "Name", FilterOperator.StartsWith, Exp_StartsWith, "Luis" },
  1176. new object[] { "Name", FilterOperator.EndsWith, Exp_EndsWith, "Luis" },
  1177. new object[] { "Name", FilterOperator.Contains, Exp_Contains, "Luis" },
  1178. new object[] { "Name", FilterOperator.DoesNotContain, Exp_DoesNotContains, "Luis" },
  1179. new object[] { "Name", FilterOperator.IsEqualTo, Exp_IsEqualTo, "Luis" },
  1180. new object[] { "Name", FilterOperator.IsNotEqualTo, Exp_IsNotEqualTo, "Luis" },
  1181. new object[] { "Name", FilterOperator.IsNotEqualTo, Exp_NullLiteralIsNotEqualTo, null },
  1182. new object[] { "Name", FilterOperator.IsEqualTo, Exp_NullLiteralIsEqualTo, null }
  1183. };
  1184. // ReSharper restore InconsistentNaming
  1185. #endregion
  1186. [TestCaseSource("ExpressionCases")]
  1187. public void single_expressions(string member, FilterOperator @operator, Expression<Func<Foo, bool>> exp, object value)
  1188. {
  1189. var filter = new FilterDescriptor(member, @operator, value);
  1190. var expressionWhereClause = new ExpressionWhereClause<Foo, FooModel>(filter, new CaseInsensitive<Foo>(true, true), false, null);
  1191. expressionWhereClause.Predicate.ToString().Replace("Tests.Entity.Foo", "foo").Should().Be(exp.ToString());
  1192. }
  1193. [TestCaseSource("ExpressionCases")]
  1194. public void double_expressions_with_orElse_operator(string member, FilterOperator @operator, Expression<Func<Foo, bool>> exp, object value)
  1195. {
  1196. var filter = new FilterDescriptor(member, @operator, value);
  1197. var expressionWhereClause = new ExpressionWhereClause<Foo, FooModel>(filter, new CaseInsensitive<Foo>(true, true), false, null);
  1198. expressionWhereClause.Predicate.ToString().Replace("Tests.Entity.Foo", "foo").Should().Be(exp.ToString());
  1199. expressionWhereClause.OrElse(expressionWhereClause);
  1200. expressionWhereClause.Predicate.ToString().Replace("Tests.Entity.Foo", "foo").Should().Be(exp.OrElse(exp).ToString());
  1201. }
  1202. [TestCaseSource("ExpressionCases")]
  1203. public void double_expressions_with_andAlso_operator(string member, FilterOperator @operator, Expression<Func<Foo, bool>> exp, object value)
  1204. {
  1205. var filter = new FilterDescriptor(member, @operator, value);
  1206. var expressionWhereClause = new ExpressionWhereClause<Foo, FooModel>(filter, new CaseInsensitive<Foo>(true, true), false, null);
  1207. expressionWhereClause.Predicate.ToString().Replace("Tests.Entity.Foo", "foo").Should().Be(exp.ToString());
  1208. expressionWhereClause.AndAlso(expressionWhereClause);
  1209. expressionWhereClause.Predicate.ToString().Replace("Tests.Entity.Foo", "foo").Should().Be(exp.AndAlso(exp).ToString());
  1210. }
  1211. #region CustomExpression_Cases
  1212. // ReSharper disable InconsistentNaming
  1213. static readonly Expression<Func<Foo, bool>> CustomExpression_IsLessThan = foo => foo.UnitPrice + foo.UnitsInStock < 5;
  1214. static readonly Expression<Func<Foo, bool>> CustomExpression_IsLessThanOrEqualTo = foo => foo.UnitPrice + foo.UnitsInStock <= 5;
  1215. static readonly Expression<Func<Foo, bool>> CustomExpression_IsGreaterThanOrEqualTo = foo => foo.UnitPrice + foo.UnitsInStock >= 5;
  1216. static readonly Expression<Func<Foo, bool>> CustomExpression_IsGreaterThan = foo => foo.UnitPrice + foo.UnitsInStock > 5;
  1217. static readonly Expression<Func<Foo, bool>> CustomExpression_StartsWith = foo => (foo.FirstName + " " + foo.LastName).ToLowerInvariant().StartsWith("luis fernando");
  1218. static readonly Expression<Func<Foo, bool>> CustomExpression_EndsWith = foo => (foo.FirstName + " " + foo.LastName).ToLowerInvariant().EndsWith("luis fernando");
  1219. static readonly Expression<Func<Foo, bool>> CustomExpression_Contains = foo => (foo.FirstName + " " + foo.LastName).ToLowerInvariant().Contains("luis fernando");
  1220. static readonly Expression<Func<Foo, bool>> CustomExpression_DoesNotContains = foo => !(foo.FirstName + " " + foo.LastName).ToLowerInvariant().Contains("luis fernando");
  1221. static readonly Expression<Func<Foo, bool>> CustomExpression_IsEqualTo = foo => (foo.FirstName + " " + foo.LastName).ToLowerInvariant() == "luis fernando";
  1222. static readonly Expression<Func<Foo, bool>> CustomExpression_IsNotEqualTo = foo => (foo.FirstName + " " + foo.LastName).ToLowerInvariant() != "luis fernando";
  1223. static readonly Expression<Func<Foo, bool>> CustomExpression_NullLiteralIsEqualTo = foo => foo.FirstName + " " + foo.LastName == null;
  1224. static readonly Expression<Func<Foo, bool>> CustomExpression_NullLiteralIsNotEqualTo = foo => foo.FirstName + " " + foo.LastName != null;
  1225. static readonly object[] CustomExpression_Cases =
  1226. {
  1227. new object[] { "TotalPrice", FilterOperator.IsLessThan, CustomExpression_IsLessThan, 5 },
  1228. new object[] { "TotalPrice", FilterOperator.IsLessThanOrEqualTo, CustomExpression_IsLessThanOrEqualTo, "5" },
  1229. new object[] { "TotalPrice", FilterOperator.IsGreaterThanOrEqualTo, CustomExpression_IsGreaterThanOrEqualTo, "5" },
  1230. new object[] { "TotalPrice", FilterOperator.IsGreaterThan, CustomExpression_IsGreaterThan, "5" },
  1231. new object[] { "FullName", FilterOperator.StartsWith, CustomExpression_StartsWith, "Luis Fernando" },
  1232. new object[] { "FullName", FilterOperator.EndsWith, CustomExpression_EndsWith, "Luis Fernando" },
  1233. new object[] { "FullName", FilterOperator.Contains, CustomExpression_Contains, "Luis Fernando" },
  1234. new object[] { "FullName", FilterOperator.DoesNotContain, CustomExpression_DoesNotContains, "Luis Fernando" },
  1235. new object[] { "FullName", FilterOperator.IsEqualTo, CustomExpression_IsEqualTo, "Luis Fernando" },
  1236. new object[] { "FullName", FilterOperator.IsNotEqualTo, CustomExpression_IsNotEqualTo, "Luis Fernando" },
  1237. new object[] { "FullName", FilterOperator.IsEqualTo, CustomExpression_NullLiteralIsEqualTo, null },
  1238. new object[] { "FullName", FilterOperator.IsNotEqualTo, CustomExpression_NullLiteralIsNotEqualTo, null }
  1239. };
  1240. // ReSharper restore InconsistentNaming
  1241. #endregion
  1242. [TestCaseSource("CustomExpression_Cases")]
  1243. public void single_expressions_with_gridModelMapper_customExpression(string member, FilterOperator @operator, Expression<Func<Foo, bool>> exp, object value)
  1244. {
  1245. var filter = new FilterDescriptor(member, @operator, value);
  1246. var expressionWhereClause = new ExpressionWhereClause<Foo, FooModel>(filter, new CaseInsensitive<Foo>(true, true), false, null);
  1247. expressionWhereClause.Predicate.ToString().Should().Be(exp.ToString().Replace("Convert(5)", "5"));
  1248. }
  1249. [TestCaseSource("CustomExpression_Cases")]
  1250. public void double_expressions_with_gridModelMapper_customExpression_and_orElse_operator(string member, FilterOperator @operator, Expression<Func<Foo, bool>> exp, object value)
  1251. {
  1252. var filter = new FilterDescriptor(member, @operator, value);
  1253. var expressionWhereClause = new ExpressionWhereClause<Foo, FooModel>(filter, new CaseInsensitive<Foo>(true, true), false, null);
  1254. expressionWhereClause.Predicate.ToString().Should().Be(exp.ToString().Replace("Convert(5)", "5"));
  1255. expressionWhereClause.OrElse(expressionWhereClause);
  1256. expressionWhereClause.Predicate.ToString().Should().Be(exp.OrElse(exp).ToString().Replace("Convert(5)", "5"));
  1257. }
  1258. [TestCaseSource("CustomExpression_Cases")]
  1259. public void double_expressions_with_gridModelMapper_customExpression_and_andAlso_operator(string member, FilterOperator @operator, Expression<Func<Foo, bool>> exp, object value)
  1260. {
  1261. var filter = new FilterDescriptor(member, @operator, value);
  1262. var expressionWhereClause = new ExpressionWhereClause<Foo, FooModel>(filter, new CaseInsensitive<Foo>(true, true), false, null);
  1263. expressionWhereClause.Predicate.ToString().Should().Be(exp.ToString().Replace("Convert(5)", "5"));
  1264. expressionWhereClause.AndAlso(expressionWhereClause);
  1265. expressionWhereClause.Predicate.ToString().Should().Be(exp.AndAlso(exp).ToString().Replace("Convert(5)", "5"));
  1266. }
  1267. }
  1268. public class ExpressionWhereClauseWithClientSideCaseInsensitiveTests
  1269. {
  1270. [SetUp]
  1271. public void SetUp()
  1272. {
  1273. Mapper.Reset();
  1274. GridModelMapper.Reset();
  1275. GridModelMapper.CreateMap<Foo, FooModel>()
  1276. .MapProperty(foo => foo.FirstName + " " + foo.LastName, model => model.FullName)
  1277. .MapProperty(foo => foo.UnitPrice + foo.UnitsInStock, model => model.TotalPrice);
  1278. }
  1279. #region ExpressionCases
  1280. // ReSharper disable InconsistentNaming
  1281. static readonly Expression<Func<Foo, bool>> Exp_IsLessThan = foo => foo.UnitPrice < 5;
  1282. static readonly Expression<Func<Foo, bool>> Exp_IsLessThanOrEqualTo = foo => foo.UnitPrice <= 5;
  1283. static readonly Expression<Func<Foo, bool>> Exp_IsGreaterThanOrEqualTo = foo => foo.UnitPrice >= 5;
  1284. static readonly Expression<Func<Foo, bool>> Exp_IsGreaterThan = foo => foo.UnitPrice > 5;
  1285. static readonly Expression<Func<Foo, bool>> Exp_StartsWith = foo => foo.Name.StartsWith("luis");
  1286. static readonly Expression<Func<Foo, bool>> Exp_EndsWith = foo => foo.Name.EndsWith("luis");
  1287. static readonly Expression<Func<Foo, bool>> Exp_Contains = foo => foo.Name.Contains("luis");
  1288. static readonly Expression<Func<Foo, bool>> Exp_DoesNotContains = foo => !foo.Name.Contains("luis");
  1289. static readonly Expression<Func<Foo, bool>> Exp_IsEqualTo = foo => foo.Name == "luis";
  1290. static readonly Expression<Func<Foo, bool>> Exp_IsNotEqualTo = foo => foo.Name != "luis";
  1291. static readonly Expression<Func<Foo, bool>> Exp_NullLiteralIsEqualTo = foo => foo.Name == null;
  1292. static readonly Expression<Func<Foo, bool>> Exp_NullLiteralIsNotEqualTo = foo => foo.Name != null;
  1293. static readonly object[] ExpressionCases =
  1294. {
  1295. new object[] { "UnitPrice", FilterOperator.IsLessThan, Exp_IsLessThan, 5 },
  1296. new object[] { "UnitPrice", FilterOperator.IsLessThanOrEqualTo, Exp_IsLessThanOrEqualTo, "5" },
  1297. new object[] { "UnitPrice", FilterOperator.IsGreaterThanOrEqualTo, Exp_IsGreaterThanOrEqualTo, "5" },
  1298. new object[] { "UnitPrice", FilterOperator.IsGreaterThan, Exp_IsGreaterThan, "5" },
  1299. new object[] { "Name", FilterOperator.StartsWith, Exp_StartsWith, "Luis" },
  1300. new object[] { "Name", FilterOperator.EndsWith, Exp_EndsWith, "Luis" },
  1301. new object[] { "Name", FilterOperator.Contains, Exp_Contains, "Luis" },
  1302. new object[] { "Name", FilterOperator.DoesNotContain, Exp_DoesNotContains, "Luis" },
  1303. new object[] { "Name", FilterOperator.IsEqualTo, Exp_IsEqualTo, "Luis" },
  1304. new object[] { "Name", FilterOperator.IsNotEqualTo, Exp_IsNotEqualTo, "Luis" },
  1305. new object[] { "Name", FilterOperator.IsNotEqualTo, Exp_NullLiteralIsNotEqualTo, null },
  1306. new object[] { "Name", FilterOperator.IsEqualTo, Exp_NullLiteralIsEqualTo, null }
  1307. };
  1308. // ReSharper restore InconsistentNaming
  1309. #endregion
  1310. [TestCaseSource("ExpressionCases")]
  1311. public void single_expressions(string member, FilterOperator @operator, Expression<Func<Foo, bool>> exp, object value)
  1312. {
  1313. var filter = new FilterDescriptor(member, @operator, value);
  1314. var expressionWhereClause = new ExpressionWhereClause<Foo, FooModel>(filter, new CaseInsensitive<Foo>(false, true), false, null);
  1315. expressionWhereClause.Predicate.ToString().Replace("Tests.Entity.Foo", "foo").Should().Be(exp.ToString());
  1316. }
  1317. [TestCaseSource("ExpressionCases")]
  1318. public void double_expressions_with_orElse_operator(string member, FilterOperator @operator, Expression<Func<Foo, bool>> exp, object value)
  1319. {
  1320. var filter = new FilterDescriptor(member, @operator, value);
  1321. var expressionWhereClause = new ExpressionWhereClause<Foo, FooModel>(filter, new CaseInsensitive<Foo>(false, true), false, null);
  1322. expressionWhereClause.Predicate.ToString().Replace("Tests.Entity.Foo", "foo").Should().Be(exp.ToString());
  1323. expressionWhereClause.OrElse(expressionWhereClause);
  1324. expressionWhereClause.Predicate.ToString().Replace("Tests.Entity.Foo", "foo").Should().Be(exp.OrElse(exp).ToString());
  1325. }
  1326. [TestCaseSource("ExpressionCases")]
  1327. public void double_expressions_with_andAlso_operator(string member, FilterOperator @operator, Expression<Func<Foo, bool>> exp, object value)
  1328. {
  1329. var filter = new FilterDescriptor(member, @operator, value);
  1330. var expressionWhereClause = new ExpressionWhereClause<Foo, FooModel>(filter, new CaseInsensitive<Foo>(false, true), false, null);
  1331. expressionWhereClause.Predicate.ToString().Replace("Tests.Entity.Foo", "foo").Should().Be(exp.ToString());
  1332. expressionWhereClause.AndAlso(expressionWhereClause);
  1333. expressionWhereClause.Predicate.ToString().Replace("Tests.Entity.Foo", "foo").Should().Be(exp.AndAlso(exp).ToString());
  1334. }
  1335. #region CustomExpression_Cases
  1336. // ReSharper disable InconsistentNaming
  1337. static readonly Expression<Func<Foo, bool>> CustomExpression_IsLessThan = foo => foo.UnitPrice + foo.UnitsInStock < 5;
  1338. static readonly Expression<Func<Foo, bool>> CustomExpression_IsLessThanOrEqualTo = foo => foo.UnitPrice + foo.UnitsInStock <= 5;
  1339. static readonly Expression<Func<Foo, bool>> CustomExpression_IsGreaterThanOrEqualTo = foo => foo.UnitPrice + foo.UnitsInStock >= 5;
  1340. static readonly Expression<Func<Foo, bool>> CustomExpression_IsGreaterThan = foo => foo.UnitPrice + foo.UnitsInStock > 5;
  1341. static readonly Expression<Func<Foo, bool>> CustomExpression_StartsWith = foo => (foo.FirstName + " " + foo.LastName).StartsWith("luis fernando");
  1342. static readonly Expression<Func<Foo, bool>> CustomExpression_EndsWith = foo => (foo.FirstName + " " + foo.LastName).EndsWith("luis fernando");
  1343. static readonly Expression<Func<Foo, bool>> CustomExpression_Contains = foo => (foo.FirstName + " " + foo.LastName).Contains("luis fernando");
  1344. static readonly Expression<Func<Foo, bool>> CustomExpression_DoesNotContains = foo => !(foo.FirstName + " " + foo.LastName).Contains("luis fernando");
  1345. static readonly Expression<Func<Foo, bool>> CustomExpression_IsEqualTo = foo => (foo.FirstName + " " + foo.LastName) == "luis fernando";
  1346. static readonly Expression<Func<Foo, bool>> CustomExpression_IsNotEqualTo = foo => (foo.FirstName + " " + foo.LastName) != "luis fernando";
  1347. static readonly Expression<Func<Foo, bool>> CustomExpression_NullLiteralIsEqualTo = foo => foo.FirstName + " " + foo.LastName == null;
  1348. static readonly Expression<Func<Foo, bool>> CustomExpression_NullLiteralIsNotEqualTo = foo => foo.FirstName + " " + foo.LastName != null;
  1349. static readonly object[] CustomExpression_Cases =
  1350. {
  1351. new object[] { "TotalPrice", FilterOperator.IsLessThan, CustomExpression_IsLessThan, 5 },
  1352. new object[] { "TotalPrice", FilterOperator.IsLessThanOrEqualTo, CustomExpression_IsLessThanOrEqualTo, "5" },
  1353. new object[] { "TotalPrice", FilterOperator.IsGreaterThanOrEqualTo, CustomExpression_IsGreaterThanOrEqualTo, "5" },
  1354. new object[] { "TotalPrice", FilterOperator.IsGreaterThan, CustomExpression_IsGreaterThan, "5" },
  1355. new object[] { "FullName", FilterOperator.StartsWith, CustomExpression_StartsWith, "Luis Fernando" },
  1356. new object[] { "FullName", FilterOperator.EndsWith, CustomExpression_EndsWith, "Luis Fernando" },
  1357. new object[] { "FullName", FilterOperator.Contains, CustomExpression_Contains, "Luis Fernando" },
  1358. new object[] { "FullName", FilterOperator.DoesNotContain, CustomExpression_DoesNotContains, "Luis Fernando" },
  1359. new object[] { "FullName", FilterOperator.IsEqualTo, CustomExpression_IsEqualTo, "Luis Fernando" },
  1360. new object[] { "FullName", FilterOperator.IsNotEqualTo, CustomExpression_IsNotEqualTo, "Luis Fernando" },
  1361. new object[] { "FullName", FilterOperator.IsEqualTo, CustomExpression_NullLiteralIsEqualTo, null },
  1362. new object[] { "FullName", FilterOperator.IsNotEqualTo, CustomExpression_NullLiteralIsNotEqualTo, null }
  1363. };
  1364. // ReSharper restore InconsistentNaming
  1365. #endregion
  1366. [TestCaseSource("CustomExpression_Cases")]
  1367. public void single_expressions_with_gridModelMapper_customExpression(string member, FilterOperator @operator, Expression<Func<Foo, bool>> exp, object value)
  1368. {
  1369. var filter = new FilterDescriptor(member, @operator, value);
  1370. var expressionWhereClause = new ExpressionWhereClause<Foo, FooModel>(filter, new CaseInsensitive<Foo>(false, true), false, null);
  1371. expressionWhereClause.Predicate.ToString().Should().Be(exp.ToString().Replace("Convert(5)", "5"));
  1372. }
  1373. [TestCaseSource("CustomExpression_Cases")]
  1374. public void double_expressions_with_gridModelMapper_customExpression_and_orElse_operator(string member, FilterOperator @operator, Expression<Func<Foo, bool>> exp, object value)
  1375. {
  1376. var filter = new FilterDescriptor(member, @operator, value);
  1377. var expressionWhereClause = new ExpressionWhereClause<Foo, FooModel>(filter, new CaseInsensitive<Foo>(false, true), false, null);
  1378. expressionWhereClause.Predicate.ToString().Should().Be(exp.ToString().Replace("Convert(5)", "5"));
  1379. expressionWhereClause.OrElse(expressionWhereClause);
  1380. expressionWhereClause.Predicate.ToString().Should().Be(exp.OrElse(exp).ToString().Replace("Convert(5)", "5"));
  1381. }
  1382. [TestCaseSource("CustomExpression_Cases")]
  1383. public void double_expressions_with_gridModelMapper_customExpression_and_andAlso_operator(string member, FilterOperator @operator, Expression<Func<Foo, bool>> exp, object value)
  1384. {
  1385. var filter = new FilterDescriptor(member, @operator, value);
  1386. var expressionWhereClause = new ExpressionWhereClause<Foo, FooModel>(filter, new CaseInsensitive<Foo>(false, true), false, null);
  1387. expressionWhereClause.Predicate.ToString().Should().Be(exp.ToString().Replace("Convert(5)", "5"));
  1388. expressionWhereClause.AndAlso(expressionWhereClause);
  1389. expressionWhereClause.Predicate.ToString().Should().Be(exp.AndAlso(exp).ToString().Replace("Convert(5)", "5"));
  1390. }
  1391. }
  1392. public class ExpressionWhereClauseWithServerSideCaseInsensitiveTests
  1393. {
  1394. [SetUp]
  1395. public void SetUp()
  1396. {
  1397. Mapper.Reset();
  1398. GridModelMapper.Reset();
  1399. GridModelMapper.CreateMap<Foo, FooModel>()
  1400. .MapProperty(foo => foo.FirstName + " " + foo.LastName, model => model.FullName)
  1401. .MapProperty(foo => foo.UnitPrice + foo.UnitsInStock, model => model.TotalPrice);
  1402. }
  1403. #region ExpressionCases
  1404. // ReSharper disable InconsistentNaming
  1405. static readonly Expression<Func<Foo, bool>> Exp_IsLessThan = foo => foo.UnitPrice < 5;
  1406. static readonly Expression<Func<Foo, bool>> Exp_IsLessThanOrEqualTo = foo => foo.UnitPrice <= 5;
  1407. static readonly Expression<Func<Foo, bool>> Exp_IsGreaterThanOrEqualTo = foo => foo.UnitPrice >= 5;
  1408. static readonly Expression<Func<Foo, bool>> Exp_IsGreaterThan = foo => foo.UnitPrice > 5;
  1409. static readonly Expression<Func<Foo, bool>> Exp_StartsWith = foo => foo.Name.ToLowerInvariant().StartsWith("Luis");
  1410. static readonly Expression<Func<Foo, bool>> Exp_EndsWith = foo => foo.Name.ToLowerInvariant().EndsWith("Luis");
  1411. static readonly Expression<Func<Foo, bool>> Exp_Contains = foo => foo.Name.ToLowerInvariant().Contains("Luis");
  1412. static readonly Expression<Func<Foo, bool>> Exp_DoesNotContains = foo => !foo.Name.ToLowerInvariant().Contains("Luis");
  1413. static readonly Expression<Func<Foo, bool>> Exp_IsEqualTo = foo => foo.Name.ToLowerInvariant() == "Luis";
  1414. static readonly Expression<Func<Foo, bool>> Exp_IsNotEqualTo = foo => foo.Name.ToLowerInvariant() != "Luis";
  1415. static readonly Expression<Func<Foo, bool>> Exp_NullLiteralIsEqualTo = foo => foo.Name == null;
  1416. static readonly Expression<Func<Foo, bool>> Exp_NullLiteralIsNotEqualTo = foo => foo.Name != null;
  1417. static readonly object[] ExpressionCases =
  1418. {
  1419. new object[] { "UnitPrice", FilterOperator.IsLessThan, Exp_IsLessThan, 5 },
  1420. new object[] { "UnitPrice", FilterOperator.IsLessThanOrEqualTo, Exp_IsLessThanOrEqualTo, "5" },
  1421. new object[] { "UnitPrice", FilterOperator.IsGreaterThanOrEqualTo, Exp_IsGreaterThanOrEqualTo, "5" },
  1422. new object[] { "UnitPrice", FilterOperator.IsGreaterThan, Exp_IsGreaterThan, "5" },
  1423. new object[] { "Name", FilterOperator.StartsWith, Exp_StartsWith, "Luis" },
  1424. new object[] { "Name", FilterOperator.EndsWith, Exp_EndsWith, "Luis" },
  1425. new object[] { "Name", FilterOperator.Contains, Exp_Contains, "Luis" },
  1426. new object[] { "Name", FilterOperator.DoesNotContain, Exp_DoesNotContains, "Luis" },
  1427. new object[] { "Name", FilterOperator.IsEqualTo, Exp_IsEqualTo, "Luis" },
  1428. new object[] { "Name", FilterOperator.IsNotEqualTo, Exp_IsNotEqualTo, "Luis" },
  1429. new object[] { "Name", FilterOperator.IsNotEqualTo, Exp_NullLiteralIsNotEqualTo, null },
  1430. new object[] { "Name", FilterOperator.IsEqualTo, Exp_NullLiteralIsEqualTo, null }
  1431. };
  1432. // ReSharper restore InconsistentNaming
  1433. #endregion
  1434. [TestCaseSource("ExpressionCases")]
  1435. public void single_expressions(string member, FilterOperator @operator, Expression<Func<Foo, bool>> exp, object value)
  1436. {
  1437. var filter = new FilterDescriptor(member, @operator, value);
  1438. var expressionWhereClause = new ExpressionWhereClause<Foo, FooModel>(filter, new CaseInsensitive<Foo>(true, false), false, null);
  1439. expressionWhereClause.Predicate.ToString().Replace("Tests.Entity.Foo", "foo").Should().Be(exp.ToString());
  1440. }
  1441. [TestCaseSource("ExpressionCases")]
  1442. public void double_expressions_with_orElse_operator(string member, FilterOperator @operator, Expression<Func<Foo, bool>> exp, object value)
  1443. {
  1444. var filter = new FilterDescriptor(member, @operator, value);
  1445. var expressionWhereClause = new ExpressionWhereClause<Foo, FooModel>(filter, new CaseInsensitive<Foo>(true, false), false, null);
  1446. expressionWhereClause.Predicate.ToString().Replace("Tests.Entity.Foo", "foo").Should().Be(exp.ToString());
  1447. expressionWhereClause.OrElse(expressionWhereClause);
  1448. expressionWhereClause.Predicate.ToString().Replace("Tests.Entity.Foo", "foo").Should().Be(exp.OrElse(exp).ToString());
  1449. }
  1450. [TestCaseSource("ExpressionCases")]
  1451. public void double_expressions_with_andAlso_operator(string member, FilterOperator @operator, Expression<Func<Foo, bool>> exp, object value)
  1452. {
  1453. var filter = new FilterDescriptor(member, @operator, value);
  1454. var expressionWhereClause = new ExpressionWhereClause<Foo, FooModel>(filter, new CaseInsensitive<Foo>(true, false), false, null);
  1455. expressionWhereClause.Predicate.ToString().Replace("Tests.Entity.Foo", "foo").Should().Be(exp.ToString());
  1456. expressionWhereClause.AndAlso(expressionWhereClause);
  1457. expressionWhereClause.Predicate.ToString().Replace("Tests.Entity.Foo", "foo").Should().Be(exp.AndAlso(exp).ToString());
  1458. }
  1459. #region CustomExpression_Cases
  1460. // ReSharper disable InconsistentNaming
  1461. static readonly Expression<Func<Foo, bool>> CustomExpression_IsLessThan = foo => foo.UnitPrice + foo.UnitsInStock < 5;
  1462. static readonly Expression<Func<Foo, bool>> CustomExpression_IsLessThanOrEqualTo = foo => foo.UnitPrice + foo.UnitsInStock <= 5;
  1463. static readonly Expression<Func<Foo, bool>> CustomExpression_IsGreaterThanOrEqualTo = foo => foo.UnitPrice + foo.UnitsInStock >= 5;
  1464. static readonly Expression<Func<Foo, bool>> CustomExpression_IsGreaterThan = foo => foo.UnitPrice + foo.UnitsInStock > 5;
  1465. static readonly Expression<Func<Foo, bool>> CustomExpression_StartsWith = foo => (foo.FirstName + " " + foo.LastName).ToLowerInvariant().StartsWith("Luis Fernando");
  1466. static readonly Expression<Func<Foo, bool>> CustomExpression_EndsWith = foo => (foo.FirstName + " " + foo.LastName).ToLowerInvariant().EndsWith("Luis Fernando");
  1467. static readonly Expression<Func<Foo, bool>> CustomExpression_Contains = foo => (foo.FirstName + " " + foo.LastName).ToLowerInvariant().Contains("Luis Fernando");
  1468. static readonly Expression<Func<Foo, bool>> CustomExpression_DoesNotContains = foo => !(foo.FirstName + " " + foo.LastName).ToLowerInvariant().Contains("Luis Fernando");
  1469. static readonly Expression<Func<Foo, bool>> CustomExpression_IsEqualTo = foo => (foo.FirstName + " " + foo.LastName).ToLowerInvariant() == "Luis Fernando";
  1470. static readonly Expression<Func<Foo, bool>> CustomExpression_IsNotEqualTo = foo => (foo.FirstName + " " + foo.LastName).ToLowerInvariant() != "Luis Fernando";
  1471. static readonly Expression<Func<Foo, bool>> CustomExpression_NullLiteralIsEqualTo = foo => foo.FirstName + " " + foo.LastName == null;
  1472. static readonly Expression<Func<Foo, bool>> CustomExpression_NullLiteralIsNotEqualTo = foo => foo.FirstName + " " + foo.LastName != null;
  1473. static readonly object[] CustomExpression_Cases =
  1474. {
  1475. new object[] { "TotalPrice", FilterOperator.IsLessThan, CustomExpression_IsLessThan, 5 },
  1476. new object[] { "TotalPrice", FilterOperator.IsLessThanOrEqualTo, CustomExpression_IsLessThanOrEqualTo, "5" },
  1477. new object[] { "TotalPrice", FilterOperator.IsGreaterThanOrEqualTo, CustomExpression_IsGreaterThanOrEqualTo, "5" },
  1478. new object[] { "TotalPrice", FilterOperator.IsGreaterThan, CustomExpression_IsGreaterThan, "5" },
  1479. new object[] { "FullName", FilterOperator.StartsWith, CustomExpression_StartsWith, "Luis Fernando" },
  1480. new object[] { "FullName", FilterOperator.EndsWith, CustomExpression_EndsWith, "Luis Fernando" },
  1481. new object[] { "FullName", FilterOperator.Contains, CustomExpression_Contains, "Luis Fernando" },
  1482. new object[] { "FullName", FilterOperator.DoesNotContain, CustomExpression_DoesNotContains, "Luis Fernando" },
  1483. new object[] { "FullName", FilterOperator.IsEqualTo, CustomExpression_IsEqualTo, "Luis Fernando" },
  1484. new object[] { "FullName", FilterOperator.IsNotEqualTo, CustomExpression_IsNotEqualTo, "Luis Fernando" },
  1485. new object[] { "FullName", FilterOperator.IsEqualTo, CustomExpression_NullLiteralIsEqualTo, null },
  1486. new object[] { "FullName", FilterOperator.IsNotEqualTo, CustomExpression_NullLiteralIsNotEqualTo, null }
  1487. };
  1488. // ReSharper restore InconsistentNaming
  1489. #endregion
  1490. [TestCaseSource("CustomExpression_Cases")]
  1491. public void single_expressions_with_gridModelMapper_customExpression(string member, FilterOperator @operator, Expression<Func<Foo, bool>> exp, object value)
  1492. {
  1493. var filter = new FilterDescriptor(member, @operator, value);
  1494. var expressionWhereClause = new ExpressionWhereClause<Foo, FooModel>(filter, new CaseInsensitive<Foo>(true, false), false, null);
  1495. expressionWhereClause.Predicate.ToString().Should().Be(exp.ToString().Replace("Convert(5)", "5"));
  1496. }
  1497. [TestCaseSource("CustomExpression_Cases")]
  1498. public void double_expressions_with_gridModelMapper_customExpression_and_orElse_operator(string member, FilterOperator @operator, Expression<Func<Foo, bool>> exp, object value)
  1499. {
  1500. var filter = new FilterDescriptor(member, @operator, value);
  1501. var expressionWhereClause = new ExpressionWhereClause<Foo, FooModel>(filter, new CaseInsensitive<Foo>(true, false), false, null);
  1502. expressionWhereClause.Predicate.ToString().Should().Be(exp.ToString().Replace("Convert(5)", "5"));
  1503. expressionWhereClause.OrElse(expressionWhereClause);
  1504. expressionWhereClause.Predicate.ToString().Should().Be(exp.OrElse(exp).ToString().Replace("Convert(5)", "5"));
  1505. }
  1506. [TestCaseSource("CustomExpression_Cases")]
  1507. public void double_expressions_with_gridModelMapper_customExpression_and_andAlso_operator(string member, FilterOperator @operator, Expression<Func<Foo, bool>> exp, object value)
  1508. {
  1509. var filter = new FilterDescriptor(member, @operator, value);
  1510. var expressionWhereClause = new ExpressionWhereClause<Foo, FooModel>(filter, new CaseInsensitive<Foo>(true, false), false, null);
  1511. expressionWhereClause.Predicate.ToString().Should().Be(exp.ToString().Replace("Convert(5)", "5"));
  1512. expressionWhereClause.AndAlso(expressionWhereClause);
  1513. expressionWhereClause.Predicate.ToString().Should().Be(exp.AndAlso(exp).ToString().Replace("Convert(5)", "5"));
  1514. }
  1515. }
  1516. public class ExpressionWhereClauseTests
  1517. {
  1518. [SetUp]
  1519. public void SetUp()
  1520. {
  1521. Mapper.Reset();
  1522. GridModelMapper.Reset();
  1523. GridModelMapper.CreateMap<Foo, FooModel>()
  1524. .MapProperty(foo => foo.FirstName + " " + foo.LastName, model => model.FullName)
  1525. .MapProperty(foo => foo.UnitPrice + foo.UnitsInStock, model => model.TotalPrice);
  1526. }
  1527. #region ExpressionCases
  1528. // ReSharper disable InconsistentNaming
  1529. static readonly Expression<Func<Foo, bool>> Exp_IsLessThan = foo => foo.UnitPrice < 5;
  1530. static readonly Expression<Func<Foo, bool>> Exp_IsLessThanOrEqualTo = foo => foo.UnitPrice <= 5;
  1531. static readonly Expression<Func<Foo, bool>> Exp_IsGreaterThanOrEqualTo = foo => foo.UnitPrice >= 5;
  1532. static readonly Expression<Func<Foo, bool>> Exp_IsGreaterThan = foo => foo.UnitPrice > 5;
  1533. static readonly Expression<Func<Foo, bool>> Exp_StartsWith = foo => foo.Name.StartsWith("Luis");
  1534. static readonly Expression<Func<Foo, bool>> Exp_EndsWith = foo => foo.Name.EndsWith("Luis");
  1535. static readonly Expression<Func<Foo, bool>> Exp_Contains = foo => foo.Name.Contains("Luis");
  1536. static readonly Expression<Func<Foo, bool>> Exp_DoesNotContains = foo => !foo.Name.Contains("Luis");
  1537. static readonly Expression<Func<Foo, bool>> Exp_IsEqualTo = foo => foo.Name == "Luis";
  1538. static readonly Expression<Func<Foo, bool>> Exp_IsNotEqualTo = foo => foo.Name != "Luis";
  1539. static readonly Expression<Func<Foo, bool>> Exp_NullLiteralIsEqualTo = foo => foo.Name == null;
  1540. static readonly Expression<Func<Foo, bool>> Exp_NullLiteralIsNotEqualTo = foo => foo.Name != null;
  1541. static readonly object[] ExpressionCases =
  1542. {
  1543. new object[] { "UnitPrice", FilterOperator.IsLessThan, Exp_IsLessThan, 5 },
  1544. new object[] { "UnitPrice", FilterOperator.IsLessThanOrEqualTo, Exp_IsLessThanOrEqualTo, "5" },
  1545. new object[] { "UnitPrice", FilterOperator.IsGreaterThanOrEqualTo, Exp_IsGreaterThanOrEqualTo, "5" },
  1546. new object[] { "UnitPrice", FilterOperator.IsGreaterThan, Exp_IsGreaterThan, "5" },
  1547. new object[] { "Name", FilterOperator.StartsWith, Exp_StartsWith, "Luis" },
  1548. new object[] { "Name", FilterOperator.EndsWith, Exp_EndsWith, "Luis" },
  1549. new object[] { "Name", FilterOperator.Contains, Exp_Contains, "Luis" },
  1550. new object[] { "Name", FilterOperator.DoesNotContain, Exp_DoesNotContains, "Luis" },
  1551. new object[] { "Name", FilterOperator.IsEqualTo, Exp_IsEqualTo, "Luis" },
  1552. new object[] { "Name", FilterOperator.IsNotEqualTo, Exp_IsNotEqualTo, "Luis" },
  1553. new object[] { "Name", FilterOperator.IsNotEqualTo, Exp_NullLiteralIsNotEqualTo, null },
  1554. new object[] { "Name", FilterOperator.IsEqualTo, Exp_NullLiteralIsEqualTo, null }
  1555. };
  1556. // ReSharper restore InconsistentNaming
  1557. #endregion
  1558. [TestCaseSource("ExpressionCases")]
  1559. public void single_expressions(string member, FilterOperator @operator, Expression<Func<Foo, bool>> exp, object value)
  1560. {
  1561. var filter = new FilterDescriptor(member, @operator, value);
  1562. var expressionWhereClause = new ExpressionWhereClause<Foo, FooModel>(filter, null, false, null);
  1563. expressionWhereClause.Predicate.ToString().Replace("Tests.Entity.Foo", "foo").Should().Be(exp.ToString());
  1564. }
  1565. [TestCaseSource("ExpressionCases")]
  1566. public void double_expressions_with_orElse_operator(string member, FilterOperator @operator, Expression<Func<Foo, bool>> exp, object value)
  1567. {
  1568. var filter = new FilterDescriptor(member, @operator, value);
  1569. var expressionWhereClause = new ExpressionWhereClause<Foo, FooModel>(filter, null, false, null);
  1570. expressionWhereClause.Predicate.ToString().Replace("Tests.Entity.Foo", "foo").Should().Be(exp.ToString());
  1571. expressionWhereClause.OrElse(expressionWhereClause);
  1572. expressionWhereClause.Predicate.ToString().Replace("Tests.Entity.Foo", "foo").Should().Be(exp.OrElse(exp).ToString());
  1573. }
  1574. [TestCaseSource("ExpressionCases")]
  1575. public void double_expressions_with_andAlso_operator(string member, FilterOperator @operator, Expression<Func<Foo, bool>> exp, object value)
  1576. {
  1577. var filter = new FilterDescriptor(member, @operator, value);
  1578. var expressionWhereClause = new ExpressionWhereClause<Foo, FooModel>(filter, null, false, null);
  1579. expressionWhereClause.Predicate.ToString().Replace("Tests.Entity.Foo", "foo").Should().Be(exp.ToString());
  1580. expressionWhereClause.AndAlso(expressionWhereClause);
  1581. expressionWhereClause.Predicate.ToString().Replace("Tests.Entity.Foo", "foo").Should().Be(exp.AndAlso(exp).ToString());
  1582. }
  1583. #region CustomExpression_Cases
  1584. // ReSharper disable InconsistentNaming
  1585. static readonly Expression<Func<Foo, bool>> CustomExpression_IsLessThan = foo => foo.UnitPrice + foo.UnitsInStock < 5;
  1586. static readonly Expression<Func<Foo, bool>> CustomExpression_IsLessThanOrEqualTo = foo => foo.UnitPrice + foo.UnitsInStock <= 5;
  1587. static readonly Expression<Func<Foo, bool>> CustomExpression_IsGreaterThanOrEqualTo = foo => foo.UnitPrice + foo.UnitsInStock >= 5;
  1588. static readonly Expression<Func<Foo, bool>> CustomExpression_IsGreaterThan = foo => foo.UnitPrice + foo.UnitsInStock > 5;
  1589. static readonly Expression<Func<Foo, bool>> CustomExpression_StartsWith = foo => (foo.FirstName + " " + foo.LastName).StartsWith("Luis Fernando");
  1590. static readonly Expression<Func<Foo, bool>> CustomExpression_EndsWith = foo => (foo.FirstName + " " + foo.LastName).EndsWith("Luis Fernando");
  1591. static readonly Expression<Func<Foo, bool>> CustomExpression_Contains = foo => (foo.FirstName + " " + foo.LastName).Contains("Luis Fernando");
  1592. static readonly Expression<Func<Foo, bool>> CustomExpression_DoesNotContains = foo => !(foo.FirstName + " " + foo.LastName).Contains("Luis Fernando");
  1593. static readonly Expression<Func<Foo, bool>> CustomExpression_IsEqualTo = foo => foo.FirstName + " " + foo.LastName == "Luis Fernando";
  1594. static readonly Expression<Func<Foo, bool>> CustomExpression_IsNotEqualTo = foo => foo.FirstName + " " + foo.LastName != "Luis Fernando";
  1595. static readonly Expression<Func<Foo, bool>> CustomExpression_NullLiteralIsEqualTo = foo => foo.FirstName + " " + foo.LastName == null;
  1596. static readonly Expression<Func<Foo, bool>> CustomExpression_NullLiteralIsNotEqualTo = foo => foo.FirstName + " " + foo.LastName != null;
  1597. static readonly object[] CustomExpression_Cases =
  1598. {
  1599. new object[] { "TotalPrice", FilterOperator.IsLessThan, CustomExpression_IsLessThan, 5 },
  1600. new object[] { "TotalPrice", FilterOperator.IsLessThanOrEqualTo, CustomExpression_IsLessThanOrEqualTo, "5" },
  1601. new object[] { "TotalPrice", FilterOperator.IsGreaterThanOrEqualTo, CustomExpression_IsGreaterThanOrEqualTo, "5" },
  1602. new object[] { "TotalPrice", FilterOperator.IsGreaterThan, CustomExpression_IsGreaterThan, "5" },
  1603. new object[] { "FullName", FilterOperator.StartsWith, CustomExpression_StartsWith, "Luis Fernando" },
  1604. new object[] { "FullName", FilterOperator.EndsWith, CustomExpression_EndsWith, "Luis Fernando" },
  1605. new object[] { "FullName", FilterOperator.Contains, CustomExpression_Contains, "Luis Fernando" },
  1606. new object[] { "FullName", FilterOperator.DoesNotContain, CustomExpression_DoesNotContains, "Luis Fernando" },
  1607. new object[] { "FullName", FilterOperator.IsEqualTo, CustomExpression_IsEqualTo, "Luis Fernando" },
  1608. new object[] { "FullName", FilterOperator.IsNotEqualTo, CustomExpression_IsNotEqualTo, "Luis Fernando" },
  1609. new object[] { "FullName", FilterOperator.IsEqualTo, CustomExpression_NullLiteralIsEqualTo, null },
  1610. new object[] { "FullName", FilterOperator.IsNotEqualTo, CustomExpression_NullLiteralIsNotEqualTo, null }
  1611. };
  1612. // ReSharper restore InconsistentNaming
  1613. #endregion
  1614. [TestCaseSource("CustomExpression_Cases")]
  1615. public void single_expressions_with_gridModelMapper_customExpression(string member, FilterOperator @operator, Expression<Func<Foo, bool>> exp, object value)
  1616. {
  1617. var filter = new FilterDescriptor(member, @operator, value);
  1618. var expressionWhereClause = new ExpressionWhereClause<Foo, FooModel>(filter, null, false, null);
  1619. expressionWhereClause.Predicate.ToString().Should().Be(exp.ToString());
  1620. }
  1621. [TestCaseSource("CustomExpression_Cases")]
  1622. public void double_expressions_with_gridModelMapper_customExpression_and_orElse_operator(string member, FilterOperator @operator, Expression<Func<Foo, bool>> exp, object value)
  1623. {
  1624. var filter = new FilterDescriptor(member, @operator, value);
  1625. var expressionWhereClause = new ExpressionWhereClause<Foo, FooModel>(filter, null, false, null);
  1626. expressionWhereClause.Predicate.ToString().Should().Be(exp.ToString());
  1627. expressionWhereClause.OrElse(expressionWhereClause);
  1628. expressionWhereClause.Predicate.ToString().Should().Be(exp.OrElse(exp).ToString());
  1629. }
  1630. [TestCaseSource("CustomExpression_Cases")]
  1631. public void double_expressions_with_gridModelMapper_customExpression_and_andAlso_operator(string member, FilterOperator @operator, Expression<Func<Foo, bool>> exp, object value)
  1632. {
  1633. var filter = new FilterDescriptor(member, @operator, value);
  1634. var expressionWhereClause = new ExpressionWhereClause<Foo, FooModel>(filter, null, false, null);
  1635. expressionWhereClause.Predicate.ToString().Should().Be(exp.ToString());
  1636. expressionWhereClause.AndAlso(expressionWhereClause);
  1637. expressionWhereClause.Predicate.ToString().Should().Be(exp.AndAlso(exp).ToString());
  1638. }
  1639. }
  1640. public class DynamicWhereClauseTests
  1641. {
  1642. [SetUp]
  1643. public void SetUp()
  1644. {
  1645. Mapper.Reset();
  1646. GridModelMapper.Reset();
  1647. GridModelMapper.CreateMap<Foo, FooModel>()
  1648. .MapProperty(foo => foo.FirstName + " " + foo.LastName, model => model.FullName)
  1649. .MapProperty(foo => foo.UnitPrice + foo.UnitsInStock, model => model.TotalPrice);
  1650. }
  1651. #region ExpressionCases
  1652. // ReSharper disable InconsistentNaming
  1653. static readonly Expression<Func<Foo, bool>> Exp_IsLessThan = foo => foo.UnitPrice < 5;
  1654. static readonly Expression<Func<Foo, bool>> Exp_IsLessThanOrEqualTo = foo => foo.UnitPrice <= 5;
  1655. static readonly Expression<Func<Foo, bool>> Exp_IsGreaterThanOrEqualTo = foo => foo.UnitPrice >= 5;
  1656. static readonly Expression<Func<Foo, bool>> Exp_IsGreaterThan = foo => foo.UnitPrice > 5;
  1657. static readonly Expression<Func<Foo, bool>> Exp_StartsWith = foo => foo.Name.StartsWith("Luis");
  1658. static readonly Expression<Func<Foo, bool>> Exp_EndsWith = foo => foo.Name.EndsWith("Luis");
  1659. static readonly Expression<Func<Foo, bool>> Exp_Contains = foo => foo.Name.Contains("Luis");
  1660. static readonly Expression<Func<Foo, bool>> Exp_DoesNotContains = foo => !foo.Name.Contains("Luis");
  1661. static readonly Expression<Func<Foo, bool>> Exp_IsEqualTo = foo => foo.Name == "Luis";
  1662. static readonly Expression<Func<Foo, bool>> Exp_IsNotEqualTo = foo => foo.Name != "Luis";
  1663. static readonly Expression<Func<Foo, bool>> Exp_NullLiteralIsEqualTo = foo => foo.Name == null;
  1664. static readonly Expression<Func<Foo, bool>> Exp_NullLiteralIsNotEqualTo = foo => foo.Name != null;
  1665. static readonly object[] ExpressionCases =
  1666. {
  1667. new object[] { "UnitPrice", FilterOperator.IsLessThan, Exp_IsLessThan, 5 },
  1668. new object[] { "UnitPrice", FilterOperator.IsLessThanOrEqualTo, Exp_IsLessThanOrEqualTo, "5" },
  1669. new object[] { "UnitPrice", FilterOperator.IsGreaterThanOrEqualTo, Exp_IsGreaterThanOrEqualTo, "5" },
  1670. new object[] { "UnitPrice", FilterOperator.IsGreaterThan, Exp_IsGreaterThan, "5" },
  1671. new object[] { "Name", FilterOperator.StartsWith, Exp_StartsWith, "Luis" },
  1672. new object[] { "Name", FilterOperator.EndsWith, Exp_EndsWith, "Luis" },
  1673. new object[] { "Name", FilterOperator.Contains, Exp_Contains, "Luis" },
  1674. new object[] { "Name", FilterOperator.DoesNotContain, Exp_DoesNotContains, "Luis" },
  1675. new object[] { "Name", FilterOperator.IsEqualTo, Exp_IsEqualTo, "Luis" },
  1676. new object[] { "Name", FilterOperator.IsNotEqualTo, Exp_IsNotEqualTo, "Luis" },
  1677. new object[] { "Name", FilterOperator.IsNotEqualTo, Exp_NullLiteralIsNotEqualTo, null },
  1678. new object[] { "Name", FilterOperator.IsEqualTo, Exp_NullLiteralIsEqualTo, null }
  1679. };
  1680. // ReSharper restore InconsistentNaming
  1681. #endregion
  1682. [TestCaseSource("ExpressionCases")]
  1683. public void single_expressions(string member, FilterOperator @operator, Expression<Func<Foo, bool>> exp, object value)
  1684. {
  1685. var filter = new FilterDescriptor(member, @operator, value);
  1686. var dynamicWhereClause = new DynamicWhereClause<Foo, FooModel>(filter, null, false, null);
  1687. dynamicWhereClause.CustomExpression.ToString().Replace("Param_0", "foo").Should().Be(exp.ToString());
  1688. }
  1689. [TestCaseSource("ExpressionCases")]
  1690. public void double_expressions_with_orElse_operator(string member, FilterOperator @operator, Expression<Func<Foo, bool>> exp, object value)
  1691. {
  1692. var filter = new FilterDescriptor(member, @operator, value);
  1693. var dynamicWhereClause = new DynamicWhereClause<Foo, FooModel>(filter, null, false, null);
  1694. dynamicWhereClause.CustomExpression.ToString().Replace("Param_0", "foo").Should().Be(exp.ToString());
  1695. dynamicWhereClause.OrElse(dynamicWhereClause);
  1696. dynamicWhereClause.CustomExpression.ToString().Replace("Param_0", "foo").Should().Be(exp.OrElse(exp).ToString());
  1697. }
  1698. [TestCaseSource("ExpressionCases")]
  1699. public void double_expressions_with_andAlso_operator(string member, FilterOperator @operator, Expression<Func<Foo, bool>> exp, object value)
  1700. {
  1701. var filter = new FilterDescriptor(member, @operator, value);
  1702. var dynamicWhereClause = new DynamicWhereClause<Foo, FooModel>(filter, null, false, null);
  1703. dynamicWhereClause.CustomExpression.ToString().Replace("Param_0", "foo").Should().Be(exp.ToString());
  1704. dynamicWhereClause.AndAlso(dynamicWhereClause);
  1705. dynamicWhereClause.CustomExpression.ToString().Replace("Param_0", "foo").Should().Be(exp.AndAlso(exp).ToString());
  1706. }
  1707. #region CustomExpression_Cases
  1708. // ReSharper disable InconsistentNaming
  1709. static readonly Expression<Func<Foo, bool>> CustomExpression_IsLessThan = foo => foo.UnitPrice + foo.UnitsInStock < 5;
  1710. static readonly Expression<Func<Foo, bool>> CustomExpression_IsLessThanOrEqualTo = foo => foo.UnitPrice + foo.UnitsInStock <= 5;
  1711. static readonly Expression<Func<Foo, bool>> CustomExpression_IsGreaterThanOrEqualTo = foo => foo.UnitPrice + foo.UnitsInStock >= 5;
  1712. static readonly Expression<Func<Foo, bool>> CustomExpression_IsGreaterThan = foo => foo.UnitPrice + foo.UnitsInStock > 5;
  1713. static readonly Expression<Func<Foo, bool>> CustomExpression_StartsWith = foo => (foo.FirstName + " " + foo.LastName).StartsWith("Luis Fernando");
  1714. static readonly Expression<Func<Foo, bool>> CustomExpression_EndsWith = foo => (foo.FirstName + " " + foo.LastName).EndsWith("Luis Fernando");
  1715. static readonly Expression<Func<Foo, bool>> CustomExpression_Contains = foo => (foo.FirstName + " " + foo.LastName).Contains("Luis Fernando");
  1716. static readonly Expression<Func<Foo, bool>> CustomExpression_DoesNotContains = foo => !(foo.FirstName + " " + foo.LastName).Contains("Luis Fernando");
  1717. static readonly Expression<Func<Foo, bool>> CustomExpression_IsEqualTo = foo => foo.FirstName + " " + foo.LastName == "Luis Fernando";
  1718. static readonly Expression<Func<Foo, bool>> CustomExpression_IsNotEqualTo = foo => foo.FirstName + " " + foo.LastName != "Luis Fernando";
  1719. static readonly object[] CustomExpression_Cases =
  1720. {
  1721. new object[] { "TotalPrice", FilterOperator.IsLessThan, CustomExpression_IsLessThan, 5 },
  1722. new object[] { "TotalPrice", FilterOperator.IsLessThanOrEqualTo, CustomExpression_IsLessThanOrEqualTo, "5" },
  1723. new object[] { "TotalPrice", FilterOperator.IsGreaterThanOrEqualTo, CustomExpression_IsGreaterThanOrEqualTo, "5" },
  1724. new object[] { "TotalPrice", FilterOperator.IsGreaterThan, CustomExpression_IsGreaterThan, "5" },
  1725. new object[] { "FullName", FilterOperator.StartsWith, CustomExpression_StartsWith, "Luis Fernando" },
  1726. new object[] { "FullName", FilterOperator.EndsWith, CustomExpression_EndsWith, "Luis Fernando" },
  1727. new object[] { "FullName", FilterOperator.Contains, CustomExpression_Contains, "Luis Fernando" },
  1728. new object[] { "FullName", FilterOperator.DoesNotContain, CustomExpression_DoesNotContains, "Luis Fernando" },
  1729. new object[] { "FullName", FilterOperator.IsEqualTo, CustomExpression_IsEqualTo, "Luis Fernando" },
  1730. new object[] { "FullName", FilterOperator.IsNotEqualTo, CustomExpression_IsNotEqualTo, "Luis Fernando" }
  1731. };
  1732. // ReSharper restore InconsistentNaming
  1733. #endregion
  1734. [TestCaseSource("CustomExpression_Cases")]
  1735. public void single_expressions_with_gridModelMapper_customExpression(string member, FilterOperator @operator, Expression<Func<Foo, bool>> exp, object value)
  1736. {
  1737. var filter = new FilterDescriptor(member, @operator, value);
  1738. var dynamicWhereClause = new DynamicWhereClause<Foo, FooModel>(filter, null, false, null);
  1739. dynamicWhereClause.CustomExpression.ToString().Should().Be(exp.ToString());
  1740. }
  1741. [TestCaseSource("CustomExpression_Cases")]
  1742. public void double_expressions_with_gridModelMapper_customExpression_and_orElse_operator(string member, FilterOperator @operator, Expression<Func<Foo, bool>> exp, object value)
  1743. {
  1744. var filter = new FilterDescriptor(member, @operator, value);
  1745. var dynamicWhereClause = new DynamicWhereClause<Foo, FooModel>(filter, null, false, null);
  1746. dynamicWhereClause.CustomExpression.ToString().Should().Be(exp.ToString());
  1747. filter = new FilterDescriptor("Name", FilterOperator.IsEqualTo, "Luis");
  1748. var anotherDynamicWhereClause = new DynamicWhereClause<Foo, FooModel>(filter, null, false, null);
  1749. dynamicWhereClause.OrElse(anotherDynamicWhereClause);
  1750. Expression<Func<Foo, bool>> anotherExp = foo => foo.Name == "Luis";
  1751. dynamicWhereClause.CustomExpression.ToString().Should().Be(exp.OrElse(anotherExp).ToString());
  1752. }
  1753. [TestCaseSource("CustomExpression_Cases")]
  1754. public void double_expressions_with_gridModelMapper_customExpression_and_andAlso_operator(string member, FilterOperator @operator, Expression<Func<Foo, bool>> exp, object value)
  1755. {
  1756. var filter = new FilterDescriptor(member, @operator, value);
  1757. var dynamicWhereClause = new DynamicWhereClause<Foo, FooModel>(filter, null, false, null);
  1758. dynamicWhereClause.CustomExpression.ToString().Should().Be(exp.ToString());
  1759. filter = new FilterDescriptor("Name", FilterOperator.IsEqualTo, "Luis");
  1760. var anotherDynamicWhereClause = new DynamicWhereClause<Foo, FooModel>(filter, null, false, null);
  1761. dynamicWhereClause.AndAlso(anotherDynamicWhereClause);
  1762. Expression<Func<Foo, bool>> anotherExp = foo => foo.Name == "Luis";
  1763. dynamicWhereClause.CustomExpression.ToString().Should().Be(exp.AndAlso(anotherExp).ToString());
  1764. }
  1765. }
  1766. }