diff --git a/src/AutoFilterer/Types/StringFilter.cs b/src/AutoFilterer/Types/StringFilter.cs index 91f59a4..1889c25 100644 --- a/src/AutoFilterer/Types/StringFilter.cs +++ b/src/AutoFilterer/Types/StringFilter.cs @@ -66,6 +66,16 @@ public class StringFilter : IFilterableType /// Provides parameter to check is not null. /// public virtual bool? IsNotNull { get; set; } + + /// + /// Provides parameter to check is empty string. + /// + public virtual bool? IsEmpty { get; set; } + + /// + /// Provides parameter to check is not empty string. + /// + public virtual bool? IsNotEmpty { get; set; } /// /// @@ -114,6 +124,31 @@ public virtual Expression BuildExpression(Expression expressionBody, PropertyInf if (NotEndsWith != null) expression = expression.Combine(Expression.Not(new StringFilterOptionsAttribute(StringFilterOption.EndsWith) { Comparison = Compare }.BuildExpression(expressionBody, targetProperty, filterProperty, NotEndsWith)), CombineWith); + + if (IsEmpty != null) + { + if (IsEmpty.Value) + { + expression = expression.Combine(new StringFilterOptionsAttribute(StringFilterOption.Equals) { Comparison = Compare }.BuildExpression(expressionBody, targetProperty, filterProperty, ""), CombineWith); + } + else + { + expression = expression.Combine(Expression.Not(new StringFilterOptionsAttribute(StringFilterOption.Equals) { Comparison = Compare }.BuildExpression(expressionBody, targetProperty, filterProperty, "")), CombineWith); + } + } + + if (IsNotEmpty != null) + { + if (IsNotEmpty.Value) + { + expression = expression.Combine(Expression.Not(new StringFilterOptionsAttribute(StringFilterOption.Equals) { Comparison = Compare }.BuildExpression(expressionBody, targetProperty, filterProperty, "")), CombineWith); + } + else + { + expression = expression.Combine(new StringFilterOptionsAttribute(StringFilterOption.Equals) { Comparison = Compare }.BuildExpression(expressionBody, targetProperty, filterProperty, ""), CombineWith); + } + } + return expression; } } diff --git a/tests/AutoFilterer.Tests/Types/StringFilterTests.cs b/tests/AutoFilterer.Tests/Types/StringFilterTests.cs index 44ccfd8..f48ba47 100644 --- a/tests/AutoFilterer.Tests/Types/StringFilterTests.cs +++ b/tests/AutoFilterer.Tests/Types/StringFilterTests.cs @@ -171,4 +171,66 @@ public void BuildExpression_TitleWithIsNotNull_ShouldMatchCount(List data) foreach (var item in actualResult) Assert.Contains(item, result); } + + [Theory, AutoMoqData(count: 64)] + public void BuildExpression_TitleWithIsEmpty_ShouldMatchCount(List data) + { + for (var i = 0; i < 5; i++) + { + data[i].Title = ""; + } + + // Arrange + var filter = new BookFilter_StringFilter_Title + { + Title = new StringFilter + { + IsEmpty = true + } + }; + + // Act + var query = data.AsQueryable().ApplyFilter(filter); + var result = query.ToList(); + + // Assert + var actualResult = data.AsQueryable().Where(x => x.Title == "").ToList(); + + Assert.Equal(actualResult.Count, result.Count); + Assert.Equal(5, actualResult.Count); + Assert.Equal(5, result.Count); + foreach (var item in actualResult) + Assert.Contains(item, result); + } + + [Theory, AutoMoqData(count: 64)] + public void BuildExpression_TitleWithIsNotEmpty_ShouldMatchCount(List data) + { + for (var i = 0; i < 5; i++) + { + data[i].Title = ""; + } + + // Arrange + var filter = new BookFilter_StringFilter_Title + { + Title = new StringFilter + { + IsNotEmpty = true + } + }; + + // Act + var query = data.AsQueryable().ApplyFilter(filter); + var result = query.ToList(); + + // Assert + var actualResult = data.AsQueryable().Where(x => x.Title != "").ToList(); + + Assert.Equal(actualResult.Count, result.Count); + Assert.Equal(64 - 5, actualResult.Count); + Assert.Equal(64 - 5, result.Count); + foreach (var item in actualResult) + Assert.Contains(item, result); + } }