Skip to content

Commit d1ff636

Browse files
committed
Add tests for case-insensitive filter parsing modes
Added unit tests to verify QueryKit's handling of case-insensitive string comparisons. Tests cover default, global, and per-property case-insensitive modes, ensuring correct use of ToLower or ToUpper in generated filter expressions for all relevant operators. Per-property settings are confirmed to override global configuration.
1 parent 96d826a commit d1ff636

File tree

1 file changed

+195
-0
lines changed

1 file changed

+195
-0
lines changed

QueryKit.UnitTests/FilterParserTests.cs

Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -796,4 +796,199 @@ public void can_filter_with_has_conversion_configuration()
796796
expressionString.Should().Contain("x.Email");
797797
expressionString.Should().Contain("test@example.com");
798798
}
799+
800+
[Fact]
801+
public void case_insensitive_default_config_uses_to_lower()
802+
{
803+
// Arrange - no config, should default to ToLower
804+
var input = """Title @=* "waffle" """;
805+
806+
// Act
807+
var filterExpression = FilterParser.ParseFilter<TestingPerson>(input);
808+
809+
// Assert
810+
filterExpression.ToString().Should()
811+
.Be("""x => ((x.Title != null) AndAlso x.Title.ToLower().Contains("waffle".ToLower()))""");
812+
}
813+
814+
[Fact]
815+
public void case_insensitive_upper_mode_global_uses_to_upper()
816+
{
817+
// Arrange - global Upper mode
818+
var input = """Title @=* "waffle" """;
819+
var config = new QueryKitConfiguration(settings =>
820+
{
821+
settings.CaseInsensitiveComparison = CaseInsensitiveMode.Upper;
822+
});
823+
824+
// Act
825+
var filterExpression = FilterParser.ParseFilter<TestingPerson>(input, config);
826+
827+
// Assert - should use ToUpper instead of ToLower
828+
filterExpression.ToString().Should()
829+
.Be("""x => ((x.Title != null) AndAlso x.Title.ToUpper().Contains("waffle".ToUpper()))""");
830+
}
831+
832+
[Fact]
833+
public void case_insensitive_per_property_upper_mode_overrides_global_lower()
834+
{
835+
// Arrange - global Lower (default), per-property Title set to Upper
836+
var input = """Title @=* "waffle" """;
837+
var config = new QueryKitConfiguration(settings =>
838+
{
839+
settings.CaseInsensitiveComparison = CaseInsensitiveMode.Lower;
840+
settings.Property<TestingPerson>(x => x.Title).HasCaseInsensitiveMode(CaseInsensitiveMode.Upper);
841+
});
842+
843+
// Act
844+
var filterExpression = FilterParser.ParseFilter<TestingPerson>(input, config);
845+
846+
// Assert - Title should use ToUpper because of per-property override
847+
filterExpression.ToString().Should()
848+
.Be("""x => ((x.Title != null) AndAlso x.Title.ToUpper().Contains("waffle".ToUpper()))""");
849+
}
850+
851+
[Fact]
852+
public void case_insensitive_equals_upper_mode_uses_to_upper()
853+
{
854+
// Arrange
855+
var input = """Title ==* "waffle" """;
856+
var config = new QueryKitConfiguration(settings =>
857+
{
858+
settings.CaseInsensitiveComparison = CaseInsensitiveMode.Upper;
859+
});
860+
861+
// Act
862+
var filterExpression = FilterParser.ParseFilter<TestingPerson>(input, config);
863+
864+
// Assert
865+
filterExpression.ToString().Should()
866+
.Contain("ToUpper");
867+
filterExpression.ToString().Should()
868+
.NotContain("ToLower");
869+
}
870+
871+
[Fact]
872+
public void case_insensitive_not_equals_upper_mode_uses_to_upper()
873+
{
874+
var input = """Title !=* "lamb" """;
875+
var config = new QueryKitConfiguration(settings =>
876+
{
877+
settings.CaseInsensitiveComparison = CaseInsensitiveMode.Upper;
878+
});
879+
880+
var filterExpression = FilterParser.ParseFilter<TestingPerson>(input, config);
881+
882+
filterExpression.ToString().Should()
883+
.Be("x => ((x.Title == null) OrElse (x.Title.ToUpper() != \"lamb\".ToUpper()))");
884+
}
885+
886+
[Fact]
887+
public void case_insensitive_starts_with_upper_mode_uses_to_upper()
888+
{
889+
var input = """Title _=* "lamb" """;
890+
var config = new QueryKitConfiguration(settings =>
891+
{
892+
settings.CaseInsensitiveComparison = CaseInsensitiveMode.Upper;
893+
});
894+
895+
var filterExpression = FilterParser.ParseFilter<TestingPerson>(input, config);
896+
897+
filterExpression.ToString().Should()
898+
.Be("x => ((x.Title != null) AndAlso x.Title.ToUpper().StartsWith(\"lamb\".ToUpper()))");
899+
}
900+
901+
[Fact]
902+
public void case_insensitive_ends_with_upper_mode_uses_to_upper()
903+
{
904+
var input = """Title _-=* "lamb" """;
905+
var config = new QueryKitConfiguration(settings =>
906+
{
907+
settings.CaseInsensitiveComparison = CaseInsensitiveMode.Upper;
908+
});
909+
910+
var filterExpression = FilterParser.ParseFilter<TestingPerson>(input, config);
911+
912+
filterExpression.ToString().Should()
913+
.Be("x => ((x.Title != null) AndAlso x.Title.ToUpper().EndsWith(\"lamb\".ToUpper()))");
914+
}
915+
916+
[Fact]
917+
public void case_insensitive_not_contains_upper_mode_uses_to_upper()
918+
{
919+
var input = """Title !@=* "lamb" """;
920+
var config = new QueryKitConfiguration(settings =>
921+
{
922+
settings.CaseInsensitiveComparison = CaseInsensitiveMode.Upper;
923+
});
924+
925+
var filterExpression = FilterParser.ParseFilter<TestingPerson>(input, config);
926+
927+
filterExpression.ToString().Should()
928+
.Be("x => ((x.Title == null) OrElse Not(x.Title.ToUpper().Contains(\"lamb\".ToUpper())))");
929+
}
930+
931+
[Fact]
932+
public void case_insensitive_not_starts_with_upper_mode_uses_to_upper()
933+
{
934+
var input = """Title !_=* "lamb" """;
935+
var config = new QueryKitConfiguration(settings =>
936+
{
937+
settings.CaseInsensitiveComparison = CaseInsensitiveMode.Upper;
938+
});
939+
940+
var filterExpression = FilterParser.ParseFilter<TestingPerson>(input, config);
941+
942+
filterExpression.ToString().Should()
943+
.Be("x => ((x.Title == null) OrElse Not(x.Title.ToUpper().StartsWith(\"lamb\".ToUpper())))");
944+
}
945+
946+
[Fact]
947+
public void case_insensitive_not_ends_with_upper_mode_uses_to_upper()
948+
{
949+
var input = """Title !_-=* "lamb" """;
950+
var config = new QueryKitConfiguration(settings =>
951+
{
952+
settings.CaseInsensitiveComparison = CaseInsensitiveMode.Upper;
953+
});
954+
955+
var filterExpression = FilterParser.ParseFilter<TestingPerson>(input, config);
956+
957+
filterExpression.ToString().Should()
958+
.Be("x => ((x.Title == null) OrElse Not(x.Title.ToUpper().EndsWith(\"lamb\".ToUpper())))");
959+
}
960+
961+
[Fact]
962+
public void case_insensitive_in_operator_upper_mode_uses_to_upper()
963+
{
964+
var input = """Title ^^* ["lamb","chicken"] """;
965+
var config = new QueryKitConfiguration(settings =>
966+
{
967+
settings.CaseInsensitiveComparison = CaseInsensitiveMode.Upper;
968+
});
969+
970+
var filterExpression = FilterParser.ParseFilter<TestingPerson>(input, config);
971+
var asString = filterExpression.ToString();
972+
973+
asString.Should().Contain("ToUpper");
974+
asString.Should().NotContain("ToLower");
975+
}
976+
977+
[Fact]
978+
public void case_insensitive_per_property_lower_overrides_global_upper()
979+
{
980+
// Arrange - global Upper, per-property Title set back to Lower
981+
var input = """Title @=* "waffle" """;
982+
var config = new QueryKitConfiguration(settings =>
983+
{
984+
settings.CaseInsensitiveComparison = CaseInsensitiveMode.Upper;
985+
settings.Property<TestingPerson>(x => x.Title).HasCaseInsensitiveMode(CaseInsensitiveMode.Lower);
986+
});
987+
988+
var filterExpression = FilterParser.ParseFilter<TestingPerson>(input, config);
989+
990+
// Title should use ToLower because per-property overrides global Upper
991+
filterExpression.ToString().Should()
992+
.Be("""x => ((x.Title != null) AndAlso x.Title.ToLower().Contains("waffle".ToLower()))""");
993+
}
799994
}

0 commit comments

Comments
 (0)